Vue-基础语法(二)
1. 前言
具体细节参考
Vue官方文档 ,这一章的内容非常重要,我们开发完成之后会通过一个案例将这些知识点全部串起来。
本文主要将讲解 Vue 的基础语法,包括如下内容:
- 条件渲染( v-if 、v-else、v-else-if、v-show)
- 列表渲染( v-for )
- 属性绑定( v-bind、v-model )
- 事件处理( v-on )
- 计算属性( computed )
- 监听器( watch )
- Class 与 Style 绑定
- 任务清单-案例
2. 条件渲染
如下四个条件渲染指令在开发中使用频率非常高,类似于java中的
if、else、else-if。例如,任务状态信息等需求。
v-if
v-else
v-else-if
v-show
2.1. v-if
v-if:用于条件判断指令,一般用于界面内容的渲染,该指令会走表达式为true的分支。
2.2. v-else
v-else: 一般结合v-if使用,该指令走与v-if相反的分支。
2.3. v-else-if
v-else-if:提供的是相应于v-if的,它可以连续多次重复使用。
v-else和v-else-if必须紧跟在v-if或v-else-if的后面,并且它们只能与相同父元素的v-if或v-else-if一起使用。
具体信息如下图

假设,根据 type 类型展示不同的字母。
- HTML模板
| 1 | <body> | 
- Vue实例和数据
| 1 | <script> | 
- 结果信息

2.4. v-show
v-show:也是条件渲染指令,控制元素显示或者隐藏。 用法与v-if一致,但不能和v-else和v-else-if一起使用。
假设,根据 type 类型展示不同的字母。
- HTML模板
| 1 | <body> | 
- Vue的实例和数据
| 1 | <script> | 
- 结果信息

2.5. v-if 和 v-show 区别
- 渲染方式 - v-if:当条件为- false时,元素中不会在- DOM中存在,它会被完全移除。
- v-show:当条件为- false时,元素仍然在- DOM中存在,但是通过CSS样式将其隐藏(display)。
 
- 性能开销 - v-if:当条件为- true时,- Vue会重新创建元素并渲染。当条件为- false时,元素不会被渲染。这也就是说只要切换条件,元素都需要被创新创建和销毁,如果切换频繁这需要的性能开销就比较大了。
- v-show:当条件不管是- true或者- false元素都已经被渲染完成了,所以就不存在切换时的性能开销。
 
- 如何选择 - v-if:当条件为- false时,我们也希望减少相关的- DOM数量,那我们使用- v-if就是合适的。- 例如如下代码中,我希望展示列表页时,删除详情页的页面信息减少请求次数,就可以使用 - v-if来完成。- 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- <template> 
 <div class="class-style">
 <!-- 根据状态渲染不同组件 -->
 <!-- 当状态为 'list' 时,显示列表页 -->
 <list-page v-if="status === 'list'"></list-page>
 <!-- 当状态为 'detail' 时,显示详情页 -->
 <detail-page v-else-if="status === 'detail'"></detail-page>
 </div>
 </template>
 <script>
 import ListPage from './ListPage.vue'; // 导入列表页组件
 import DetailPage from './DetailPage.vue'; // 导入详情页组件
 export default {
 components: {
 ListPage,
 DetailPage
 },
 data() {
 return {
 status: 'list', // 默认状态为 'list'
 };
 }
 };
 </script>
- v-show:如果需要频繁切换时,而不产生较大的性能开销时,我们就可以使用- v-show。- 例如如下代码中, 展开/收起文章的详细内容时。 - 1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23- <template> 
 <div id="app">
 <h3>{{ article.title }}</h3>
 <button @click="toggleContent(article)">Toggle Content</button>
 <div v-show="article.showContent">
 {{ article.content }}
 </div>
 </div>
 </template>
 <script>
 export default {
 el: '#app',
 data: {
 article: { title: 'Article', content: 'Content of Article', showContent: false }
 },
 methods: {
 toggleContent(article) {
 article.showContent = !article.showContent;
 }
 }
 };
 </script>
 
3. 列表渲染
列表渲染(
v-for)是非常非常非常常用的一个指令,在开发中 100% 会使用到的一个指令,类似于java中的for循环。
3.1. v-for
v-for:基于一个数组进行列表的渲染。例如,我们的form表单就一定会使用到。
- 语法
| 1 | <li v-for="{ message } in items"> | 
假设我们有一个数组,需要将数组里面的元素全部遍历出来,使用 v-for 实现。
- HTML模板- 1 
 2
 3
 4
 5
 6
 7- <body> 
 <div id="app">
 <ul v-for="item in items" :key="item.message">
 <li>{{ item.message }}</li>
 </ul>
 </div>
 </body>
- Vue实例和数据- 1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11- <script> 
 new Vue({
 el: "#app",
 data: {
 items: [
 { message: 'Foo' },
 { message: 'Bar' }
 ]
 }
 })
 </script>
- 结果  
4. 属性绑定
属性绑定:在前端页面中如果需要将数据绑定在
HTML元素或者表单的属性上时,我们需要这些属性绑定的值可以随着数据的变化而进行更新。在属性绑定中,常用的指令有如下两种:
v-bind
v-model
4.1. v-bind
v-bind:用于将数据绑定到HTML元素 上,使属性值可以动态的随数据的变化而变化。如果绑定的值是
null或者undefined,那么该 attribute 将会从渲染的元素上移除。
- 语法
| 1 | <div v-bind:id="dynamicId"></div> | 
- 其中 v-bind可以省略不写,直接简化为:
| 1 | <div :id="dynamicId"></div> | 
其中针对 v-bind 的典型用法应该时分页条,如下是 Element-ui 分页条 的用法。

| 1 | <template> | 
4.2. v-model
v-model:用于将数据绑定在 表单元素(文本输入框、复选框、单选按钮等等) 上创建双向绑定数据,可以实现用户的输入与数据之间的同步。
- 语法
| 1 | <input v-model="message" placeholder="edit me" /> | 
假设我们将多个复选框绑定到同一个数组
- HTML模板
| 1 | <body> | 
- Vue实例和数据
| 1 | <script> | 
- 结果

5. 事件处理
事件处理:在前端开发中我们有时需要监听
DOM事件,并在触发时执行相应的JavaScript代码,控制数据的变化或执行特定的操作。事件处理的值可以是如下两种:
- 内联事件处理器
- 方法事件处理器
- 自定义事件处理器(后面在组建通信时讲解)
- 按钮修饰符
- Vue语法
| 1 | <button v-on:click="handler"> Click Me </button> | 
- 简写:省略 v-on:修改为@
| 1 | <button @click="handler"> Click Me </button> | 
5.1. 内联事件处理器
内联事件处理器:指的是在
HTML元素中指定事件监听函数,类似于JavaScript的onclick事件。
假设我们现在通过 内联事件处理器 实现点击按钮数字+1
- HTML模板
| 1 | <body> | 
- Vue实例和数据
| 1 | <script> | 
- 结果

5.2. 方法事件处理器
方法事件处理器:如果简单的案例可以通过
内联事件处理器进行解决,但业务一旦复杂,那么内联事件处理器的劣势(不够灵活)就出来了。这个时候我们将点击事件的处理逻辑提出来抽成一个方法,就形成了方法事件处理器。
 假设我们现在通过 方法事件处理器 实现点击按钮数字+1。如下的案例虽然很简单,但是后续我们
- HTML模板
| 1 | <body> | 
- Vue实例和数据
| 1 | <script> | 
- 结果

6. 计算属性
计算属性:我们在开发中,无法避免两个属性发生计算的,一旦某个属性的值发生变化,那么他们计算出来的结果也一定会发生变化,这个时候就需要使用到属性计算了。
6.1. computed
computed:当其依赖的属性的值发生变化的时,计算属性会重新计算。
- 语法
| 1 | export default { | 
假设我们需要判断当前数组的数量是否显示元素,不使用 计算属性 computed
- HTML模板
| 1 | <body> | 
- Vue实例和数据
| 1 | <script> | 
- 结果

假设我们需要判断当前数组的数量是否显示元素,使用 计算属性 computed
计算属性带来的优点
- 复用性高:如果在后期我们使用组件开发,那将会导致大量的冗余代码。如果使用 computed把复杂的逻辑封装为一个属性,使模板中的代码更简洁、易读。
- 性能提高: 计算属性具有自动缓存机制,只有当其依赖的响应式数据发生变化时,才会重新计算。
使用 computed 修改之后的代码如下
- HTML模板
| 1 | <body> | 
- Vue实例和数据
| 1 | <script> | 
7. 监听器
监听器:监听观察某个事件(程序)发生变化时,事件发生者(事件源) 就会给注册该事件的监听者(监听器)发送消息,告诉监听者某些信息已经发生变化了。
7.1. watch
watch:在
Vue中,监听器通常指的是watch去监听属性来响应数据的变化。
- 浅层监听器语法
| 1 | export default { | 
- 深层监听器语法
| 1 | export default { | 
❔监听器和计算属性有什么区别呢
- 异步操作:如果说我们需要的数据发生变化需要调用外部 - API时,使用计算属性是不行的,因为计算属性采用的是同步,而监听器采用的异步。
- 监控多个数据变化:如果说我们需要监听多个数据源发生变化,并且只要其中一个数据发生变化时就执行操作。那么监听器是更加合适的。 
假设我们使用监听器实现登录功能,需求如下:
- 用户名长度必须大于5
- 密码长度必须大于8
- 登录按钮必须满足以上两个条件才可以登录
- HTML模板
| 1 | <body> | 
- Vue实例和数据
| 1 | 
 | 
- 结果

8. Class 与 Style 绑定
Class 与 Style 绑定:指的是将
HTML元素的样式与CSS类进行联动的过程。
8.1. Class 绑定
通过为 HTML 元素添加一个或多个类名,你可以将元素与预定义的
CSS样式规则关联起来。
- HTML模板
| 1 | <div class="box red-border"></div> | 
- CSS样式
| 1 | .box { | 
8.2. Style 绑定
内联样式是直接在 HTML 元素中使用
style属性来定义样式。
- HTML模板
| 1 | <div style="width: 100px; height: 100px; background-color: lightgray;"></div> | 
内联样式虽然灵活,但通常不推荐在大规模项目中频繁使用,因为它容易导致代码混乱,难以维护。
8.3. Vue 绑定  class
属性绑定的一个常见需求场景是操纵元素的
CSS class列表和内联样式,这个需求是非常常见的。例如我们需要通过按钮控制表单是需要编辑还是保存。
- 语法
| 1 | <div :class="{ active: isActive }"></div> | 
假设我们通过按钮控制字体的样式
- HTML模板
| 1 | <body> | 
- Vue实例和数据
| 1 | <script> | 
- css样式
| 1 | <style> | 
- 结果

如下代码还可以改写为如下样式
| 1 | <body> | 
9. 任务清单-案例
需求如下
- 通过输入框输入任务点,添加到任务列表中;
- 在添加的任务点通过按钮实现任务是否完成以及删除任务点;
- 统计已经完成的任务数量
- 需要将任务列表添加进缓存,实现关闭浏览器也可以展示任务清单列表
效果图如下:

- 实现前端页面 - HTML前端页面
 - 1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14- <body> 
 <div id="app">
 <h3>Todo 任务清单</h3>
 <input type="text" placeholder="回车添加任务清单" />
 <ul>
 <li>
 <span> 任务点 </span>
 <button> 是否完成 </button>
 <button> 删除任务 </button>
 </li>
 </ul>
 <p>已经完成的任务数量:0</p>
 </div>
 </body>
- 通过输入框输入任务点,添加到任务列表中 - HTML前端页面
 - 1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14- <body> 
 <div id="app">
 <h3>Todo 任务清单</h3>
 <input type="text" @keyup.enter="addTask" v-model="newTask" placeholder="回车添加任务清单" />
 <ul v-for="(task , index) in taskList" :key="index">
 <li>
 <span> {{ task.task }} </span>
 <button> 是否完成 </button>
 <button> 删除任务 </button>
 </li>
 </ul>
 <p>已经完成的任务数量:0</p>
 </div>
 </body>- Vue实例和数据
 - 1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20- <script> 
 new Vue({
 el: "#app",
 data() {
 return {
 newTask: '',
 taskList: []
 }
 },
 methods: {
 // 添加任务点
 addTask() {
 if(this.newTask.trim() !== ''){
 this.taskList.push({task: this.newTask});
 this.newTask = ''
 }
 }
 }
 })
 </script>- 结果
  
- 在添加的任务点通过按钮实现任务 是否完成 以及 删除任务 - HTML前端页面
 - 1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14- <body> 
 <div id="app">
 <h3>Todo 任务清单</h3>
 <input type="text" @keyup.enter="addTask" v-model="newTask" placeholder="回车添加任务清单" />
 <ul v-for="(task , index) in taskList" :key="index">
 <li>
 <span :class="{ active: task.isActive }"> {{ task.task }} </span>
 <button @click="completedTask(task)">是否完成</button>
 <button @click="removeTask(index)">删除任务</button>
 </li>
 </ul>
 <p>已经完成的任务数量:0</p>
 </div>
 </body>- CSS样式
 - 1 
 2
 3
 4
 5
 6
 7- <style> 
 .active{
 color: green;
 text-decoration: line-through;
 }
 </style>- Vue实例和数据
 - 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- <script> 
 new Vue({
 el: "#app",
 data() {
 return {
 newTask: '',
 taskList: []
 }
 },
 methods: {
 // 添加任务点
 addTask() {
 if(this.newTask.trim() !== ''){
 this.taskList.push({task: this.newTask, isActive: false});
 this.newTask = ''
 }
 },
 // 是否完成
 completedTask(task) {
 task.isActive = !task.isActive
 },
 // 删除任务
 removeTask(index) {
 this.taskList.splice(index, 1);
 }
 }
 })
 </script>- 结果  
 
- 统计已经完成的任务数量 - HTML模板
 - 1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14- <body> 
 <div id="app">
 <h3>Todo 任务清单</h3>
 <input type="text" @keyup.enter="addTask" v-model="newTask" placeholder="回车添加任务清单" />
 <ul v-for="(task , index) in taskList" :key="index">
 <li>
 <span :class="{ active: task.isActive }"> {{ task.task }} </span>
 <button @click="completedTask(task)">是否完成</button>
 <button @click="removeTask(index)">删除任务</button>
 </li>
 </ul>
 <p>已经完成的任务数量:{{ finishedTotal }}</p>
 </div>
 </body>- Vue实例和数据
 - 1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11- <script> 
 new Vue({
 el: "#app",
 // 属性计算
 computed: {
 finishedTotal() {
 return this.taskList.filter(item => item.isActive).length;
 }
 }
 })
 </script>- 结果
  
- 需要将任务列表添加进缓存,实现关闭浏览器也可以展示任务清单列表 - Vue实例和数据
 - 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- <script> 
 new Vue({
 el: "#app",
 data() {
 return {
 newTask: '',
 taskList: []
 }
 },
 // 监听数组
 watch: {
 taskList: {
 handler(newTaskList, oldTaskList) {
 localStorage.setItem('taskList', JSON.stringify(newTaskList));
 },
 deep: true
 }
 },
 // 在生命周期中会讲到 created
 created() {
 const storedTasks = JSON.parse(localStorage.getItem("taskList"));
 if (storedTasks) {
 this.taskList = storedTasks;
 }
 }
 })
 </script>- 结果
  







