vue2.0自定义指令
前面一片文章说了vue2.0过滤器,其实自定义指令跟过滤器非常相似,单就定义方式而言,其与过滤器完全一致,分为局部指令,和全局指令。不过就是filter改为directive的区别。
过滤器一般用于对一些常见文本的格式化,而自定义指令主要是为了对底层DOM实现操作,虽然说vue主要是以数据驱动视图,但是总有一些只能操作DOM的应用场景,例如最常见的:拖拽。此时,就是自定义指令大显身手的时候了。
在移动端,常见这么一个需求,以微信为例,在微信主屏左右滑动时候,可以随着滑动法相更改工具栏,也就是随着滑动,可以在“微信”、“通讯录”、“发现”、“我”之间随意切换。
这类需求,必须是操作DOM实现的,而无法通过数据来驱动,所以这时候,不管是你使用插件,还是自己定义,必然都是通过自定义指令来实现左右滑动,而切换工具栏的。
为了方便操作,以tab切换为例:
<ul class="tabs">
<router-link to="/home" tag="li"><span>首页</span></router-link>
<router-link to="/product" tag="li"><span>产品</span></router-link>
<router-link to="/about" tag="li"><span>关于我们</span></router-link>
</ul>
在router-view上左右滑动,切换路由:
<router-view v-swipe-horizontal v-animate-css="'bounceInLeft'" appear></router-view>
我是利用Vue Animate Css来为路由切换添加了一个动画的效果,这里暂不关注。这里需要关注的就是v-swipe-horizontal,“v-”是vue中约定的各种指令的写法,所以其实真正的指令是swipe-horizontal,那么怎么定义swipe-horizontal呢?
全局定义:
// 注册一个全局自定义指令 `v-focus`
Vue.directive('swipe-horizontal', {
bind: function (el, binding, vnode, oldVnode) {
// 各种逻辑操做,这个指令中就是滑动的逻辑 }
})
局部定义:
swipeHorizontal:{
bind(el, binding, vnode){
/**
* 当前这种做法就完全依赖于路由配置的顺序需要和tab选项卡保持一致,
* 并且不能随意添加其他位置的路由了
* 如果通过为每一个路由对象的index使用数组的find方法查找的话,
* 则需要为路由对象添加index属性
*/
/* // 利用路由配置数组自身的顺序进行判断
let routes = vnode.context.$router.options.routes,
xc = routes.find((item, index)=>{
return vnode.context.$route.path == item.path
}),
currentRouteIndex = routes.indexOf(xc),
nextRoute = null,
nextIndex = null;
*/
// 利用路有对象自定义的index属性判断
let routes = vnode.context.$router.options.routes,
currentRoute = vnode.context.$route.path,
currentRouteIndex = routes.find((item)=>{
return currentRoute == item.path
}).index,
nextRoute = null,
nextIndex = null;
var arr = routes.map((item)=>{
return item.index
})
var max = Math.max(...arr)
el.ontouchstart = (ev)=>{
let touch = ev.touches[0];
let disX = touch.clientX - el.offsetLeft;
let x = disX;
document.ontouchmove = (ev)=>{
let touch = ev.touches[0];
x = touch.clientX ;
}
document.ontouchend = () => {
document.ontouchmove = null;
document.ontouchend = null;
console.log("移动距离: ", x, disX)
/**
* 需要利用(routes.length-1)的原因是 路由配置最后一个对象配置了路由重定向
*/
// 利用当前的路由对象在整个路由中的序号,即路由配置的数组的顺序
/* if (x - disX > 20) {
nextIndex = (currentRouteIndex + 1) >= (routes.length-1) ? 0 : (currentRouteIndex + 1);
} else if(disX - x > 20) {
nextIndex = (currentRouteIndex - 1) < 0 ? routes.length -2 : (currentRouteIndex - 1);
} */
nextRoute = routes[nextIndex]
if (x - disX > 20) {
nextIndex = (currentRouteIndex + 1) > max ? 0 : (currentRouteIndex + 1);
} else if(disX - x > 20) {
nextIndex = (currentRouteIndex - 1) < 0 ? max :(currentRouteIndex - 1);
}
if (nextIndex != null) {
// 利用路有对象自定义的index属性判断
nextRoute = routes.find((item)=>{
return nextIndex == item.index
})
//在自定义的指令中,只有通过vnode.context才能获取到vue对象
vnode.context.$router.replace(nextRoute)
}
}
我这里提供了两种确定路由的模式,主要是确定路由路径的需要。
一种依赖路由数组的顺序,但是这种情况下,路由数组的顺序就必须与tab选项卡视图展示的数据保持一致。
另外一种是为每一个路由添加一个index属性,以确定当前tab选项卡展示的顺序。
自定义指令中,主要逻辑是需要存在于自定义指令的钩子函数中的,而钩子函数又分为bind,inserted,update,componentUpdated,unbind五种,我不知道有多少人能够用到所有的钩子函数,从我的角度来说,常用的钩子函数bind或者inserted,两者选择其一就可以了。
而钩子函数中的参数:

真的已经很清楚了。
既然使用自定义指令了,那么尽量不要去修改vue的数据,但是如果非得修改,还是可以通过vnode.context获取到当前的Vue对象的,到这一步,当前这个示例,剩下的也就是一些路由操作,以及基本的数组操作了。
其实,主要的就是分清楚什么情况下使用自定义指令,自定义指令的钩子函数中el提供了当前操作的dom,binding提供了各类参数,vnode.context提供了当前的vue对象,然后就是逻辑操作了。各类需求不一致,逻辑就不可能相同,所以也没什么好说的了。
vue2.0自定义指令的更多相关文章
- vue2.0自定义指令的使用方法
感觉2.0好坑啊,自定义指令和1.0完全不一样,并且文档写得也不太清晰,下面是我写得一个demo,希望帮助大家更好地理解自定义指令 <!DOCTYPE html> <html lan ...
- Vue2.0 - 自定义指令 vue-directive
Vue.directive('指令',function(el,binding,vnode){ el.style='color:'+binding.value;}); el : 指令所绑定的元素,可以用 ...
- vue2.0 自定义指令
Vue指令 Vue的指令以v-开头,作用在HTML元素上,将指令绑定在元素上,给绑定的元素添加一些特殊行为. 例如: <h1 v-if="yes">Yes</h1 ...
- vue2.0 自定义指令详解
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...
- CKEditor5 + vue2.0 自定义图片上传、highlight、字体等用法
因业务需求,要在 vue2.0 的项目里使用富文本编辑器,经过调研多个编辑器,CKEditor5 支持 vue,遂采用.因 CKEditor5 文档比较少,此处记录下引用和一些基本用法. CKEdit ...
- vue3.0自定义指令(drectives)
在大多数情况下,你都可以操作数据来修改视图,或者反之.但是还是避免不了偶尔要操作原生 DOM,这时候,你就能用到自定义指令. 举个例子,你想让页面的文本框自动聚焦,在没有学习自定义指令的时候,我们可能 ...
- vue2.0 v-model指令
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...
- vue2.0 自定义过滤器
2.0中已经废弃了过滤器,需要我们自定义 <div id="app"> {{message|uppercase}} </div> //过滤器 Vue.fil ...
- vue2.0 自定义 提示框(Toast)组件
1.自定义 提示框 组件 src / components / Toast / index.js /** * 自定义 提示框( Toast )组件 */ var Toast = {}; var sho ...
随机推荐
- Python应用场景 (转)
Web应用开发 Python经常被用于Web开发.比如,通过mod_wsgi模块,Apache可以运行用Python编写的Web程序.Python定义了WSGI标准应用接口来协调Http服务器与基于P ...
- Linux crontab配置
crontab配置 1.命令功能 通过crontab 命令,我们可以在固定的间隔时间执行指定的系统指令或 shell script脚本.时间间隔的单位可以是分钟.小时.日.月.周及以上的任意组合.这个 ...
- SD-SDI播出系统---使用GTX TX产生恢复时钟
SD-SDI播出系统---使用GTX TX产生恢复时钟 1. 2.SD-SDI恢复时钟的生成
- TStrings与Memo.Lines赋值的问题
//想实现在函数中生成Memo1的内容,而后赋给Memo.Lines //方法1: var s: TStrings; begin s := TStringList.Create; AddMemoDat ...
- Python 进制转换与位运算
十进制转二进制.八进制.十六进制: dec = int(input("输入数字:")) print("十进制数为:", dec) print("转换为 ...
- linux的系统组成和计算机组成原理,linux常用操作
Linux入门 linux简介 学习目的:linux服务器操作系统稳定长期运行,python,pycharm装于linux上 linux系统组成 应用软件:调用系统软件接口 linux操作系统分两 ...
- CAD 中绘制点
首先开启点样式,否则点是看不到的 系统变量 PDMODE 和 PDSIZE 控制点对象的显示外观. PDMODE 取值为 0.2.3 .4 时指定表示点的图形,取值为 1 表示不显示任何图形,如下图所 ...
- java中对HashMap遍历的方式
第一种是利用HashMap的entrySet()方法: Map<String,String> map = new HashMap<String,String>(); Itera ...
- Unity3D工程版本管理方案【转自 兜里】
参阅:http://outofmemory.cn/wr/?u=http%3A%2F%2Fblog.dou.li%2Funity3d%25e5%25b7%25a5%25e7%25a8%258b%25e7 ...
- Ubuntu 14.10 下Eclipse安装Hadoop插件
准备环境 1 安装好了Hadoop,之前安装了Hadoop 2.5.0,安装参考http://www.cnblogs.com/liuchangchun/p/4097286.html 2 安装Eclip ...