程序员scholar 程序员scholar
首页
  • Java 基础

    • JavaSE
    • JavaIO
    • JavaAPI速查
  • Java 高级

    • JUC
    • JVM
    • Java新特性
    • 设计模式
  • Web 开发

    • Servlet
    • Java网络编程
  • Web 标准

    • HTML
    • CSS
    • JavaScript
  • 前端框架

    • Vue2
    • Vue3
    • Vue3 + TS
    • 微信小程序
    • uni-app
  • 工具与库

    • jQuery
    • Ajax
    • Axios
    • Webpack
    • Vuex
    • WebSocket
    • 第三方登录
  • 后端与语言扩展

    • ES6
    • Typescript
    • node.js
  • Element-UI
  • Apache ECharts
  • 数据结构
  • HTTP协议
  • HTTPS协议
  • 计算机网络
  • Linux常用命令
  • Windows常用命令
  • SQL数据库

    • MySQL
    • MySQL速查
  • NoSQL数据库

    • Redis
    • ElasticSearch
  • 数据库

    • MyBatis
    • MyBatis-Plus
  • 消息中间件

    • RabbitMQ
  • 服务器

    • Nginx
  • Spring框架

    • Spring6
    • SpringMVC
    • SpringBoot
    • SpringSecurity
  • SpringCould微服务

    • SpringCloud基础
    • 微服务之DDD架构思想
  • 日常必备

    • 开发常用工具包
    • Hutoll工具包
    • IDEA常用配置
    • 开发笔记
    • 日常记录
    • 项目部署
    • 网站导航
    • 产品学习
    • 英语学习
  • 代码管理

    • Maven
    • Git教程
    • Git小乌龟教程
  • 运维工具

    • Docker
    • Jenkins
    • Kubernetes
  • 算法笔记

    • 算法思想
    • 刷题笔记
  • 面试问题常见

    • 十大经典排序算法
    • 面试常见问题集锦
关于
GitHub (opens new window)
首页
  • Java 基础

    • JavaSE
    • JavaIO
    • JavaAPI速查
  • Java 高级

    • JUC
    • JVM
    • Java新特性
    • 设计模式
  • Web 开发

    • Servlet
    • Java网络编程
  • Web 标准

    • HTML
    • CSS
    • JavaScript
  • 前端框架

    • Vue2
    • Vue3
    • Vue3 + TS
    • 微信小程序
    • uni-app
  • 工具与库

    • jQuery
    • Ajax
    • Axios
    • Webpack
    • Vuex
    • WebSocket
    • 第三方登录
  • 后端与语言扩展

    • ES6
    • Typescript
    • node.js
  • Element-UI
  • Apache ECharts
  • 数据结构
  • HTTP协议
  • HTTPS协议
  • 计算机网络
  • Linux常用命令
  • Windows常用命令
  • SQL数据库

    • MySQL
    • MySQL速查
  • NoSQL数据库

    • Redis
    • ElasticSearch
  • 数据库

    • MyBatis
    • MyBatis-Plus
  • 消息中间件

    • RabbitMQ
  • 服务器

    • Nginx
  • Spring框架

    • Spring6
    • SpringMVC
    • SpringBoot
    • SpringSecurity
  • SpringCould微服务

    • SpringCloud基础
    • 微服务之DDD架构思想
  • 日常必备

    • 开发常用工具包
    • Hutoll工具包
    • IDEA常用配置
    • 开发笔记
    • 日常记录
    • 项目部署
    • 网站导航
    • 产品学习
    • 英语学习
  • 代码管理

    • Maven
    • Git教程
    • Git小乌龟教程
  • 运维工具

    • Docker
    • Jenkins
    • Kubernetes
  • 算法笔记

    • 算法思想
    • 刷题笔记
  • 面试问题常见

    • 十大经典排序算法
    • 面试常见问题集锦
关于
GitHub (opens new window)
npm

(进入注册为作者充电)

  • Vue2

    • Vue简介
    • Vue 基础使用
    • Vue的基础指令
      • 1. 指令的概念
      • 2. 内容渲染指令
        • 2-1. v-text 指令
        • 2-2. 插值表达式 {{ }}
        • 2-3. v-html 指令
      • 3. 属性绑定指令 (v-bind)
        • 3-1 基本用法
        • 3-2 属性绑定指令的简写形式
        • 3-3 使用 JavaScript 表达式
        • 3-4 动态拼接属性值
        • 3-5 动态绑定css样式
        • 1. 动态绑定 class
        • 2. 三目运算符动态绑定 class
        • 3. 动态绑定 style
      • 4. 事件绑定指令 (v-on)
        • 4-1 基本用法
        • 4-2 事件绑定的简写形式
        • 4-3 事件参数对象
        • 4-4 绑定事件并传参
        • 4.5 $event
        • 4-6 事件修饰符
        • 4-7 按键修饰符
        • 4-8 常用按键修饰符
        • 4-9 .native修饰符
      • 5. 双向绑定指令 (v-model)
        • 5-1 基本用法
        • 5-2 收集表单数据
        • 1. 文本输入框
        • 2. 单选框(radio)
        • 3. 复选框(checkbox)
        • 4. 复选框的最佳实践
        • 5-3 v-model 表单示例
        • 5-4 v-model 指令的修饰符
        • .lazy 修饰符
        • .number 修饰符
        • .trim 修饰符
      • 6. 条件渲染指令
        • 6-1 v-if 指令
        • 6-2 v-show 指令
        • 6-3 v-if 和 v-show 的区别
        • 6-4 v-else 指令
        • 6-5 v-else-if 指令
      • 7. 列表渲染指令 (v-for)
        • 7-1 v-for 的基本用法
        • 1. 遍历数组
        • 2. 遍历对象
        • 3. 遍历数组中的对象
        • 4. 商品列表网页布局
        • 7-2 v-for 中的索引
        • 7-3 使用 key 维护列表的状态
        • 7-4 key 的注意事项
        • 7-5 表格添加删除示例
        • 1. 效果演示
        • 2. 代码分析
    • 过滤器(Filters)
    • 侦听器(Watch)
    • 计算属性(computed)
    • vue-cli
    • vue.config.js配置
    • Vue组件
    • 生命周期和数据共享
    • Vue 组件实例与数据代理 (this)
    • $refs 引用
    • 动态组件
    • 插槽 (Slots)
    • 混入 (Mixin)
    • 自定义指令 (directives)
    • 插件 (Plugins)
    • 初识Vue-router
    • Vue-router的常见用法
  • Vue3

  • vue3 + TS 项目集成

  • Vue全家桶
  • Vue2
scholar
2024-07-29
目录

Vue的基础指令

# Vue的基础指令

# 1. 指令的概念

指令(Directives)是 Vue 为开发者提供的模板语法,用于辅助开发者渲染页面的基本结构。Vue 中的指令按照不同的用途可以分为如下 6 大类:

  1. 内容渲染指令
  2. 属性绑定指令
  3. 事件绑定指令
  4. 双向绑定指令
  5. 条件渲染指令
  6. 列表渲染指令

指令是 Vue 开发中最基础、最常用、最简单的知识点,通过使用指令,开发者可以更加方便地操作 DOM 元素,实现动态数据绑定和交互。

# 2. 内容渲染指令

内容渲染指令用来辅助开发者渲染 DOM 元素的文本内容。常用的内容渲染指令有如下 3 个:

  1. v-text:用于更新元素的文本内容,会覆盖元素内默认的值。
  2. 插值表达式 :用于将变量绑定到元素的文本内容中,不会覆盖元素内默认的值。
  3. v-html:用于将包含 HTML 标签的字符串渲染为页面的 HTML 元素。

# 2-1. v-text 指令

v-text 指令用于更新元素的文本内容,会覆盖元素内默认的值。

示例:








 
 
 
 




 
 
 





<!DOCTYPE html>
<html>
<head>
  <title>v-text 示例</title>
  <script src="https://cdn.jsdelivr.net/npm/vue@2"></script>
</head>
<body>
  <div id="app">
    <!-- 使用 v-text 指令来渲染文本内容 -->
    <p v-text="message">原始内容</p> <!-- 这里的 v-text 会替换原始内容 -->
  </div>

  <script>
    new Vue({
      el: '#app', // Vue 实例挂载的元素
      data: {
        message: '这是使用 v-text 指令渲染的内容' // 绑定的数据
      }
    });
  </script>
</body>
</html>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

在上述示例中,v-text 指令会将 message 数据的值渲染到 <p> 元素中,并覆盖该元素的原始内容。

# 2-2. 插值表达式

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

示例:








 
 
 
 




 
 
 





<!DOCTYPE html>
<html>
<head>
  <title>插值表达式示例</title>
  <script src="https://cdn.jsdelivr.net/npm/vue@2"></script>
</head>
<body>
  <div id="app">
    <!-- 使用插值表达式来渲染文本内容 -->
    <p>{{ message }} 原始内容</p> <!-- 这里的 {{ }} 不会替换原始内容 -->
  </div>

  <script>
    new Vue({
      el: '#app', // Vue 实例挂载的元素
      data: {
        message: '这是使用插值表达式渲染的内容' // 绑定的数据
      }
    });
  </script>
</body>
</html>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

在上述示例中,插值表达式 会将 message 数据的值渲染到 <p> 元素中,并保留该元素的原始内容。

# 2-3. v-html 指令

v-text 指令和插值表达式只能渲染纯文本内容。如果要把包含 HTML 标签的字符串渲染为页面的 HTML 元素,则需要用到 v-html 这个指令。

示例:








 
 
 
 




 
 
 





<!DOCTYPE html>
<html>
<head>
  <title>v-html 示例</title>
  <script src="https://cdn.jsdelivr.net/npm/vue@2"></script>
</head>
<body>
  <div id="app">
    <!-- 使用 v-html 指令来渲染包含 HTML 标签的内容 -->
    <p v-html="htmlContent"></p> <!-- 这里的 v-html 会将 HTML 字符串渲染为真正的 HTML 元素 -->
  </div>

  <script>
    new Vue({
      el: '#app', // Vue 实例挂载的元素
      data: {
        htmlContent: '<strong>这是加粗的内容</strong>' // 绑定的数据,包含 HTML 标签
      }
    });
  </script>
</body>
</html>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

在上述示例中,v-html 指令会将包含 HTML 标签的字符串 htmlContent 渲染为真正的 HTML 元素。

# 3. 属性绑定指令 (v-bind)

Vue 提供了 v-bind 指令,用于动态绑定 HTML 元素的属性。通过 v-bind,可以将数据中的值绑定到元素的属性上,实现动态更新。

# 3-1 基本用法

使用 v-bind 指令,可以为元素的属性动态绑定属性值。

示例:








 
 
 
 




 
 
 
 





<!DOCTYPE html>
<html>
<head>
  <title>属性绑定指令示例</title>
  <script src="https://cdn.jsdelivr.net/npm/vue@2"></script>
</head>
<body>
  <div id="app">
    <!-- 使用 v-bind 指令动态绑定属性 -->
    <img v-bind:src="imageSrc" v-bind:alt="imageAlt">
  </div>

  <script>
    new Vue({
      el: '#app', // Vue 实例挂载的元素
      data: {
        imageSrc: 'https://example.com/image.jpg', // 动态绑定的图片路径
        imageAlt: '示例图片' // 动态绑定的图片描述
      }
    });
  </script>
</body>
</html>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

在上述示例中,v-bind:src 将 imageSrc 数据的值绑定到 <img> 元素的 src 属性上,而 v-bind:alt 将 imageAlt 数据的值绑定到 <img> 元素的 alt 属性上。

# 3-2 属性绑定指令的简写形式

由于 v-bind 指令在开发中使用频率非常高,Vue 官方为其提供了简写形式,即可以使用冒号 : 代替 v-bind:。

示例:








 
 
 
 




 
 
 
 





<!DOCTYPE html>
<html>
<head>
  <title>属性绑定指令简写形式示例</title>
  <script src="https://cdn.jsdelivr.net/npm/vue@2"></script>
</head>
<body>
  <div id="app">
    <!-- 使用 v-bind 指令的简写形式 -->
    <img :src="imageSrc" :alt="imageAlt">
  </div>

  <script>
    new Vue({
      el: '#app', // Vue 实例挂载的元素
      data: {
        imageSrc: 'https://example.com/image.jpg', // 动态绑定的图片路径
        imageAlt: '示例图片' // 动态绑定的图片描述
      }
    });
  </script>
</body>
</html>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

在上述示例中,使用了 : 代替 v-bind:,简化了代码。

# 3-3 使用 JavaScript 表达式

在 Vue 提供的模板渲染语法中,除了支持绑定简单的数据值外,还支持使用 JavaScript 表达式进行运算,从而动态生成属性值。吗

示例:








 
 
 
 




 
 
 





<!DOCTYPE html>
<html>
<head>
  <title>使用 JavaScript 表达式示例</title>
  <script src="https://cdn.jsdelivr.net/npm/vue@2"></script>
</head>
<body>
  <div id="app">
    <!-- 使用 v-bind 指令绑定 JavaScript 表达式 -->
    <p :title="'当前时间是:' + currentTime">鼠标悬停查看当前时间</p>
  </div>

  <script>
    new Vue({
      el: '#app', // Vue 实例挂载的元素
      data: {
        currentTime: new Date().toLocaleString() // 动态生成的当前时间字符串
      }
    });
  </script>
</body>
</html>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

在上述示例中,使用了 JavaScript 表达式 '当前时间是:' + currentTime 来动态生成 title 属性的值,实现了更加灵活的属性绑定。

# 3-4 动态拼接属性值

在使用 v-bind 属性绑定期间,如果绑定的内容需要进行动态拼接,则字符串的外面应该包裹单引号。例如:




 







 





<!-- 动态拼接属性值 -->
<template>
  <div>
    <img :src="'/images/' + imageName + '.jpg'" alt="动态图片">
  </div>
</template>

<script>
export default {
  data() {
    return {
      imageName: 'example'
    };
  }
};
</script>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

在这个示例中,通过 v-bind 绑定动态拼接的 src 属性值,使其根据 imageName 动态生成图片路径。

注意事项

v-bind 属性绑定的内容里面如果没有加单引号,那么这些参数都会去data里面去找,没有就会报错。

# 3-5 动态绑定css样式

在 Vue 2 中,动态绑定 CSS 样式的写法通常有两种方式:通过动态绑定 class 和动态绑定 style。

# 1. 动态绑定 class

当你需要根据条件动态地应用一个或多个 CSS 类时,可以使用 :class 动态绑定。以下是一个示例:

<template>
  <div :class="{'active': isActive, 'hidden': !isActive}">
    这是一个带有动态 class 的 div
  </div>
</template>

<script>
export default {
  data() {
    return {
      isActive: true // 控制是否应用 class
    };
  }
};
</script>

<style>
.active {
  color: red;
}

.hidden {
  display: none;
}
</style>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25

在这个示例中,:class 根据 isActive 的值来动态应用 active 和 hidden 类。当 isActive 为 true 时,div 将有 active 类并显示红色;当 isActive 为 false 时,div 将应用 hidden 类并被隐藏。

# 2. 三目运算符动态绑定 class

在 Vue 中你也可以使用三目运算符来动态绑定 class,效果是相同的。用三目运算符会让语法更加简洁,尤其是在你只需要根据条件应用单个类时非常方便。

<template>
  <div :class="isActive ? 'active' : 'hidden'">
    这是一个带有动态 class 的 div
  </div>
</template>

<script>
export default {
  data() {
    return {
      isActive: true // 控制是否应用 class
    };
  }
};
</script>

<style>
.active {
  color: red;
}

.hidden {
  display: none;
}
</style>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
  • 如果 isActive 为 true,div 将使用 active 类。
  • 如果 isActive 为 false,div 将使用 hidden 类。

这种方式更为简洁,尤其是在只有两个条件时使用三目运算符是非常合适的。如果有更多的条件或更复杂的逻辑,你可能还是希望用对象语法来绑定 class,这样会更具可读性。

# 3. 动态绑定 style

如果你想根据某个条件来动态设置内联样式,可以使用 :style 绑定一个对象。下面是一个示例:

<template>
  <div :style="divStyle">
    这是一个带有动态样式的 div
  </div>
</template>

<script>
export default {
  data() {
    return {
      isRed: true // 控制颜色
    };
  },
  computed: {
    divStyle() {
      return {
        color: this.isRed ? 'red' : 'blue',
        fontSize: '20px'
      };
    }
  }
};
</script>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

在这个示例中,:style 绑定了一个对象,div 的颜色将根据 isRed 的值在红色和蓝色之间切换。

# 4. 事件绑定指令 (v-on)

Vue 提供了 v-on 事件绑定指令,用于为 DOM 元素绑定事件监听器。使用 v-on 指令,可以轻松地为元素添加各种事件监听,如 click、input、keyup 等。

# 4-1 基本用法

在 Vue 中,可以使用 v-on 指令绑定事件监听器。语法格式如下:



 







 






<!-- 基本语法:v-on:eventName="handlerFunction" -->
<div id="app">
  <button v-on:click="handleClick">点击我</button>
</div>

<script>
  new Vue({
    el: '#app', // Vue 实例挂载的元素
    methods: {
      // 声明事件处理函数
      handleClick() {
        alert('按钮被点击了!');
      }
    }
  });
</script>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

在上述示例中,通过 v-on:click 为按钮绑定了 click 事件,当按钮被点击时,会执行 handleClick 方法。

提示

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

# 4-2 事件绑定的简写形式

由于 v-on 指令在开发中使用频率非常高,Vue 官方为其提供了简写形式,使用 @ 代替 v-on:。



 














<!-- 使用 @ 代替 v-on: -->
<div id="app">
  <button @click="handleClick">点击我</button>
</div>

<script>
  new Vue({
    el: '#app', // Vue 实例挂载的元素
    methods: {
      // 声明事件处理函数
      handleClick() {
        alert('按钮被点击了!');
      }
    }
  });
</script>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

上述代码中,使用了 @click 代替 v-on:click,简化了代码。

# 4-3 事件参数对象

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


 







 
 
 
 




<div id="app">
  <button @click="handleClick">点击我</button>
</div>

<script>
  new Vue({
    el: '#app', // Vue 实例挂载的元素
    methods: {
      // 声明事件处理函数,接收事件对象作为参数
      handleClick(event) {
        console.log(event); // 打印事件对象
        alert('按钮被点击了!');
      }
    }
  });
</script>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

在上述示例中,handleClick 方法接收了事件参数对象 event,可以通过 event 对象获取事件的详细信息。

# 4-4 绑定事件并传参

在使用 v-on 指令绑定事件时,可以通过括号 () 为事件处理函数传递参数。


 







 
 
 




<div id="app">
  <button @click="handleClick('参数1')">点击我</button>
</div>

<script>
  new Vue({
    el: '#app', // Vue 实例挂载的元素
    methods: {
      // 声明事件处理函数,接收传递的参数
      handleClick(param) {
        alert('传递的参数是:' + param);
      }
    }
  });
</script>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

在上述示例中,handleClick 方法接收了传递的参数 param,并在警告框中显示该参数。

# 4.5 $event

在事件处理函数中,可以接收事件参数对象 event,它默认作为事件处理函数的第一个参数,与原生 JavaScript 一样。通过 Vue 的 v-on 指令(或其简写 @),我们可以轻松地绑定事件处理函数。

在事件处理函数中如果传递参数,那么默认的事件对象会被覆盖,导致事件对象无法正确使用。



 






 
 
 




<div id="app">
  <!-- 错误示例:传递多个参数,覆盖了事件对象 -->
  <button @click="handleClick('参数1')">点击我</button>
</div>

<script>
  new Vue({
    el: '#app',
    methods: {
      handleClick(param) {
        console.log('参数:', param);  // 这里的 param 是 '参数1',不是事件对象
      }
    }
  });
</script>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

在上面的错误示例中,由于 event 被 '参数1' 覆盖。

为了解决这个问题,Vue 提供了特殊变量 $event,表示原生的事件参数对象 event。通过使用 $event,可以确保事件对象正确传递到事件处理函数中。



 






 
 
 
 




<div id="app">
  <!-- 正确示例:使用 $event 保留事件对象 -->
  <button @click="handleClick('参数1', $event)">点击我</button>
</div>

<script>
  new Vue({
    el: '#app',
    methods: {
      handleClick(param, event) {
        console.log('参数:', param);  // 正确输出 '参数1'
        console.log('事件对象:', event);  // 正确的事件对象
      }
    }
  });
</script>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

在这个正确的示例中,通过 $event 变量确保了事件对象能够正确传递到 handleClick 函数中,同时可以传递其他参数。

总结

虽然 Vue 可能在某些情况下自动处理事件对象,但为了代码的可靠性和可读性,建议总是使用 $event 来显式传递事件对象,特别是在传递多个参数时。这可以避免事件对象被覆盖的问题,确保事件对象能够正确传递到事件处理函数中。

# 4-6 事件修饰符

在事件处理函数中调用 event.preventDefault() 或 event.stopPropagation() 是非常常见的需求。因此,Vue 提供了事件修饰符,用于更方便地控制事件的触发。常用的事件修饰符如下:

  • .stop:调用 event.stopPropagation() 阻止事件冒泡。
  • .prevent:调用 event.preventDefault() 阻止默认行为。
  • .capture:以捕获模式添加事件监听器。
  • .self:仅当事件发生在该元素本身时触发事件。
  • .once:事件只触发一次。

 

 













 



 






<div id="app">
  <button @click.stop="handleClick">点击我</button>
    
  <form @submit.prevent="handleSubmit">
    <input type="text" v-model="inputValue">
    <button type="submit">提交</button>
  </form>
</div>

<script>
  new Vue({
    el: '#app', // Vue 实例挂载的元素
    data: {
      inputValue: '' // 输入框的值
    },
    methods: {
      // 声明事件处理函数,处理按钮点击事件
      handleClick() {
        alert('按钮被点击了,但事件不会冒泡!');
      },
      // 声明事件处理函数,处理表单提交事件
      handleSubmit() {
        alert('表单已提交,但页面不会刷新!');
      }
    }
  });
</script>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27

在上述示例中,使用了 .stop 和 .prevent 修饰符,分别阻止了事件冒泡和表单的默认提交行为。

# 4-7 按键修饰符

在监听键盘事件时,我们经常需要判断具体的按键。此时,可以为键盘相关的事件添加按键修饰符,如 .enter、.tab、.delete 等。


 
 







 



 






<div id="app">
  <input type="text" @keyup.enter="handleEnter" placeholder="按 Enter 键触发">
  <input type="text" @keyup.delete="handleDelete" placeholder="按 Delete 键触发">
</div>

<script>
  new Vue({
    el: '#app', // Vue 实例挂载的元素
    methods: {
      // 声明事件处理函数,处理 Enter 键按下事件
      handleEnter() {
        alert('Enter 键被按下');
      },
      // 声明事件处理函数,处理 Delete 键按下事件
      handleDelete() {
        alert('Delete 键被按下');
      }
    }
  });
</script>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

在上述示例中,使用了 .enter 和 .delete 修饰符,分别监听了 Enter 键和 Delete 键的按键事件,并在按键被触发时执行对应的事件处理函数。

# 4-8 常用按键修饰符

Vue 提供了一些常用的按键修饰符,用于处理键盘事件:

  • .enter:监听 Enter 键。
  • .tab:监听 Tab 键。
  • .delete:监听 Delete 键(捕获 "Delete" 和 "Backspace" 键)。
  • .esc:监听 Escape 键。
  • .space:监听空格键。
  • .up:监听向上箭头键。
  • .down:监听向下箭头键。
  • .left:监听向左箭头键。
  • .right:监听向右箭头键。

 
 
 







 



 



 






<div id="app">
  <input type="text" @keyup.enter="handleEnter" placeholder="按 Enter 键触发">
  <input type="text" @keyup.esc="handleEscape" placeholder="按 Escape 键触发">
  <input type="text" @keyup.space="handleSpace" placeholder="按空格键触发">
</div>

<script>
  new Vue({
    el: '#app', // Vue 实例挂载的元素
    methods: {
      // 处理 Enter 键按下事件
      handleEnter() {
        alert('Enter 键被按下');
      },
      // 处理 Escape 键按下事件
      handleEscape() {
        alert('Escape 键被按下');
      },
      // 处理空格键按下事件
      handleSpace() {
        alert('空格键被按下');
      }
    }
  });
</script>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25

在上述示例中,使用了 .enter、.esc 和 .space 修饰符,分别监听了 Enter 键、Escape 键和空格键的按键事件,并在按键被触发时执行对应的事件处理函数。

# 4-9 .native修饰符

在Vue项目中,如果第三方组件没有提供某些点击事件的监听功能,但你需要在某些交互时触发事件,你可以使用.native修饰符来监听原生的DOM事件。这个方法适用于大多数情况。

<template>
  <div>
    <!-- 假设第三方组件名为ThirdPartyComponent -->
    <ThirdPartyComponent @click.native="handleClick" />
  </div>
</template>

<script>
export default {
  methods: {
    handleClick() {
      console.log('Third party component clicked');
      // 在这里处理点击事件
    }
  }
};
</script>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

.native修饰符告诉Vue监听的是原生DOM的click事件,而不是组件自身的自定义事件。

# 5. 双向绑定指令 (v-model)

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

# 5-1 基本用法

v-model 指令可以在 <input>、<textarea> 和 <select> 元素上使用,实现表单输入值和应用数据之间的双向绑定。


 
 






 




<div id="app">
  <input v-model="message" placeholder="请输入内容">
  <p>输入的内容是:{{ message }}</p>
</div>

<script>
  new Vue({
    el: '#app',
    data: {
      message: ''
    }
  });
</script>
1
2
3
4
5
6
7
8
9
10
11
12
13

在这个例子中,v-model 绑定了 message 变量到 <input> 元素。当用户在输入框中输入内容时,message 的值会自动更新,并且 p 元素中的文本也会随之更新。

# 5-2 收集表单数据

在 Vue 中,使用 v-model 指令可以轻松地实现表单数据的双向绑定。不同类型的输入元素(如文本框、单选框和复选框)的行为和数据收集方式有所不同。

# 1. 文本输入框

对于 <input type="text"/>,v-model 收集的是 value 值,用户输入的内容就是 value 值。


 
 






 





<template>
  <input type="text" v-model="textValue" />
  <!-- v-model 绑定到 textValue,收集用户输入的 value 值 -->
</template>

<script>
export default {
  data() {
    return {
      textValue: '' // 用于收集文本输入框的值
    };
  }
};
</script>
1
2
3
4
5
6
7
8
9
10
11
12
13
14

# 2. 单选框(radio)

对于 <input type="radio"/>,v-model 收集的也是 value 值,并且需要为标签配置 value 值,哪个 value 被收集,哪个 value 所在的单选框就会被选中。



 
 
 







 





<template>
  <div>
    <input type="radio" v-model="selectedOption" value="option1" /> 选项1
    <input type="radio" v-model="selectedOption" value="option2" /> 选项2
    <!-- v-model 绑定到 selectedOption,收集选中的 radio 的 value 值 -->
  </div>
</template>

<script>
export default {
  data() {
    return {
      selectedOption: '' // 用于收集单选框的值,哪个 value 被收集,哪个 value 所在的单选框就会被选中。
    };
  }
};
</script>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

# 3. 复选框(checkbox)

对于 <input type="checkbox"/>,收集方式有两种情况,取决于是否配置 value 属性以及 v-model 的初始值类型。

1. 没有配置 value 属性

  • 如果没有配置 input 的 value 属性,v-model 收集的是 checked 状态(勾选或未勾选,是布尔值)。
  • 对于多个独立的复选框,每个复选框需要一个独立的 data 属性值来存储其 checked 状态:

 
 






 





<template>
  <input type="checkbox" v-model="isChecked" /> 勾选状态
  <!-- v-model 绑定到 isChecked,收集 checked 状态(布尔值) -->
</template>

<script>
export default {
  data() {
    return {
      isChecked: false // 用于收集复选框的勾选状态
    };
  }
};
</script>
1
2
3
4
5
6
7
8
9
10
11
12
13
14

2. 配置 value 属性

(1) v-model 的初始值是非数组,收集的是 checked 状态(勾选或未勾选,是布尔值)。

当 v-model 的初始值不是数组时(例如一个布尔值),复选框会根据其 checked 状态(是否勾选)来更新 v-model 绑定的变量。即使配置了 value 属性,v-model 仍然会收集 checked 状态,并不会收集value的值。


 
 






 





<template>
  <input type="checkbox" v-model="isAgreed" value="agree" /> 同意条款
  <!-- v-model 绑定到 isAgreed,收集 checked 状态(布尔值) -->
</template>

<script>
export default {
  data() {
    return {
      isAgreed: false // 用于收集复选框的勾选状态
    };
  }
};
</script>
1
2
3
4
5
6
7
8
9
10
11
12
13
14

(2) v-model 的初始值是数组,收集的是 value 组成的数组。

对于 v-model 的初始值是数组的复选框,数组中收集了哪些 value,相应的复选框就会被选中。如果数组中包含某个复选框的 value 值,那么该复选框就会显示为选中状态。



 
 
 







 





<template>
  <div>
    <input type="checkbox" v-model="checkedValues" value="value1" /> 选项1
    <input type="checkbox" v-model="checkedValues" value="value2" /> 选项2
    <!-- v-model 绑定到 checkedValues,收集选中的复选框的 value 值,组成数组 -->
  </div>
</template>

<script>
export default {
  data() {
    return {
      checkedValues: [] // 用于收集复选框的值组成的数组
    };
  }
};
</script>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

# 4. 复选框的最佳实践

对于复选框的使用,确实建议采用第三种写法,即配置 value 属性并使用数组来管理多个复选框的状态。这种方式更加简洁和高效,尤其是在复选框数量较多的情况下。此外,如果采用第一种写法,没有配置 value 属性,并且需要独立管理每个复选框的 checked 状态,这种方式与单选框的使用方式类似,但没有单选框的互斥性。

# 5-3 v-model 表单示例

下面是一个使用纯 HTML 和 Vue.js 的示例,通过 v-model 实现表单输入值和应用数据之间的双向绑定,并在表单提交时将数据传递给后端,同时在页面上渲染一个表格来显示提交的数据。











































     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     






    <!DOCTYPE html>
    <html lang="en">
    <head>
      <meta charset="UTF-8">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <title>Vue v-model 示例</title>
      <script src="https://cdn.jsdelivr.net/npm/vue@2"></script>
      <script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
       <link rel="stylesheet" href="./css/carousel.css"> <!-- 引入CSS文件 -->
    </head>
    <body>
      <div id="app">
        <h1>Vue v-model 表单示例</h1>
        <form @submit.prevent="submitForm">
          <!-- 输入框 (input) 示例 -->
          <div>
            <label for="inputMessage">输入内容:</label>
            <input id="inputMessage" v-model="formData.message" placeholder="请输入内容">
          </div>
    
          <!-- 多行文本框 (textarea) 示例 -->
          <div>
            <label for="textareaMessage">多行文本:</label>
            <textarea id="textareaMessage" v-model="formData.textareaMessage" placeholder="请输入多行文本"></textarea>
          </div>
    
          <!-- 选择框 (select) 示例 -->
          <div>
            <label for="selectOption">选择一个选项:</label>
            <select id="selectOption" v-model="formData.selectedOption">
              <option disabled value="">请选择</option>
              <option>A</option>
              <option>B</option>
              <option>C</option>
            </select>
          </div>
    
          <button type="submit">提交</button>
        </form>
    
          
        <h2>提交的数据</h2> 
        <table> <!-- 表格 -->
          <thead>
            <tr>
              <th>输入内容</th>
              <th>多行文本</th>
              <th>选择的选项</th>
            </tr>
          </thead>
          <tbody>
            <tr v-for="(data, index) in submittedData" :key="index">
              <td>{{ data.message }}</td>
              <td>{{ data.textareaMessage }}</td>
              <td>{{ data.selectedOption }}</td>
            </tr>
          </tbody>
        </table>
      </div>
    
    
    </body>
    </html>
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    <style>
        #app {
          font-family: Avenir, Helvetica, Arial, sans-serif;
          text-align: center;
          color: #2c3e50;
          margin-top: 60px;
        }
        
        form div {
          margin: 20px 0;
        }
    
        label {
          display: block;
          margin-bottom: 5px;
        }
    
        input, textarea, select {
          width: 300px;
          padding: 5px;
          font-size: 16px;
        }
    
        button {
          padding: 10px 20px;
          font-size: 16px;
          background-color: #42b983;
          color: white;
          border: none;
          border-radius: 5px;
          cursor: pointer;
        }
    
        button:hover {
          background-color: #3a8d75;
        }
    
        table {
          margin: 20px auto;
          border-collapse: collapse;
          width: 80%;
        }
    
        th, td {
          padding: 10px;
          border: 1px solid #ddd;
          text-align: center;
        }
    
        th {
          background-color: #f4f4f4;
        }
      </style>
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
      <script>
        new Vue({
          el: '#app',
          data() {
            return {
              formData: {
                message: '',             // 存储输入框内容
                textareaMessage: '',     // 存储多行文本框内容
                selectedOption: ''       // 存储选择框选项
              },
              submittedData: []          // 存储提交的数据
            }
          },
          methods: {
            submitForm() {
              // 打印表单数据,确认数据被正确捕获
              console.log(this.formData);
    
              // 添加表单数据到 submittedData 数组
              this.submittedData.push({ ...this.formData });
    
              // 发送表单数据到后端
              axios.post('https://example.com/api/submit', this.formData)
                .then(response => {
                  // 处理响应数据
                  console.log('提交成功:', response.data);
                })
                .catch(error => {
                  // 处理错误
                  console.error('提交失败:', error);
                });
    
              // 清空表单数据
              this.formData.message = '';
              this.formData.textareaMessage = '';
              this.formData.selectedOption = '';
            }
          }
        });
      </script>
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    // Make sure to add code blocks to your code group

    表单元素:

    • 使用 v-model 指令绑定输入框、文本框和选择框的值到 formData 对象中相应的属性。
    • formData 对象包含 message、textareaMessage 和 selectedOption 属性,用于存储表单输入的数据。

    表单提交:

    • 使用 @submit.prevent="submitForm" 监听表单提交事件,并调用 submitForm 方法。
    • 在 submitForm 方法中,首先打印表单数据以确认数据捕获正确,然后将表单数据添加到 submittedData 数组中,用于在表格中显示。
    • 使用 Axios 将数据发送到后端,成功或失败后打印响应。

    表格渲染:

    • 使用 v-for 指令迭代 submittedData 数组,并生成表格行。
    • 表格显示已提交的数据,包括输入内容、多行文本和选择的选项。

    # 5-4 v-model 指令的修饰符

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

    image-20240730022619980

    # .lazy 修饰符

    默认情况下,v-model 会同步更新数据,当输入框的值变化时立即更新绑定的变量。.lazy 修饰符可以将更新触发条件改为在输入框失去焦点或按下回车键时进行。


     
     






     




    <div id="app">
      <input v-model.lazy="message" placeholder="请输入内容">
      <p>输入的内容是:{{ message }}</p>
    </div>
    
    <script>
      new Vue({
        el: '#app',
        data: {
          message: ''
        }
      });
    </script>
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13

    在这个例子中,只有当输入框失去焦点或按下回车键时,message 的值才会更新。

    # .number 修饰符

    .number 修饰符可以将用户输入的字符串值自动转换为数值类型。


     
     






     




    <div id="app">
      <input v-model.number="age" placeholder="请输入年龄">
      <p>输入的年龄是:{{ age }}</p>
    </div>
    
    <script>
      new Vue({
        el: '#app',
        data: {
          age: ''
        }
      });
    </script>
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13

    在这个例子中,用户输入的内容会被自动转换为数值并存储在 age 变量中。

    # .trim 修饰符

    .trim 修饰符可以自动移除用户输入的首尾空格。


     












    <div id="app">
      <input v-model.trim="name" placeholder="请输入姓名">
      <p>输入的姓名是:{{ name }}</p>
    </div>
    
    <script>
      new Vue({
        el: '#app',
        data: {
          name: ''
        }
      });
    </script>
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13

    在这个例子中,用户输入的内容会被自动去掉首尾空格并存储在 name 变量中。

    # 6. 条件渲染指令

    条件渲染指令用于按需控制 DOM 元素的显示与隐藏,在 Vue 中有两种主要的条件渲染指令:

    1. v-if:用于根据表达式的真假值,动态地创建或移除 DOM 元素。
    2. v-show:用于根据表达式的真假值,通过切换元素的 display 样式来控制元素的显示与隐藏。

    # 6-1 v-if 指令

    v-if 指令用于根据表达式的真假值,动态地创建或移除 DOM 元素。



     






     




    <!-- v-if 用法示例 -->
    <div id="app">
      <p v-if="isVisible">这段文本会根据 isVisible 的值显示或隐藏。</p>
    </div>
    
    <script>
    new Vue({
      el: '#app',
      data: {
        isVisible: true // 控制文本显示或隐藏
      }
    });
    </script>
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13

    在上面的例子中,当 isVisible 为 true 时,<p> 元素会被渲染到 DOM 中;当 isVisible 为 false 时,<p> 元素会从 DOM 中移除。

    # 6-2 v-show 指令

    v-show 指令用于根据表达式的真假值,通过切换元素的 display 样式来控制元素的显示与隐藏。



     






     




    <!-- v-show 用法示例 -->
    <div id="app">
      <p v-show="isVisible">这段文本会根据 isVisible 的值显示或隐藏。</p>
    </div>
    
    <script>
    new Vue({
      el: '#app',
      data: {
        isVisible: true // 控制文本显示或隐藏
      }
    });
    </script>
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13

    在上面的例子中,无论 isVisible 的值如何,<p> 元素始终存在于 DOM 中,只是通过 display: none 样式来控制显示或隐藏。

    # 6-3 v-if 和 v-show 的区别

    实现原理不同

    • v-if:动态地创建或移除 DOM 元素,从而控制元素在页面上的显示与隐藏。
    • v-show:通过动态添加或移除 style="display: none;" 样式来控制元素的显示与隐藏。

    性能消耗不同

    • v-if:有更高的切换开销,适合在运行时条件很少改变的情况下使用。
    • v-show:有更高的初始渲染开销,适合需要非常频繁地切换显示状态的情况下使用。

    # 6-4 v-else 指令

    v-if 可以单独使用,也可以与 v-else 指令配合使用,v-else 指令用于在 v-if 判断为 false 时,显示相应的元素。



     
     






     




    <!-- v-if 和 v-else 配合使用 -->
    <div id="app">
      <p v-if="isVisible">显示状态为真。</p>
      <p v-else>显示状态为假。</p>
    </div>
    
    <script>
    new Vue({
      el: '#app',
      data: {
        isVisible: false // 控制文本显示或隐藏
      }
    });
    </script>
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14

    在上面的例子中,当 isVisible 为 true 时,显示状态为真;当 isVisible 为 false 时,显示状态为假。

    注意

    v-else 指令必须紧跟在 v-if 指令或 v-else-if 指令之后,否则不会被识别。

    # 6-5 v-else-if 指令

    v-else-if 指令,顾名思义,充当 v-if 的“else-if 块”,可以连续使用来判断多个条件。



     
     
     






     




    <!-- v-if 和 v-else-if 和 v-else 配合使用 -->
    <div id="app">
      <p v-if="status === 'success'">操作成功。</p>
      <p v-else-if="status === 'pending'">操作进行中。</p>
      <p v-else>操作失败。</p>
    </div>
    
    <script>
    new Vue({
      el: '#app',
      data: {
        status: 'pending' // 控制文本显示内容
      }
    });
    </script>
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15

    在上面的例子中,status 的值可以为 'success'、'pending' 或其他值,页面会根据不同的 status 显示相应的信息。

    注意

    v-else-if 指令必须紧跟在 v-if 指令或其他 v-else-if 指令之后,否则不会被识别。

    # 7. 列表渲染指令 (v-for)

    Vue 提供了 v-for 列表渲染指令,用来帮助开发者基于一个数组来循环渲染一个列表结构。v-for 指令需要使用 item in items 形式的特殊语法,其中:

    • items 是待循环的数组
    • item 是被循环的每一项

    提示

    • v-for 指令加在哪个标签上,哪个标签就会被循环生成,包括该标签内部的内容。也就是说,包含 v-for 的标签及其子元素都会被循环生成。
    • 也就是说当你将 v-for 放在一个标签上时,它会生成多个相同类型的标签,并且每个标签中都会包含相同结构的内容。

    适用场景:

    • 等份布局:例如商品列表、卡片式布局、新闻列表等,这些布局中的每个卡片或元素的结构是一样的,只是填充的数据(例如商品名称、图片、价格)不同。使用 v-for 可以方便地实现这一点。
    • 内容动态变化:当你需要根据不同的内容生成相同结构的多个元素时,v-for 可以极大简化代码,减少重复劳动。

    # 7-1 v-for 的基本用法

    # 1. 遍历数组

    语法:v-for="item in items"



     
     
     
     
     


    <!-- 遍历数组 -->
    <ul>
      <!-- v-for 指令加在 <li> 标签上,循环生成 <li> 元素 --> 
      <li v-for="(item, index) in items" :key="index">
        <!-- item 是数组的每一项,index 是当前项的索引 -->
        {{ item }}
      </li>
    </ul>
    
    1
    2
    3
    4
    5
    6
    7
    8

    要遍历的数组结构:

    data() {
      return {
        items: ['苹果', '香蕉', '橙子'] // 待遍历的数组
      }
    }
    
    1
    2
    3
    4
    5

    # 2. 遍历对象

    语法:v-for="(value, key) in object"



     
     
     
     
     


    <!-- 遍历对象 -->
    <ul>
      <!-- v-for 指令加在 <li> 标签上,循环生成 <li> 元素 -->
      <li v-for="(value, key) in object" :key="key">
        <!-- key 是对象的属性名,value 是对象的属性值 -->
        {{ key }}: {{ value }}
      </li>
    </ul>
    
    1
    2
    3
    4
    5
    6
    7
    8

    要遍历的对象结构:

    data() {
      return {
        object: { name: 'Alice', age: 25, city: 'New York' } // 待遍历的对象
      }
    }
    
    1
    2
    3
    4
    5

    # 3. 遍历数组中的对象

    语法:v-for="item in items"












     
     
     
     
     
     



    <!-- 遍历数组中的对象 -->
    <table>
      <thead>
        <tr>
          <th>属性1</th>
          <th>属性2</th>
          <th>属性3</th>
        </tr>
      </thead>
      <tbody>
        <!-- v-for 指令加在 <tr> 标签上,循环生成 <tr> 元素及其子元素 -->      
        <tr v-for="item in items" :key="item.id">
          <!-- item 是数组的每一个对象 -->
          <td>{{ item.property1 }}</td>
          <td>{{ item.property2 }}</td>
          <td>{{ item.property3 }}</td>
        </tr>
      </tbody>
    </table>
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19

    要遍历的数组中的对象结构:

    data() {
      return {
        items: [
          { id: 1, property1: '值1-1', property2: '值1-2', property3: '值1-3' },
          { id: 2, property1: '值2-1', property2: '值2-2', property3: '值2-3' },
          { id: 3, property1: '值3-1', property2: '值3-2', property3: '值3-3' }
        ] // 待遍历的数组中的对象
      }
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9

    # 4. 商品列表网页布局

    假设我们有一个商品数组,每个商品包含 name、price 和 img(图片链接)。我们可以使用 v-for 来遍历这个商品数组,并生成对应的商品卡片。





       













      <div id="app">
      <!-- 商品列表 -->
      <div class="goods-list">
        <!-- 使用 v-for 指令循环渲染商品卡片 -->
        <div class="goods-item" v-for="item in goods" :key="item.id">
          <img :src="item.img" alt="商品图片" class="goods-image">
          <div class="goods-info">
            <h3 class="goods-name">{{ item.name }}</h3>
            <p class="goods-price">¥{{ item.price }}</p>
          </div>
          <div class="goods-buttons">
            <button class="cart-btn" @click="addToCart(item)">加入购物车</button>
            <button class="buy-btn" @click="buyNow(item)">立即购买</button>
          </div>
        </div>
      </div>
      </div>
      
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
       <!-- 导入 Vue.js 的 script 脚本文件 -->
        <script src="https://cdn.jsdelivr.net/npm/vue@2"></script>
        <script>
          new Vue({
            el: '#app',
            data() {
              return {
                // 商品数据
                goods: [{
                    id: 1,
                    name: '商品1',
                    price: 79,
                    img: 'https://img2.baidu.com/it/u=2391467471,3212210600&fm=253&fmt=auto&app=138&f=JPEG?w=1011&h=374'
                  },
                  {
                    id: 2,
                    name: '商品2',
                    price: 200,
                    img: 'https://img0.baidu.com/it/u=262402321,3310484181&fm=253&fmt=auto&app=138&f=JPEG?w=1018&h=500'
                  },
                  {
                    id: 3,
                    name: '商品3',
                    price: 300,
                    img: 'https://img2.baidu.com/it/u=3124829697,2175694045&fm=253&fmt=auto&app=138&f=JPEG?w=889&h=500',
                  },
                  {
                    id: 4,
                    name: '商品4',
                    price: 400,
                    img: 'https://img1.baidu.com/it/u=2222665852,1606584561&fm=253&fmt=auto&app=138&f=JPEG?w=1097&h=500'
                  }
                ]
              };
            },
            methods: {
              addToCart(item) {
                console.log(`${item.name} 加入购物车`);
              },
              buyNow(item) {
                console.log(`${item.name} 立即购买`);
              }
            }
          });
        </script>
      
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      33
      34
      35
      36
      37
      38
      39
      40
      41
      42
      43
      44
      45
        <style>
          .goods-list {
            display: flex;
            grid-template-columns: repeat(2, 1fr);
            /* 设置每行显示两个商品 */
            gap: 2px;
            justify-content: space-between;
          }
      
          .goods-item {
            width: 200px;
            border: 1px solid #ddd;
            border-radius: 8px;
            overflow: hidden;
            box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
            padding: 10px;
            background: #fff;
            flex: 1;
          }
      
          .goods-image {
            width: 100%;
            height: 150px;
            object-fit: cover;
          }
      
          .goods-info {
            margin-top: 10px;
            display: flex;
            justify-content: space-between;
          }
      
          .goods-name {
            font-size: 16px;
            font-weight: bold;
          }
      
          .goods-price {
            font-size: 14px;
            color: #ff6b81;
          }
      
          .goods-buttons {
            display: flex;
            justify-content: space-between;
            margin-top: 10px;
          }
      
          .cart-btn,
          .buy-btn {
            width: 48%;
            padding: 8px;
            background-color: #ff6b81;
            color: #fff;
            border: none;
            border-radius: 4px;
            cursor: pointer;
          }
      
          .cart-btn:hover,
          .buy-btn:hover {
            background-color: #e55b74;
          }
        </style>
      
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      33
      34
      35
      36
      37
      38
      39
      40
      41
      42
      43
      44
      45
      46
      47
      48
      49
      50
      51
      52
      53
      54
      55
      56
      57
      58
      59
      60
      61
      62
      63
      64
      // Make sure to add code blocks to your code group
      1. v-for="item in goods":通过 v-for 指令遍历 goods 数组,动态渲染每个商品的布局。
      2. 商品结构:每个商品项包含一个图片(img)、商品名称(goods-name)、价格(goods-price)和两个按钮(cart-btn 和 buy-btn)。
      3. 响应式布局:
        • 使用 flex 布局来排列商品卡片,确保商品项在不同屏幕下能够自适应。
        • 使用 flex-wrap: wrap 来让商品项在空间不足时自动换行。
      4. 按钮功能:每个商品项的按钮通过 @click 绑定事件,点击后会调用 addToCart 或 buyNow 方法。

      # 7-2 v-for 中的索引

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


       
       
       
       






       




      <div id="app">
        <ul>
          <!-- 使用 v-for 指令循环渲染列表,并包含索引 -->
          <li v-for="(item, index) in items">{{ index }} - {{ item }}</li>
        </ul>
      </div>
      
      <script>
      new Vue({
        el: '#app',
        data: {
          items: ['苹果', '香蕉', '橙子'] // 待渲染的数组
        }
      });
      </script>
      
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15

      在上面的例子中,v-for 指令不仅遍历 items 数组,还提供了每一项的索引 index。

      注意

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

      # 7-3 使用 key 维护列表的状态

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

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

      以下是一个使用 key 属性的示例:






















         
         
         
         
         
         
         









         
         
         
         
         
         







        <!DOCTYPE html>
        <html lang="en">
        <head>
          <meta charset="UTF-8">
          <meta name="viewport" content="width=device-width, initial-scale=1.0">
          <title>Vue v-for 渲染四列表格示例</title>
          <script src="https://cdn.jsdelivr.net/npm/vue@2"></script>
        </head>
        <body>
          <div id="app">
            <h1>水果列表</h1>
            <table>
              <thead>
                <tr>
                  <th>ID</th>
                  <th>名称</th>
                  <th>颜色</th>
                  <th>价格</th>
                </tr>
              </thead>
              <tbody>
                <!-- 使用 v-for 指令循环渲染表格的行,并为每一行提供唯一的 key 属性 -->
                <tr v-for="item in items" :key="item.id">
                  <td>{{ item.id }}</td>
                  <td>{{ item.name }}</td>
                  <td>{{ item.color }}</td>
                  <td>{{ item.price }}</td>
                </tr>
              </tbody>
            </table>
          </div>
        
          <script>
            new Vue({
              el: '#app',
              data() {
                return {
                  items: [
                    { id: 1, name: '苹果', color: '红色', price: '$1.00' },
                    { id: 2, name: '香蕉', color: '黄色', price: '$0.50' },
                    { id: 3, name: '橙子', color: '橙色', price: '$0.80' },
                    { id: 4, name: '葡萄', color: '紫色', price: '$2.00' }
                  ] // 待渲染的数组
                }
              }
            });
          </script>
        </body>
        </html>
        
        1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        12
        13
        14
        15
        16
        17
        18
        19
        20
        21
        22
        23
        24
        25
        26
        27
        28
        29
        30
        31
        32
        33
        34
        35
        36
        37
        38
        39
        40
        41
        42
        43
        44
        45
        46
        47
        48
        49
          <style>
            table {
              width: 50%;
              margin: 0 auto;
              border-collapse: collapse;
            }
            th, td {
              border: 1px solid #ddd;
              padding: 8px;
              text-align: center;
            }
            th {
              background-color: #f4f4f4;
            }
          </style>
        
        1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        12
        13
        14
        15
        // Make sure to add code blocks to your code group

        在上面的例子中,每一项都提供了一个唯一的 key 属性,以确保 Vue 能够正确地跟踪每个节点的身份。

        # 7-4 key 的注意事项

        在使用 v-for 指令时,指定 key 属性时需要注意以下几点:

        • key 的值只能是字符串或数字类型。
        • key 的值必须具有唯一性(即:key 的值不能重复)。
        • 建议将数据项 id 属性的值作为 key 的值,因为 id 属性的值具有唯一性。
        • 使用 index 的值当作 key 的值没有任何意义,因为 index 的值不具有唯一性。
        • 建议使用 v-for 指令时一定要指定 key 的值,既提升性能,又防止列表状态紊乱。

        为什么不能用索引index作为key?

        使用 index 作为 key 会导致在数组项重新排序或更新时,Vue 无法正确地复用已有节点,从而降低性能并可能导致状态丢失。

        # 7-5 表格添加删除示例


































           
           
           
           
           
           
           
           










           
           
           
           
           



           










           










          <!DOCTYPE html>
          <html lang="en">
          
          <head>
            <meta charset="UTF-8">
            <meta name="viewport" content="width=device-width, initial-scale=1.0">
            <title>Vue.js 表格示例</title>
            <script src="https://cdn.jsdelivr.net/npm/vue@2"></script>
          </head>
          
          <body>
            <div id="app">
                <h2>数据表格</h2>
                <!-- 输入框组,用于添加新数据 -->
                <div class="form-group">
                    <label for="name">姓名:</label>
                    <input type="text" id="name" v-model="newName" placeholder="输入姓名">
                </div>
                <div class="form-group">
                    <label for="age">年龄:</label>
                    <input type="number" id="age" v-model="newAge" placeholder="输入年龄">
                </div>
                <button @click="addData">添加数据</button>
                <table>
                    <thead>
                        <tr>
                            <th>ID</th>
                            <th>姓名</th>
                            <th>年龄</th>
                            <th>操作</th>
                        </tr>
                    </thead>
                    <tbody>
                        <!-- 使用 v-for 指令遍历 list 数组,并生成表格行 -->
                        <tr v-for="(item, index) in list" :key="item.id">
                            <td>{{ item.id }}</td>
                            <td>{{ item.name }}</td>
                            <td>{{ item.age }}</td>
                            <!-- 删除按钮,点击时调用 removeData 方法 -->
                            <td><button @click="removeData(item.id)">删除</button></td>
                        </tr>
                    </tbody>
                </table>
            </div>
          
            <script>
                new Vue({
                    el: '#app',
                    data: {
                        newName: '', // 用于存储新添加数据的姓名
                        newAge: '', // 用于存储新添加数据的年龄
                        list: [
                            { id: 1, name: 'Alice', age: 25 },
                            { id: 2, name: 'Bob', age: 30 },
                        ], // 存储数据列表
                        nextId: 3 // 下一个数据项的 ID
                    },
                    methods: {
                        // 添加数据的方法
                        addData() {
                            // 检查姓名和年龄是否为空
                            if (this.newName && this.newAge) {
                                // 将新数据项添加到 list 数组中
                                this.list.push({ id: this.nextId++, name: this.newName, age: parseInt(this.newAge) });
                                // 清空输入框
                                this.newName = '';
                                this.newAge = '';
                            }
                        },
                        // 删除数据的方法
                        removeData(id) {
                            // 使用 filter 方法过滤掉要删除的项
                            this.list = this.list.filter(item => item.id !== id);
                        }
                    }
                });
            </script>
          </body>
          
          </html>
          
          1
          2
          3
          4
          5
          6
          7
          8
          9
          10
          11
          12
          13
          14
          15
          16
          17
          18
          19
          20
          21
          22
          23
          24
          25
          26
          27
          28
          29
          30
          31
          32
          33
          34
          35
          36
          37
          38
          39
          40
          41
          42
          43
          44
          45
          46
          47
          48
          49
          50
          51
          52
          53
          54
          55
          56
          57
          58
          59
          60
          61
          62
          63
          64
          65
          66
          67
          68
          69
          70
          71
          72
          73
          74
          75
          76
          77
          78
          79
          80
          <style>
          body {
            font-family: Arial, sans-serif;
            margin: 20px;
          }
          
          table {
            width: 100%;
            border-collapse: collapse;
            margin-bottom: 20px;
          }
          
          th,
          td {
            border: 1px solid #ddd;
            padding: 8px;
            text-align: center;
          }
          
          th {
            background-color: #f4f4f4;
          }
          
          button {
            padding: 8px 16px;
            margin: 5px;
            border: none;
            background-color: #42b983;
            color: white;
            cursor: pointer;
          }
          
          button:hover {
            background-color: #3a8d75;
          }
          
          .form-group {
            margin-bottom: 15px;
          }
          
          .form-group label {
            display: block;
            margin-bottom: 5px;
          }
          
          .form-group input {
            width: calc(100% - 16px);
            padding: 8px;
            margin-bottom: 10px;
          }
          </style>
          
          1
          2
          3
          4
          5
          6
          7
          8
          9
          10
          11
          12
          13
          14
          15
          16
          17
          18
          19
          20
          21
          22
          23
          24
          25
          26
          27
          28
          29
          30
          31
          32
          33
          34
          35
          36
          37
          38
          39
          40
          41
          42
          43
          44
          45
          46
          47
          48
          49
          50
          51
          // Make sure to add code blocks to your code group

          # 1. 效果演示

          # 2. 代码分析

          1. 数据绑定:

          • 使用 v-model 绑定输入框的值到 newName 和 newAge,用于输入新数据。

          2. 添加数据:

          • addData 方法检查输入框是否有值,然后将新数据添加到 list 数组中,并清空输入框。新增数据时自动生成唯一的 ID。
          addData() {
            // 检查姓名和年龄是否为空
            if (this.newName && this.newAge) {
              // 将新数据项添加到 list 数组中
              this.list.push({
                id: this.nextId++, // 自动生成唯一的 ID
                name: this.newName, // 输入的姓名
                age: parseInt(this.newAge) // 输入的年龄,转换为整数
              });
              // 清空输入框
              this.newName = '';
              this.newAge = '';
            }
          }
          
          1
          2
          3
          4
          5
          6
          7
          8
          9
          10
          11
          12
          13
          14

          在这个方法中,push 方法用于将一个新对象(包含 id、name 和 age 属性)添加到 list 数组的末尾,并返回数组的新长度。这种方式非常适合用于动态添加数据到数组中。

          3. 删除数据:

          删除方案一:removeData 方法使用 filter 方法根据 ID 删除对应的数据项。

          // 删除方案一 (不局限于索引,适合用于有唯一标识符(如 ID)的数据项删除操作)
          removeData(id) {
            // 使用 filter 方法过滤掉要删除的项
            this.list = this.list.filter(item => item.id !== id);
          }
          
          
          
          1
          2
          3
          4
          5
          6
          7
          • 使用 filter 方法:filter 方法不修改原数组,而是返回一个新的数组,包含所有通过筛选函数的元素。
          • 参数:filter 的参数是一个函数,在这里是 (item => item.id !== id),表示保留所有 id 不等于给定 id 的元素。

          删除方案二:removeData 方法使用 splice 方法根据 index 删除对应的数据项。

          // 删除方案二 (只能根据索引删除,必须知道要删除元素的具体位置)
          removeData(index) {
            this.list.splice(index, 1);
          }
          
          1
          2
          3
          4
          • 使用 splice 方法:splice 方法直接修改原数组,在指定的位置删除指定数量的元素。
          • 参数:splice 的参数是元素的索引和删除的数量。在这里,index 是元素的索引,1 表示删除一个元素。

          4. 表格渲染:

          • 使用 v-for 指令遍历 list 数组,并生成表格行。
          • 使用 :key 属性为每个数据项提供唯一的标识。
          <tr v-for="(item, index) in list" :key="item.id">
            <td>{{ item.id }}</td>
            <td>{{ item.name }}</td>
            <td>{{ item.age }}</td>
            <!-- 删除按钮,点击时调用 removeData 方法 -->
            <td><button @click="removeData(item.id)">删除</button></td>
          </tr>
          
          1
          2
          3
          4
          5
          6
          7
          编辑此页 (opens new window)
          上次更新: 2025/01/30, 23:55:43
          Vue 基础使用
          过滤器(Filters)

          ← Vue 基础使用 过滤器(Filters)→

          Theme by Vdoing | Copyright © 2019-2025 程序员scholar
          • 跟随系统
          • 浅色模式
          • 深色模式
          • 阅读模式