vue进阶——vue指令

一、什么是指令?

​ 根据vue官方文档的说法:指令 (Directives) 是带有 v- 前缀的特殊 attribute。指令 attribute 的值预期是单个 JavaScript 表达式 (v-for 是例外情况,稍后我们再讨论)。指令的职责是,当表达式的值改变时,将其产生的连带影响,响应式地作用于 DOM。简单来说,就是使用自定义属性的方式比较方便快捷的对元素进行DOM操作。

二、常用指令

  • v-text: 更新元素的 textContent。如果要更新部分的 textContent,需要使用 {{ Mustache }} 插值。

    <div v-text="msg"></div>
    <!-- 插值表达式写法,上下两种效果一样 -->
    <div>{{msg}}</div>
    
  • v-html: 更新元素的 innerHTML。注意:内容按普通 HTML 插入 - 不会作为 Vue 模板进行编译。如果视图使用 v-html 组合模板,可以重新考虑是否通过使用组件来替代。

    <div v-html="msg"></div>
    <!-- 需要注意的是:在网站上动态渲染任意 HTML 是非常危险的,因为容易导致 XSS 攻击。只在可信内容上使用 v-html,永不用在用户提交的内容上。 -->
    
  • v-show: 根据表达式之真假值,切换元素的 display样式属性,来控制元素显示隐藏。当条件变化时该指令触发过渡效果。

    <div v-show="flag"></div>
    <!-- 当元素flag值为true时,元素展示;反之元素隐藏 -->
    
  • v-if: 根据表达式的值的Boolean来有条件地渲染元素。在切换时元素及它的数据绑定 / 组件被销毁并重建。如果元素是 <template>,将提出它的内容作为条件块。当条件变化时该指令触发过渡效果。

    <div v-if="flag"></div>
    <!-- 当元素flag值为true时,元素渲染;反之元素销毁 -->
    <!-- v-show通过css样式控制元素显示隐藏,适用于频繁点击等业务场景,而v-if当条件为真的时候才渲染会有性能的一个提升 -->
    
  • v-else-if: 与v-if搭配使用,可以进行链式条件调用;与js里面if条件判断效果一样。注意:前一兄弟元素必须有 v-ifv-else-if

    <div v-if="type === 'A'">A</div>
    <div v-else-if="type === 'B'">B</div>
    <div v-else-if="type === 'C'">C</div>
    
  • v-else: 不需要表达式,与v-if搭配使用,进行链式调用,注意:前一兄弟元素必须有 v-ifv-else-if

    <div v-if="type === 'A'">A</div>
    <div v-else-if="type === 'B'">B</div>
    <div v-else>C</div>
    
  • v-for: 基于源数据多次渲染元素或模板块。可以渲染的值为(Array | Object | number | string | Iterable (2.6 新增));

    <!-- v-for 指令需要使用 item in items 形式的特殊语法,其中 items 是源数据数组,而 item 则是被迭代的数组元素的别名。 -->
    <!-- item代表每项的值,index代表索引,items就是循环变量 -->
    <div v-for="(item, index) in items"></div>
    <!-- val代表每项的值,name代表对象的键名,index代表索引,object循环对象 -->
    <div v-for="(val, name, index) in object" :key="val"></div>
    <!-- key 的特殊 attribute 主要用在 Vue 的虚拟 DOM 算法,在新旧 nodes 对比时辨识 VNodes。如果不使用 key,Vue 会使用一种最大限度减少动态元素并且尽可能的尝试就地修改/复用相同类型元素的算法。而使用 key 时,它会基于 key 的变化重新排列元素顺序,并且会移除 key 不存在的元素。绑定key会提升项目渲染速度 -->
    
  • v-on: 缩写@,绑定事件监听器。事件类型由参数指定。表达式可以是一个方法的名字或一个内联语句,如果没有修饰符也可以省略。

    • 事件修饰符: 在触发事件的同时去处理 DOM 事件细节。

      1. .stop - 调用 event.stopPropagation(), 阻止单击事件继续传播。
      2. .prevent - 调用 event.preventDefault(),不再重载页面
      3. .capture - 添加事件侦听器时使用 capture 模式。
      4. .self - 只当事件是从侦听器绑定的元素本身触发时才触发回调。
      5. .{keyCode | keyAlias} - 只当事件是从特定键触发时才触发回调。
      6. .native - 监听组件根元素的原生事件。
      7. .once - 只触发一次回调。
      8. .left - (2.2.0) 只当点击鼠标左键时触发。
      9. .right - (2.2.0) 只当点击鼠标右键时触发。
      10. .middle - (2.2.0) 只当点击鼠标中键时触发。
      11. .passive - (2.3.0) 以 { passive: true } 模式添加侦听器
      <!-- 方法处理器 -->
      <button v-on:click="doThis"></button>
      
      <!-- 动态事件 (2.6.0+) -->
      <button v-on:[event]="doThis"></button>
      
      <!-- 内联语句 -->
      <button v-on:click="doThat('hello', $event)"></button>
      
      <!-- 缩写 -->
      <button @click="doThis"></button>
      
      <!-- 动态事件缩写 (2.6.0+) -->
      <button @[event]="doThis"></button>
      
      <!-- 停止冒泡 -->
      <button @click.stop="doThis"></button>
      
      <!-- 阻止默认行为 -->
      <button @click.prevent="doThis"></button>
      
      <!-- 阻止默认行为,没有表达式 -->
      <form @submit.prevent></form>
      
      <!--  串联修饰符 -->
      <button @click.stop.prevent="doThis"></button>
      
      <!-- 键修饰符,键别名 -->
      <input @keyup.enter="onEnter">
      
      <!-- 键修饰符,键代码 -->
      <input @keyup.13="onEnter">
      
      <!-- 点击回调只会触发一次 -->
      <button v-on:click.once="doThis"></button>
      
      <!-- 对象语法 (2.4.0+) -->
      <button v-on="{ mousedown: doThis, mouseup: doThat }"></button>
      
    • 按键修饰符: 在监听键盘事件时,我们经常需要检查详细的按键。Vue 允许为 v-on 在监听键盘事件时添加按键修饰符;

      1. .enter
      2. .tab
      3. .delete (捕获“删除”和“退格”键)
      4. .esc
      5. .space
      6. .up
      7. .down等等一系列按键。
      8. .exact 修饰符允许你控制由精确的系统修饰符组合触发的事件。
      <!-- 即使 Alt 或 Shift 被一同按下时也会触发 -->
      <button v-on:click.ctrl="onClick">A</button>
      
      <!-- 有且只有 Ctrl 被按下的时候才触发 -->
      <button v-on:click.ctrl.exact="onCtrlClick">A</button>
      
      <!-- 没有任何系统修饰符被按下的时候才触发 -->
      <button v-on:click.exact="onClick">A</button>
      
    • 自定义按键修饰符:

      // 可以使用 `v-on:keyup.f1` f1就是自定义按键修饰符名字,112对应键盘码
      Vue.config.keyCodes.f1 = 112
      
  • v-bind: 缩写,动态地绑定一个或多个 attribute,或一个组件 prop 到表达式。单向数据绑定,当绑定值发生变化,做出对应改变。

    <!-- 绑定一个 attribute -->
    <img v-bind:src="imageSrc">	
    
    <!-- 动态 attribute 名 (2.6.0+) -->
    <button v-bind:[key]="value"></button>
    
    <!-- 缩写 -->
    <img :src="imageSrc">
    
    <!-- 动态 attribute 名缩写 (2.6.0+) -->
    <button :[key]="value"></button>
    
    <!-- 内联字符串拼接 -->
    <img :src="'/path/to/images/' + fileName">
    
    <!-- class 绑定 -->
    <div :class="{ red: isRed }"></div>
    <div :class="[classA, classB]"></div>
    <div :class="[classA, { classB: isB, classC: isC }]">
    
    <!-- style 绑定 -->
    <div :style="{ fontSize: size + 'px' }"></div>
    <div :style="[styleObjectA, styleObjectB]"></div>
    
    <!-- 绑定一个全是 attribute 的对象 -->
    <div v-bind="{ id: someProp, 'other-attr': otherProp }"></div>
    
    <!-- 通过 prop 修饰符绑定 DOM attribute -->
    <div v-bind:text-content.prop="text"></div>
    
    <!-- prop 绑定。“prop”必须在 my-component 中声明。-->
    <my-component :prop="someThing"></my-component>
    
    <!-- 通过 $props 将父组件的 props 一起传给子组件 -->
    <child-component v-bind="$props"></child-component>
     <!-- .camel 修饰符允许在使用 DOM 模板时将 v-bind property 名称驼峰化,例如 SVG 的 viewBox property: -->
     <svg :view-box.camel="viewBox"></svg>
    
  • v-model: 对于表单的双向数据绑定,随表单控件类型不同而不同。

    <!-- 
        .lazy - 取代 input 监听 change 事件
        .number - 输入字符串转为有效的数字
        .trim - 输入首尾空格过滤 
    -->
    <input v-model.trim="text" placeholder="请输入">
    
  • v-slot: 缩写#,可放置在函数参数位置的 JavaScript 表达式 (在支持的环境下可使用解构)。可选,即只需要在为插槽传入 prop 的时候使用。

    <!-- 具名插槽 -->
    <base-layout>
      <template v-slot:header>Header content</template>
      <template v-slot:footer>Footer content</template>
    </base-layout>
    
    <!-- 接收 prop 的具名插槽 -->
    <infinite-scroll>
      <template v-slot:item="slotProps">
        <div class="item">{{ slotProps.item.text }}</div>
      </template>
    </infinite-scroll>
    
    <!-- 接收 prop 的默认插槽,使用了解构 -->
    <mouse-position v-slot="{ x, y }">Mouse position: {{ x }}, {{ y }}</mouse-position>
    
  • v-pre: 跳过这个元素和它的子元素的编译过程。可以用来显示原始 Mustache 标签。跳过大量没有指令的节点会加快编译。(提升性能)

    <span v-pre>{{ "跳过" }}</span>
    
  • v-cloak: 这个指令保持在元素上直到关联实例结束编译。和 CSS 规则如 [v-cloak] { display: none } 一起用时,这个指令可以隐藏未编译的 Mustache 标签直到实例准备完毕。

    <style>
        [v-cloak] {
          display: none;
        }
    </style>
    <div v-cloak>
      {{ message }}
    </div>
    
  • v-once: 只渲染元素和组件一次。随后的重新渲染,元素/组件及其所有的子节点将被视为静态内容并跳过。这可以用于优化更新性能。

    <!-- 单个元素 -->
    <span v-once>This will never change: {{msg}}</span>
    <!-- 有子元素 -->
    <div v-once>
      <h1>comment</h1>
      <p>{{msg}}</p>
    </div>
    <!-- 组件 -->
    <my-component v-once :comment="msg"></my-component>
    <!-- `v-for` 指令-->
    <ul>
      <li v-for="i in list" v-once>{{i}}</li>
    </ul>
    

三、自定义指令

​ 除了核心功能默认内置的指令 (v-modelv-show),Vue 也允许注册自定义指令。注意,在 Vue2.0 中,代码复用和抽象的主要形式是组件。

  1. 注册全局自定义指令: 页面一加载就聚焦输入框

    // 注册一个全局自定义指令 `v-focus`
    Vue.directive('focus', {
      // 当被绑定的元素插入到 DOM 中时……
      inserted: function (el) {
        // 聚焦元素
        el.focus()
      }
    })
    
  2. 注册局部指令: 组件中也接受一个 directives 的选项:

    directives: {
      focus: {
        // 指令的定义
        inserted: function (el) {
          el.focus()
        }
      }
    }
    // 使用:<input v-focus>
    
  3. 钩子函数: 一个指令定义对象可以提供如下几个钩子函数 (均为可选)

    • bind:只调用一次,指令第一次绑定到元素时调用。在这里可以进行一次性的初始化设置。
    • inserted:被绑定元素插入父节点时调用 (仅保证父节点存在,但不一定已被插入文档中)。
    • update:所在组件的 VNode 更新时调用,但是可能发生在其子 VNode 更新之前。指令的值可能发生了改变,也可能没有。但是你可以通过比较更新前后的值来忽略不必要的模板更新 (详细的钩子函数参数见下)。
    • unbind:只调用一次,指令与元素解绑时调用。
  4. 钩子函数参数:

    • el:指令所绑定的元素,可以用来直接操作 DOM。
    • binding:一个对象,包含以下 property:
      • name:指令名,不包括 v- 前缀。
      • value:指令的绑定值,例如:v-my-directive="1 + 1" 中,绑定值为 2
      • oldValue:指令绑定的前一个值,仅在 updatecomponentUpdated 钩子中可用。无论值是否改变都可用。
      • expression:字符串形式的指令表达式。例如 v-my-directive="1 + 1" 中,表达式为 "1 + 1"
      • arg:传给指令的参数,可选。例如 v-my-directive:foo 中,参数为 "foo"
      • modifiers:一个包含修饰符的对象。例如:v-my-directive.foo.bar 中,修饰符对象为 { foo: true, bar: true }
    • vnode:Vue 编译生成的虚拟节点。移步 VNode API 来了解更多详情。
    • oldVnode:上一个虚拟节点,仅在 updatecomponentUpdated 钩子中可用。
  5. 实例:

    // <div id="hook-arguments-example" v-demo:foo.a.b="message"></div>
    Vue.directive('demo', {
      bind: function (el, binding, vnode) {
        var s = JSON.stringify
        el.innerHTML =
          'name: '       + s(binding.name) + '<br>' +
          'value: '      + s(binding.value) + '<br>' +
          'expression: ' + s(binding.expression) + '<br>' +
          'argument: '   + s(binding.arg) + '<br>' +
          'modifiers: '  + s(binding.modifiers) + '<br>' +
          'vnode keys: ' + Object.keys(vnode).join(', ')
      }
    })
    
    new Vue({
      el: '#hook-arguments-example',
      data: {
        message: 'hello!'
      }
    })
    

四、特殊的attribute

  1. **key:**key可以管理可复用的元素,减少不必要的元素的重新渲染,也要让必要的元素能够重新渲染。

  2. ref:ref 被用来给元素或子组件注册引用信息。引用信息将会注册在父组件的 $refs 对象上。如果在普通的 DOM 元素上使用,引用指向的就是 DOM 元素;如果用在子组件上,引用就指向组件实例;

  3. is: 用于动态组件且基于 DOM 内模板的限制来工作。

    <!-- 当 `currentView` 改变时,组件也跟着改变 -->
    <component v-bind:is="currentView"></component>
    
    <!-- 这样做是有必要的,因为 `<my-row>` 放在一个 -->
    <!-- `<table>` 内可能无效且被放置到外面 -->
    <table>
      <tr is="my-row"></tr>
    </table>
    

四、内置的组件

  1. component: 渲染一个“元组件”为动态组件。依 is 的值,来决定哪个组件被渲染。

    <!-- 动态组件由 vm 实例的 `componentId` property 控制 -->
    <component :is="componentId"></component>
    
    <!-- 也能够渲染注册过的组件或 prop 传入的组件 -->
    <component :is="$options.components.child"></component>
    
  2. transition: <transition> 元素作为单个元素/组件的过渡效果。<transition> 只会把过渡效果应用到其包裹的内容上,而不会额外渲染 DOM 元素,也不会出现在可被检查的组件层级中,如果有业务需求可以去详细了解,这里就不多做阐述。

  3. transition-group: <transition-group> 元素作为多个元素/组件的过渡效果。<transition-group> 渲染一个真实的 DOM 元素。默认渲染 <span>,可以通过 tag attribute 配置哪个元素应该被渲染。

  4. keep-alive: <keep-alive> 包裹动态组件时,会缓存不活动的组件实例,而不是销毁它们。和 <transition> 相似,<keep-alive> 是一个抽象组件:它自身不会渲染一个 DOM 元素,也不会出现在组件的父组件链中。当组件在 <keep-alive> 内被切换,它的 activateddeactivated 这两个生命周期钩子函数将会被对应执行。

    <!-- 基本 -->
    <keep-alive>
      <component :is="view"></component>
    </keep-alive>
    
    <!-- 多个条件判断的子组件 -->
    <keep-alive>
      <comp-a v-if="a > 1"></comp-a>
      <comp-b v-else></comp-b>
    </keep-alive>
    
    <!-- 和 `<transition>` 一起使用 -->
    <transition>
      <keep-alive>
        <component :is="view"></component>
      </keep-alive>
    </transition>
    
  5. slot: <slot> 元素作为组件模板之中的内容分发插槽。<slot> 元素自身将被替换。

    Vue.component('alert-box', {
      template: `
        <div class="demo-alert-box">
          <strong>Error!</strong>
          <slot></slot>
        </div>
      `
    })
    
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值