当前位置: 首页 > news >正文

vue3.0 如何自定义指令

前言


本篇博客是基于vue3.0的自定义指令开发教程,(有版本变化会持续更新)其中会列出如何使用以及与vue2.0的自定义指令的对比。


一, Vue3.0自定义指令教程


demo中,包含一个很简单的一键复制指令,不需要再下载插件,很好用的


先看看 vue3.0官方文档如何介绍: 官方文档传送门

自定义指令的作用:主要是为了重用涉及普通元素的的底层DOM的访问逻辑


自定义指令可以局部注册也可以全局注册,再平时开发过程中使用较多的是全局自定义指令。

一:局部注册

直接上代码,一目了然

<template>
    <input type="text" name="" v-focus value="">
</template>
<script>
// 局部自定义指令
const focus = {
    mounted: (el) => {
        el.focus();
    }
}
export default {
    directives: {
        focus
    },
    data() {
        return {}
    },
}
</script>

二:全局注册

1. 在src目录下新建文件directives目录,里边建index.js文件

文件内容如下

const directives = {
   install: ((app) => {
       // 更改颜色   一般就是用这种简化形式就足够了
       // 这种简化形式的写法会在钩子函数'mounted'和'updated'中调用
       app.directive('selfcolor', (el, binding) => {
           el.style.color = binding.value;
       });
       // 点击按钮一键复制
       app.directive('selfCopy', (el, binding) => {
           el.onclick = () => {
               console.log(binding.value)
               if (!binding.value) {
                   alert('不能复制空文本');
                   return false;
               }
               navigator.clipboard.writeText(binding.value);
               alert('复制成功')
           }

       });
       // 对象字面量  指令可以接受任何合法的javascript表达式
       app.directive('objectParams', (el, binding) => {
           console.log(binding.value)
           console.log(binding.arg)
       });
       //数组
       app.directive('arrayParams', (el, binding) => {
           console.log(binding.value[1])
       });
       // 测试所有生命周期
       app.directive('testLifeCycle', {
           // 在绑定元素的 attribute 前
           // 或事件监听器应用前调用
           created(el, binding, vnode, prevVnode) {
               // 下面会介绍各个参数的细节
           },
           // 在元素被插入到 DOM 前调用
           beforeMount(el, binding, vnode, prevVnode) {},
           // 在绑定元素的父组件
           // 及他自己的所有子节点都挂载完成后调用
           mounted(el, binding, vnode, prevVnode) {
               console.log(binding);
               console.log(binding.modifiers);
               if (Object.keys(binding.modifiers).length == 0) {
                   alert('说明没有传修饰符');
                   return false;
               }
               alert('说明传了修饰符')
           },
           // 绑定元素的父组件更新前调用
           beforeUpdate(el, binding, vnode, prevVnode) {},
           // 在绑定元素的父组件
           // 及他自己的所有子节点都更新后调用
           updated(el, binding, vnode, prevVnode) {},
           // 绑定元素的父组件卸载前调用
           beforeUnmount(el, binding, vnode, prevVnode) {},
           // 绑定元素的父组件卸载后调用
           unmounted(el, binding, vnode, prevVnode) {}
       });
   })
}
export default directives;
2. 在main.js文件中注册
import { createApp } from 'vue'
import App from './App.vue'
const app = createApp(App);
// 全局注册自定义指令
import selfDirectives from './directives/index.js';
app.use(selfDirectives);
app.mount('#app');

如上,注册完毕,就可以在整个项目中使用了。

3. 在页面中使用
<template>
   <div class="main" v-selfcolor="color">测试自定义指令 </div>
   //一键复制功能
   <input type="button" name="" v-selfCopy="text" value="复制按钮">
   //默认聚焦
   <input type="text" name="" v-focus value="">
   指令内传对象以及arg 传递给指令的参数
   <div v-objectParams:argVariable="{color:'blue',name:'张三'}">指令内传对象</div>
   <div v-arrayParams="[{
     name:'张三',
     age:13
   },{
     name:'李四',
     age:12
   }]">指令内传数组</div>
   //修饰符
   <div v-testLifeCycle.selfModifiers="'测试生命周期'">测试生命周期</div>
</template>
<script>
export default {
   data() {
       return {
           color: 'red',
       }
   },
}
</script>
<style scoped>
</style>

二, 自定义指令钩子生命周期和钩子参数

  • a, 指令钩子的生命周期
生命周期何时调用参数
created在绑定元素的 attribute 前或事件监听器应用前调用el, binding, vnode, prevVnode
beforeMount在元素被插入到 DOM 前调用el, binding, vnode, prevVnode
mounted在绑定元素的父组件及他自己的所有子节点都挂载完成后调用el, binding, vnode, prevVnode
beforeUpdate绑定元素的父组件更新前调用el, binding, vnode, prevVnode
updated在绑定元素的父组件及他自己的所有子节点都更新后调用el, binding, vnode, prevVnode
beforeUnmount绑定元素的父组件卸载前调用el, binding, vnode, prevVnode
unmounted绑定元素的父组件卸载后调用el, binding, vnode, prevVnode
  • b, 指令钩子的钩子参数
钩子参数作用
el指令绑定到的元素。这可以用于直接操作 DOM。
binding一个对象,包含以下属性。
binding.value传递给指令的值。例如在 v-my-directive=“1 + 1” 中,值是 2。
binding.oldValue之前的值,仅在 beforeUpdate 和 updated 中可用。无论值是否更改,它都可用。
binding.arg:传递给指令的参数 (如果有的话)。例如在 v-my-directive:foo 中,参数是 “foo”。
binding.modifiers一个包含修饰符的对象 (如果有的话)。例如在 v-my-directive.foo.bar 中,修饰符对象是 { foo: true, bar: true }。
binding.instance使用该指令的组件实例。
binding.dir指令的定义对象。
vnode代表绑定元素的底层 VNode。
prevNode之前的渲染中代表指令所绑定元素的 VNode。仅在 beforeUpdate 和 updated 钩子中可用。

三,Vue3.0自定义指令和2.0自定义指令的异同?

生命周期不同,钩子函数参数不同


以下列出vue2.0的指令的钩子函数和钩子函数参数,请自行与上文中的3.0的对比

vue2.0钩子函数

生命周期何时调用参数
bind只调用一次,指令第一次绑定到元素时调用。在这里可以进行一次性的初始化设置。el, binding, vnode, oldVnode
inserted被绑定元素插入父节点时调用 (仅保证父节点存在,但不一定已被插入文档中)。el, binding, vnode, oldVnode
update所在组件的 VNode 更新时调用,但是可能发生在其子 VNode 更新之前。指令的值可能发生了改变,也可能没有el, binding, vnode, oldVnode
componentUpdated指令所在组件的 VNode 及其子 VNode 全部更新后调用。el, binding, vnode, oldVnode
unbind只调用一次,指令与元素解绑时调用。el, binding, vnode, oldVnode

vue2.0钩子函数参数

钩子参数作用
el指令绑定到的元素。这可以用于直接操作 DOM。
binding一个对象,包含以下属性。
binding.name指令名,不包括 v- 前缀。
binding.value传递给指令的值。例如在 v-my-directive=“1 + 1” 中,值是 2。
binding.oldValue之前的值,仅在 beforeUpdate 和 updated 中可用。无论值是否更改,它都可用。
binding.expression字符串形式的指令表达式。例如 v-my-directive=“1 + 1” 中,表达式为 “1 + 1”。
binding.arg:传递给指令的参数 (如果有的话)。例如在 v-my-directive:foo 中,参数是 “foo”。
binding.modifiers一个包含修饰符的对象 (如果有的话)。例如在 v-my-directive.foo.bar 中,修饰符对象是 { foo: true, bar: true }。
vnodeVue 编译生成的虚拟节点
oldVnode上一个虚拟节点,仅在 update 和 componentUpdated 钩子中可用。

相关文章:

  • 浅析RocketMQ-消息重建
  • Kickstarter众筹需要准备哪些资料?
  • 数据分享|函数型数据分析部分省市新冠疫情数据
  • 莱佛士学生服装设计作品登知名时尚杂志NÜYOU
  • 【微搭低代码】小程序中利用弹窗组件实现城市切换选择
  • 【数据挖掘】XGBoost面试题:与GBDT的区别?为什么使用泰勒二阶展开?为什么可以并行训练?为什么快?防止过拟合的方法?如何处理缺失值?
  • 【物理应用】基于相场法模拟金属镍的晶粒的长大过程附matlab完整代码
  • 这三个步骤让你知道WPS如何转换成WORD文档
  • sql优化最新干货---mysql存储过程、索引和锁
  • 摄像头测试软件汇总
  • 葡聚糖-NHS/N3/Alkyne/SH/Biotin/CHO/OPSS/OH/NH2/COOH/MAL各种活性基团
  • 【linux操作系统】基础指令(入门必备)
  • 【基础教程】Matlab实现等高线图
  • 零信任策略下K8s安全监控最佳实践(K+)
  • Git之本地分支和远程分支建立追踪关系的几种方式
  • 【个人向】《HTTP图解》阅后小结
  • Computed property XXX was assigned to but it has no setter
  • ES6, React, Redux, Webpack写的一个爬 GitHub 的网页
  • JavaScript 事件——“事件类型”中“HTML5事件”的注意要点
  • JSONP原理
  • Js实现点击查看全文(类似今日头条、知乎日报效果)
  • Linux gpio口使用方法
  • springboot_database项目介绍
  • tweak 支持第三方库
  • vue从入门到进阶:计算属性computed与侦听器watch(三)
  • 初识 webpack
  • 猴子数据域名防封接口降低小说被封的风险
  • 基于Volley网络库实现加载多种网络图片(包括GIF动态图片、圆形图片、普通图片)...
  • 基于游标的分页接口实现
  • 每天10道Java面试题,跟我走,offer有!
  • 前端技术周刊 2019-01-14:客户端存储
  • 三分钟教你同步 Visual Studio Code 设置
  • 深入 Nginx 之配置篇
  • 十年未变!安全,谁之责?(下)
  • 用jQuery怎么做到前后端分离
  • PostgreSQL之连接数修改
  • 阿里云重庆大学大数据训练营落地分享
  • 好程序员大数据教程Hadoop全分布安装(非HA)
  • ​​​​​​​​​​​​​​汽车网络信息安全分析方法论
  • ​2021半年盘点,不想你错过的重磅新书
  • #基础#使用Jupyter进行Notebook的转换 .ipynb文件导出为.md文件
  • (32位汇编 五)mov/add/sub/and/or/xor/not
  • (Note)C++中的继承方式
  • (react踩过的坑)antd 如何同时获取一个select 的value和 label值
  • (第8天)保姆级 PL/SQL Developer 安装与配置
  • (二)linux使用docker容器运行mysql
  • (十) 初识 Docker file
  • (十三)Maven插件解析运行机制
  • (四)图像的%2线性拉伸
  • (提供数据集下载)基于大语言模型LangChain与ChatGLM3-6B本地知识库调优:数据集优化、参数调整、Prompt提示词优化实战
  • (原創) 如何優化ThinkPad X61開機速度? (NB) (ThinkPad) (X61) (OS) (Windows)
  • (转)使用VMware vSphere标准交换机设置网络连接
  • .bat批处理(十一):替换字符串中包含百分号%的子串
  • .Net CF下精确的计时器
  • .Net Framework 4.x 程序到底运行在哪个 CLR 版本之上