


Detailed explanation of custom Vue instruction v-selectable similar to jQuery UI Selectable
This article mainly introduces the relevant information about customizing the Vue instruction v-selectable similar to jQuery UI Selectable. Friends in need can refer to it. I hope it can help everyone.
Without further ado, let’s look at the effect first.
In fact, it is a function that allows you to hold down the mouse to select items in an area. I believe everyone who has used Jquery UI knows that this is a selectable function. However, if we use Vue There is no similar plug-in for development. Of course, you can still use jquery directly, but I don’t want to introduce jquery and jquery UI into my project, so I tried to implement similar functions myself.
There are two steps to achieve this function. The first step is to implement the function of mouse selection area, and the second step is to add an active class to the selected item in this area.
Let’s first look at how to draw a dotted frame by holding down the mouse. The idea is to first change the positioning of the container element to relative and then determine when the mouse is pressed (mousedown) and remember the position of the click point (e .layerX, e.layerY), and then monitor the mouse position (e.layerX, e.layerY) in real time when the mouse moves (mousemove). With these two positions, you can dynamically create a p and its positioning For absolute, then add it to the container box, and clear the previous box each time. Why use e.layerX e.layerY?
layerX layerY
If the position style of the element is not the default static, we say this Elements have positioning attributes.
Find the nearest element with positioning attribute among the element that currently triggers the mouse event and its ancestor element, calculate the offset value of the mouse to it, and find the diplomatic point of the upper left corner of the element's border as the relative point . If an element with a positioning attribute is not found, the offset is calculated relative to the current page, which is equivalent to pageY. Complete the following code according to this idea:
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 }) }
At this time, you can achieve the effect of drawing a dotted box
The next step is how to set each item to be selected state. The idea is to traverse all the child elements li of this container ul, and then determine whether each li is inside the selected box. Then look at the offsetLeft and offsetTop of each element to calculate the element's position relative to the parent element, and then determine the width and height of the child element through getBoundingClientRect().height and getBoundingClientRect().width. These can calculate the position and size of the element, and then how to determine whether the element is within the selection area? My rule is that if any of the four corners of this element is within the selection area or the selection area is inside this area, the element is considered selected (this judgment method does not feel perfect). Following this idea, continue to complete our code:
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 }) }
After completion, let’s see how to use it, html structure:
<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>
Note that the v-selectable of ul is our custom instruction, but Before using it, you must Vue.use
import Vue from 'vue' import Selectable from '@/components/vue-selectable/vue-selectable.js' //这个修改为你的js路径 Vue.use(Selectable);
Add some style to our ul li. Note that our selected item will be added with an active class. Use this to change the style of the selected item
<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>
This will achieve the initial effect. In fact, there are still many small bugs in the running process of the code. This article only provides a simple idea and code. You can modify the code and add more functions by yourself. If you don’t understand why this custom instruction is written like this, you can refer to my other article on customizing the lazy loading image plug-in v-lazyload.
Related recommendations:
Yii Framework Development Tutorial Zii Component-Selectable Example_PHP Tutorial
##Yii Framework Development Tutorial Zii Component-Selectable Example
The above is the detailed content of Detailed explanation of custom Vue instruction v-selectable similar to jQuery UI Selectable. For more information, please follow other related articles on the PHP Chinese website!

Introduction I know you may find it strange, what exactly does JavaScript, C and browser have to do? They seem to be unrelated, but in fact, they play a very important role in modern web development. Today we will discuss the close connection between these three. Through this article, you will learn how JavaScript runs in the browser, the role of C in the browser engine, and how they work together to drive rendering and interaction of web pages. We all know the relationship between JavaScript and browser. JavaScript is the core language of front-end development. It runs directly in the browser, making web pages vivid and interesting. Have you ever wondered why JavaScr

Node.js excels at efficient I/O, largely thanks to streams. Streams process data incrementally, avoiding memory overload—ideal for large files, network tasks, and real-time applications. Combining streams with TypeScript's type safety creates a powe

The differences in performance and efficiency between Python and JavaScript are mainly reflected in: 1) As an interpreted language, Python runs slowly but has high development efficiency and is suitable for rapid prototype development; 2) JavaScript is limited to single thread in the browser, but multi-threading and asynchronous I/O can be used to improve performance in Node.js, and both have advantages in actual projects.

JavaScript originated in 1995 and was created by Brandon Ike, and realized the language into C. 1.C language provides high performance and system-level programming capabilities for JavaScript. 2. JavaScript's memory management and performance optimization rely on C language. 3. The cross-platform feature of C language helps JavaScript run efficiently on different operating systems.

JavaScript runs in browsers and Node.js environments and relies on the JavaScript engine to parse and execute code. 1) Generate abstract syntax tree (AST) in the parsing stage; 2) convert AST into bytecode or machine code in the compilation stage; 3) execute the compiled code in the execution stage.

The future trends of Python and JavaScript include: 1. Python will consolidate its position in the fields of scientific computing and AI, 2. JavaScript will promote the development of web technology, 3. Cross-platform development will become a hot topic, and 4. Performance optimization will be the focus. Both will continue to expand application scenarios in their respective fields and make more breakthroughs in performance.

Both Python and JavaScript's choices in development environments are important. 1) Python's development environment includes PyCharm, JupyterNotebook and Anaconda, which are suitable for data science and rapid prototyping. 2) The development environment of JavaScript includes Node.js, VSCode and Webpack, which are suitable for front-end and back-end development. Choosing the right tools according to project needs can improve development efficiency and project success rate.

Yes, the engine core of JavaScript is written in C. 1) The C language provides efficient performance and underlying control, which is suitable for the development of JavaScript engine. 2) Taking the V8 engine as an example, its core is written in C, combining the efficiency and object-oriented characteristics of C. 3) The working principle of the JavaScript engine includes parsing, compiling and execution, and the C language plays a key role in these processes.


Hot AI Tools

Undresser.AI Undress
AI-powered app for creating realistic nude photos

AI Clothes Remover
Online AI tool for removing clothes from photos.

Undress AI Tool
Undress images for free

Clothoff.io
AI clothes remover

Video Face Swap
Swap faces in any video effortlessly with our completely free AI face swap tool!

Hot Article

Hot Tools

WebStorm Mac version
Useful JavaScript development tools

Dreamweaver Mac version
Visual web development tools

ZendStudio 13.5.1 Mac
Powerful PHP integrated development environment

PhpStorm Mac version
The latest (2018.2.1) professional PHP integrated development tool

EditPlus Chinese cracked version
Small size, syntax highlighting, does not support code prompt function
