vue-touch is based on hammer, which is too large for ordinary simple gesture pages!
So I wanted to implement one of the most commonly used gesture taps myself. Following the custom instructions and plug-in documentation, I implemented a v-tap instruction last night and posted this article.
Instructions and plug-ins introduction
Custom instructions and plug-ins are also introduced in the official documentation in a relatively simple and detailed manner, so I won’t go into too much detail.
Let me start by saying that this plug-in uses three APIs. If you don’t understand them, it’s best to read the documentation in advance to avoid confusion in the subsequent code.
Instruction part
1.update(nVal,oVal)
2.acceptStatement
Plug-in part
Vue.use()
Then we need to learn the format of writing Vue plug-ins like writing jQuery plug-ins.
Continue to the official document
MyPlugin.install = function (Vue, options) {
// 1. 添加全局方法或属性
Vue.myGlobalMethod = ...
// 2. 添加全局资源
Vue.directive('my-directive', {})
// 3. 添加实例方法
Vue.prototype.$myMethod = ...
}
Don’t you still understand? Then we can look directly at the author's plug-in code.
;(function () {
var vueTouch = {}
vueTouch.install = function (Vue) {
Vue.directive('touch', {
isFn: true,
acceptStatement: true,
bind: function () {
},
update: function (fn) {
},
unbind: function () {
}
})
}
if (typeof exports == "object") {
module.exports = vueTouch
} else if (typeof define == "function" && define.amd) {
define([], function(){ return vueTouch })
} else if (window.Vue) {
window.VueTouch = vueTouch
Vue.use(vueTouch)
}
})()
I deleted all the redundant irrelevant code, and you can find that the format is actually like this, and the rest can be written directly using our own js skills.
PS: Regarding the attribute "isFn:true", I did not find relevant information in the document. I personally think it may be a comment, indicating that this instruction requires an expression of fn (this is the expression of the instruction, see the instruction instance attribute for details) .
Just do it
First, write the outer layer according to the plug-in format.
;(function() {
var vueTap = {};
vueTap.install = function(Vue) {
};
if (typeof exports == "object") {
module.exports = vueTap;
} else if (typeof define == "function" && define.amd) {
define([], function(){ return vueTap })
} else if (window.Vue) {
window.vueTap = vueTap;
Vue.use(vueTap);
}
})();
Then write our own custom instructions in our vueTap.install
Vue.directive('tap', {
isFn : true,
bind : function() {
},
update : function(fn) {
},
unbind : function() {},
isTap : function() {
//判断是否为tap
},
touchstart : function(e,self) {
},
touchend : function(e,self) {
}
});
};
Since only update has parameters to pass and can receive our expression, so I bound the event The processing procedures are all written in the update.
PS: Of course, some friends like to assign all fn to this (here this is a directve instance), and finally bind the event at the bind location. I haven't found the standard for this, and I don't know which one is better to write.
update : function(fn) {
var self = this; //存下this,方便以后用
//在directive上绑定的属性和方法
//都可通过self.xxx self.touchstart()获取
self.tapObj = {}; //初始化我们的tap对象
if(typeof fn !== 'function') {
//你别给我搞事!
return console.error('The param of directive "v-tap" must be a function!');
}
self.handler = function(e) { //给当前directive存个handler方便之后调用
e.tapObj = self.tapObj;
//把我们的tap对象赋值给原生event对象上,方便回调里获取参数
fn.call(self,e);
};
//把我们的start和end剥离出来,写在directive上
//由于只有tap事件,所以我们在move过程就不需要做处理
this.el.addEventListener('touchstart',function(e) {
self.touchstart(e,self);
},false);
this.el.addEventListener('touchend',function(e) {
self.touchend(e,self,fn);
},false);
}
In update, it is very simple, which is the process of initialization, event binding and assigning values to instances.
The last step is the logical processing of isTap, touchstart, and touchend.
isTap : function() {
var tapObj = this.tapObj;
return this.time < 150 && Math.abs(tapObj.distanceX) < 2 && Math.abs(tapObj.distanceY) < 2;
},
touchstart : function(e,self) {
var touches = e.touches[0];
var tapObj = self.tapObj;
tapObj.pageX = touches.pageX;
tapObj.pageY = touches.pageY;
tapObj.clientX = touches.clientX;
tapObj.clientY = touches.clientY;
self.time = +new Date();
},
touchend : function(e,self) {
var touches = e.changedTouches[0];
var tapObj = self.tapObj;
self.time = +new Date() - self.time;
tapObj.distanceX = tapObj.pageX - touches.pageX;
tapObj.distanceY = tapObj.pageY - touches.pageY;
if (self.isTap(tapObj))
self.handler(e);
}
Finally there is a big question, how can we make our expression accept parameters?
<ul>
<li v-for="el in list"
v-tap="args($index,el,$event)"
>
{{el.name}}---{{el.age}}
</li>
</ul>
Then we need to add an attribute acceptStatement:true to our directive (see the document acceptStatement for details)
Summary
Written this v-tap plug-in to share with you some experiences.
1. This in update points to the directive instance, not vm, nor dom
2. Customizable properties and methods can be used in the directive('name',{}) object. The call is self.xxx
3. Enable custom instructions to accept inline statements acceptStatement:true
4. Don’t forget Vue.use(obj) for the final interface
I don’t have v-tap.stop, v-tap.prevent here , v-tap.stop.prevent is used for processing, you can implement it yourself! Also very simple.