一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第2天,点击查看活动详情。
前言
在项目中我们最常见的指令有很多,比如 v-if v-show ......,但是有些时候我们的组件中有些功能是重复的,我们完全可以自定义指令(小项目就算了,不至于),今天我们就来简单的聊聊自定义指令。
vue2中创建指令
vue2中提供了api(directive)供我们使用。
自定义指令: 输入框的值大于7时为红色,如果小于7则显示绿色
基本代码如下:
Vue.directive('shownumber', {
bind: function (el, binding, vnode) {
// console.log(el,binding,vnode)
console.log(binding.value);
console.log(vnode)
if(binding.value>7){
el.style.color='red';
}else {
el.style.color='green';
}
},
inserted:function (a,b,c){
console.log(a,b,c)
},
update: function (el,binding,vnnode) {
console.log(el,binding)
},
componentUpdated: function (el,binding,vnnode) {
if(binding.value>7){
el.style.color='red';
}else {
el.style.color='green';
}
}
});
自定义指令中的特定函数:
- bind: 指令第一次绑定到元素上时调用,相当于初始化某个节点
- instead: 被绑定元素插入父节点时调用,这句话是什么意思呢,就是当前的节点插入的对象并不一定是文本,只是引入了到父级内。
- update: 当其所在的Vnode更新时进行调用
- componentUpdate: 指令所在的组件全部更新后调用
- unbind:解绑,只调用一次
注释:
el: 就是指当前的dom节点了
binding: 一个对象,最主要的有两点:
- value: 指令绑定的值
- oldvalue: 绑定前的值
注意:自定义指令最好不要用箭头函数,这样你就失去了传参的机会。
页面中使用指令
代码如下:
<template>
<div style="padding-top: 100px;height: 250px">
<input v-shownumber="input" v-model="input" placeholder="请输入内容"/>
<el-button @click="input++">增加</el-button>
</div>
</template>
<script>
export default {
data () {
return {
input:5
}
},
}
</script>
效果如下:
当数字小于7时:
当数字大于7时:
指令在el-input中失效
失效原因: 我们在原生中绑定的就是当前的dom节点,也就是input,但是我们在使用elementui插件时,我们添加的一些属性可以覆盖掉input的属性,但是一些属性是覆盖不掉的,比如color
原生的input就是一个简单的input,但是el_input的真实节点中套了一层div:
解决办法: 找到子集,直接对子集进行修改,代码调整如下:
Vue.directive('shownumber', {
bind: function (el, binding, vnode) {
if (binding.value > 7) {
setTimeout(()=>{
const nodes = el.getElementsByTagName('input')[0]
nodes.style.color = 'red';
nodes.style.fontSize = '50px';
},100)
} else {
setTimeout(()=>{
const nodes = el.getElementsByTagName('input')[0]
nodes.style.color = 'green';
nodes.style.fontSize = '50px';
},100)
}
},
inserted:function (a,b,c){
console.log(a,b,c)
},
update: function (el,binding,vnnode) {
if (binding.value > 7) {
setTimeout(()=>{
const nodes = el.getElementsByTagName('input')[0]
nodes.style.color = 'red';
nodes.style.fontSize = '50px';
},100)
} else {
setTimeout(()=>{
const nodes = el.getElementsByTagName('input')[0]
nodes.style.color = 'green';
nodes.style.fontSize = '50px';
},100)
}
},
componentUpdated: function (el,binding,vnnode) {
if (binding.value > 7) {
setTimeout(()=>{
const nodes = el.getElementsByTagName('input')[0]
nodes.style.color = 'red';
nodes.style.fontSize = '50px';
},100)
} else {
setTimeout(()=>{
const nodes = el.getElementsByTagName('input')[0]
nodes.style.color = 'green';
nodes.style.fontSize = '50px';
},100)
}
}
});
<template>
<div style="padding-top: 100px;height: 250px">
<el-input v-shownumber="input" v-model="input" placeholder="请输入内容"></el-input>
<el-button @click="input++">增加</el-button>
</div>
</template>
<script>
export default {
data () {
return {
input:5
}
},
}
</script>
效果如下:
vue3中的自定义指令
其实vue3中的指令与vue2中的指令大差不差,我们可以按照模板来搞下:
import { createApp } from 'vue'
import './style.css'
import App from './App.vue'
import router from "./router";
import ElementPlus from 'element-plus'
import 'element-plus/dist/index.css'
const app = createApp(App);
app.use(ElementPlus);
app.use(router);
// 自定义指令
app.directive('showNumber', {
// 在绑定元素的 attribute 或事件监听器被应用之前调用, 在指令需要附加须要在普通的 v-on 事件监听器前调用的事件监听器时,这很有用
created(el, binding) {},
// 当指令第一次绑定到元素并且在挂载父组件之前调用
beforeMount(el, binding) {},
// 在绑定元素的父组件被挂载后调用
mounted(el, binding) {},
// 在更新包含组件的 VNode 之前调用
beforeUpdate(el, binding) {},
// 在包含组件的 VNode 及其子组件的 VNode 更新后调用
updated(el, binding) {},
// 在卸载绑定元素的父组件之前调用
beforeUnmount(el, binding) {},
// 当指令与元素解除绑定且父组件已卸载时, 只调用一次
unmounted(el, binding) {},
});
不得不说,vue3中的函数比vue2看起来更加的直观一些,就像vue2中的生命周期一样。
// 自定义指令
app.directive('showNumber', {
// 在绑定元素的 attribute 或事件监听器被应用之前调用, 在指令需要附加须要在普通的 v-on 事件监听器前调用的事件监听器时,这很有用
created(el, binding) {},
// 当指令第一次绑定到元素并且在挂载父组件之前调用
beforeMount(el, binding) {
if(binding.value<7){
el.style.color ='green'
}else {
el.style.color ='red'
}
},
// 在绑定元素的父组件被挂载后调用
mounted(el, binding) {},
// 在更新包含组件的 VNode 之前调用
beforeUpdate(el, binding) {},
// 在包含组件的 VNode 及其子组件的 VNode 更新后调用
updated(el, binding) {
if(binding.value<7){
el.style.color ='green'
}else {
el.style.color ='red'
}
},
// 在卸载绑定元素的父组件之前调用
beforeUnmount(el, binding) {},
// 当指令与元素解除绑定且父组件已卸载时, 只调用一次
unmounted(el, binding) {},
});
<input v-showNumber="val1" v-model="val1">
<el-button @click="val1++">++</el-button>
效果如下:
同样的,在elementui中一样对节点的子集进行css的修改才能达到预期的效果。