使用 Sortable.js 在 uni App 上实现拖拽排序功能
它可以用来实现这个拖拽的功能。Sortable.js —是一个JavaScript库,用于在现代浏览器和触摸设备上对拖放列表进行重新排序,无需jQuery。特点有:轻量级但功能强大移动列表项时有动画支持触屏设备和大多数浏览器(IE9及以下除外)支持单个列表容器内部拖拽排序,也支持两个列表容器互相拖拽排序支持拖放操作和可选择的文本非常友善的滚动效果基于原生HTML5中的拖放API支持多种框架(Ang
sortable.js,它可以用来实现这个拖拽的功能。
Sortable.js —是一个JavaScript库,用于在现代浏览器和触摸设备上对拖放列表进行重新排序,无需jQuery。 特点有:
-
轻量级但功能强大
-
移动列表项时有动画
-
支持触屏设备和大多数浏览器(IE9及以下除外)
-
支持单个列表容器内部拖拽排序,也支持两个列表容器互相拖拽排序
-
支持拖放操作和可选择的文本
-
非常友善的滚动效果
-
基于原生HTML5中的拖放API
-
支持多种框架(Angular、Vue、React等)
-
支持所有的CSS框架,如:Bootstrap
-
简单的API,方便调用
-
CDN
-
不依赖于jQuery
步骤
安装sortable.js
npm install sortablejs --save-dev
获取节点
这里获取的节点是需要拖拽列表的父节点
// 使用DOM id 获取DOM
let el = document.getElementById('list')
或者
// 使用类名
let el = document.querySelector('.list')
通过Sortable()构建函数,接收容器元素和配置项
let el = document.querySelector('.list')
sortable = Sortable.create(this.dragData, {
sort: true, //是否可进行拖拽排序
animation: 500,
// 允许被拖拽的类名
draggable: '.data',
// 元素被选中
onChoose: (/**Event*/evt) => {
console.log("元素被选中,事件对象",evt)
// element index within parent
},
// 开始拖拽的时候
onStart: (/**Event*/evt) => {
evt.oldIndex;
// element index within parent
},
// 列表内元素顺序更新的时候触发
onUpdate: (/**Event*/evt) => {
// same properties as onEnd
console.log("顺序更新",evt)
},
onEnd: (evt) => {
// h5使用此方式修改数组顺序
const val = this.list[evt.oldIndex]
this.list.splice(evt.oldIndex, 1)
this.list.splice(evt.newIndex, 0, val)
}
}
拖动时会触发各种事件
可以选择 onUpdate 或 onEnd 事件被触发时改变数组顺序
需要把 用Sortable()构建函数创建 sortable 对象 这一操作封装到 methods 中,然后在 mounted 中调用 完整代码
<template>
<view>
<view class="list" :list="list" :change:list="Sortable.getListData">
<view
v-for="text of list"
:key="text.id"
class="data">
<view class="name">{{text.name}}</view>
<view class="id">{{text.id}}</view>
<view class="url">{{text.url}}</view>
</view>
<view class="block"></view>
</view>
</view>
</template>
<script>
export default {
data() {
return {
list: [{
name: '啊啊啊',
id: 1,
url: '',
},
{
name: '不不不',
id: 2,
url: '',
},
{
name: '陈琛琛',
id: 3,
url: '',
},
{
name: '顶顶顶',
id: 4,
url: '',
},
{
name: '烦烦烦',
id: 5,
url: '',
}],
}
},
mounted() {
this.initSortable()
},
methods: {
initSortable() {
this.el = document.querySelector('.list')
console.log("被选中的DOM",this.el)
this.sortable = Sortable.create(this.dragData, {
sort: true, //是否可进行拖拽排序
animation: 500, //动画时间
// 允许被拖拽的类名
draggable: '.data',
onEnd: (evt) => {
// h5使用此方式修改数组数据
const val = this.list[evt.oldIndex]
this.list.splice(evt.oldIndex, 1)
this.list.splice(evt.newIndex, 0, val)
},
})
},
}
}
</script>
但是此方式只能用于h5 无法在APP使用,原因为 APP中无法使用 document对象 ,更不能通过document对象获取元素DOM,需要结合 renderjs 使用才能实现
结合 renderjs 使用方法
使用renderjs 关于使用renderjs[]
// 在<script>中添加 module='' lang="renderjs"
// module='' 中内容为自己设置的名称 ,相当于命名空间,之后会根据这个名字调用其中的方法
//例如
<script module="Sortable" lang="renderjs">
</script>
但是在 renderjs 中 无法直接获取到 service层 的 vue 中的数据,也无法直接把数据返回到 service层的 vue 中,需要在 renderjs与vue建立通信
在 renderjs与vue建立通信
数据从service层传输到 renderjs :
在template中的父节点绑定一个service中定义的值,然后在同样的位置增加:change:(属性名)=(触发的方法)
来实现通信。 例如在父节点上添加 :list="list" :change:list="Sortable.getListData"
// prop是个名字,可以随意改,注意:change:[name]这两个名字需要相同就行了
<view class="list" :prop="list" :change:prop="Sortable.getListData">
<view v-for="text of list" :key="text.id" class="data">
<view class="name">{{text.name}}</view>
<view class="id">{{text.id}}</view>
<view class="url">{{text.url}}</view>
</view>
</view>
<script lang="renderjs" module="Sortable">
export default {
methods: {
getListData(newValue, oldValue, ownerInstance, instance) {
console.log('service层中的options发生变化')
console.log('新值', newValue)
console.log('旧值', oldValue)
// 通过this.prop看可以直接使用
console.log(this.prop)
// ownerInstance和this.$ownerInstance一样,可用来向service层通信
// instance和ownerInstance的区别是:
// instance.$el指向的是触发事件的那个节点;ownerInstance.$el指向当前vue文件中的根节点;
// instance的作用目前尚不明确,官方没有给出用法
},
}
}
</script>
数据从renderjs层传递到service层
直接在renderjs层层修改数据是无法在service层提现,需要传输到service层 通过this.$ownerInstance.callMethod()
方法可以调用service中的方法,第一个参数是方法名,第二个参数是传过去的参数
methods: {
initSortable() {
this.dragData = document.querySelector('.list')
console.log("被选中的DOM",this.dragData)
this.sortable = Sortable.create(this.dragData, {
sort: true, //是否可进行拖拽排序
animation: 500,
// 允许被拖拽的类名
draggable: '.data',
// 结束拖拽时触发此函数
onEnd: (evt) => {
let returnDate = {
oldIndex : evt.oldIndex,
newIndex : evt.newIndex,
oldV : this.list[evt.oldIndex],
newV : this.list[evt.newIndex]
}
// APP中需要把数据返回到service层再修改数组顺序
this.$ownerInstance.callMethod('setDataList', returnDate);
},
})
},
}
然后在service层修改数组顺序
methods:{
setDataList(returnDate){
// 修改数组顺序
let tempVal = this.list[returnDate.oldIndex]
this.list.splice(returnDate.oldIndex, 1)
this.list.splice(returnDate.newIndex, 0, tempVal)
}
}
至此整个功能完成实现
更多推荐
所有评论(0)