因为没有时间研究jquery的sortable功能(也没有文档),所以用HTML5的drag完成了简单的拖拽,这里记录下
`@dragstart` , `@dragover` , `@dragend` , `dragable`
dragable 确认可以被拖拽的元素
<ul @dragstart="onDragStart($event)"
@dragover="onDragOver($event)" @dragend="onDragEnd($event)" ref="box"> <li v-for="(item,index) in options" :index="index" class="item" draggable="true" :value="item.value" :key="item.value" v-show="item._checked"> {{item.label}} </li>
</ul>
script内部代码
/** * 拖拽开始 */ onDragStart(e) { boxHeight = Math.floor(e.target.offsetHeight/2) this.draging = e.target }, /** * 拖拽过程 */ onDragOver(e) { // console.log('move', e) this.target = e.target let targetTop = e.target.getBoundingClientRect().top let dragingTop = this.draging.getBoundingClientRect().top // console.log('drag move', targetTop) if(this.target.nodeName==='LI'&&this.target !== this.draging) { if(this.target&&this.target.animated) { return } let targetIndex = this.target.getAttribute('index') let dragingIndex = this.draging.getAttribute('index') if(targetIndex > dragingIndex) {//拖拽元素往下移动 //target的下一个元素 this.target.parentNode.insertBefore(this.draging, this.target.nextSibling) }else{ this.target.parentNode.insertBefore(this.draging, this.target) } this._animation(targetTop, this.target) this._animation(dragingTop, this.draging) } }, /** * 拖拽结束 */ onDragEnd(e) { var tOptions = JSON.parse(JSON.stringify(this.options)); let currentArray = Array.from(this.$refs['box'].childNodes) let data = currentArray.map((item,i)=>{ let obj = tOptions.find(c=>c.value===item.getAttribute('value')) obj.index = i return obj }) this.options = data this.initOptions() }, /** * 拖拽的动画过程 */ _animation(clientTop, dom) { let offset = clientTop - dom.getBoundingClientRect().top //元素移动后的新位置 //console.log('target+draging', offset) dom.style.transition = 'none'; dom.style.transform = `translateY(${offset}px)` //触发重绘 //console.log('offsetWidth:', dom.offsetWidth) //offsetWidth导致了浏览器重绘(了解浏览器重排、重绘) dom.style.transition = 'transform 0.3s'; dom.style.transform = ''; clearTimeout(dom.animated); dom.animated = setTimeout(()=>{ dom.style.transition = '' dom.style.transform = '' dom.animated=false },150) },
这样简单的拖拽就完成了,在这里要着重强调 `v-for` 的情况下,key值很重要,因为key值我给的是index值,发现每次排完序之后都是没重新排序的样子,犯了低级错误
key 为每个节点提供身份标识,数据改变时会重排,所以最好绑定唯一标识。
注意:如果用index标识可能得不到想要的效果,所以我在项目中使用了每个元素的value来作为 key