VUE.DRAGGABLE實現從左到右拖拽功能


功能描述:

1、左邊【一級、二級、三級】字樣是不能拖拽的,【item1、item2...】可以拖拽

2、左邊items位置固定,只能向右拖拽,不能上下拖拽,如:item7從左邊拖到右邊,左邊的item7消失,右邊增加item7

3、右邊items可以自由拖拽,但不能向左拖拽

4、右邊items可以刪除,如:點擊item7的“×”,右邊item7消失,左邊item7出現

5、重置時,頁面回復初始化狀態

實現方法:

1、左右json格式如下:

left=[
  {"name": "一級","indexid": 1},
  {"name": "item1", "id": 1,"indexid": 2},
  {"name": "item2","id": 2,"indexid": 3},
  {"name": "二級","indexid": 4},
  {"name": "item3","id": 3,"indexid": 5},
  {"name": "item4","id": 4,"indexid": 6}
   ...
];
right=[
  {"name": "item8","id": 8,"indexid": 10},
  {"name": "item7","id": 7,"indexid": 9}
]

2、dom原始使用flex布局,拖拽時使用Vue.Draggable插件,

下載地址:https://github.com/SortableJS/Vue.Draggable#start-of-content

演示地址:https://sortablejs.github.io/Vue.Draggable/#/simple

3、一開始左邊加載所有的items,右邊加載展示的items,注意:左邊要過濾掉(隱藏)右邊有的items,參考filterComs(left,right)方法;

在渲染dom、移動、刪除時,通過操作dom來實現展示與隱藏;

4、左邊draggle插件,:group="{ name: 'dragobj', pull: 'clone', put: false}" 

{    name: 'dragobj'取相同名字的可以來回拖拽;pull: 'clone'從左向右克隆,后面用右邊draggle插件的dragChangeR()方法讓左側數據隱藏了,left並不是真正的刪除這條數據;put: false 禁止從右向左拖放數據   }

:move="checkMove" 移動時綁定checkMove方法,判斷是上下還是向右移動,上下時,不執行拖拽;向右時,執行

5、右邊draggle插件的deleteItme(element,index)方法實現刪除時,right數據-1,左側顯示該條數據

6、【重置】時,重新調用this.filterComs(this.left,this.right);即可

7、問題:從左往右移動時,右側一直會出現items的name值,拖拽結束后,name值消失,

解決方法:左右分別綁定一個v-bind="dragOptionsL",v-bind="dragOptionsR"

8、問題:當右側沒有任何的items時,需要給右側v-for循環的父元素指定一個min-height,否則從左側拖到右側時,沒有接收的地方,則拖放失效

<template>
    <div class="box">
      <div class="dragset-msg">請將左側內容拖到右側進行配置</div>
      <!-- 1 左邊指標 -->
      <draggable tag="ul" class="lul"
        v-bind="dragOptionsL"
        :move="checkMove"
        :list="left" 
        :group="{ name: 'dragobj', pull: 'clone', put: false}">
        <li v-for="element in left" :key="element.name" 
          :class="element.id?'dragindex':'dragtheme'" 
          :ref="`li${element.indexid}`">
          {{ element.name }}
        </li>
      </draggable>
      <!-- 2 右邊展示區 -->
      <draggable  tag="div" class="rconfig"
        group="dragobj"
        :list="right"
        v-bind="dragOptionsR"
        @change="dragChangeR"
        @start="drag = true"
        @end="drag = false">
        <transition-group type="transition" :name="!drag ? 'flip-list' : null" tag="ul" class="rul">
           <li class="showindex" v-for="(element,index) in right" :key="element.name" >
              {{ element.name }}
              <input type="button" class="btnindex" @click.stop="deleteItme(element,index)"> 
            </li>
        </transition-group>
      </draggable>
</div>
</template>
 
<script>
import draggable from "vuedraggable";
import Vue from "vue";
export default {
  components: { draggable },
  data() {
    return {
      blnShowDlg: false,
      dlgType: "add", // 窗口類型
      titleName: "", // 窗口標題顯示
      settingData: {}, //獲取左右配置數據
      dataFormStore:{},//保存數據
      left:[],//左邊數據
      right:[],//右邊數據
      drag:false,
    };
  },
  computed: {
    dragOptionsL() {
      return {
        disabled: false,
        ghostClass: "ghostL"//注意:在左側上下移動時,使用這個類;移動到右側時,使用ghostR類!!!
      };
    },
    dragOptionsR() {
      return {
        animation: 500,
        disabled: false,
        ghostClass: "ghostR"//注意:在右側上下移動時,使用這個類;
      };
    }
  },
  methods: {
    /** 1、顯示彈框 row不傳為添加 傳參為修改 */
    showDlg(row) {
      this.titleName = "頁面配置";
      this.dlgType = "edit";
      this.blnShowDlg = true;
      this.dataFormStore =  this.$common.deepCopy(row);//存儲原始數據
      this.left=row.left;
      this.right=row.right;
      this.restoreForm();
    },
    // 2 左側list移動,禁止在左側上下移動
    checkMove(evt){
      let classObj=evt.to.className;
      if(evt.draggedContext.element.id===""){
        return false;
      }else if(classObj.indexOf("lul")>-1){
        return false;
      }
    },
    // 2.1 拖拽事件,添加時隱藏左側添加的數據
    dragChangeR(evt) {
      if(evt.added){//這時候已經添加了
        this.$refs[`li${evt.added.element.indexid}`][0].style.display='none';
      }
    },
    // 3 刪除
    deleteItme(element,index){
      this.right.splice(index,1);
      this.$refs[`li${element.indexid}`][0].style.display='block';
    },
    // 4 取消
    closeDialog() {
      this.blnShowDlg = false;
    },
    // 5 關閉
    hidDlg() {
      this.blnShowDlg = false;
    },
    /** 6 修改-還原 */
    restoreForm() {
      this.left=this.$common.deepCopy(this.dataFormStore.left);
      this.right=this.$common.deepCopy(this.dataFormStore.right);
      this.filterComs(this.left,this.right);
    },
    /** 7 添加/保存 */
    submitForm() {
      let newright=this.right;
      let rlens=this.right.length;
      if(rlens>0){
        let idArr=[];
        for(let i=0;i<rlens;i++){
          idArr.push(newright[i].indexid);
        }
        this.$emit("doSaveRow",idArr);  // 把id數組傳遞過去
      }else{
        this.$HiAlert.showFail(this.$HiAlert.getMsgText("至少選擇一個菜單"));
      }
    },
    // 8 過濾不顯示的左側item
    filterComs(left,right){
      if(right.length > 0){
        // 初始化,全置為blcok,后面根據right數據過濾顯示
        for(let i=0;i< left.length;i++){
          this.$nextTick(() => {
            this.$refs[`li${left[i].indexid}`][0].style.display='block';
          });
        }
        for(let i=0;i< right.length;i++){
          let filteritem=left.filter((element,index,self)=>{
            return element.indexid==right[i].indexid;
          });
            // 右側有數據時,dom生成之后再來渲染,否則會報錯:cannot read property '0' of undefined
          this.$nextTick(() => {
            this.$refs[`li${filteritem[0].indexid}`][0].style.display='none';
          });
        }
      }
    }
  }
};
</script>
<style  lang="stylus" scoped>
//應用樣式文件
.ghostL{
    opacity:0.5;
    width:230px;
}
.ghostR{
    opacity:0;
    width:230px;
}
</style>


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM