vue下使用drag完成簡單拖拽


因為沒有時間研究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

 


免責聲明!

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



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