这是我参与更文挑战的第16天,活动详情查看: 更文挑战
因运营人员需要排序某个产品列表,这里记录使用SortableJS实现元素排序的过程。
sortableJs官网
引入
package.json
中添加:
需要排序的组件上添加:
1
| import Sortable from 'sortablejs'
|
添加控制标签
在需要添加拖拽效果的控件上添加id
标签。vue
环境下为el-table
增加拖拽排序则需要添加ref
与row-key
,代码如下所示:
1 2 3 4 5 6 7 8 9 10 11 12 13
| <el-table ref="myDragTable" v-loading="loading" :data="dataList" row-key="id" element-loading-text="商品加载中" border fit style="width: 100%;" highlight-current-row > .... </el-table>
|
其中的关键在于以下两个标签:
1 2
| ref="myDragTable" row-key="id"
|
不要忘记设置row-key
,否则会发生拖拽后行不规则的移动。
给其中的某列添加拖拽功能标识:
1 2 3 4 5
| <el-table-column align="center" label="拖动" width="45" class-name="allow"> <template> <i class="el-icon-rank" /> </template> </el-table-column>
|
该列展示效果如下图所示:
辅助数据与排序方法
在vue组件的data中需要添加两个数组来记录拖拽前与拖拽后的顺序:
1 2 3 4 5 6 7
| data() { return { dataList: [...] oldPList: [], newPList: [] } }
|
两个排序数组的初始化应该放在什么地方呢?
setSort
方法又该在什么时间点去执行呢?
应该在获取数据之后与渲染DOM之后,关键代码如下图:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44
| methods: { getData() { api...({ ... }).then(res => { this.dataList = res.data this.oldPList = this.dataList.map(v => v.id) this.newPList = this.oldPList.slice() this.$nextTick(() => { this.setSort() }) }) }, setSort() { const el = this.$refs.myDragTable.$el.querySelectorAll('.el-table__body-wrapper > table > tbody')[0] this.sortable = Sortable.create(el, { ghostClass: 'sortable-ghost', handle: '.allow', setData: function(dataTransfer) { dataTransfer.setData('Text', '') }, onEnd: evt => { const targetRow = this.dataList.splice(evt.oldIndex, 1)[0] this.dataList.splice(evt.newIndex, 0, targetRow)
const tempIndex = this.newPList.splice(evt.oldIndex, 1)[0] this.newPList.splice(evt.newIndex, 0, tempIndex) } }) }, }
|
具体接口配置信息:http://www.sortablejs.com/options.html
编写序号排序
拖拽排序适合少量数据的情况,不适合大数据量或者将一个元素从末尾拖到头部。我们还需要可以手动修改序号的方式来辅助。
这样操作人员可以很方便的将某些元素置顶或设置到末尾。
我们需要监听el-input
的change
事件,请求后台,更新排序信息。
为什么是监听change
事件而不是input
事件呢?因为input
事件在你的输入框内有任何变动时会立即请求,而change
则会在你输入完毕后(比如输入完毕点击enter或者鼠标点击空白处等)