vue自定義指令實(shí)現(xiàn)v-tap插件
放棄jQuery,擁抱MVVM,擁抱組件吧!
vue-touch基于hammer,對(duì)于普通簡(jiǎn)單手勢(shì)的頁(yè)面來說過于龐大!
于是想自己實(shí)現(xiàn)一個(gè)最常用的手勢(shì)tap。順著自定義指令和插件文檔,昨晚實(shí)現(xiàn)了一個(gè)v-tap指令,丟出這篇干貨。
指令與插件介紹
自定義指令和插件官方文檔中也介紹比較簡(jiǎn)單詳細(xì),就不過多介紹。
我先說下本插件就用了三個(gè)API,如果大家不了解最好先事先看下文檔避免后面的代碼看的迷糊。
指令部分
1.update(nVal,oVal)
2.acceptStatement
插件部分
Vue.use()
接著我們需要像寫jQuery插件一樣學(xué)習(xí)寫Vue插件的格式。
繼續(xù)官方文檔
MyPlugin.install = function (Vue, options) {
// 1. 添加全局方法或?qū)傩?
Vue.myGlobalMethod = ...
// 2. 添加全局資源
Vue.directive('my-directive', {})
// 3. 添加實(shí)例方法
Vue.prototype.$myMethod = ...
}
是不是看的還不太明白?那我們可以直接看作者的插件代碼。
;(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)
}
})()
我把多余無關(guān)代碼都刪除了,可以發(fā)現(xiàn)其實(shí)格式就是如此,剩下的就是利用我們自己js的功底直接編寫即可。
PS:關(guān)于 isFn:true 這個(gè)屬性,我在文檔中沒有查到相關(guān)信息,個(gè)人認(rèn)為可能是一種注釋,代表這個(gè)指令是需要fn的expression(這個(gè)是指令的表達(dá)式,詳見指令實(shí)例屬性)。
Just do it
首先,按照插件格式先寫好外層。
;(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);
}
})();
接著在我們的 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) {
}
});
};
由于只有update才有參數(shù)可傳,可以接收到我們expression,于是我把事件綁定處理過程都寫在了update里。
PS: 當(dāng)然也有小伙伴喜歡在這把fn都賦予在this(這里的this是directve實(shí)例)上,最后在bind的地方綁定事件。這個(gè)我并沒有找到規(guī)范,還不知道寫哪比較好。
update : function(fn) {
var self = this; //存下this,方便以后用
//在directive上綁定的屬性和方法
//都可通過self.xxx self.touchstart()獲取
self.tapObj = {}; //初始化我們的tap對(duì)象
if(typeof fn !== 'function') {
//你別給我搞事!
return console.error('The param of directive "v-tap" must be a function!');
}
self.handler = function(e) { //給當(dāng)前directive存?zhèn)€handler方便之后調(diào)用
e.tapObj = self.tapObj;
//把我們的tap對(duì)象賦值給原生event對(duì)象上,方便回調(diào)里獲取參數(shù)
fn.call(self,e);
};
//把我們的start和end剝離出來,寫在directive上
//由于只有tap事件,所以我們?cè)趍ove過程就不需要做處理
this.el.addEventListener('touchstart',function(e) {
self.touchstart(e,self);
},false);
this.el.addEventListener('touchend',function(e) {
self.touchend(e,self,fn);
},false);
}
在update很簡(jiǎn)單,就是一些初始化,事件綁定和給實(shí)例賦值的過程。
最后就是isTap,touchstart,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);
}
最后有個(gè)大問題,如何能讓我們的expression可接受傳參?
<ul>
<li v-for="el in list"
v-tap="args($index,el,$event)"
>
{{el.name}}---{{el.age}}
</li>
</ul>
那就要在我們的directive上加一個(gè)屬性acceptStatement:true(詳見文檔acceptStatement)
總結(jié)
寫了這個(gè)v-tap插件幾個(gè)心得分享給大家。
1.在update里的this指向是directive實(shí)例,而不是vm,也不是dom
2.在directive('name',{}) 對(duì)象里可自定義屬性和方法。調(diào)用就是self.xxx
3.開啟自定義指令接受內(nèi)聯(lián)語(yǔ)句 acceptStatement:true
4.最后的接口別忘了 Vue.use(obj)
我這里沒有對(duì)v-tap.stop, v-tap.prevent,v-tap.stop.prevent做處理,大家可以自己實(shí)現(xiàn)!也灰常簡(jiǎn)單。
(我之后會(huì)對(duì)v-tap進(jìn)行補(bǔ)充)
最后丟出github地址: https://github.com/MeCKodo/vue-tap
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
vue單頁(yè)應(yīng)用加百度統(tǒng)計(jì)代碼(親測(cè)有效)
這篇文章主要介紹了vue單頁(yè)應(yīng)用加百度統(tǒng)計(jì)代碼的解決方法,需要的朋友參考下吧2018-01-01
vue 和vue-touch 實(shí)現(xiàn)移動(dòng)端左右導(dǎo)航效果(仿京東移動(dòng)站導(dǎo)航)
這篇文章主要介紹了vue 和vue-touch 實(shí)現(xiàn)移動(dòng)端左右導(dǎo)航效果(仿京東移動(dòng)站導(dǎo)航),需要的朋友可以參考下2017-04-04
vue 項(xiàng)目中使用websocket的正確姿勢(shì)
這篇文章主要介紹了vue 項(xiàng)目中使用websocket的實(shí)例代碼,通過實(shí)例代碼給大家介紹了在utils下新建websocket.js文件的方法,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2022-01-01
vue實(shí)現(xiàn)無限消息無縫滾動(dòng)
這篇文章主要為大家詳細(xì)介紹了vue實(shí)現(xiàn)無限消息無縫滾動(dòng),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-04-04
vue3?Table分頁(yè)保留選中狀態(tài)代碼示例
這篇文章主要給大家介紹了關(guān)于vue3?Table分頁(yè)保留選中狀態(tài)的相關(guān)資料,vue table組件是一個(gè)非常方便的表格組件,它可以幫助我們實(shí)現(xiàn)分頁(yè)和選中功能,需要的朋友可以參考下2023-08-08
vue 登錄滑動(dòng)驗(yàn)證實(shí)現(xiàn)代碼
這篇文章主要介紹了vue 登錄滑動(dòng)驗(yàn)證實(shí)現(xiàn)代碼,代碼簡(jiǎn)單易懂,非常不錯(cuò),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2018-08-08

