首頁 >web前端 >js教程 >關於Vue拖曳組件的開發介紹

關於Vue拖曳組件的開發介紹

不言
不言原創
2018-06-30 16:51:232685瀏覽

本文重點介紹Vue拖曳元件開發實例,拖曳的原理是手指在移動的過程中,即時改變元素的位置即top和left值,使元素隨著手指的移動而移動。對實例程式碼有興趣的朋友一起學習吧

為什麼選擇Vue?

#主要原因:對於前端開發來說,相容性是我們必須要考慮的問題之一。我們的專案不需要相容低版本瀏覽器。專案本身也是一個數據驅動型的。加之,Vue本身俱有以下主要特性:

•使用虛擬DOM;
•輕量級框架;
•高效的資料綁定;
•靈活的元件系統;
•完整的開發生態鏈。

這就是我們為什麼選擇Vue框架的一些原因。

為什麼要封裝成一個Vue元件?

主要目的是可提高程式碼的複用性和可維護性。

•重複使用性:組件化後,一些樣式和邏輯都透過配置參數的方式去差異化體現,所以參數的可配置性提高了組件的複用率和靈活性。

•可維護性:組件化後,元件內部的邏輯只對元件負責,外部的邏輯只透過設定參數適配,所以提高了程式碼的邏輯清晰度,可以快速定位程式碼出現問題的地方。

元件化建置頁面圖示:

上圖可看出,在Vue中,所謂元件化建置頁面,簡單來說,頁面實際上是由一個個功能獨立的組件搭建而成。這些元件之間可以組合、嵌套,最終形成了我們的頁面。

元件構成

下面是一個完成的元件組成:

// 组件内模板
// 组件内逻辑代码
<script type="text/javascript"></script>
// 组件内封装的样式
<style lang="scss" scoped></style>

開發Vue移動拖曳組件為例

#拖曳原理

手指在移動的過程中,即時改變元素的位置即top和left值,使元素隨著手指的移動而移動。

拖曳實作

•開始拖曳時:取得到接觸點相對於整個視圖區的座標clientX,clientY ;取得元素距離視圖上側和左側的距離initTop,initLeft;計算接觸點距離元素上側和左側的距離elTop = clientY - initTop, elLeft = clientX - initLeft;
•拖曳過程中:透過currTop = clientY - elTop, currLeft = clientX - elLeft即時取得元素距離視圖上側和左側的距離值,並賦值給元素,使元素跟著手指的移動而動起來;
•拖曳結束,定位元素。

Vue中的實作

使用Vue,最大的不同之處在於我們幾乎不去操作DOM,要充分利用Vue的數據驅動來實現拖曳功能。本例中,我們只需在垂直方向上拖曳元素,所以只需考慮垂直方向的移動即可。

上圖中,透過data中的dragList渲染拖曳區域列表,程式碼如下:

template:
<p class="drag-title">拖拽可调整顺序</p>
<ul class="drag-list">
 <li class="drag-item">{{item.txt}}</li>
</ul>
script:
 
export default {
data() {
return {
dragList:null
}
},
created() {
this.dragList = [
{
isDrag: false,
txt: &#39;列表1&#39;,
isShow: false
}
...
]
},
}

假設我們將元素從位置1拖曳至位置3,本質上是陣列的順序改變了。這就有必要提一下Vue的最大特性:資料驅動。

所謂的資料驅動就是當資料改變時,透過修改資料狀態,使使用者介面發生對應的改變,開發者不需要手動的去修改DOM。

Vue的資料驅動是透過MVVM這種框架來實現的,MVVM框架主要包含3個部分:Model、View、Viewmodel。

– Model:資料部分;
– View:視圖部分;
– Viewmodel:連接視圖與資料的中間件。

順著這個思路走下去,我們知道:

– oldIndex:元素在陣列中的初始索引index;
– elHeight:單一元素區塊的高;
– currTop = clientY - elTop:元素在拖曳過程中距離可視區上側距離;
– currTop - initTop > 0:得知元素是向上拖曳;
– currTop - initTop < ; 0:得知元素是向下拖曳。

我們以向下拖曳來說:

– 首先,我们要在拖拽结束事件touchend中判断元素从拖动开始到拖动结束时拖动的距离。若小于某个设定的值,则什么也不做;
– 然后,在touchmove事件中判断,若(currTop - initTop) % elHeight>= elHeight/2成立,即当元素拖至另一个元素块等于或超过1/2的位置时,即可将元素插入到最新的位置为newIndex = (currTop - initTop) / elHeight + oldIndex。
– 最后,若手指离开元素,那么我们在touchend事件中,通过this.dragList.splice(oldIndex, 1),this.dragList.splice(newIndex, 0, item)重新调整数组顺序。页面会根据最新的dragList渲染列表。

写到这里,我们俨然已经用Vue实现了移动端的拖拽功能。但是拖拽体验并不好,接下来,我们对它进行优化。

优化点:我们希望,在元素即将可能落到的位置,提前留出一个可以放得下元素的区域,让用户更好的感知拖拽的灵活性。

方案:(方案已被验证是可行的)将li的结构做一下修改,代码如下:

<ul>
 <li class="drag-item">
<p class="leave-block"></p>
// 向上拖拽时留空
<p class="">{{item.txt}}</p>
<p class="leave-block"></p>
// 向下拖拽时留空</li>
</ul>

•拖拽开始:将元素的定位方式由static设置为absolute,z-index设置为一个较大的值,防止元素二次拖拽无效;

•拖拽过程中:将元素即将落入新位置的那个li下p的item.isShow设置为true,其他li下p的item.isShow均设置为false;

•拖拽结束:将所有li下p的item.isShow 均设置为false,将元素定位方式由absolute设置为static。

贴一段伪代码:

touchStart(e){
// 获取元素距离视口顶部的初始距离
initTop = e.currentTarget.offsetTop;
// 开始拖动时,获取鼠标距离视口顶部的距离
initClientY = e.touches[0].clientY;
// 计算出接触点距离元素顶部的距离
elTop = e.touches[0].clientY - initTop;
},
touchMove(index, item, e){
// 将拖拽结束时,给元素设置的static定位方式移除,防止元素二次拖拽无效
e.target.classList.remove(&#39;static&#39;);
// 给拖拽的元素设置绝对定位方式
e.target.classList.add(&#39;ab&#39;);
// 获取元素在拖拽过程中距离视口顶部距离
currTop = e.touches[0].clientY - elTop;
// 元素在拖拽过程中距离视口顶部距离赋给元素
e.target.style.top = currTop ;
// 获取元素初始位置
oldIndex = index;
// 获取拖拽元素
currItem = item;
// 若元素已经拖至区域外
if(e.touches[0].clientY > (this.dragList.length) * elHeight){
// 将元素距离上侧的距离设置为拖动区视图的高
currTop = (this.dragList.length) * elHeight;
return;
}
// 向下拖拽
if(currTop > initTop ){
// 若拖拽到大于等于元素的一半时,即可将元素插入到最新的位置
if((currTop - initTop) % elHeight>= elHeight / 2){
// 计算出元素拖到的最新位置
newIndex = Math.round((currTop - initTop) / elHeight) + index;
// 确保新元素的索引不能大于等于列表的长度
if(newIndex < this.dragList.length){
// 将所有列表留空处隐藏
for(var i = 0;i< this.dragList.length;i++){
this.dragList[i].isShow = false;
}
// 将元素即将拖到的新位置的留空展示
this.dragList[newIndex].isShow = true;
}
else {
return;
}
}
}
// 向上拖拽,原理同上
if(currTop < initTop){ ... } }, touchEnd(e){ // 若拖动距离大于某个设定的值,则按照上述,执行相关代码 if(Math.abs(e.changedTouches[0].clientY - initClientY ) > customVal){
this.dragList.splice(oldIndex, 1);
this.dragList.splice(newIndex, 0, currItem);
for(var i = 0;i< this.dragList.length;i++){
this.dragList[i].isShow = false;
this.dragList[i].isShowUp = false;
}
}
e.target.classList.remove(&#39;ab&#39;);
e.target.classList.add(&#39;static&#39;);
}

优化后,如下图所示:

以上便是用Vue实现移动端拖拽组件的过程。我们知道,有些项目是需要在PC端用Vue实现此功能。这里简单提一下PC与移动端的区别如下:

•PC端可以使用的事件组有两种:第一种:H5新特性draggable,dragstart,drag,dragend;第二种:mousedown,mousemove,mouseup;

•PC端获取鼠标坐标是通过e.clientX,clientY,区别于移动端的e.touches[0].clientX,e.touches[0].clientY。

小结

本文从Vue拖拽组件开发为例,剖析Vue组件的结构、开发思路、Vue的数据驱动等,对Vue组件化的原理,进行了更深入的理解。 并将Vue实现拖拽的方案提供给大家学习研究。

P.S. 牢记一点,切勿在Vue中过多得操作DOM,要能深入理解Vue数据驱动的核心思想。

以上就是本文的全部内容,希望对大家的学习有所帮助,更多相关内容请关注PHP中文网!

相关推荐:

Vue组件选项props的使用介绍

关于vux uploader 图片上传组件的安装使用方法

Vue实现返回顶部backToTop的组件

以上是關於Vue拖曳組件的開發介紹的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn