Vue中使用MouseMove事件 获取鼠标坐标频率降低或事件卡顿
栏目: JavaScript · 发布时间: 6年前
内容简介:当我们使用Vue进行项目开发时,因为Vue的简介和易用性使我们可能会忽略,Vue的生命周期这件事儿。 尤其是在使用事件时,稍有不意就会造成意外发生!当拖拽一个div元素时,很明显会造成鼠标快速滑动时div跟随卡顿共通代码:
当我们使用Vue进行项目开发时,因为Vue的简介和易用性使我们可能会忽略,Vue的生命周期这件事儿。 尤其是在使用事件时,稍有不意就会造成意外发生!
本文章使用常见的拖拽为案例。
当拖拽一个div元素时,很明显会造成鼠标快速滑动时div跟随卡顿
共通代码:
<script> export default { data() { return { // 测试数据 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> 复制代码
上述所示,testData是测试的数据(用于数据数据循环),testFun是测试的方法(此方法用于拉长函数执行时长), 以及Style。
Box1代码:
<template> <div class="box box1" :style="box1Style" ref="box1" > <div class="dargbtn" @mousedown="box1ButtonDown">点此拖拽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); // 代码关键处 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> 复制代码
Box2代码:
<template> <div class="box box2" :style="box2Style" ref="box2" > <div class="dargbtn" @mousedown="box2ButtonDown">点此拖拽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); // 代码关键处 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> 复制代码
运行代码如图所示:
代码分析
上诉两段代码中,我们发现唯一的差别只有 box1是通过computed的计算属性对style赋值进行的赋值 box2是通过methos的Move方法对style赋值进行的赋值 但是实际问题不在于此,这也就是该代码的炸弹!
在Vue中数据绑定有两种方式:计算属性和方法
计算属性缓存 vs 方法
<p>Reversed message: "{{ reversedMessage() }}"</p> // 在组件中 methods: { reversedMessage: function () { return this.message.split('').reverse().join('') } } 复制代码
我们可以将同一函数定义为一个方法而不是一个计算属性。两种方式的最终结果确实是完全相同的。然而,不同的是 计算属性是基于它们的依赖进行缓存的 。只在相关依赖发生改变时它们才会重新求值。这就意味着只要 message 还没有发生改变,多次访问 reversedMessage 计算属性会立即返回之前的计算结果,而不必再次执行函数。
这也同样意味着下面的计算属性将不再更新,因为 Date.now() 不是响应式依赖:
computed: { now: function () { return Date.now() } } 复制代码
相比之下,每当触发重新渲染时,调用方法将总会再次执行函数。
我们为什么需要缓存?假设我们有一个性能开销比较大的计算属性 A,它需要遍历一个巨大的数组并做大量的计算。然后我们可能有其他的计算属性依赖于 A 。如果没有缓存,我们将不可避免的多次执行 A 的 getter!如果你不希望有缓存,请用方法来替代。
总结:如果能用计算属性满足需求优先使用,如果使用方法需注意方法执行时长
项目源码: github.com/MrDerry/blo…
*版权声明:本文为博主原创文章,未经博主允许不得转载。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:- Highcharts 坐标轴标签点击事件
- View 体系详解:坐标系、滑动、手势和事件分发机制
- HQChart 1.9334 版本发布,增加等比坐标、黄金分割坐标、等分坐标
- cocos creator教程之世界坐标和局部坐标
- arcgis for jsapi开发:坐标系、经纬度与平面坐标的互换
- iOS坐标系探究
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
C++沉思录
Andrew Koenig、Barbara Moo / 黄晓春、孟岩(审校) / 人民邮电出版社 / 2002-11-01 / 50.00元
《C++ 沉思录》集中反映了C++的关键思想和编程技术,不仅告诉你如何编程,还告诉你为什么要这样编程。本书曾出现在众多的C++专家推荐书目中。 这将是C++程序员的必读之作。因为: 它包含了丰富的C++思想和技术,从详细的代码实例总结出程序设计的原则和方法。 不仅教你如何遵循规则,还教你如何思考C++编程。 既包括面向对象编程也包括泛型编程。 探究STL这一近年来C++最重要的新成果的内在思想。一起来看看 《C++沉思录》 这本书的介绍吧!