【快速入门Vue系列】第二篇:Vue常用指令,带你吃透

举报
前端老实人 发表于 2021/11/29 11:31:12 2021/11/29
【摘要】 Vue相关指令具有特殊含义、拥有特殊功能的特性指令带有v-前缀,表示它们是Vue提供的特殊特性指令可以直接使用data中的数据 v-pre跳过这个元素和它的子元素的编译过程。可以用来显示原始 Mustache 标签。跳过大量没有指令的节点会加快编译。 <!-- 不会被编译 --> <span v-pre>{{ msg }}</span> v-cloak这个指令保持在元素上直到关联实例结束编...

Vue相关指令

  • 具有特殊含义、拥有特殊功能的特性
  • 指令带有v-前缀,表示它们是Vue提供的特殊特性
  • 指令可以直接使用data中的数据

v-pre

  • 跳过这个元素和它的子元素的编译过程。可以用来显示原始 Mustache 标签。跳过大量没有指令的节点会加快编译。

     <!-- 不会被编译 --> 
    <span v-pre>{{ msg }}</span>
    

v-cloak

  • 这个指令保持在元素上直到关联实例结束编译

  • 可以解决闪烁的问题

  • 和 CSS 规则如 [v-cloak] { display: none } 一起用时,这个指令可以隐藏未编译的 Mustache 标签直到实例准备完毕

    [v-cloak] {
      display: none;
    }
    
     <!-- {{ message }}不会显示,直到编译结束 --> 
    <div v-cloak>
      {{ message }}
    </div>
    

v-once

  • 只渲染元素一次。随后的重新渲染,元素及其所有的子节点将被视为静态内容并跳过。这可以用于优化更新性能

     <!-- 单个元素 --> 
    <span v-once>{{msg}}</span>
     <!-- 有子元素 --> 
    <div v-once>
      <h1>comment</h1>
      <p>{{msg}}</p>
    </div>
    

v-text

  • 更新元素的 textContent

    <span v-text="msg"></span>
     <!-- 和下面的一样 --> 
    <span>{{msg}}</span>
    

v-text VS Mustache

  • v-text替换元素中所有的文本,Mustache只替换自己,不清空元素内容

     <!-- 渲染为:<span>杉杉最美</span> --> 
    <span v-text="msg">----</span>
     <!-- 渲染为:<span>----杉杉最美----</span> --> 
    <span>----{{msg}}----</span>
    
  • v-text 优先级高于 {{ }}

textContent VS innerText

  1. 设置文本替换时,两者都会把指定节点下的所有子节点也一并替换掉。
  2. textContent 会获取所有元素的内容,包括 <script> 和 <style>元素,然而 innerText 不会。
  3. innerText 受 CSS 样式的影响,并且不会返回隐藏元素的文本,而textContent会。
  4. 由于 innerText 受 CSS 样式的影响,它会触发重排(reflow),但textContent 不会。
  5. innerText 不是标准制定出来的 api,而是IE引入的,所以对IE支持更友好。textContent虽然作为标准方法但是只支持IE8+以上的浏览器,在最新的浏览器中,两个都可以使用。
  6. 综上,Vue这里使用textContent是从性能的角度考虑的。

测试一下innerText & textContent两者性能

<ul class="list">
  <li>1</li>
   <!-- 此处省略998--> 
  <li>1000</li>
</ul>
const oList = document.getElementById("list");

console.time("innerText");
for(let i = 0; i < oList.childElementCount; i++){
  ul.children[i].innerText="innerText";
}
console.timeEnd("innerText");

console.time("textContent");
for(let i = 0; i < oList.childElementCount; i++){
  ul.children[i].textContent="innerText";
}
console.timeEnd("textContent");

v-html

  • 更新元素的innerHTML

  • 注意:内容按普通 HTML 插入,不会作为 Vue 模板进行编译

  • 在网站上动态渲染任意 HTML 是非常危险的,因为容易导致 XSS 攻击。只在可信内容上使用 v-html,永不用在用户提交的内容上。

    <input type="text" />
    <button>点击</button>
    <div id="app">
      <div v-html="msg"></div>
    </div>
    
    const vm = new Vue({
      el: '#app',
      data: {
        msg: 'hello world'
      }
    })
    
    const oInput = document.getElementsByTagName('input')[0];
    const oButton = document.getElementsByTagName('button')[0];
    let msg = null;
    oButton.onclick = function () {
      vm.msg = oInput.value;
    }
    

条件渲染

v-if

  • 用于条件性地渲染一块内容。这块内容只会在指令的表达式返回 truthy 值的时候被渲染。

切换多个元素

  • 因为 v-if 是一个指令,所以必须将它添加到一个元素上,但是如果想切换多个元素呢?此时可以把一个 <template> 元素当做不可见的包裹元素,并在上面使用 v-if。最终的渲染结果将不包含 <template> 元素

    <template v-if="ok">
      <h1>Title</h1>
      <p>Paragraph 1</p>
      <p>Paragraph 2</p>
    </template>
    

v-else

  • 为 v-if 或者 v-else-if 添加“else 块”。

  • 注意:前一兄弟元素必须有 v-if 或 v-else-if

    <div v-if="Math.random() > 0.5">
      杉杉
    </div>
    <div v-else>
      你看不见杉杉啦
    </div>
    

v-else-if

  • 表示 v-if 的 “else if 块”。可以链式调用。

  • 注意:前一兄弟元素必须有 v-if 或 v-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>
    <div v-else>
      Not A/B/C
    </div>
    

v-show

  • 根据表达式之真假值,切换元素的 display CSS 属性。

    <h1 v-show="ok">Hello!</h1>
    

v-if VS v-show

  1. v-if 是惰性的,如果在初始渲染时条件为假,则什么也不做,直到条件第一次变为真时,才会开始渲染条件块。v-show则不管初始条件是什么,元素总是会被渲染,并且只是简单地基于 CSS 进行切换。
  2. v-if 有更高的切换开销,v-show 有更高的初始渲染开销,如果需要非常频繁地切换,则使用 v-show 较好,如果在运行时条件很少改变,则使用 v-if 较好
  3. v-show不支持<template>元素
  4. v-show不支持v-else/v-else-if

v-bind 指令

  • 动态地绑定一个或多个特性

  • :后的为传递的参数

     <!-- 绑定一个属性 --> 
    <img v-bind:src="imageSrc">
    
     <!-- 动态特性名 (2.6.0+) --> 
    <button v-bind:[key]="value"></button>
    
     <!-- 缩写 --> 
    <img :src="imageSrc">
    
     <!-- 动态特性名缩写 (2.6.0+) --> 
    <button :[key]="value"></button>
    
     <!-- 内联字符串拼接 --> 
    <img :src="'/path/to/images/' + fileName">
    
  • 没有参数时,可以绑定到一个包含键值对的对象。注意此时 class 和 style 绑定不支持数组和对象。

     <!-- 绑定一个有属性的对象 --> 
    <div v-bind="{ id: someProp, 'other-attr': otherProp }"></div>
    
  • 由于字符串拼接麻烦且易错,所以在绑定 class 或 style 特性时,Vue做了增强,表达式的类型除了字符串之外,还可以是数组或对象。

    • 绑定class

      • 对象语法

        <div v-bind:class="{ red: isRed }"></div>
        

        上面的语法表示 active 这个 class 存在与否将取决于数据属性 isActive 的 真假。

      • 数组语法 我们可以把一个数组传给 v-bind:class,以应用一个 class 列表

        <div v-bind:class="[classA, classB]"></div>
        
      • 在数组语法总可以使用三元表达式来切换class

        <div v-bind:class="[isActive ? activeClass : '', errorClass]"></div>
        
      • 在数组语法中可以使用对象语法

          <div v-bind:class="[classA, { classB: isB, classC: isC }]">
          <div v-bind:class="classA" class="red">
        
      • v-bind:class 可以与普通 class 共存

          <div v-bind:class="classA" class="red">
        
    • 绑定style

      • 使用对象语法 看着比较像CSS,但其实是一个JavaScript对象 CSS属性名可以用驼峰式(camelCase)或者短横线分隔(kebab-case)来命名 但是使用短横线分隔时,要用引号括起来

        <div v-bind:style="{ fontSize: size + 'px' }"></div>
        
        data: {
          size: 30
        }
        

        也可以直接绑定一个样式对象,这样模板会更清晰:

        <div v-bind:style="styleObject"></div>
        
        data: {
          styleObject: {
            fontSize: '13px'
          }
        }
        
      • 使用数组语法 数组语法可以将多个样式对象应用到同一个元素

        <div v-bind:style="[styleObjectA, styleObjectB]"></div>
        
      • 自动添加前缀 绑定style时,使用需要添加浏览器引擎前缀的CSS属性时,如 transform,Vue.js会自动侦测并添加相应的前缀。

      • 多重值 从 2.3.0 起你可以为 style 绑定中的属性提供一个包含多个值的数组,常用于提供多个带前缀的值:

        <div v-bind:style="{ display: ['-webkit-box', '-ms-flexbox', 'flex'] }"></div>
        

        这样写只会渲染数组中最后一个被浏览器支持的值。在本例中,如果浏览器支持不带浏览器前缀的 flexbox,那么就只会渲染 display: flex。

  • 缩写: :

  • 修饰符: 修饰符 (modifier) 是以英文句号 . 指明的特殊后缀,用于指出一个指令应该以特殊方式绑定。

    • .camel 由于绑定特性时,会将大写字母转换为小写字母,如:

       <!-- 最终渲染的结果为:<svg viewbox="0 0 100 100"></svg> --> 
      <svg :viewBox="viewBox"></svg>
      

      所以,Vue提供了v-bind修饰符 camel,该修饰符允许在使用 DOM 模板时将 v-bind 属性名称驼峰化,例如 SVG 的 viewBox 属性

      <svg :view-box.camel="viewBox"></svg>
      
    • .prop 被用于绑定 DOM 属性 (property)

      <div v-bind:text-content.prop="text"></div>
      
    • .sync 讲解组件时再说

v-on指令

  • v-on 指令可以监听 DOM 事件,并在触发时运行一些 JavaScript 代码

  • 事件类型由参数指定

    <div id="app">
      <button v-on:click="counter += 1">点击加 1</button>
      <p>按钮被点击了 {{ counter }}</p>
    </div>
    
    const vm = new Vue({
      el: 'app',
      data: {
        counter: 0
      }
    })
    
  • 但是很多事件处理逻辑是非常复杂的,所以直接把 JavaScript 代码写在 v-on 指令中是不可行的。所以 v-on 还可以接收一个需要调用的方法名称。

    <div id="app">
       <!-- `addCounter` 是在下面定义的方法名 --> 
      <button v-on:click="addCounter">点击加 1</button>
      <p>按钮被点击了 {{ counter }}</p>
    </div>
    
    const vm = new Vue({
      el: '#app',
      data: {
        counter: 0
      },
       // 在 methods 对象中定义方法
      methods: {
        addCounter: function (e) {
           // this 在方法里指向当前 Vue 实例
          this.counter += 1// e 是原生 DOM 事件
          cosnole.log(e.target)}
      }
    })
    
  • methods中的函数,也会直接代理给Vue实例对象,所以可以直接运行:

      vm.addCounter();
    
  • 除了直接绑定到一个方法,也可以在内联JavaScript 语句中调用方法:

    <div id="app">
      <button v-on:click="addCounter(5)">点击加 5</button>
      <p>按钮被点击了 {{ counter }}</p>
    </div>
    
    new Vue({
      el: '#app',
      data: {
        counter: 0
      },
      methods: {
        addCounter: function (num) {
          this.counter += 5;
        }
      }
    })
    
  • 在内联语句中使用事件对象时,可以利用特殊变量 $event:

    <div id="app">
     <button v-on:click="addCounter(5, $event)">点击加 5</button>
     <p>按钮被点击了 {{ counter }}</p>
    </div>
    
    new Vue({
      el: '#app',
      methods: {
        addCounter: function (num, e) {
          this.counter += 5;
          cosnole.log(e.target)}
      }
    })
    
  • 可以绑定动态事件,Vue版本需要2.6.0+

    <div v-on:[event]="handleClick">点击,弹出1</div>  
    
    const vm = new Vue({
      el: '#app',
      data: {
        event: 'click'
      },
      methods: {
        handleClick () {
          alert(1);
        }
      }
    })
    
  • 可以不带参数绑定一个对象,Vue版本需要2.4.0+。

    • { 事件名:事件执行函数 }
    • 使用此种方法不支持函数传参&修饰符
    <div v-on="{ mousedown: doThis, mouseup: doThat }"></div>
    
  • v-on指令简写:@

为什么在 HTML 中监听事件?

  1. 扫一眼 HTML 模板便能轻松定位在 JavaScript 代码里对应的方法。
  2. 因为你无须在 JavaScript 里手动绑定事件,你的 ViewModel 代码可以是非常纯粹的逻辑,和 DOM 完全解耦,更易于测试
  3. 当一个 ViewModel 被销毁时,所有的事件处理器都被删除。你无须担心如何清理它们

最后

如果对您有帮助,希望能给个👍评论收藏三连!

博主为人老实,无偿解答问题哦❤

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。