是什么
vue 中的指令一般是以 v- 开头 , 定义在 DOM 行间(:href = “https://juejin.cn/post/msg”),指令对应的值均是变量。
当表达式的值改变时,会响应式的对 DOM 产生影响。
通过指令可以实现 视图层 和 数据层之间的交互。
讲什么
- 内置指令
- 自定义指令
- 局部自定义指令
- 全局自定义指令
- 指令中钩子函数
- 指令的实现原理
- Vue3 中指令的变化
- 常用指令插件
内置指令
vue 中自带的指令
v-text=”msg”
输出文本,防止 {{…}} 出现在页面上,标签里面的写字符串是默认值。
v-html=”msg”
输出 html 把普通 html 当成 dom 可渲染的方式
v-once
只会绑定一次输出,当数据再次发生变化也不导致页面刷新,写在不想刷新的标签上。
v-if / v-elseif / v-else
控制 dom, 初始化时 Dom 是否存在。
注意:v-if 和 v-else 之间不能存在多余的 div。
v-show=”flag”
控制样式,如果频繁切换 dom 的时候会使用。
v-for
循环数据绑定到 dom 上,默认使用 (value index) in fruits 循环方式。
- 拼接字符串 innerHTML 弊端: 造成页面重复渲染,低效。
- v-for 渲染:页面不会重复渲染,会复用原有的结构,高效。
- 要循环谁就在谁上面加 v-for
- 会默认复用原有的 dom 元素,如果加了 key 并且 key 值不同 才会被认为是不同的循环。
循环一:
|
循环二:
v-model=”msg”
表单中双向数据绑定,msg 的值会赋予给输入框、同样输入框的值改变会影响数据的变化。
注意: checked 和 selected 在有 v-model 指令的元素上是无效的。
<input type="text" v-model="msg" placeholder="内容" />
复制代码
- 表单元素 checkbox
单选 fruits 用布尔类型,多选 fruits 用 [ ] 才可以取出 value 值
<input type="checkbox" v-model="fruits" value="苹果" />
<input type="checkbox" v-model="fruits" value="香蕉" />
<input type="checkbox" v-model="fruits" value="西瓜" />
复制代码
- 表单元素 radio
单选 msg 用布尔类型。
<input type="radio " v-model="sex" value="男" />
<input type="radio " v-model="sex" value="女" />
复制代码
- 表单元素 select
<select v-model="fruits">
<option value="苹果" disabled />
<option value="香蕉" />
<option value="西瓜" />
</select>
复制代码
v-cloak
通常在 body 中添加 v-cloak,可以隐藏未编译的标签,直到实例编译完成。
[v-cloak] { display: none }
复制代码
自定义指令
我们可以根据需求来自定义实现指令,来操作 DOM 。
自定义指令分为:局部自定义指令 和 全局自定义指令。我们通过一个简单的例子来熟悉下指令的写法,区分下全局/局部指令。
v-focus 指令是每一个新接触指令的同学,都会写的指令: 实现当页面加载时,元素将获得焦点。
<input v-focus />
复制代码
全局指令
Vue.directive("focus", {
bind() {},
inserted(el) {
el.focus();
},
update() {},
componentUpdated() {},
unbind() {},
});
复制代码
局部自定义指令
directives: {
focus: {
bind() {},
inserted(el) {
el.focus();
},
update() {},
componentUpdated() {},
unbind() {},
}
}
复制代码
在 Vue2 中给一个指令定义对象可以提供 bind、inserted、update、componentUpdated、unbind 五个钩子函数
指令中钩子函数
-
bind(el, binding, vnode): 只调用一次,指令第一次绑定到元素时调用,用这个钩子函数可以定义一个在绑定时执行一次的初始化动作。
-
inserted(el): 被绑定元素插入父节点时调用(父节点存在即可调用,不必存在于 document 中)。
-
update(el): 被绑定元素所在的模板更新时调用,而不论绑定值是否变化。通过比较更新前后的绑定值,可以忽略不必要的模板更新。
-
componentUpdated(el): 被绑定元素所在模板完成一次更新周期时调用。
-
unbind: 只调用一次, 指令与元素解绑时调用。
指令中钩子函数-参数
- el: 指令所绑定的元素,可以用来直接操作 DOM 。
- binding: 一个对象,包含以下属性:
-
- name: 指令名,不包括 v- 前缀。
-
- value: 指令的绑定值, 例如: v-my-directive=”1 + 1″, value 的值是 2。
-
- oldValue: 指令绑定的前一个值,仅在 update 和 componentUpdated 钩子中可用。无论值是否改变都可用。
-
- expression: 绑定值的表达式或变量名。 例如 v-my-directive=”1 + 1″ , expression 的值是 “1 + 1″。
-
- arg: 传给指令的参数。例如 v-my-directive:foo, arg 的值是 “foo”。
-
- modifiers: 一个包含修饰符的对象。 例如: v-my-directive.foo.bar, 修饰符对象 modifiers 的值是 { foo: true, bar: true }。
-
- vnode: Vue 编译生成的虚拟节点。
- oldVnode: 上一个虚拟节点,仅在 update 和 componentUpdated 钩子中可用。
上面大体讲解了指令的基础配置, 那么指令的实现原理是什么呢?
指令的实现原理
通过源码,我们可以大体了解到:
- 在生成 AST 语法树时,遇到指令会给当前元素添加 directives 属性
- 通过 genDirectives 生成指令代码
- 在 patch 前将指令的钩子提取到 cbs 中,在 patch 过程中调用对应的钩子
- 当执行指令对应钩子函数时,调用对应指令定义的方法
- 指令相当于 vue 生命周期中的一个微任务操作。
Vue3 中指令的变化
vue3 中指令的钩子函数发生了一些变化, 和 vue 的生命周期钩子函数名称统一化。由原来的 5 个钩子函数变成了 7 个钩子函数。
app.directive("focus", {
// 在绑定元素的 attribute 或事件监听器被应用之前调用
created() {},
// 当指令第一次绑定到元素并且在挂载父组件之前调用
beforeMount() {},
// 在绑定元素的父组件被挂载后调用
mounted() {},
// 在更新包含组件的 VNode 之前调用
beforeUpdate() {},
// 在包含组件的 VNode 及其子组件的 VNode 更新后调用
updated() {},
// 在卸载绑定元素的父组件之前调用
beforeUnmount() {},
// 当指令与元素解除绑定且父组件已卸载时, 只调用一次
unmounted() {},
});
复制代码
常用指令插件
- v-loading
- v-permission
- v-permission
- v-input:type
- v-longpress
- v-lazy-img
- v-real-img
- v-copy
- v-expandClick
- v-screenfull
- v-tooltip
- v-ellipsis
- v-backtop
- v-empty
- v-drag
- v-resize
github: github.com/wolichuang/…
总结
基础知识总结, 学习中….