一. 什么是自定义指令
我们看到的v-开头的行内属性,都是指令,不同的指令可以完成或实现不同的功能,vue中有默认的指令。vue 也允许注册自定义指令对普通 DOM元素进行底层操作。
二. 常见的vue指令
- v-once:只会执行一次渲染,当数据发生改变时,不会再变化。
<div id="app">
<p v-once>{{msg}}</p>
<input v-model="msg" type="text" /> // 当输入值变化的时候msg回发生变化,但是p标签渲染出的msg不会变化了
</div>
<script>
let vue = new Vue({
el:"#app",
data:{
msg:'你好,佳佳'
}
})
</script>
- v-show:接受一个表达式或一个布尔值。相当于给元素添加一个display属性
<div id="app">
<div v-show="msg == 'wangjiajia' ">{{msg}}</div> // 只有当input框输入了wangjiajia,才会显示。在这里相当于给div标签添加了display:none属性
<input v-model="msg" type="text" />
</div>
<script>
let vue = new Vue({
el:"#app",
data:{
msg:'你好,佳佳',
}
})
</script>
- v-if、v-else、v-else-if
- v-if和v-show有同样的效果,不同在于v-if是重新渲染,属于真正意义上的删除,渲染开销大。而v-show使用display:none属性来控制显示隐藏。
- 频繁切换的话建议使用v-show减少渲染带来的开销。
- v-if可以单独使用,而v-else-if,v-else必须与v-if组合使用
<div id="app">
<div v-if="msg == 'wangjiajia' ">{{msg}}</div>
<div v-else-if="msg == 'wangtongtong' ">{{msg}}</div>
<div v-else>davide</div>
<input v-model="msg" type="text" /> //只有在input框输入wangjiajia才会显示wangjiajia,输入wangtongtong才会显示wangtongtong。否则都是显示davide
</div>
<script>
let vue = new Vue({
el:"#app",
data:{
msg:'你好,佳佳',
}
})
</script>
- v-for:可用来遍历数组、对象、字符串。
<div id="app">
<div v-for="(item, index) in bookList" :key="index">{{ item }}</div>
</div>
<script>
let vue = new Vue({
el:"#app",
data:{
msg:'你好,佳佳',
bookList:['三国演义', '西游记', '水浒传', '红楼梦']
}
})
</script>
- v-text:是渲染字符串,和{{ }} 效果类似,推荐使用{{ }}
<p>{{msg}}</p> 等价于 <p v-text='msg'></p>
- v-html:渲染为html结构
<div>{{innerHtml}}</div>
<div v-text="innerHtml"></div>
<div v-html="innerHtml"></div>
<script>
let vue = new Vue({
el:"#app",
data:{
msg:'你好,佳佳',
bookList:['三国演义', '西游记', '水浒传', '红楼梦'],
innerHtml:'<button>一个按钮</button>'
}
})
</script>
7. v-bind:用于数据的传递,语法糖形式为:。即v-bind:value=‘value’ 等价于 :value=‘value’。
8. v-on:用于事件绑定,语法糖形式为@。即v-on:click=“clickfunc” 等价于 @click=“clickfunc”
9. v-model:双向绑定。v-model=‘变量名’。限制在 <input>
、<select>、<textarea>
、components中使用。
ps:详见vue2篇:vue指令
三. 如何实现自定义指令
- 在vue2中:
// 注册一个全局自定义指令 `v-focus`
Vue.directive('focus', {
// 当被绑定的元素插入到 DOM 中时……
inserted: function (el) {
// 聚焦元素
el.focus() // 页面加载完成之后自动让输入框获取到焦点的小功能
}
})
// 注册一个局部自定义指令 `v-focus`
directives: {
focus: {
// 指令的定义
inserted: function (el) {
el.focus() // 页面加载完成之后自动让输入框获取到焦点的小功能
}
}
}
- 在vue3中:(以通过权限控制按钮为例)
- 一般新建一个directives.js文件。用于自定义指令
- 在main.js中引入该文件并挂载
七大钩子函数:
- created:在绑定元素的 attribute 或事件监听器被应用之前调用。在指令需要附加在普通的 v-on 事件监听器调用前的事件监听器中时,这很有用。
- beforeMount:当指令第一次绑定到元素并且在挂载父组件之前调用。
mounted:在绑定元素的父组件被挂载后调用,大部分自定义指令都写在这里。
- beforeUpdate:在更新包含组件的 VNode 之前调用。
- updated:在包含组件的 VNode 及其子组件的 VNode 更新后调用。
- beforeUnmount:在卸载绑定元素的父组件之前调用
- unmounted:当指令与元素解除绑定且父组件已卸载时,只调用一次。
四个参数:
- el:
指令所绑定的元素,可以用来直接操作 DOM。
- binding:我们通过自定义指令
传递的各种参数,主要存在于这个对象中
,该对象属性较多,如下属性是我们日常开发使用较多的几个:例如:v-buttonCheck:some="['delete', 'create']"
value:指令绑定的值,在这里就是['delete', 'create']
arg:传给指令的参数,在这里就是some
- vnode:Vue 编译生成的虚拟节点。
- oldVnode:上一个虚拟节点,仅在 update 和 componentUpdated 钩子中可用。
注意:除了 el 之外,其它参数都应该是只读的,切勿进行修改。如果需要在钩子之间共享数据,建议通过元素的 dataset 来进行。
<el-button v-buttonCheck:some="['delete', 'create']" type="primary">点击</el-button> // 指令的使用,some是传递的参数。['delete', 'create']是指令绑定的值。这里的意思就是,button按钮只有在具备delete或者create权限时才会显示。
// usersPermissions:表示当前用户所具备的权限,正常该数据应该是从服务端加载而来,但是我这里简单起见,就直接定义好了,这里表示当前用户具备delete和edit权限。
const usersPermissions = ['create', 'edit']
const buttonCheck = {
mounted(el,binding) {
const { value } = binding
// 看value提供的权限是否在usersPermissions中具备。如果有,说明当前按钮具备权限,此时应该正常显示,如果没有,说明当前按钮不具备权限,此时不应该显示。
let f = value.some(item => {
return usersPermissions.includes(item)
})
if (!f) {
// 从父节点删除按钮
el.parentNode && el.parentNode.removeChild(el)
}
}
}
export default app => {
app.directive('buttonCheck', buttonCheck)
}
在main.js中引用并挂载
import App from './App.vue'
import directives from 'utils/directives.js'
let app =createApp(App)
directives(app)
注:自定义vue指令灵活多变,本文只是提供一种常见流程。具体逻辑可以根据具体业务需求自行定义指令。