谈到该组件就很有意思呢,因为需要自定义Vue指令,这是计数器的核心代码也是最难代码下面我们来看看吧
前面那两个span分别代表了加和减 值得注意的是用到了我们从来没有用过的一个指令
v-repeat-click
大家看到了吧是自定义vue指令,局部引入的,那现在我们来看看是怎么写的吧
有关于Vue自定义知识请访问Vue官网这里不做过多介绍
1.首先初始化定时器和startTime
2.vnode.context获取vue上下文,binding.expression指的是在这里指定的是传递进来的函数,这里就是执行那个函数
3.clear函数简单的来说就是判断是否达到预期时间,达到就执行2步骤函数
4.用户如果触发了mousedown就会执行下面内容会调用once外部方法
5 执行定时器定时执行
once源码解析
import Vue from 'vue';
const isServer = Vue.prototype.$isServer;
export default {
bind(el, binding, vnode) {
let interval = null;
let startTime;
const handler = () => vnode.context[binding.expression].apply();
const clear = () => {
if (Date.now() - startTime < 1000) {
handler();
}
clearInterval(interval);
interval = null;
};
on(el, 'mousedown', (e) => {
console.log('mousedown')
if (e.button !== 0) {
return
}
startTime = Date.now()
once(document, 'mouseup', clear);
clearInterval(interval);
console.log("清楚定时器")
interval = setInterval(handler, 1000);
})
}
}
const once = function(el, event, fn) {
var listener = function() {
if (fn) {
fn.apply(this, arguments);
}
off(el, event, listener);
};
on(el, event, listener);
};
const on = (function() {
if (!isServer && document.addEventListener) {
return function(element, event, handler) {
console.log(handler);
if (element && event && handler) {
console.log("clear开始执行了")
element.addEventListener(event, handler, false);
}
};
} else {
return function(element, event, handler) {
if (element && event && handler) {
element.attachEvent('on' + event, handler);
}
};
}
})(); /* istanbul ignore next */
const off = (function() {
if (!isServer && document.removeEventListener) {
return function(element, event, handler) {
console.log(handler);
if (element && event) {
element.removeEventListener(event, handler, false);
}
};
} else {
return function(element, event, handler) {
if (element && event) {
element.detachEvent('on' + event, handler);
}
};
}
})();
下面来讲一下整个执行流程
1.用户按下鼠标后判断是不是左键如果是加入下一步
2.赋值初始化startTime
3.调用once后清除定时器最后执行解绑事件和重新绑定事件 "mouseup"
4.定时器执行直到松开鼠标做左键被触发清除定时器
最后一点:once方法的第一个参数是document,这个也很关键,你可能以为在加减按钮上绑定onmousedown就应该在加减按钮上绑定onmouseup,这样做就会出bug,考虑一种情况,当你鼠标在加减按钮上按下时,然后移动鼠标到按钮外,再放开鼠标,此时会发现数字还在增加,这就是bug,因此要在document这个最外层的dom元素上绑定mouseup,这样mouseup事件总能被响应,否则乱移动鼠标就会造成数字一直增加
总结:其实这些代码是我最浅显直观的认识希望各位大牛多多提一些建议,没想到就这几行代码实现了一个看似复杂的功能,确实有趣,确实很酷,once函数简单的来说是一个观察者模式:当一个对象的状态发生变化时,能够自动通知其他关联对象,继续加油冲冲冲!