이 글은 주로 jQuery UI Selectable과 유사한 Vue 명령 v-selectable을 사용자 정의하는 관련 정보를 소개합니다. 도움이 필요한 친구들이 모두 참고할 수 있기를 바랍니다.
더 이상 고민하지 말고 먼저 결과를 살펴보겠습니다.
사실 Jquery UI를 사용해보신 분들은 이것이 선택 가능한 기능이라는 것을 아실 거라 생각합니다. 하지만 Vue로 개발한다면 말이죠. 물론 비슷한 플러그인은 없습니다. 아직은 jquery를 가져와서 직접 사용할 수 있지만 제 프로젝트에 jquery와 jquery UI를 도입하고 싶지 않아서 비슷한 기능을 직접 구현해 보았습니다.
이 기능을 구현하는 데는 두 단계가 있습니다. 첫 번째 단계는 마우스 선택 영역의 기능을 구현하는 것이고, 두 번째 단계는 이 영역에서 선택된 항목에 활성 클래스를 추가하는 것입니다.
먼저 마우스를 누른 채 점선 프레임을 그리는 방법을 살펴보겠습니다. 먼저 컨테이너 요소의 위치를 상대 위치로 변경한 다음 마우스를 누르는 시점(마우스다운)을 확인하고 클릭 위치를 기억하는 것입니다. 점(e.layerX, e.layerY)을 사용하고 마우스가 움직일 때(mousemove) 마우스 위치(e.layerX, e.layerY)를 실시간으로 모니터링하여 p를 동적으로 생성할 수 있습니다. 그 위치는 절대적입니다. 그런 다음 컨테이너 상자에 추가하고 매번 이전 상자를 지우십시오. e.layerX를 사용하는 이유 e.layerY,
layerX layerY
요소의 위치 스타일이 기본 정적이 아닌 경우 이 요소에 위치 속성이 있다고 말합니다.
현재 마우스 이벤트를 발생시킨 요소와 그 조상 요소 중 positioning 속성이 있는 가장 가까운 요소를 찾아 그에 대한 마우스 오프셋 값을 계산하고, 요소 테두리의 왼쪽 상단 모서리의 외교점을 상대 요소로 찾습니다. 가리키다. 위치 지정 속성이 있는 요소를 찾을 수 없는 경우 오프셋은 현재 페이지를 기준으로 계산되며 이는 pageY와 동일합니다. 이 아이디어를 따라 다음 코드를 완성하세요.
export default (Vue, options = {}) =>{ const listener = (ele, binding) =>{ let reactArea = { startX: 0, startY: 0, endX: 0, endY: 0 } //是否一直按下鼠标 let isMouseDown = false let areaSelect = {} //将元素定位改为relative ele.style.position = 'relative' ele.addEventListener('mousedown', function(e) { reactArea.startX = e.layerX; reactArea.startY = e.layerY; isMouseDown = true }) ele.addEventListener('mousemove', function(e) { if(isMouseDown){ let preArea = ele.getElementsByClassName('v-selected-area') if(preArea.length){ ele.removeChild(preArea[0]) } reactArea.endX = e.layerX reactArea.endY = e.layerY let leftValue = 0 let topValue = 0 let widthValue = Math.abs(reactArea.startX - reactArea.endX) let heightValue = Math.abs(reactArea.startY - reactArea.endY) if(reactArea.startX >= reactArea.endX){ leftValue = reactArea.endX }else{ leftValue = reactArea.startX } if(reactArea.startY > reactArea.endY ){ topValue = reactArea.endY }else{ topValue = reactArea.startY } //判断同时有宽高才开始画虚线框 if(reactArea.startX != reactArea.endX && reactArea.startY !=reactArea.endY){ areaSelect = document.createElement('p') areaSelect.classList.add("v-selected-area") areaSelect.style.position = "absolute"; areaSelect.style.left = leftValue + 'px' areaSelect.style.top = topValue + 'px' areaSelect.style.width = widthValue + 'px' areaSelect.style.height = heightValue + 'px' areaSelect.style.border = "1px dashed grey" ele.append(areaSelect) } } }) ele.addEventListener('mouseup', function(e) { isMouseDown = false //每次鼠标点击完了areaSelect if(areaSelect && areaSelect.childNodes && ele.contains(areaSelect)){ ele.removeChild(areaSelect) } areaSelect = null }) } Vue.directive('selectable',{ inserted:listener, updated:listener }) }
이때 점선 상자를 그리는 효과를 얻을 수 있습니다.
다음 단계는 각 항목을 선택한 상태로 설정하는 방법입니다. 아이디어는 이 컨테이너 ul의 모든 하위 요소 li를 순회한 다음 각 li가 선택한 상자 안에 있는지 확인하는 것입니다. 그런 다음 각 요소의 offsetLeft 및 offsetTop을 확인하여 상위 요소를 기준으로 요소의 위치를 계산한 다음 getBoundingClientRect().height 및 getBoundingClientRect().width를 통해 하위 요소의 너비와 높이를 결정합니다. 요소의 위치와 크기를 계산할 수 있으며 요소가 선택 영역 내에 있는지 확인하는 방법은 무엇입니까? 내 규칙은 이 요소의 네 모서리 중 하나라도 선택 영역 내에 있거나 선택 영역이 이 영역 내에 있으면 해당 요소가 선택된 것으로 간주된다는 것입니다(이 판단 방법은 완벽하다고 느껴지지 않습니다). 이 아이디어에 따라 계속해서 코드를 완성하세요.
export default (Vue, options = {}) =>{ const listener = (ele, binding) =>{ let reactArea = { startX: 0, startY: 0, endX: 0, endY: 0 } //是否一直按下鼠标 let isMouseDown = false let areaSelect = {} //将元素定位改为relative ele.style.position = 'relative' ele.addEventListener('mousedown', function(e) { reactArea.startX = e.layerX; reactArea.startY = e.layerY; isMouseDown = true }) ele.addEventListener('mousemove', function(e) { if(isMouseDown){ let preArea = ele.getElementsByClassName('v-selected-area') if(preArea.length){ ele.removeChild(preArea[0]) } reactArea.endX = e.layerX reactArea.endY = e.layerY let leftValue = 0 let topValue = 0 let widthValue = Math.abs(reactArea.startX - reactArea.endX) let heightValue = Math.abs(reactArea.startY - reactArea.endY) if(reactArea.startX >= reactArea.endX){ leftValue = reactArea.endX }else{ leftValue = reactArea.startX } if(reactArea.startY > reactArea.endY ){ topValue = reactArea.endY }else{ topValue = reactArea.startY } //判断同时有宽高才开始画虚线框 if(reactArea.startX != reactArea.endX && reactArea.startY !=reactArea.endY){ areaSelect = document.createElement('p') areaSelect.classList.add("v-selected-area") areaSelect.style.position = "absolute"; areaSelect.style.left = leftValue + 'px' areaSelect.style.top = topValue + 'px' areaSelect.style.width = widthValue + 'px' areaSelect.style.height = heightValue + 'px' areaSelect.style.border = "1px dashed grey" ele.append(areaSelect) } let children = ele.getElementsByTagName('li') for(let i =0 ; i < children.length ; i ++ ){ let childrenHeight = children[i].getBoundingClientRect().height let childrenWidth = children[i].getBoundingClientRect().width //每个li元素的位置 let offsetLeft = children[i].offsetLeft let offsetTop = children[i].offsetTop //每个li元素的宽高 let endPositionH = childrenHeight + offsetTop let endPositionW = childrenWidth + offsetLeft //五个条件满足一个就可以判断被选择 //一是右下角在选择区域内 let require1 = endPositionH > topValue && endPositionW > leftValue && endPositionH < topValue + heightValue && endPositionW < leftValue + widthValue //二是左上角在选择区域内 let require2 = offsetTop > topValue && offsetLeft > leftValue && offsetTop < topValue + heightValue && offsetLeft < leftValue + widthValue //三是右上角在选择区域内 let require3 = offsetTop > topValue && offsetLeft + childrenWidth > leftValue && offsetTop < topValue + heightValue && offsetLeft + childrenWidth< leftValue + widthValue //四是左下角在选择区域内 let require4 = offsetTop + childrenHeight > topValue && offsetLeft > leftValue && offsetTop + childrenHeight < topValue + heightValue && offsetLeft < leftValue + widthValue //五选择区域在元素体内 let require5 = offsetTop < topValue && offsetLeft < leftValue && offsetTop + childrenHeight > topValue + heightValue && offsetLeft + childrenWidth > leftValue + widthValue if(require1 || require2 || require3 || require4 || require5){ children[i].classList.add('active') }else{ children[i].classList.remove('active') } } } }) ele.addEventListener('mouseup', function(e) { isMouseDown = false if(areaSelect && areaSelect.childNodes && ele.contains(areaSelect)){ ele.removeChild(areaSelect) } areaSelect = null }) } Vue.directive('selectable',{ inserted:listener, updated:listener }) }
완료 후 사용 방법을 살펴보겠습니다. html 구조:
<ul v-selectable > <li class="square"> item1 </li> <li class="oval"> item2 </li> <li class="triangle"> item3 </li> <li class="triangle-topleft"> item4 </li> <li class="curvedarrow"> item5 </li> <li class="triangle-topleft"> item6 </li> </ul>
ul의 v-selectable은 사용자 정의 명령이지만 사용하기 전에 Vue.use를 사용해야 합니다. it
import Vue from 'vue' import Selectable from '@/components/vue-selectable/vue-selectable.js' //这个修改为你的js路径 Vue.use(Selectable);
ul li에 스타일을 추가하세요. 선택한 항목에 활성 클래스가 추가됩니다. 이를 사용하여 선택한 항목의 스타일을 변경하세요.
<style scoped> ul{ margin: 40px 40px 40px 40px; border: 1px solid red; width: 300px; padding-bottom: 20px; } ul li { width: 200px; height: 30px; list-style: none; border: 1px solid black; margin-left: 10px; margin-top: 30px; text-align: center; line-height: 30px; user-select:none; } ul li.active{ background-color: red; } </style>
이렇게 하면 처음에 효과를 얻을 수 있습니다. 사실, 코드를 실행하는 과정에는 여전히 작은 버그가 많이 있습니다. 이 글에서는 간단한 아이디어와 코드만 제공할 뿐입니다. 직접 코드를 수정하고 더 많은 기능을 추가해도 됩니다. 이 사용자 정의 명령이 왜 이렇게 작성되었는지 이해하지 못한다면 지연 로딩 이미지 플러그인 v-lazyload 사용자 정의에 대한 다른 기사를 참조할 수 있습니다.
관련 권장 사항:
Yii 프레임워크 개발 튜토리얼 Zii 구성 요소 선택 가능 예제_PHP 튜토리얼
Yii 프레임워크 개발 튜토리얼 Zii 구성 요소 선택 가능 예시
위 내용은 jQuery UI와 유사한 v-selectable 사용자 정의 Vue 명령에 대한 자세한 설명 선택 가능의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!