이 글에서는 Vue 드래그 컴포넌트 개발 사례를 집중적으로 소개합니다. 드래그의 원리는 손가락이 움직이는 동안 요소의 위치, 즉 위쪽 및 왼쪽 값이 실시간으로 변경되어 요소가 변경된다는 것입니다. 손가락의 움직임에 따라 움직입니다. 예제 코드에 관심 있는 친구들, 함께 배워봐요
Vue를 선택하는 이유?
주요 이유: 프론트엔드 개발에 있어서 호환성은 반드시 고려해야 할 문제 중 하나입니다. 우리 프로젝트는 하위 버전의 브라우저와 호환될 필요가 없습니다. 프로젝트 자체도 데이터 기반입니다. 또한 Vue 자체에는 다음과 같은 주요 기능이 있습니다.
•경량 프레임워크•유연한 구성 요소 시스템
•완전한 개발 생태계.
우리가 Vue 프레임워크를 선택하는 몇 가지 이유는 다음과 같습니다.
주요 목적은 코드 재사용성과 유지 관리성을 향상시키는 것입니다.
•재사용성: 컴포넌트화 후 일부 스타일과 로직은 매개변수 구성을 통해 차별화되고 반영되므로 매개변수 구성 가능성은 컴포넌트의 재사용률과 유연성을 향상시킵니다. •유지 관리성: 컴포넌트화 후 컴포넌트의 내부 로직은 컴포넌트만 담당하고 외부 로직은 구성 매개변수를 통해서만 조정되므로 코드의 로직 명확성이 향상되고 코드 문제를 빠르게 해결할 수 있습니다. 위치하고 있습니다. 컴포넌트 기반 빌딩 페이지 예시:위 그림에서 볼 수 있듯이, 소위 컴포넌트 기반 빌딩 페이지인 Vue에서는 간단히 말해서 독립적인 기능을 가진 컴포넌트들로 페이지가 실제로 구축됩니다. . 이러한 구성 요소를 결합하고 중첩하여 페이지를 구성할 수 있습니다.
컴포넌트 구성다음은 완성된 컴포넌트 구성입니다.
// 组件内模板 // 组件内逻辑代码 <script type="text/javascript"></script> // 组件内封装的样式 <style lang="scss" scoped></style>
드래그 원리
움직이는 손가락 이 과정에서 요소의 위치, 즉 상단 및 왼쪽 값이 실시간으로 변경되므로 손가락의 움직임에 따라 요소가 움직입니다.
드래그 구현
•드래그 시작 시: 전체 뷰 영역을 기준으로 접점의 clientX, clientY 좌표를 가져오고, 요소와 뷰 initTop의 위쪽 및 왼쪽 사이의 거리를 가져옵니다. initLeft; 점과 요소의 위쪽 및 왼쪽 사이의 거리를 계산합니다. elTop = clientY - initTop, elLeft = clientX - initLeft; 드래그 과정 중: 요소와 위쪽 및 왼쪽 사이의 거리를 가져옵니다. currTop = clientY - elTop, currLeft = clientX - elLeft를 통해 실시간으로 뷰의 요소가 손가락의 움직임에 따라 이동하도록 측면의 거리 값이 요소에 할당됩니다. • 드래그 후 요소의 위치를 지정합니다.
Vue에서 구현
Vue를 사용할 때 가장 큰 차이점은 DOM을 거의 조작하지 않고 드래그 앤 드롭 기능을 구현하려면 Vue의 데이터 드라이버를 최대한 활용해야 한다는 것입니다. 이 경우 요소를 수직 방향으로만 드래그하면 되므로 수직 이동만 고려됩니다.
위 그림에서 드래그 영역 목록은 데이터의 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: '列表1', isShow: false } ... ] }, }
요소를 위치 1에서 위치 3으로 드래그한다고 가정합니다. 배열의 순서가 변경됩니다. Vue의 가장 큰 특징인 데이터 기반을 언급할 필요가 있습니다.
소위 데이터 기반이란 데이터가 변경되면 데이터 상태를 수정하여 그에 따라 사용자 인터페이스도 변경되는 것을 의미합니다. 개발자가 DOM을 수동으로 수정할 필요가 없습니다.
Vue의 데이터 드라이브는 MVVM 프레임워크를 통해 구현됩니다. MVVM 프레임워크는 주로 Model, View 및 Viewmodel의 세 부분으로 구성됩니다.
– 모델: 데이터 부분
– 뷰: 뷰 부분– 뷰모델: 뷰와 데이터를 연결하는 미들웨어.
이 아이디어에 따라 다음을 알 수 있습니다.
– elHeight: 단일 요소 블록의 높이
– currTop = clientY - elTop: 드래그하는 동안의 요소 process 가시 영역의 중간 거리 위의 거리;
– 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('static'); // 给拖拽的元素设置绝对定位方式 e.target.classList.add('ab'); // 获取元素在拖拽过程中距离视口顶部距离 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('ab'); e.target.classList.add('static'); }
优化后,如下图所示:
以上便是用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 드래그 앤 드롭 구성 요소 개발 소개의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!