vuedraggable 兩個不同結構的數組之間拖拽


官方文檔:

需求

最近做一個菜單收藏功能. 界面交互: 將沒有收藏的菜單, 拖到已收藏的菜單中,
來實現收藏的功能.

需求:

  1. 能從未收藏區域, 拖動到已收藏的區域
  2. 未收藏的菜單區域, 不能拖動排序(順序是排好的)
  3. 未收藏的菜單區域, 不能從已收藏的菜單中拖回來
  4. 已收藏的菜單, 點擊刪除后, 按原順序回到未收藏的菜單中

使用的是 vuedraggable

數據結構如下:

+---------------------+              +---------------+
|    Collection       |              |       Menu    |
+---------------------+ 1          1 +---------------+
|-id:String           |--------------|-id:String     |
|-collectedTime:Date  | -menu        |-name:String   |
+---------------------+              +---------------+

實現

代碼片段

模板:

<!-- 已收藏 -->
<el-row>
  <el-col :span='24'>
    <draggable
      :group='{name: "menu", put: true}'
      @add='addCollection'
      @update='sortCollection'
      :value="collections">
      <div v-for='collection in collections' :key='collection.id'>
        <collection-item
          @delete='deleteCollection'
          :deletable='modified'
          :collection='collection'></collection-item>
      </div>
    </draggable>
  </el-col>
</el-row>
<!-- 未收藏 -->
<el-row>
  <el-col :span='24'>
    <draggable
      :group='{name: "menu", put: false}'
      :sort='false'
      :value="notCollectedMenus">
      <div v-for='menu in notCollectedMenus' :key='menu.id'>
        <menu-item :menu='menu'></menu-item>
      </div>
    </draggable>
  </el-col>
</el-row>

js:

data: function () {
  return {
	collections: [],
	availableMenus: [],
  }
},
computed: {
  notCollectedMenus: function () {
	return this.availableMenus.filter(menu => {
	  let collection = this.collections.find(collection => collection.menu.id === menu.id)
	  return collection == undefined ? true : false
	})
  },
},
methods: {
  deleteCollection (collectionToBeDeleted) {
	let index = this.collections.findIndex(collection => collection.id == collectionToBeDeleted.id)
	this.collections.splice(index, 1)
  },
  addCollection (evt) {
	let newCollectionIndex = evt.newIndex
	let menuIndex = evt.oldIndex

	let menu = this.notCollectedMenus[menuIndex]
	let newCollection = {}
	newCollection.menu = menu
	newCollection.username = this.username
	this.collections.splice(newCollectionIndex, 0, newCollection)
  },
  sortCollection (evt) {
	let newIndex = evt.newIndex
	let oldIndex = evt.oldIndex

	let collection = this.collections[oldIndex]
	this.collections.splice(oldIndex, 1)
	this.collections.splice(newIndex, 0, collection)
  },
}
  • collections 為收藏的數組, 里面的對象為 Collection,
  • availableMenus 為所有可被收藏菜單的數組, 里面的對象為 Menu
  • notCollectedMenus 為一個計算值, 為沒有被收藏菜單的數組, 里面的對象為 Menu

實現說明

vuedraggable 中, 不能使用 v-model, 而使用 value 屬性.
v-model 會在排序, 拖進, 拖出的時候, 修改數組的內容, 而兩個數組是不同構的,
這樣程序會出錯的.

既然不能用 v-model 來自動操作數據, 所以對應的排序, 拖進, 拖出操作,
需要自己來寫相應的事件處理.

  • add 拖進
  • update 排序
  1. 能從未收藏區域, 拖動到已收藏的區域

    兩個 draggable 節點中, group 的 name 是一樣的, 這樣就可以實現兩個區域的相互拖拽.

  2. 未收藏的菜單區域, 不能拖動排序(順序是排好的)

    未收藏的 draggable 節點中加上 :sort='false'

  3. 未收藏的菜單區域, 不能從已收藏的菜單中拖回來

    未收藏的 draggable 節點中, group 添加 put: false

  4. 已收藏的菜單, 點擊刪除后, 按原順序回到未收藏的菜單中

    該需求沒有拖出要求, 從 collections 數組中刪除, 通過計算屬性 notCollectedMenus
    來添加到下面的區域.


免責聲明!

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



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