When we use Vue for project development, Vue's introduction and ease of use make it possible for us to ignore Vue's lifecycle. Especially when using events, a slight surprise will cause an accident!
This article uses common drag and drop as a case.
When dragging a div element, it will obviously cause the div to follow the Snap when the mouse slides quickly.
Common code:
<script>
export default {
data() {
return {
// Test Data
testData: [
{value: '1'},
{value: '2'},
{value: '3'},
{value: '4'},
{value: '5'},
{value: '6'},
{value: '7'},
{value: '9'},
{value: '10'}
],
/// ...
};
},
methods: {
testFun(name) {
console.time(name + '-delay');
for (let i = 0; i < 10240000; i++) {}
console.timeEnd(name + '-delay');
},
// ...
}
}
</script>
<style>
*::selection {
background: none;
}
.box {
position: fixed;
z-index: 100;
width: 200px;
height: 80px;
}
.dargbtn {
margin: 15px;
color: #222222;
background: #eee;
cursor: pointer;
}
.box1 {
background: #c0c;
}
.box2 {
background: #0cc;
}
</style>
Copy code
As shown above, testData is the test data (for data data loops), testFun is the test method (this method is used to lengthen the execution time of the function), and Style.
Box1 code:
<template>
<div class="box box1"
:style="box1Style"
ref="box1"
>
<div class="dargbtn" @mousedown="box1ButtonDown">Click here to drag 1</div>
<div class="delay-box">
<span
v-for="(item, index) in testData"
:key="index"
:data-testdata="testFun('box1')"
>{{item.value}}</span>
</div>
</div>
</template>
<script>
export default {
data() {
return {
// 1
box1X: 0,
box1Y: 0,
box1L: 0,
box1T: 0,
box1CurrentX: 0,
box1CurrentY: 0,
};
},
computed: {
box1Style() {
return {
top: this.box1CurrentY + 'px',
left: this.box1CurrentX + 'px'
};
}
},
methods: {
box1Start(e) {
let dv = this.$refs.box1;
this.box1X = e.clientX;
this.box1Y = e.clientY;
this.box1L = dv.offsetLeft;
this.box1T = dv.offsetTop;
},
box1Move(e) {
console.log('box1 move');
let nx = e.clientX;
let ny = e.clientY;
let nl = nx - (this.box1X - this.box1L);
let nt = ny - (this.box1Y - this.box1T);
// code key
this.box1CurrentX = nl;
this.box1CurrentY = nt;
},
box1End(e) {
window.removeEventListener('mousemove', this.box1Move);
window.removeEventListener('mouseup', this.box1End);
},
box1ButtonDown(e) {
this.box1Start(e);
window.addEventListener('mousemove', this.box1Move);
window.addEventListener('mouseup', this.box1End);
}
}
}
</script>
Copy code
Box2 code:
<template>
<div class="box box2"
:style="box2Style"
ref="box2"
>
<div class="dargbtn" @mousedown="box2ButtonDown">Click here to drag 2</div>
<div class="delay-box">
<span
v-for="(item, index) in testData2"
:key="index"
:data-testdata="testFun('box2')"
>{{item.value}}</span>
</div>
</div>
</template>
<script>
export default {
data() {
return {
// 2
box2X: 0,
box2Y: 0,
box2L: 0,
box2T: 0,
box2CurrentX: 0,
box2CurrentY: 100
};
},
computed: {
box2Style() {
return {
top: '100px',
left: '0px'
};
}
},
methods: {
box2Start(e) {
let dv = this.$refs.box2;
this.box2X = e.clientX;
this.box2Y = e.clientY;
this.box2L = dv.offsetLeft;
this.box2T = dv.offsetTop;
},
box2Move(e) {
console.log('box2 move');
let nx = e.clientX;
let ny = e.clientY;
let nl = nx - (this.box2X - this.box2L);
let nt = ny - (this.box2Y - this.box2T);
// code key
this.box2CurrentX = nl;
this.box2CurrentY = nt;
let legendBox = this.$refs.box2;
legendBox.style.left = nl + 'px';
legendBox.style.top = nt + 'px';
},
box2End(e) {
window.removeEventListener('mousemove', this.box2Move);
window.removeEventListener('mouseup', this.box2End);
},
box2ButtonDown(e) {
this.box2Start(e);
window.addEventListener('mousemove', this.box2Move);
window.addEventListener('mouseup', this.box2End);
}
}
}
</script>
Copy code
Run the code as shown:
Code analysis
In the two pieces of code of the appeal, we found that the only difference is that box1 is the assignment of the style assignment by the computed property of the computed box2 is passed by methos The Move method assigns a value to the style assignment But the actual problem is not here, this is the bomb of the code!
There are two ways to bind data in Vue: calculating properties and methods.
Calculate attribute cache vs method
<p>Reversed message: "{{ reversedMessage() }}"</p>
// in the component
methods: {
reversedMessage: function () {
return this.message.split('').reverse().join('')
}
}
Copy code
We can define the same function as a method instead of a computed property. The end result of the two methods is indeed exactly the same. However, the difference isComputational properties are cached based on their dependencies. They are only reevaluated when the relevant dependencies change. This means that as long as the message has not changed, multiple access to the reversedMessage calculation property immediately returns the previous calculation without having to execute the function again.
This also means that the following computed properties will no longer be updated because Date.now() is not a reactive dependency:
computed: {
now: function () {
return Date.now()
}
}
Copy code
In contrast, whenever a re-render is triggered, the calling method will always execute the function again.
Why do we need to cache? Suppose we have a computational property A with a large performance overhead, which requires traversing a huge array and doing a lot of calculations. Then we may have other computational properties that depend on A. If there is no cache, we will inevitably execute A's getter multiple times! If you don't want to have a cache, use a method instead.
to sum up
If you can use the calculation attribute to meet the demand priority, if you use the method, you need to pay attention to the method execution time.
example:
This article provides a demo to see:GitHub
*Copyright statement: This article is an original article and may not be reproduced without permission.