title: 创建自定义指令

在组件标签的使用中,我们经常使用一些指令,例如v-for/v-model,在这里我们学习一下如何实现一个自定义指令,如何写一个自己想要实现的自定义指令功能,最好进行好封装,保证代码的可复用性

自定义指令的实现类似于组件的实现,文件内内写好指令代码进行引用即可

在创建自定指令前,先了解指令内的几个钩子函数

  • bind():当指令第一次绑定到元素时被调用,并只会被调用一次,用于初始化配置;
  • inserted():当绑定的元素被插入到父元素时被调用;
  • update():当绑定的组件被更新时调用,但会在其子组件更新之前被调用;
  • componentUpdated():当绑定的组件及其子组件全部更新之后被调用;
  • unbind():当指令和绑定的元素解绑时被调用,并且只会被调用一次

钩子函数有四个参数,分别是el(绑定元素,可以获得子元素),binding(一个对象),vNode(虚拟节点),oldNode(上一个虚拟节点)

binding对象内参数

  • value 传递给指令的值
  • oldValue 上一个值
  • arg 传递给指令的参数
  • modifiers 指令修饰符的对象
  • instance 指令组件实例
  • dir 指令对象

基本使用

//在元素中使用绑定指令,注册指令
<div>
   //传入多个值用{},传入单个值时需要添加'',说明这是值不是字符串
<button v-rloes="'admin'">编辑</button>
</div>
<script>
//类似于注册组件一样注册指令,引入指令,注册指令
import roles from './directives/(xxx)自定义指令.js';
export default {
   directives:{
      roles(自定义指令名);
   }
}
</script>

当自定指令被注册了,接下来就是对指令的内容进行编辑

//这里做一个操作,假设登录者没有权限,就隐藏编辑按钮
import store from '../store/index'  //获取当前使用者权限
//默认导出
export default {
   //绑定元素时进行的操作
   bind(el,binding,vnode,oldnode){
      //假设获取当前使用者信息来确认权限,我们在上面传入值admin
      const roles = store.userInfo.rloes
      //如果传入的值不是store中的值,或者不包含这个值就隐藏button
      if(roles !== binding.value || !roles.includes(binding.value)){
         el.style.display = none;
      }
   }
   //更新时进行的操作
   update(){}
}

假设,这个div内部有多个按钮,部分需要权限设置,部分不需要,这如何满足呢,这时候需要利用到另一个钩子函数inserted,因为bind只是初始化的时候调用,无法获取到父元素,实现如下

<div>
<button v-roles="'admin'">编辑</button>
<button v-roles="'admin'">删除</button>
<button v-roles="'user'">新增</button>
</div>
//这里做一个操作,假设登录者没有权限,就隐藏编辑按钮
import store from '../store/index'  //获取当前使用者权限
//默认导出
export default {
   //参数时一样的
	inserted(el,binding,vnode,oldnode){
      const roles = store.userInfo.roles;
      //如果不包含用户权限就删除
      if(roles !== binding.value || !roles.includes(binding.value)){
         el.parentNode.removeChild(el)
      }
   }
}
//以上就是一些简单的实现一个自定义指令

封装使用(复用)

接下来这里再封装一些自定义指令的使用,比如点击某个子元素产生某种效果

//html部分
<div 
	class="xxx"
	v-xxx(自定义指令)="{
	curIdx,				 //可以通过子元素事件改变当前值,来获取索引
	className:'tag'     //传入子元素class获取子元素(复用性)、
	activeClass: ''
}"
>
	<div 
	class='tag'
	v-for="(item,index) of items"
	:key = "index"
	class='xxx'
	@click=changeIndex(index)
	></div>
</div>

接下来就是指令的封装

//默认导出
//假设需要点击某个,某个变红,变红的效果就添加在activeClass:'xxx'
export default{
   //初始化绑定
   bind(el,binding,vnode,oldnode){
      const _ops = binging.value; //获取传递的所有值
      const _c = el.getElementsByClassName(_ops.calssName)  //绑定在父元素中,可以获取父元素,也可以通过类获取子元素
   },
   update(el,binding,vnode,oldnode){
      const _ops = binging.value;
      const _c = el.getElementsByClassName(_ops.calssName);
      const _oOps = binding.oldValue,     //获取标签前一个值,没有前一个默认是空
      //点击某个某个产生效果(先清除上一个)
		_c[_oOps.curIdx].calssName = `${_oOps.className}`;   //点击之后,将上一个元素className还原即可
		_c[_ops.curIdx].calssName += `${_ops.activeClass}`;  //将事件触发的新的index元素添加 效果类
   }
}

//以上代码进行部分修改可以达成多种效果,具体看实际需要,实际要达成的效果(意思就是封装之后可复用)

原文地址:http://www.cnblogs.com/YYang333/p/16868023.html

1. 本站所有资源来源于用户上传和网络,如有侵权请邮件联系站长! 2. 分享目的仅供大家学习和交流,请务用于商业用途! 3. 如果你也有好源码或者教程,可以到用户中心发布,分享有积分奖励和额外收入! 4. 本站提供的源码、模板、插件等等其他资源,都不包含技术服务请大家谅解! 5. 如有链接无法下载、失效或广告,请联系管理员处理! 6. 本站资源售价只是赞助,收取费用仅维持本站的日常运营所需! 7. 如遇到加密压缩包,默认解压密码为"gltf",如遇到无法解压的请联系管理员! 8. 因为资源和程序源码均为可复制品,所以不支持任何理由的退款兑现,请斟酌后支付下载 声明:如果标题没有注明"已测试"或者"测试可用"等字样的资源源码均未经过站长测试.特别注意没有标注的源码不保证任何可用性