vue 系列-指令

175 阅读5分钟

是什么

vue 中的指令一般是以 v- 开头 , 定义在 DOM 行间(:href = "msg"),指令对应的值均是变量。

当表达式的值改变时,会响应式的对 DOM 产生影响。

通过指令可以实现 视图层 和 数据层之间的交互。

讲什么

  1. 内置指令
  2. 自定义指令
  3. 局部自定义指令
  4. 全局自定义指令
  5. 指令中钩子函数
  6. 指令的实现原理
  7. Vue3 中指令的变化
  8. 常用指令插件

内置指令

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 循环方式。

  1. 拼接字符串 innerHTML 弊端: 造成页面重复渲染,低效。
  2. v-for 渲染:页面不会重复渲染,会复用原有的结构,高效。
  3. 要循环谁就在谁上面加 v-for
  4. 会默认复用原有的 dom 元素,如果加了 key 并且 key 值不同 才会被认为是不同的循环。

循环一:

  • {{ item }}
  • | 循环二:
  • {{ value }} {{key}}
  • v-model="msg"

    表单中双向数据绑定,msg 的值会赋予给输入框、同样输入框的值改变会影响数据的变化。

    注意: checked 和 selected 在有 v-model 指令的元素上是无效的。

    <input type="text" v-model="msg" placeholder="内容" />
    
    1. 表单元素 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="西瓜" />
    
    1. 表单元素 radio

    单选 msg 用布尔类型。

    <input type="radio " v-model="sex" value="男" />
    <input type="radio " v-model="sex" value="女" />
    
    1. 表单元素 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 五个钩子函数

    指令中钩子函数

    1. bind(el, binding, vnode): 只调用一次,指令第一次绑定到元素时调用,用这个钩子函数可以定义一个在绑定时执行一次的初始化动作。

    2. inserted(el): 被绑定元素插入父节点时调用(父节点存在即可调用,不必存在于 document 中)。

    3. update(el): 被绑定元素所在的模板更新时调用,而不论绑定值是否变化。通过比较更新前后的绑定值,可以忽略不必要的模板更新。

    4. componentUpdated(el): 被绑定元素所在模板完成一次更新周期时调用。

    5. unbind: 只调用一次, 指令与元素解绑时调用。

    指令中钩子函数-参数

    1. el: 指令所绑定的元素,可以用来直接操作 DOM 。
    2. binding: 一个对象,包含以下属性:
        1. name: 指令名,不包括 v- 前缀。
        1. value: 指令的绑定值, 例如: v-my-directive="1 + 1", value 的值是 2。
        1. oldValue: 指令绑定的前一个值,仅在 update 和 componentUpdated 钩子中可用。无论值是否改变都可用。
        1. expression: 绑定值的表达式或变量名。 例如 v-my-directive="1 + 1" , expression 的值是 "1 + 1"。
        1. arg: 传给指令的参数。例如 v-my-directive:foo, arg 的值是 "foo"。
        1. modifiers: 一个包含修饰符的对象。 例如: v-my-directive.foo.bar, 修饰符对象 modifiers 的值是 { foo: true, bar: true }。
    3. vnode: Vue 编译生成的虚拟节点。
    4. oldVnode: 上一个虚拟节点,仅在 update 和 componentUpdated 钩子中可用。

    上面大体讲解了指令的基础配置, 那么指令的实现原理是什么呢?

    指令的实现原理

    通过源码,我们可以大体了解到:

    1. 在生成 AST 语法树时,遇到指令会给当前元素添加 directives 属性
    2. 通过 genDirectives 生成指令代码
    3. 在 patch 前将指令的钩子提取到 cbs 中,在 patch 过程中调用对应的钩子
    4. 当执行指令对应钩子函数时,调用对应指令定义的方法
    5. 指令相当于 vue 生命周期中的一个微任务操作。

    Vue3 中指令的变化

    vue3 中指令的钩子函数发生了一些变化, 和 vue 的生命周期钩子函数名称统一化。由原来的 5 个钩子函数变成了 7 个钩子函数。

    app.directive("focus", {
      // 在绑定元素的 attribute 或事件监听器被应用之前调用
      created() {},
      // 当指令第一次绑定到元素并且在挂载父组件之前调用
      beforeMount() {},
      // 在绑定元素的父组件被挂载后调用
      mounted() {},
      // 在更新包含组件的 VNode 之前调用
      beforeUpdate() {},
      // 在包含组件的 VNode 及其子组件的 VNode 更新后调用
      updated() {},
      // 在卸载绑定元素的父组件之前调用
      beforeUnmount() {},
      // 当指令与元素解除绑定且父组件已卸载时, 只调用一次
      unmounted() {},
    });
    

    常用指令插件

    1. v-loading
    2. v-permission
    3. v-permission
    4. v-input:type
    5. v-longpress
    6. v-lazy-img
    7. v-real-img
    8. v-copy
    9. v-expandClick
    10. v-screenfull
    11. v-tooltip
    12. v-ellipsis
    13. v-backtop
    14. v-empty
    15. v-drag
    16. v-resize

    github: github.com/wolichuang/…

    总结

    基础知识总结, 学习中....