「Vue学习记录四」指令全集

286 阅读7分钟

v-text

更新元素的 textContent,如果要更新部分的 textContent,需要使用 {{}} 插值

<span v-text="msg"></span>
<!-- 等价于 -->
<span>{{msg}}</span>

v-html

更新元素的 innerHTML

<div v-html="html"></div>

v-pre

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

<div id="app">
    <span v-pre>{{message}}</span>  //这条语句不进行编译
    <span>{{message}}</span>
</div>

v-cloak

使用v-cloak,再给定一个display:none,可以解决在 F12-Network-slow3G 下{{message}}出现闪烁的问题

<div id="app" v-cloak>
    <div>
        {{message}}
    </div>
</div>
<script type="text/javascript">
    new Vue({
      el:'#app',
      data:{
        message:'hello world'
      }
    })
</script>

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-if

v-if可以实现条件渲染,Vue 会根据表达式的值的真假条件来渲染元素。在切换时元素及它的数据绑定 / 组件被销毁并重建。

<a v-if="ok">yes</a>

如果属性值oktrue,则显示。否则,不会渲染这个元素。

v-else

v-else 是搭配 v-if 使用的,它必须紧跟在 v-if 或者 v-else-if 后面,否则不起作用。

<a v-if="ok">yes</a>
<a v-else>No</a>

v-else-if

v-else-if 充当 v-ifelse-if 块,可以链式的使用多次。可以更加方便的实现switch语句。

<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

用于根据条件展示元素。和v-if不同的是,如果v-if的值是false,则这个元素被销毁,不在 dom 中。但是v-show的元素会始终被渲染并保存在 dom 中,它只是简单的切换cssdispaly属性。

<h1 v-show="ok">hello world</h1>

提示:

v-if 有更高的切换开销

v-show 有更高的初始渲染开销。

因此,如果要非常频繁的切换,则使用v-show较好;如果在运行时条件不太可能改变,则v-if较好

v-for

用 v-for 指令根据遍历数组来进行渲染

<!-- 为当前遍历的元素提供别名:-->
<div v-for="item in items">
  {{ item.text }}
</div>

另外也可以为数组索引指定别名 (或者用于对象的键):

<div v-for="(item, index) in items"></div>
<div v-for="(val, key) in object"></div>
<div v-for="(val, name, index) in object"></div>

v-for 的默认行为会尝试原地修改元素而不是移动它们。要强制其重新排序元素,你需要用特殊 attribute key来提供一个排序提示:

<div v-for="item in items" :key="item.id">
  {{ item.text }}
</div>

在 v-for 中,拥有对父作用域属性的完全访问权限。

<ul id="app">
    <li v-for="item in items">
        {{parent}}-{{item.text}}
    </li>
</ul>
<script type="text/javascript">
    var example = new Vue({
      el:'#app',
      data:{
        parent:'父作用域'
        items:[
          {text:'文本1'},
          {text:'文本2'}
        ]
      }
    })
</script>


<!-- 被渲染为: -->

  <ul id="app">
    <li>父作用域-文本1</li>
    <li>父作用域-文本2</li>
</ul>

注意:

v-forv-if 同处于一个节点时,v-for的优先级比v-if更高。这意味着v-if将运行在每个v-for循环中

v-bind

v-bind用来动态的绑定一个或者多个特性。没有参数时,可以绑定到一个包含键值对的对象。常用于动态绑定classstyle。以及href等。 简写为一个冒号[ ]

<!-- 绑定一个 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 绑定 -->
<!--当data里面定义的 classB等于true时,isB这个类才会被添加起作用 -->
<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>

<!-- XLink -->
<svg><a :xlink:special="foo"></a></svg>

v-model

这个指令用于在表单上创建双向数据绑定。

  • <input>
  • <select>
  • <textarea>
  • components

v-model会忽略所有表单元素的valuecheckedselected特性的初始值。因为它选择 Vue 实例数据做为具体的值。

<div id="app">
    <input v-model="somebody">
    <p>hello {{somebody}}</p>
</div>
<script>
    var app = new Vue({
        el: '#app',
        data: {
            somebody:'小明'
        }
    })
</script>

直接在浏览器 input 中输入别的名字,下面的 p 的内容会直接跟着变。这就是双向数据绑定。

v-model 修饰符

  • lazy - 取代 input 监听 change 事件

默认情况下,v-model 同步输入框的值和数据。可以通过这个修饰符,转变为在 change 事件再同步

<input v-model.lazy="msg">
  • number - 输入字符串转为有效的数字
<input v-model.number="msg">
  • trim - 输入首尾空格过滤
<input v-model.trim="msg">

v-on

v-on主要用来监听 dom 事件,以便执行一些代码块。表达式可以是一个方法名。 简写为:【 @

<div id="app">
    <button @click="consoleLog"></button>
</div>
<script>
    var app = new Vue({
        el: '#app',
        methods:{
            consoleLog:function (event) {
                console.log(1)
            }
        }
    })
</script>

修饰符:

  • .stop - 调用 event.stopPropagation(),阻止事件继续传播。
  • .prevent - 调用 event.preventDefault(),事件不再重载页面。
  • .capture - 添加事件侦听器时使用 capture 模式,使用事件捕获模式,即元素自身触发的事件先在此处处理,然后才交由内部元素进行处理。
  • .self - 只当事件是从侦听器绑定的元素本身触发时才触发回调。
  • .{keyCode | keyAlias} - 只当事件是从特定键触发时才触发回调。
  • .native - 监听组件根元素的原生事件。
  • .once - 只触发一次回调。
  • .left - (2.2.0) 只当点击鼠标左键时触发。
  • .right - (2.2.0) 只当点击鼠标右键时触发。
  • .middle - (2.2.0) 只当点击鼠标中键时触发。
  • .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>

注意:

使用修饰符时,顺序很重要;相应的代码会以同样的顺序产生。因此,用v-on:click.prevent.self会阻止所有的点击,而v-on:click.self.prevent 只会阻止对元素自身的点击。

v-slot

v-slot插槽就是子组件中的提供给父组件使用的一个占位符,用<slot></slot> 表示,父组件可以在这个占位符中填充任何模板代码,如 HTML、组件等,填充的内容会替换子组件的<slot></slot>标签。

<!-- 在子组件中放一个占位符: -->

<template>
    <div>
       <h1>今天天气状况:</h1>
       <slot></slot>
   </div>
</template>
<script>
    export default {
        components: {
            Name:'child'
        },
    };
</script>

<!-- 在父组件中给这个占位符填充内容: -->

<template>
    <div>
        <div>使用slot分发内容</div>
        <div style="margin-top: 30pc;">
           <child>
               <div>多云,最高气温34C°,最低气温28C°,微风</div>
           </child>
        </div>
    </div>
</template>

1.具名插槽

描述:具名插槽其实就是给插槽娶个名字。一个子组件可以放多个插槽,而且可以放在不同的地方,而父组件填充内容时,可以根据这个名字把内容填充到对应插槽中。

子组件的代码,设置了两个插槽(header 和 footer):

<!--  子组件代码 -->

<template>
    <div>
        <div class="header">
            <h1>我是页头标题</h1>
            <div>
                <slot name="header"></slot>
            </div>
        </div>
        <div class="footer">
            <h1>我是页尾标题</h1>
            <div>
                <slot name="footer"></slot>
            </div>
        </div>
    </div>
</template>
<script>
    export default {
        components: {
            Name:'child'
        },
    };
</script>

父组件填充内容, 父组件通过 v-slot:[name]的方式指定到对应的插槽中, 父组件填充内容时,是可以根据对应名字把内容填充到对应插槽中的

<!--  父组件代码 -->
<template>
    <div>
        <div>使用slot分发内容</div>
        <child>
            <template v-slot:header>
                <div>我是页头的具体内容</div>
            </template>
            <template v-slot:footer>
                <div>我是页尾的具体内容</div>
            </template>
        </child>
    </div>
</template>

效果如下:

2.默认插槽

描述: 默认插槽就是指没有名字的插槽,子组件未定义的名字的插槽,父级将会把 未指定插槽的填充的内容填充到默认插槽中。

  • 子组件定义一个默认插槽
<template>
    <div>
        <div class="header">
            <h1>我是页头标题</h1>
            <div>
                <!-- 这里是页头的具体内容 -->
                <slot name="header"></slot>
            </div>
        </div>
        <div class="default">
            <h1>我是页头标题</h1>
            <div>
                <!-- 这里是默认插槽的具体内容 -->
                <slot></slot>
            </div>
        </div>
        <div class="footer">
            <h1>我是页尾标题</h1>
            <div>
                <!-- 这里是页尾的具体内容 -->
                <slot name="footer"></slot>
            </div>
        </div>
    </div>
</template>
  • 父组件给默认插槽填充内容:
<template>
    <div>
        <div>使用slot分发内容</div>
        <child>
            <template v-slot:header>
                <div>我是页头的具体内容</div>
            </template>
            <template v-slot:footer>
                <div>我是页尾的具体内容</div>
            </template>
            <template>
                <div>我是默认插槽的具体内容</div>
            </template>
        </child>
    </div>
</template>

效果如下:

注意:

  1. 父级的填充内容如果指定到子组件的没有对应名字插槽,那么该内容 不会 被填充到默认插槽中。

  2. 如果子组件没有默认插槽,而父级的填充内容指定到默认插槽中,那么该内容就 “不会” 填充到子组件的任何一个插槽中。

  3. 如果子组件有多个默认插槽,而父组件所有指定到默认插槽的填充内容,将 “会” “全都” 填充到子组件的每个默认插槽中。

3.作用域插槽

描述: 作用域插槽其实就是带数据的插槽,即带参数的插槽,简单的来说就是子组件提供给父组件的参数,该参数仅限于插槽中使用,父组件可根据子组件传过来的插槽数据来进行不同的方式展现和填充插槽内容。

应用场景: 如果子组件中的某一部分的数据,每个父组件都会有自己的一套对该数据的不同的呈现方式,这时就需要用到作用域插槽。

  • 子组件存放一个带数据的插槽: firstNamelastName是子组件传给父组件的参数
<template>
    <div>
        <slot name="header" :firstName="firstName" :lastName="lastName"></slot>
    </div>
</template>
  • 父组件通过 slot-scope 来接收子组件传过来的插槽数据,再根据插槽数据来填充插槽的内容
<div id="app">
  <!-- 老版本使用slot-scope具名插槽 -->
  <lv-hello>
    <p slot="header" slot-scope="hh">我是头部 {{ hh.firstName }} {{ hh.lastName }}</p>
  </lv-hello>
  <!-- 新版本使用具名插槽 -->
  <lv-hello>
    <!-- 注意:这块的 v-slot 指令只能写在 template 标签上面,而不能放置到 p 标签上 -->
    <template v-slot:header="hh">
      <p>我是头部 {{ hh.firstName }} {{ hh.lastName }}</p>
    </template>
  </lv-hello>
</div>

简写

v-onv-bind 一样,v-slot 也有缩写,即把参数之前的所有内容 (v-slot:) 替换为字符 #。例如 v-slot:header 可以被重写为 #header

<template v-slot:footer>
  <p>具名插槽 footer</p>
</template>
<!-- 等价于 -->
<template #footer>
  <p>具名插槽 footer</p>
</template>
...
...
<current-user #default="{ user }">
  {{ user.firstName }}
</current-user>