Vue学习笔记-Vue的指令

二、 指令


指令是 vue 为开发者提供的模板语法,用于辅助开发者渲染页面的基本结构。

vue 中的指令按照不同的用途可以分为如下 6 大类:

  1. 内容渲染指令

  2. 属性绑定指令

  3. 事件绑定指令

  4. 双向绑定指令

  5. 条件渲染指令

  6. 列表渲染指令

1. 内容渲染指令

v-text

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script src="./vue-2.6.12.js"></script>
</head>

<body>
    <div id="app">
        <p v-text="username"></p>
        <!-- v-text 会覆盖标签原有的值 -->
        <p v-text="gender">性别</p>
    </div>
    <script>
        const vm = new Vue({
      
      
            el: '#app',
            data: {
      
      
                username: '张三',
                gender: '男'
            }
        })
    </script>
</body>

</html>

image-20221123232736648

{ {}}

vue 提供的 { { }} 语法,专门用来解决 v-text 会覆盖默认文本内容的问题。这种 { { }} 语法的专业名称是插值表达式(英文名为:Mustache)

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script src="./vue-2.6.12.js"></script>
</head>

<body>
    <div id="app">
        <!-- <p v-text="username"></p> -->
        <!-- v-text 会覆盖标签原有的值 -->
        <!-- <p v-text="gender">性别</p> -->
        <!-- 插值表达式保留元素自带的内容 -->
        <p>姓名:{
   
   {username}}</p>
        <p>性别:{
   
   {gender}}</p>
    </div>
    <script>
        const vm = new Vue({
      
      
            el: '#app',
            data: {
      
      
                username: '张三',
                gender: '男'
            }
        })
    </script>
</body>

</html>

image-20221123233138230

v-html

如果要把包含 HTML 标签的字符串渲染为页面的 HTML 元素,则需要用到 v-html 这个指令

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script src="./vue-2.6.12.js"></script>
</head>

<body>
    <div id="app">
        <!-- <p v-text="username"></p> -->
        <!-- v-text 会覆盖标签原有的值 -->
        <!-- <p v-text="gender">性别</p> -->
        <!-- 插值表达式保留元素自带的内容 -->
        <p>姓名:{
   
   {username}}</p>
        <p>性别:{
   
   {gender}}</p>

        <p>---------------------</p>
        <p v-text="desc"></p>
        <p>{
   
   {desc}}</p>
        <p v-html="desc"></p>

    </div>
    <script>
        const vm = new Vue({
      
      
            el: '#app',
            data: {
      
      
                username: '张三',
                gender: '男',
                desc:'<h1>abc</h1>'
            }
        })
    </script>
</body>

</html>

2. 属性绑定指令

初始内容为:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script src="./vue-2.6.12.js"></script>
</head>
<body>
    <div id="app">
        <input type="text" placeholder="默认内容">

    </div>
    <script>
        const vm = new Vue({
      
      
            el:'#app',
            data:{
      
      
                inputValue:'请输入内容',
                imgSrc:'./images/girl.jpg'
            },
        })
    </script>
    
</body>
</html>

image-20221123234808954

现在想要将placeholder的属性进行动态绑定,就需要在这个属性的前面加上v-bind

v-bind可以简写为

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script src="./vue-2.6.12.js"></script>
</head>
<body>
    <div id="app">
        <input type="text" v-bind:placeholder="inputValue">
        <br>
        <br>
        <br>
        <!-- 下面对v-bind进行了简写  简写为  : -->
        <img :src="imgSrc" height="500px">

    </div>
    <script>
        const vm = new Vue({
      
      
            el:'#app',
            data:{
      
      
                inputValue:'请输入内容',
                imgSrc:'./images/girl.jpg'
            },
        })
    </script>
    
</body>
</html>

3. 使用JavaScript表达式

在 vue 提供的模板渲染语法中,除了支持绑定简单的数据值之外,还支持 Javascript 表达式的运算

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script src="./vue-2.6.12.js"></script>
</head>

<body>
    <div id="app">
        <!-- 数字算术运算 -->
        <p>{
   
   {number + 1}}</p>
        <!-- 布尔值的三元表达式 -->
        <p>{
   
   {ok ? '正确':'错误'}}</p>
        <!-- 字符串的反转操作 -->
        <p>{
   
   {message.split('').reverse().join('')}}</p>
        <!-- 属性值的字符串拼接操作 -->
        <p :id="'list - ' + id">xxx</p>
        <!-- 显示对象的内部属性值 -->
        <p>{
   
   {user.name}}</p>

    </div>
    <script>
        const vm = new Vue({
      
      
            el: '#app',
            data: {
      
      
                // 数值
                number: 99,
                // 布尔值
                ok: true,
                // 字符串
                message: 'ABC',
                // id值
                id: 3,
                // 用户的信息对象
                user: {
      
      
                    name: '张三',
                    age: 34,
                }

            },
        })
    </script>

</body>

</html>

4. 事件绑定指令

vue 提供了 v-on 事件绑定指令,用来辅助程序员为 DOM 元素绑定事件监听。

注意:原生 DOM 对象有 onclick、oninput、onkeyup 等原生事件,替换为 vue 的事件绑定形式后,分别为:v-on:click、v-on:input、v-on:keyup

通过 v-on 绑定的事件处理函数,需要在 methods 节点中进行声明

由于 v-on 指令在开发中使用频率非常高,因此提供了简写形式 @

语法格式为 v-on:事件名称=“时间处理函数的名称”。例如 v-on:click=“addCount”

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script src="./vue-2.6.12.js"></script>
</head>

<body>
    <div id="app">
        <h3>count 的值为:{
   
   {count}}</h3>
        <!-- 点击按钮,让data中的count值自增1 -->
        <button v-on:click="addCount">+1</button>
    </div>
    <script>
        const vm = new Vue({
      
      
            el: '#app',
            data: {
      
      
                // 计数器的值
                count: 0,
            },
            methods: {
      
      
                // 点击按钮,让count值自增1
                addCount() {
      
      //事件处理函数的名字
                    // this表示当前new出来的vm实例对象
                    // 通过this可以访问到data中的数据
                    this.count += 1
                },
            },
        })
    </script>

</body>

</html>

v-on还可以简写

<body>
    <div id="app">
        <h3>count 的值为:{
   
   {count}}</h3>
        <!-- 点击按钮,让data中的count值自增1 -->
        <button v-on:click="addCount">+1</button>
        <br>
        <!-- v-on 的简写形式 -->
        <button @click="addCount">+1</button>
        <br>

        <!-- 简写到行内 -->
        <button @click="count += 1">+1</button>
    </div>

事件对象event

在原生的 DOM 事件绑定中,可以在事件处理函数的形参处,接收事件对象 event。同理,在 v-on 指令(简写为 @ )所绑定的事件处理函数中,同样可以接收到事件对象 event。

以下的例子是接收事件对象的背景颜色,改变按钮的颜色

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script src="./vue-2.6.12.js"></script>
</head>

<body>
    <div id="app">
        <p>{
   
   {count}}</p>
        <button @click="addCount">+1</button>
    </div>
    <script>
        const vm = new Vue({
      
      
            el: '#app',
            data: {
      
      
                count: 0,
            },
            methods: {
      
      
                // 点击按钮,让count自增1
                addCount(e) {
      
      
                    // 获取当前时间对象的背景颜色
                    const nowBgColor = e.target.style.backgroundColor
                    e.target.style.backgroundColor = nowBgColor == 'red' ? '' : 'red'
                    console.log(nowBgColor)
                    this.count += 1
                },
            },
        })
    </script>

</body>

</html>

初始image-20221124111832532点击后image-20221124111853206

绑定事件并传参

在使用 v-on 指令绑定事件时,可以使用 ( ) 进行传参。当需要传值的时候就需要加上小括号,不需要传值的时候可以省略。

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script src="./vue-2.6.12.js"></script>
</head>

<body>
    <div id="app">
        <p>{
   
   {count}}</p>
        <button @click="addCount">+1</button>
        <button @click="addCount2(2)">+2</button>
    </div>
    <script>
        const vm = new Vue({
      
      
            el: '#app',
            data: {
      
      
                count: 0,
            },
            methods: {
      
      
                // 点击按钮,让count自增1
                addCount() {
      
      
                    this.count += 1
                },
                // 点击按钮,让count自增传过来的参数
                addCount2(step) {
      
      
                    this.count += step
                },
            },
        })
    </script>

</body>

</html>

image-20221124112708167

$event

如果想要在自增+2的同时还要改变按钮的背景颜色,这个时候需要既获取传的参数又要获取事件对象e。但是事件对象会被参数覆盖。

$event 是 vue 提供的特殊变量,用来表示原生的事件参数对象 event。可以解决事件参数对象 event 被覆盖的问题。

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script src="./vue-2.6.12.js"></script>
</head>

<body>
    <div id="app">
        <p>{
   
   {count}}</p>
        <button @click="addCount">+1</button>
        <button @click="addCount2(2,$event)">+2</button>
    </div>
    <script>
        const vm = new Vue({
      
      
            el: '#app',
            data: {
      
      
                count: 0,
            },
            methods: {
      
      
                // 点击按钮,让count自增1
                addCount() {
      
      
                    this.count += 1
                },
                // 点击按钮,让count自增传过来的参数
                addCount2(step,e) {
      
      
                    const bgColor = e.target.style.backgroundColor
                    e.target.style.backgroundColor = bgColor === 'red' ? '' : 'red'
                    this.count += step
                },
            },
        })
    </script>

</body>

</html>

事件修饰符

在事件处理函数中调用 preventDefault() 或 stopPropagation() 是非常常见的需求。因此,vue 提供了事件修饰符的概念,来辅助程序员更方便的对事件的触发进行控制。

事件修饰符 说明
.prevent 阻止默认行为(例如:阻止 a 连接的跳转、阻止表单的提交等)
.stop 阻止事件冒泡
.capture 以捕获模式触发当前的事件处理函数
.once 绑定的事件只触发1次
.self 只有在 event.target 是当前元素自身时触发事件处理函数

最初的代码以及实现的效果

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <style>
    .inner {
      
      
      line-height: 100px;
      background-color: aliceblue;
      font-size: 13px;
      text-align: center;
    }

    .outer {
      
      
      background-color: bisque;
      padding: 50px;
      font-size: 13px;
    }

    .box {
      
      
      background-color: coral;
      padding: 50px;
    }
  </style>
</head>

<body>
  <!-- 在页面中声明一个将要被 vue 所控制的 DOM 区域 -->
  <div id="app">
    <h4>① .prevent 事件修饰符的应用场景</h4>
    <a href="https://www.baidu.com" @click="onLinkClick">百度首页</a>

    <hr />

    <h4>② .stop 事件修饰符的应用场景</h4>
    <div class="outer" @click="onOuterClick">
      外层的 div
      <div class="inner" @click="onInnerClick">内部的 div</div>
    </div>

    <hr />

    <h4>③ .capture 事件修饰符的应用场景</h4>
    <div class="outer" @click="onOuterClick">
      外层的 div
      <div class="inner" @click="onInnerClick">内部的 div</div>
    </div>

    <hr />

    <h4>④ .once 事件修饰符的应用场景</h4>
    <div class="inner" @click="onInnerClick">内部的 div</div>

    <hr />

    <h4>⑤ .self 事件修饰符的应用场景</h4>
    <div class="box" @click="onBoxClick">
      最外层的 box
      <div class="outer" @click="onOuterClick">
        中间的 div
        <div class="inner" @click="onInnerClick">内部的 div</div>
      </div>
    </div>

    <hr />
  </div>

  <script src="./lib/vue-2.6.12.js"></script>
  <script>
    const vm = new Vue({
      
      
      el: '#app',
      // 声明处理函数的节点
      methods: {
      
      
        // 超链接的点击事件处理函数
        onLinkClick() {
      
      
          alert('ok')
        },
        // 点击了外层的 div
        onOuterClick() {
      
      
          console.log('触发了 outer 的 click 事件处理函数')
        },
        // 点击了内部的 div
        onInnerClick() {
      
      
          console.log('触发了 inner 的 click 事件处理函数')
        },
        onBoxClick() {
      
      
          console.log('触发了 box 的 click 事件处理函数')
        }
      },
    })
  </script>
</body>

</html>

① .prevent

初始页面是点击百度首页字符后跳转到百度的首页。

如果不想点击后就跳转到百度就需要使用 .prevent 事件修饰符

执行后的效果就是点击 百度首页 只会出现一个弹窗 ok

    <h4>① .prevent 事件修饰符的应用场景</h4>
    <!-- 修改前点击就可以跳转到百度 -->
    <!-- <a href="https://www.baidu.com" @click="onLinkClick">百度首页</a> -->
    <!-- 修改后 -->
    <a href="https://www.baidu.com" @click.prevent="onLinkClick">百度首页</a>

②.stop

事件冒泡就是指父元素和子元素有相同的事件,当触发子元素事件时,会向上冒泡,同时也会触发父元素事件.

源程序的效果是点击内部的盒子会在控制台显示“触发了 inner 的 click 事件处理函数”,随后出发外部盒子的函数,显示“触发了 outer 的 click 事件处理函数”。

如果不想出发外部盒子的函数(也就是不冒泡),可以使用.stop

        <h4>② .stop 事件修饰符的应用场景</h4>
        <div class="outer" @click="onOuterClick">
            外层的 div
            <!-- <div class="inner" @click="onInnerClick">内部的 div</div> -->
            <div class="inner" @click.stop="onInnerClick">内部的 div</div>
        </div>

初始效果

使用.stop后

③.capture

默认的触发方式是冒泡,想要改为捕获的方式触发就要使用.capture

使用后的效果就是点击内部,先触发的外部,然后触发的内部。

        <h4>③ .capture 事件修饰符的应用场景</h4>
        <div class="outer" @click="onOuterClick">
            外层的 div
            <!-- <div class="inner" @click="onInnerClick">内部的 div</div> -->
            <div class="inner" @click.capture="onInnerClick">内部的 div</div>
        </div>

在这里插入图片描述

④.once

事件触发的次数默认是不限制的,想要事件只触发一次,就可以使用.once

        <h4>④ .once 事件修饰符的应用场景</h4>
        <!-- <div class="inner" @click="onInnerClick">内部的 div</div> -->
        <div class="inner" @click.once="onInnerClick">内部的 div</div>

初始(点击了7次,就触发了7次)
]

使用.once后,点击7次,依旧只触发了1次

⑤.self

事件触发默认都是冒泡触发的,但是如果想让中间的事件只有在点击的时候才触发就需要使用.self

        <h4>⑤ .self 事件修饰符的应用场景</h4>
        <div class="box" @click="onBoxClick">
            最外层的 box
            <div class="outer" @click.self="onOuterClick">
                中间的 div
                <div class="inner" @click="onInnerClick">内部的 div</div>
            </div>
        </div>

初始

使用后

按键修饰符

在监听键盘事件时,我们经常需要判断详细的按键。此时,可以为键盘相关的事件添加按键修饰符。

以下例子为 监测键盘,按下回车在控制台打印出文本框内写入的值,按下esc清空文本框。

当然将‘enter’和‘esc’改为其他按键也可以,比如‘a’

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script src="./vue-2.6.12.js"></script>
</head>

<body>
    <div id="app">
        <input type="text" @keyup.enter="submit" @keyup.esc="clearInput">
    </div>
    <script>
        const vm = new Vue({
      
      
            el: '#app',
            data: {
      
      

            },
            methods: {
      
      
                submit(e) {
      
      
                    // 获取文本框最新的值
                    console.log('按下了 enter 键,最新的值为:' + e.target.value)
                },
                // 清空文本框的值
                clearInput(e) {
      
      
                    e.target.value = ''
                },
            },
        })
    </script>

</body>

</html>

5. 双向绑定指令

vue 提供了 v-model 双向数据绑定指令,用来辅助开发者在不操作 DOM 的前提下,快速获取表单的数据。

注意:v-model 指令只能配合表单元素一起使用!

初始效果

想要在文本框内也将名字渲染进去,再将省份的value值也同步上去,就需要使用双向绑定

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script src="./vue-2.6.12.js"></script>
</head>

<body>
    <div id="app">
        <p>用户名是:{
   
   {username}}</p>
        <input type="text" v-model="username">
        <hr>
        <p>选中的省份是:{
   
   {province}}</p>
        <select v-model="province">
            <option value="">请选择</option>
            <option value="1">北京</option>
            <option value="2">上海</option>
            <option value="3">河北</option>
        </select>
    </div>
    <script>
        const vm = new Vue({
      
      
            el: '#app',
            data: {
      
      
                // 姓名
                username: '张三',
                // 省份
                province: ''
            },
            methods: {
      
      

            },
        })
    </script>

</body>

</html>

v-model指令的修饰符

为了方便对用户输入的内容进行处理,vue 为 v-model 指令提供了 3 个修饰符

修饰符 作用 示例
.number 自动将用户的输入值转为数值类型

6. 条件渲染指令

条件渲染指令用来辅助开发者按需控制 DOM 的显示与隐藏。

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script src="./vue-2.6.12.js"></script>
</head>

<body>
    <div id="app">
        <button @click="flag =! flag">Toggle Flag</button>
        <p v-if="flag">请求成功 --- 被 v-if 控制</p>
        <p v-show="flag">请求成功 --- 被 v-show 控制</p>
    </div>
    <script>
        const vm = new Vue({
      
      
            el: '#app',
            data: {
      
      
                // flag用来控制元素的显示与隐藏
                // 值为true时显示元素
                // 值为false时隐藏元素
                flag: true,
            },
            methods: {
      
      

            },
        })
    </script>

</body>

</html>

在这里插入图片描述

v-if 和 v-show 的区别

实现原理不同:

⚫ v-if 指令会动态地创建或移除 DOM 元素,从而控制元素在页面上的显示与隐藏;

⚫ v-show 指令会动态为元素添加或移除 style=“display: none;” 样式,从而控制元素的显示与隐藏;

image-20221125161732819image-20221125161746652

性能消耗不同:

v-if 有更高的切换开销,而 v-show 有更高的初始渲染开销。

⚫ 如果需要非常频繁地切换,则使用 v-show 较好

⚫ 如果在运行时条件很少改变,则使用 v-if 较好

v-else

v-if 可以单独使用,或配合 v-else 指令一起使用

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script src="./vue-2.6.12.js"></script>
</head>

<body>
    <div id="app">
        <p v-if="type === 'A'">优秀</p>
        <p v-else-if="type === 'B'">良好</p>
        <p v-else-if="type === 'C'">合格</p>
        <p v-else></p>
    </div>
    <script>
        const vm = new Vue({
      
      
            el: '#app',
            data: {
      
      
                type: 'B'
            },
            methods: {
      
      

            },
        })
    </script>

</body>

</html>

在这里插入图片描述

7.列表渲染指令

vue 提供了 v-for 指令,用来辅助开发者基于一个数组来循环渲染相似的 UI 结构。

v-for 指令需要使用 item in items 的特殊语法,其中:

⚫ items 是待循环的数组

⚫ item 是当前的循环项

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script src="./vue-2.6.12.js"></script>
</head>

<body>
    <div id="app">
        <ul>
            <!-- user 是当前循环到的内容,list是被遍历的数组 -->
            <li v-for="user in list">姓名是:{
   
   {user.name}}</li>
        </ul>
    </div>
    <script>
        const vm = new Vue({
      
      
            el: '#app',
            data: {
      
      
                // 用户列表的数据
                list: [
                    {
      
       id: 1, name: '张三' },
                    {
      
       id: 2, name: '李四' },
                ],
            },
            methods: {
      
      

            },
        })
    </script>

</body>

</html>

image-20221125182216190

v-for 指令还支持一个可选的第二个参数,即当前项的索引。语法格式为 (item, index) in items。

注意:v-for 指令中的 item 项和 index 索引都是形参,可以根据需要进行重命名。例如 (user, i) in userlist

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script src="./vue-2.6.12.js"></script>
</head>

<body>
    <div id="app">
        <ul>
            <!-- user 是当前循环到的内容,list是被遍历的数组 -->
            <!-- i 是数组元素的索引 -->
            <li v-for="(user,i) in list">索引是:{
   
   {i}},姓名是:{
   
   {user.name}}</li>
        </ul>
    </div>
    <script>
        const vm = new Vue({
      
      
            el: '#app',
            data: {
      
      
                // 用户列表的数据
                list: [
                    {
      
       id: 1, name: '张三' },
                    {
      
       id: 2, name: '李四' },
                ],
            },
            methods: {
      
      

            },
        })
    </script>

</body>

</html>

image-20221125182957734

使用key维护列表的顺序

当列表的数据变化时,默认情况下,vue 会尽可能的复用已存在的 DOM 元素,从而提升渲染的性能。但这种默认的性能优化策略,会导致有状态的列表无法被正确更新。

为了给 vue 一个提示,以便它能跟踪每个节点的身份,从而在保证有状态的列表被正确更新的前提下,提升渲染的性能。此时,需要为每项提供一个唯一的 key 属性

比如:

现在选中了李四这个选项,然后添加王五

]]

点击添加后:

列表的顺序和选中的状态混乱

image-20221125185142244

解决方案

因为数组中每个user都有唯一的id作为区分,所以添加属性绑定,将id绑定进去方便区分每个user。

:key=“user.id”

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>

<body>
  <!-- 在页面中声明一个将要被 vue 所控制的 DOM 区域 -->
  <div id="app">

    <!-- 添加用户的区域 -->
    <div>
      <input type="text" v-model="name">
      <button @click="addNewUser">添加</button>
    </div>

    <!-- 用户列表区域 -->
    <ul>
      <li v-for="(user, index) in userlist" :key="user.id">
        <input type="checkbox" />
        姓名:{
   
   {user.name}}
      </li>
    </ul>
  </div>

  <script src="./vue-2.6.12.js"></script>
  <script>
    const vm = new Vue({
      
      
      el: '#app',
      data: {
      
      
        // 用户列表
        userlist: [
          {
      
       id: 1, name: '张三' },
          {
      
       id: 2, name: '李四' }
        ],
        // 输入的用户名
        name: '',
        // 下一个可用的 id 值
        nextId: 3
      },
      methods: {
      
      
        // 点击了添加按钮
        addNewUser() {
      
      
          this.userlist.unshift({
      
       id: this.nextId, name: this.name })
          this.name = ''
          this.nextId++
        }
      },
    })
  </script>
</body>

</html>

在这里插入图片描述

key的注意事项

① key 的值只能是字符串或数字类型

② key 的值必须具有唯一性(即:key 的值不能重复)

③ 建议把数据项 id 属性的值作为 key 的值(因为 id 属性的值具有唯一性)

④ 使用 index 的值当作 key 的值没有任何意义(因为 index 的值不具有唯一性)

⑤ 建议使用 v-for 指令时一定要指定 key 的值(既提升性能、又防止列表状态紊乱)

猜你喜欢

转载自blog.csdn.net/qq_45842943/article/details/128042672