First, background
The development of a customized component portal configuration page, during the use of vUE framework as a front-end view engine, as a budding vUE, the development of the first function encountered obstacles. You need a container box that can be dragged and resized. At that time, I looked at the Vue development documentation and looked at Github and couldn’t find an implementation that I liked, so instead of asking others, I would rather ask myself. So you have the vuedragx wheel, x for more than drag. Making address: github.com/464884492/v…
Second, the effect drawing
Third, development ideas
- Through mouse movement to achieve component movement, change the size, must operate dom, view the vUE official documentation, from practicality, has been universal, choose to develop a custom VUE instruction
- Dynamically change size or position through the displacement generated by mouse movement
- Update the bind value through event notification
So with that in mind, you need to master three important things at once
- Vue how to develop a custom directive
- The meaning of the various values of the MouseEvent object during mouse movement
- How do I use and distribute a custom event
3.1 the vue instruction
Remember, no matter what framework you’re using, you need to learn a skill, you need to learn how to use various API methods, the best way to do that is to look at the official documentation, right
Vue development custom instruction address cn.vuejs.org/v2/guide/cu… Read a passage through and then type on the blackboard to underline it
- When to use the Vue directive
In Vue2.0, the main form of code reuse and abstraction is components. However, there are cases where you still need to perform low-level operations on normal DOM elements, and custom directives are used
Obviously, with the displacement required to use the mouse, passing through the blah blah is more difficult
- How to develop
For the vUE directive, several hook functions are provided for developers to inject functions developed by developers. The so-called hook functions are used to insert embedded functions into normal code
Vue provides injection points (BIND, INSERTED, Update, componentUpdated, unbind) for developers.
- Bind is called only once, the first time a directive is bound to an element
- Inserted When a bound element is inserted into a parent node, the parent node is only guaranteed to exist, but not necessarily to be inserted.
- Update is called when the VNode of the component is updated, but may occur before its child VNode is updated. Therefore, the parameter provided contains VNode oldVnode
- ComponentUpdated directive is called after all vNodes and sub-VNodes of the component are updated.
- Unbind is called only once; instruction and element unbinding is called
Each hook takes parameters EL, binding, vNode, and oldVnode
- El The dom currently bound
- The Binding object, which contains the following properties
- Name Specifies the name of the directive, but I personally understand that this parameter is not used in the scenario
- The value of the bind directive, if a runnable expression, returns the result of the calculation. If the binding is an object, the object, vuedragx, is returned, passing in personalization information with this property.
- The previous value of the oldValue directive binding, available only in the UPDATE and componentUpdated hook functions
- Expression Specifies an instruction expression in the form of A string. In code development v-dragx= “A”, the A is the expression
- The arg passes an argument to the directive, such as V-dragx :foo, which takes the argument foo. Note the identifier:
- Modifiers object contains a modifier, such as: v – dragx. Dragable. Resizeable, modifier for the object
{dragable:true,resizeable:true}
, but vuedragx does not use this method. Instead, it uses binding.value - Vnode Virtual node generated by Vue compilation
- A virtual node on oldVnode, available only in update and componentUpdated hooks
Vue instruction hook function, parameters and other related instructions, basically from the official website reference. I feel the need to emphasize again that the best way to use a third-party framework is to consult official documentation. Second, look at the corresponding source code, if any.
3.2 MouseEvent
In the introduction to the Vue directive, we emphasized the importance of checking official documentation, but what about javascript apis? MDN, of course. There is no second
Address of MouseEvent description in MDN: developer.mozilla.org/zh-CN/docs/… The two most important MouseEvent attributes MouseEvent. PageX and MouseEvent. PageY are required to develop VueDragx
- The x (horizontal) coordinate of mouseEvent.pagex relative to the entire document. This property contains the scrolling distance of the element, officially interpreted as
This property takes into account horizontal scrolling on any page, based on the edge of the document. For example, if you scroll 200px to the right and the scroll bar appears, which is outside the window, then click 100px to the left of the window and the pageX will return 300.
As an extension, the properties of other corresponding coordinates in MonuseEvent are respectively checked
- Mouseevent. clientX provides the horizontal coordinates of the application client area at the time of the event (unlike the page coordinate PageX, clientX does not contain the distance of the scroll bar), so PageX =clientX+ the distance of the horizontal scroll
- Mouseevent.movementx provides the horizontal mouse movement value between the current event and the last Mousemove event. This value is used to capture the increment of each mouse movement. Vuedargx development did not focus on this property, otherwise it would have saved some calculation code.
- Mouseevent. offsetX specifies the X offset of the event object from the target node’s padding edge
- Mouseevent. screenX provides the horizontal offset of the mouse relative to the screen coordinate system that does not include the scrolling distance
- Mouseevent. x is the alias of the MouseEvent. ClientX property.
So, the relationship should go something like this
OffsetX =clientx=x,movementX is not easy to draw.
3.3 Custom Events
The trigger ‘ ‘triggerHandler method triggers custom events, and with the help of JQ, custom events are easily handled. For comparison, how does JQ use custom events
// Add an appropriate event listener
$(
'#foo').on(
'custom'.
function(event, param1, param2) {
alert(param1 +
"\n" + param2);
});
$(
'#foo').trigger(
'custom'[
'Custom'.
'Event']);
Copy the code
Yeah, it’s that simple, definition, pass it along! However, with Vue, these functions are implemented in native code, and the industry is increasingly emphasizing native code voice is also more and more high. Perhaps this sentence is the es standard gradually improved, browser gradually compatible with the new API brought good news. Hats off to IE6 (escape). Anyway, how does the standard interface use custom events? So you found MDN developer.mozilla.org/zh-CN/docs/… , found the demo
// Add an appropriate event listener
obj.addEventListener(
"custom".
function(e) {
console.log(
JSON.stringify(e.detail));
})
// Create and distribute events
var event =
new CustomEvent(
"custom", {
"detail": {
"Custom":
true}});
obj.dispatchEvent(event)
Copy the code
In my opinion, the way events are defined is pretty much the same, and passing unique parameters is complicated. There are always some bad things.
Four, implementation,
4.1 Operation Judgment
When the mouse moves over the left edge of the target object, the mouse displays a different resize style to remind the user of the currently operable type. The basic idea is to get the corresponding left and top values of the current object in the document, and compare them with the pageX, pageY and tolerable edge values in MouseEvent
- Left – on the left edge < pageX < left + edge && top + edge < pageY < top + height – edge
- On the right side of the left + widht – edge < pageX < left + widht + edge && top + edge < pageY < top + height – edge
- Top top-edge
- Top +heigth-edge
- The upper left corner of top edge < pageY < top + edge && left – edge < pageX < left + edge
- The lower-left corner of top + height – edge < pageY < top + height + edge && left – edge < pageX < left + edge
- The upper right corner of the top edge < pageY < top + edge && left + width – edge < pageX < left + + edge width
- The top and the bottom right hand corner + height – edge < pageY < top + height + edge && left + width – edge < pageX < left + widht + edge
So the code looks like this
It’s much easier to determine if the mouse is currently dragging the object, passing it directly through the OnMousemove event
e.target.classList.contains(cfg.dragBarClass)
Judgment can be
4.2 Resize
Deltx and delty values of mouse movement were obtained by calculation, and width and Heigth attributes were updated respectively. Currently resizing to the left and up, you also need to adjust the left and height attributes of one
4.3 drag
Drag, do not change the size of the target object, directly use the calculated deltx and delty to update the corresponding left and top attributes. If you need to limit the movement area, you need to calculate the coordinates of the parent container corresponding to the inner margin
function setConstraint(data) {
if (cfg.dragContainerId) {
let constraintDom =
document.querySelector(
"#" + cfg.dragContainerId);
let constraintRect = constraintDom.getBoundingClientRect();
if (data.left <=
0) data.left =
0;
if (data.top <=
0) data.top =
0;
if (data.top + data.height+data.borderTop+data.borderBottom >= constraintRect.height) data.top = constraintRect.height - data.height-data.borderTop-data.borderBottom;
if (data.left + data.width+data.borderLeft+data.borderRight > constraintRect.width) data.left = constraintRect.width - data.width-data.borderLeft-data.borderRight;
}
}
Copy the code
Five, the summary
Although the function is not big, but to make each link clear, the feeling is very laborious. I really envy those developers who can write books, the documentation ability is quite good. Writing documentation is really no better than writing code, but do it anyway, otherwise people won’t know what your code does.