• 【Vue】通过自定义指令回顾 v-内置指令


    Vue.js 的各种指令(Directives)更加方便我们去数据驱动 DOM,例如 v-bind、v-on、v-model、v-if、v-for、v-once 等内置指令,这些指令的职责就是当表达式改变时将某些行为应用到 DOM 上,尽量不去操作增删改 DOM。通过了解如何去自定义指令,可以想象内置指令是如何完成的。

    一、自定义指令

    在需要特殊功能时,使用自定义指令对 DOM 进行底层操作

    1.1 注册

    自定义指令的注册分为全局注册局部注册,类似组件的注册,只是方法名为 directive,写法如下:

    
    // 全局注册 自定义指令
    Vue.directive(‘mydir’,{
        // 指令选项
    });
    // 全局注册 自定义指令函数
    Vue.directive('mydir', function () {
      // 这里将会被 `bind` 和 `update` 调用
    })
    // 局部注册(只针对组件内元素)
    export default {
        directives: {
            mydir: {
                // 指令选项
            }
        }
    }
    
    需要注意的是:Vue.directive( ) 注册指令要在实例初始化 new Vue( ) 之前才能全局注册指令。定义指令时驼峰式写法会报错,所以一般小写。

    1.2 指令选项

    自定义指令的选项是由几个钩子函数(可选)组成,可以根据需求选择不同的钩子,例如使用全局注册一个指令时:

    
    Vue.directive('mydir', {
      bind: function () {
        // 只调用一次,指令第一次绑定到元素时调用,用于在绑定元素时执行一次的初始化动作。
        },
      update: function () {
        // 第一次是紧跟在 bind 之后调用,获得的参数是绑定的初始值,
        // 之后被绑定元素所在的模板更新时调用,而不论绑定值是否变化,可以忽略不必要的模板更新。    
        },  
      inserted: function () {
        // 被绑定元素插入父节点时调用(父节点存在即可调用,不必存在于 document 中)。
        },
      componentUpdated: function () {
        // 被绑定元素所在模板完成一次更新周期时调用。
        },
      unbind: function () {
        // 只调用一次, 指令与元素解绑时调用。
        }
    })
    

    以上每个钩子函数都有几个参数可用:

    • el:指令所绑定的元素,可以用来直接操作 DOM;
    • binding:包含指令信息的一个对象;
    • vnode:Vue 编译的生成虚拟节点;
    • oldVnode:上一次的虚拟节点,仅在update和componentUpdated钩子函数中可用。

    1.3 示例

    
    // 一个带自定义指令的元素
    <div v-mytest:foo.m1.m2="1+1">MyDirective</div>
    
    // 部分 JS 代码
    export default {
        directives:{
          mytest: {
            bind: function (el, binding, vnode) {
              console.log(el)
              console.log(binding)
              console.log(vnode)
            }
          }
        }
    }
    

    控制台输出截图:

    在这里插入图片描述

    其中对于 binding 对象输出的属性有:

    • rawName: "v-mytest:foo.m1.m2" // 自定义指令
    • name: "mytest" // 指令名称
    • arg: "foo" // 指令的参数
    • modifiers: {m1: true, m2: true} // 指令的修饰符
    • expression: "1+1" // 指令绑定值的字符串形式
    • value: 2 // 指令的绑定值

    二、v-bind || : 绑定属性

    Vue 内置指令 v-bind 用于动态更新 HTML 元素属性,使用 v-bind:someAttr = "someData"或者语法糖 :someAttr = "someData"就可以在 someData 改变时更新绑定的 someAttr 属性。

    2.1 基本用法

    绑定单一的属性值

    
    <a :href="url" :id="linkID">链接</a>
    

    测试 data 如下:

    
    // js
    data : {
        url: 'https://www.baidu.com/',
        linkID : 'myid'
    }
    

    元素渲染输出:
    <a href="https://www.baidu.com/" id="myid">链接</a>

    2.2 对象语法

    v-bind 最常用的是绑定 class 或 style 属性来动态改变样式。例如可以给 :class 设置一个对象来动态切换 class 的值:

    
    &lt;!-- class 绑定 --&gt;
    &lt;div :class="{colorRed: isRed}"&gt;&lt;/div&gt;
    

    当 isRed:true 时渲染输出:
    <div class="colorRed"></div>

    对象中可以传入多个属性值来动态切换 class:

    
    &lt;!-- class 绑定,传入多个属性 --&gt;
    &lt;div :class="{ classA: isA, classB: isB }"&gt;
    

    当 isA、isB 变化时 classA、classB 会动态更新,当都为 true 时显然渲染结果为:
    <div class="classA classB"></div>

    同理对于 style 可以传入对象属性,并且可以使用字符串拼接:

    
    &lt;!-- style 绑定 --&gt;
    &lt;div :style="{ fontSize: size + 'px' }"&gt;&lt;/div&gt;
    

    对于元素中的各个对象可以统一用 v-bind 绑定:

    
    &lt;!-- 绑定一个有属性的对象 --&gt;
    &lt;div v-bind="{ id: someProp, 'other-attr': otherProp }"&gt;&lt;/div&gt;
    

    2.3 数组语法

    class 可以传入多值,给 :class 绑定一个数组就可以使用 class 列表

    
    &lt;div :class="[activeA, activeB]"&gt;&lt;/div&gt;
    

    例如当 {activeA: 'class1', activeB: 'class2'} 时渲染结果为:
    <div class="class1 class2"></div>

    还可以在数组语法中使用三元表达式切换 class,例如:

    
    &lt;div :class="[isA ? activeA : '', activeB]"&gt;
    

    在 class 有多个条件时使用三元表达式比较繁琐,可以在数组语法中使用对象语法

    
    &lt;div :class="[{activeA: isA}, activeB]"&gt;
    

    2.4 修饰符

    v-bind 的修饰符很少,API 中只提供.prop.camel.sync,并且多用于组件,使用方式示例:

    
    &lt;!-- 通过 prop 修饰符绑定 DOM 属性 (property) --&gt;
    &lt;div v-bind:text-content.prop="text"&gt;&lt;/div&gt;
    
    &lt;!-- .camel 修饰符(2.1.0+)将 v-bind 属性名称 kebab-case 驼峰化为 camelCase --&gt;
    &lt;svg :view-box.camel="viewBox"&gt;&lt;/svg&gt;
    
    &lt;!-- .sync 修饰符(2.3.0+) 语法糖,会扩展成一个更新父组件绑定值的 v-on 侦听器--&gt;
    &lt;text-document v-bind:title.sync="doc.title"&gt;&lt;/text-document&gt;
    &lt;!-- 批量绑定,将 doc 对象中的每一个属性 (如 title) 都作独立的 prop ,各自添加 v-on 监听器--&gt;
    &lt;text-document v-bind.sync="doc"&gt;&lt;/text-document&gt;
    

    三、v-on || @ 监听事件

    v-on 用于动态绑定事件监听器,使用 v-on:someEvent = "someFunction"或者语法糖 @someEvent = "someFunction"就可以监听 someEvent 进行交互。

    3.1 基本用法

    @someEvent 调用的方法名后面可以不跟(),例如:

    
    &lt;a :href="url" :id="linkID"&gt;链接&lt;/a&gt;
    &lt;!-- 监听一个事件 --&gt;
    &lt;button @click="changeFun"&gt;change button&lt;/button&gt;
    

    可以在 methods 中添加函数:

    
    // 部分 JS 代码
    methods :{
      changeFun : function () {
        this.linkID = 'changeID' // 指向当前组件本身
      }
    }
    

    点击 button 按钮后 a 元素的 id 改变:
    <a href="https://www.baidu.com/" id="changeID">链接</a>

    当然 v-on 还可以使用对象语法监听多个事件:

    
    &lt;!-- v2.4.0+ --&gt;
    &lt;button v-on="{ mousedown: doThis, mouseup: doThat }"&gt;&lt;/button&gt;
    
    对于在 HTML 元素上监听的事件,当 ViewModel 销毁时,所有的事件处理器会自动删除,无需自己清理。

    3.2 修饰符

    Vue 可以将原生事件对象参数 event 传入事件方法中,并提供了特殊变量$event用来访问元素 DOM 事件。此外可以通过一些事件修饰符来实现特定的事件,如 .stop.prevent.capture.once 等,常用的使用示例:

    
    &lt;!-- 停止单击事件冒泡,调用 event.stopPropagation()--&gt;
    &lt;button @click.stop="doThis"&gt;&lt;/button&gt;
    
    &lt;!-- 阻止默认行为,调用 event.preventDefault() --&gt;
    &lt;button @submit.prevent="doThis"&gt;&lt;/button&gt;
    
    &lt;!-- 添加事件侦听器时使用 capture 事件捕获模式 --&gt;
    &lt;button @click.capture="doThis"&gt;&lt;/button&gt;
    
    &lt;!-- 点击回调只会触发一次 --&gt;
    &lt;button @click.once="doThis"&gt;&lt;/button&gt;
    
    &lt;!-- 只当点击鼠标左键时触发(2.2.0)  --&gt;
    &lt;button @click.left="doThis"&gt;&lt;/button&gt;
    
    &lt;!-- 串联修饰符 --&gt;
    &lt;button @click.stop.prevent="doThis"&gt;&lt;/button&gt;
    
    

    此外,v-on 还提供按键修饰符来监听键盘事件,键值为 .keyCode,常用有.entry.delete.tab.esc.space.down等,如下:

    
    &lt;!-- 只有在 `keyCode` 是 5 时调用 `vm.submit()` --&gt;
    &lt;input v-on:keyup.5="submit"&gt;
    
    &lt;!-- 为重要的 keyCode 如 enter 提供别名--&gt;
    &lt;input v-on:keyup.enter="submit"&gt;
    
    &lt;!-- 缩写语法 --&gt;
    &lt;input @keyup.enter="submit"&gt;
    
    此外还有系统修饰符监听键盘事件,不同的系统其键盘/系统修饰符不一样。这些按键修饰符可以任意组合使用。

    四、v-if、v-show 条件渲染

    条件渲染 v-if 根据表达式的值的真假条件渲染元素,在表达式为真时渲染,为假时移除。

    
    &lt;p v-if="status === 1"&gt;当 status 为 1 时显示此行&lt;/p&gt;
    
    &lt;p v-else-if="status === 1"&gt;当 status 为 2 时显示此行&lt;/p&gt;
    
    &lt;p v-else&gt;其它情况默认显示此行&lt;/p&gt;
    

    v-show 也是条件渲染,但只切换元素的 CSS 属性 display,无论条件真假都会被编译,相比于 v-if 更适用于频繁切换场景。

    
    &lt;p v-show="status === 1"&gt;当 status 为 1 时显示此行&lt;/p&gt;
    

    当 data: {status: 2} 时隐藏,但依旧会被编译,渲染结果为:
    <p style="display: none;">当 status 为 1 时显示此行</p>

    显然在 Vue.js 内置的 <template> 元素上可以使用 v-if,但不能使用 v-show,可以思考下为什么。

    五、v-for 列表渲染

    列表渲染指令 v-for 常用于数组遍历或枚举一个对象的循环显示,必须结合 in 使用特定语法 alias in expression 为当前遍历的元素提供别名:

    
    &lt;!-- 遍历一个数组 --&gt;
    &lt;div v-for="item in items"&gt;{{ item.text }}&lt;/div&gt;
    
    &lt;!-- 提供第二个的参数为数组的索引 --&gt;
    &lt;div v-for="(item, index) in items"&gt;{{ index }} - {{ item.text }}&lt;/div&gt;
    
    &lt;!-- 遍历对象属性 --&gt;
    &lt;div v-for="value in object"&gt;{{ value }}&lt;/div&gt;
    
    &lt;!-- 提供第二个可选的参数:对象的键名 --&gt;
    &lt;div v-for="(value, key) in object"&gt;{{ key }}: {{ value }}&lt;/div&gt;
    
    &lt;!-- 提供第三个的可选参数:对象的索引 --&gt;
    &lt;div v-for="(value, key, index) in object"&gt;{{ index }}. {{ key }}: {{ value }}&lt;/div&gt;
    
    可以用 of 替代 in 作为分隔符

    v-forv-if 在同一节点一起使用时,v-for 的优先级比 v-if 更高。

    六、v-model 表单控件双向绑定

    v-model 其实也是一个特殊的语法糖,其实实现的数据双向绑定也可用v-bindv-on实现,但v-model在不同表单上会有更加智能的处理。

    6.1 文本框

    经典的使用案例是对<input><textarea>文本框的双向数据绑定:

    
    &lt;!-- 输入框 --&gt;
    &lt;input type="text" v-model="message" placeholder="edit me"&gt;
    &lt;!-- 文本域 --&gt;
    &lt;textarea v-model="message" placeholder="edit me"&gt;&lt;/textarea&gt;
    &lt;!-- 实时更新 --&gt;
    &lt;p&gt;Message is: {{ message }}&lt;/p&gt;
    

    6.2 动态选择

    对于单选按钮,复选框及选择框的选项,v-model配合 Vue 实例的数据作为value属性值实现不同效果,即会忽略所有表单元素的 value、checked、selected 特性的值。

    
    &lt;!--单选按钮的互斥效果--&gt;
    &lt;div id="example-radio"&gt;
      &lt;input type="radio" id="one" value="One" v-model="picked"&gt;
      &lt;label for="one"&gt;One&lt;/label&gt;
      
      &lt;input type="radio" id="two" value="Two" v-model="picked"&gt;
      &lt;label for="two"&gt;Two&lt;/label&gt;
      
      &lt;!-- picked 显示的是 value 的值 --&gt;
      &lt;p&gt;Picked: {{ picked }}&lt;/p&gt;
    &lt;/div&gt;
    
    &lt;!--多选按钮--&gt;
    &lt;div id='example-checkbox'&gt;
      &lt;input type="checkbox" id="one" value="One" v-model="checkedNames"&gt;
      &lt;label for="jack"&gt;Jack&lt;/label&gt;
      &lt;input type="checkbox" id="two" value="Two" v-model="checkedNames"&gt;
      &lt;label for="john"&gt;John&lt;/label&gt;
    
        &lt;!-- Checked 显示的是 value 组成的数组 --&gt;
      &lt;p&gt;Checked: {{ checkedNames }}&lt;/p&gt;
    &lt;/div&gt;
    

    6.3修饰符

    v-model的修饰符的使用限制在<input>、<select>、<textarea> 和组件。

    • .lazy - 取代 input 监听 change 事件
    • .number - 输入字符串转为数字
    • .trim - 输入首尾空格过滤

    七、v-pre、v-cloak、v-once

    这三个指令的共同点是无需表达式,用法如下:

    
    &lt;!-- 不显示未编译的标签直到实例初始化完 --&gt;
    &lt;div v-cloak&gt;{{ message }}&lt;/div&gt;
    &lt;!-- 需要配合 CSS 隐藏样式 [v-cloak]{ display: none;}--&gt;
    
    &lt;!-- 只渲染一次,随后的渲染将被视为静态内容并跳过 --&gt;
    &lt;div v-once&gt;{{ message }}&lt;/div&gt;
    
    &lt;!-- 不会被编译,直接显示显示原始{{ }}标签 --&gt;
    &lt;div v-pre&gt;{{ message }}&lt;/div&gt;
    

    继续加油鸭~ 少年!

    来源:

  • 相关阅读:
    一个小型软件公司关于研发、管理、实施、团队等讨论
    二十七、EFW框架BS系统开发中的MVC模式探讨
    EFW框架问题收集与答疑
    EFW框架源代码版本升级记录说明
    【开源EFW框架】框架中自定义控件GridBoxCard使用实例说明
    二十七(序幕)、【开源】EFW框架破茧成蝶
    二十六、【开源框架】EFW框架Winform前端开发之Grid++Report报表、条形码、Excel导出、图表控件
    二十五、【开源】EFW框架Winform前端开发之强大的自定义控件库
    二十四、【开源】EFW框架Winform前端开发之项目结构说明和调试方法
    二十三、【开源】EFW框架Web前端开发之常用组件(FusionCharts图表、ReportAll报表等)
  • 原文地址:https://www.cnblogs.com/datiangou/p/10144787.html
Copyright © 2020-2023  润新知