vue-day02

目录

2指令修饰符

问题:

3v-bind

问题:

4v-model应用于其它表单元素

问题

5计算属性

问题

6成绩案例

7watch监视器-简写-语法

问题

8wathc完整版

问题

9水果购物车

问题

总结


2指令修饰符

问题:

1@keyup.enter就相当于 @keyup然后在绑定的方法里面加上if(e.key=='enter')判断才进行下一步操作

2v-model:双向绑定的数据默认是String类型,想要输入数值的话得使用v-model.number

3.stop可以阻止冒泡行为,就是如果内外两层甚至多层有同一个类似于鼠标点击事件的话,只会执行最内层的

4.prevetn是阻止默认行为,尝应用在@submit.prevent中,因为在传统的html的表单提交会默认导致页面刷新,而.prevent就是阻止默认行为的

3v-bind

问题:

第三张图片的@click是activeIndex=index(可以实现点击切换)

transition: all 1s//这可可以添加动画效果,如进度条不是直接变化,而是缓慢变化

4v-model应用于其它表单元素

问题

多个单选框怎么确定是同一范围的,使用相同的name=""来进行控制同一组别,使用value用于提交给后台数据,要不然表单不知道选择这个单选框要提交什么,同理select里面的option标签的value值也是如此

5计算属性

问题

在差值表达式中使用totalCount为什么不需要加()?

因为它是一个属性

reduce如何使用?

int total=this.list.reduce((sum,item)=>sum+item.num,0)//sum表示累加器,item表示正在处理的数组元素,=>{}里面是处理逻辑,最后面是初始值

6成绩案例

7watch监视器-简写-语法

问题

属性名要和上面相同

如果不是data的子对象,而是子对象的子属性,该怎么办?

一是绑定要换成 子对象.属性名,下面就是引号里面写这样即可

防抖操作,延时函数,另外还需要清空函数,要不然最后延时的结果还是会输出,加上清空就好多了

8wathc完整版

问题

因为watch是只有数据被修改才会执行,那么我想在一刷新浏览器就执行该怎么办?

immediate:true即可

9水果购物车

问题

item.isChecked是bool类型,在标签里面设置v-model=item.isChecked就是为true才绑定,同理:class="{active:item.isChecked}"也是这个意思(active是高亮显示)

:disabled="item.num<=1"可以设置当个数小于等于1的时候就禁止再按了

data属性里面fruitList后面加个||defaultArr

总结

上面看懂下面可以不看

Vue 核心知识点深度总结:从基础到实战的全面解析

在前端开发领域,Vue.js 凭借其易用性、灵活性和高效性,成为了开发者们青睐的框架之一。本文将围绕 Vue 的核心知识点,从指令、数据绑定、计算属性到实战案例,进行一次全面且深入的总结,帮助大家夯实 Vue 基础,提升实战能力。

一、课程介绍

Vue 是一款渐进式 JavaScript 框架,所谓 "渐进式",意味着我们可以根据项目需求,逐步引入 Vue 的功能。它的核心库只关注视图层,易于上手,同时也能通过丰富的生态系统构建复杂的单页应用。

Vue 的核心优势在于:

响应式数据绑定:当数据发生变化时,视图会自动更新,无需手动操作 DOM。

组件化开发:将页面拆分为可复用的组件,提高代码的可维护性和复用性。

轻量级:体积小,加载速度快,性能出色。

丰富的生态:拥有 Vue Router(路由)、Vuex(状态管理)、Vue CLI(脚手架)等周边工具,能满足各种项目需求。

学习 Vue,我们可以从基础的指令、数据绑定开始,逐步深入到组件通信、状态管理,最后通过实战案例将知识融会贯通。

二、指令修饰符

Vue 指令是带有v-前缀的特殊属性,它们提供了便捷的 DOM 操作和数据响应式能力。而指令修饰符则是对指令功能的扩展,以.的形式附加在指令后面,用于处理一些常见的场景,让代码更加简洁高效。

2.1 事件修饰符

在v-on(简写为@)指令中,事件修饰符可以帮助我们处理事件的冒泡、默认行为等。

.stop:阻止事件冒泡。例如,在一个嵌套的元素中,点击子元素时,父元素的点击事件不会触发。

vue

<div @click="parentClick">

<button @click.stop="childClick">点击我</button>

</div>

.prevent:阻止事件的默认行为,如表单提交的刷新页面。

vue

<form @submit.prevent="submitForm">

<button type="submit">提交</button>

</form>

.capture:使用事件捕获模式,即事件从外层元素向目标元素传播时触发。

.self:只有当事件是从当前元素本身触发时才会触发回调。

.once:事件只触发一次。

2.2 按键修饰符

用于监听键盘事件时,对特定按键进行过滤。

常见的按键别名:.enter、.tab、.delete(捕获 "删除" 和 "退格" 键)、.esc、.space、.up、.down、.left、.right。

vue

<input @keyup.enter="submit">

还可以自定义按键别名,通过Vue.config.keyCodes来设置。

2.3 表单修饰符

在v-model指令中,表单修饰符用于处理表单元素的数据绑定。

.lazy:将输入事件的同步时机从 "输入时" 改为 "失焦时",减少数据更新的频率。

vue

<input v-model.lazy="msg">

.number:将输入的值转换为数字类型。如果输入的内容无法被解析为数字,就会返回原始的字符串。

vue

<input v-model.number="age" type="number">

.trim:自动过滤输入内容的首尾空格。

vue

<input v-model.trim="username">

三、v-bind

v-bind指令用于动态地绑定一个或多个属性,或者向组件传递 props。它的简写形式是:。

3.1 绑定 HTML 属性

可以绑定元素的任何 HTML 属性,如class、style、src、href等。

vue

<img :src="imageUrl" :alt="imageAlt">

<a :href="linkUrl">链接</a>

3.2 绑定 Class

绑定class有多种方式,非常灵活。

对象语法:根据对象的属性值是否为true,来决定是否添加对应的类名。

vue

<div :class="{ active: isActive, 'text-danger': hasError }"></div>

数组语法:可以将多个类名放在一个数组中进行绑定。

vue

<div :class="[activeClass, errorClass]"></div>

数组与对象语法结合:在数组中可以嵌套对象语法。

vue

<div :class="[{ active: isActive }, errorClass]"></div>

3.3 绑定 Style

绑定style同样支持对象语法和数组语法。

对象语法:直接将样式对象绑定到元素上。

vue

<div :style="{ color: textColor, fontSize: fontSize + 'px' }"></div>

数组语法:可以将多个样式对象数组合并。

vue

<div :style="[baseStyles, overridingStyles]"></div>

自动添加前缀:当绑定的 CSS 属性需要浏览器前缀时,Vue 会自动为其添加合适的前缀。

3.4 向组件传递 Props

在组件中,使用v-bind向子组件传递 props 数据。

vue

<child-component :message="parentMsg" :user="currentUser"></child-component>

四、v-model 应用于其它表单元素

v-model是 Vue 中用于实现表单元素双向数据绑定的指令,它不仅可以用于input、textarea、select等常见表单元素,还可以应用于一些自定义组件,实现数据的双向同步。

4.1 基本表单元素的 v-model

文本输入框(input [type="text"])和文本域(textarea):

vue

<input v-model="message" placeholder="请输入">

<textarea v-model="message" rows="3"></textarea>

单选按钮(input [type="radio"]):

vue

<input type="radio" id="male" value="male" v-model="gender">

<label for="male">男</label>

<input type="radio" id="female" value="female" v-model="gender">

<label for="female">女</label>

复选框(input [type="checkbox"]):

单个复选框,绑定布尔值:

vue

<input type="checkbox" id="agree" v-model="isAgree">

<label for="agree">同意协议</label>

多个复选框,绑定数组:

vue

<input type="checkbox" id="apple" value="apple" v-model="fruits">

<label for="apple">苹果</label>

<input type="checkbox" id="banana" value="banana" v-model="fruits">

<label for="banana">香蕉</label>

下拉选择框(select):

单选:

vue

<select v-model="selected">

<option value="">请选择</option>

<option value="vue">Vue</option>

<option value="react">React</option>

</select>

多选(绑定数组):

vue

<select v-model="selected" multiple>

<option value="vue">Vue</option>

<option value="react">React</option>

<option value="angular">Angular</option>

</select>

4.2 v-model 的原理

v-model实际上是v-bind和v-on的语法糖。对于输入框来说,大致等价于:

vue

<input :value="message" @input="message = $event.target.value">

其中,input事件是在输入框内容变化时触发的,将输入框的当前值赋值给message变量,从而实现双向绑定。

4.3 自定义组件的 v-model

在自定义组件中,可以通过model选项来定制v-model的 prop 和事件。默认情况下,自定义组件的v-model会使用value作为 prop,并以input事件作为触发事件。

vue

// 子组件

Vue.component('custom-input', {

model: {

prop: 'checked',

event: 'change'

},

props: {

checked: Boolean

},

template: `

<input

type="checkbox"

:checked="checked"

@change="emit('change', event.target.checked)"

>

`

})

// 父组件使用

<custom-input v-model="isChecked"></custom-input>

这样,在父组件中使用v-model时,就会将isChecked的值传递给子组件的checked prop,并且子组件触发change事件时,会更新isChecked的值。

五、计算属性

计算属性是 Vue 中用于处理复杂数据逻辑的重要工具,它基于响应式依赖进行缓存,只有当依赖的数据发生变化时,才会重新计算,从而提高性能。

5.1 基本用法

在 Vue 实例的computed选项中定义计算属性,它的使用方式和普通属性一样。

vue

<div id="app">

<p>原始消息: {{ message }}</p>

<p>反转后的消息: {{ reversedMessage }}</p>

</div>

<script>

new Vue({

el: '#app',

data: {

message: 'Hello Vue!'

},

computed: {

reversedMessage: function () {

return this.message.split('').reverse().join('')

}

}

})

</script>

在上面的例子中,reversedMessage是一个计算属性,它依赖于message的值。当message发生变化时,reversedMessage会自动重新计算。

5.2 计算属性的缓存 vs 方法

我们也可以通过方法来实现和计算属性相同的功能:

vue

<p>反转后的消息: {{ reverseMessage() }}</p>

<script>

methods: {

reverseMessage: function () {

return this.message.split('').reverse().join('')

}

}

</script>

但是,计算属性和方法的主要区别在于缓存。计算属性会根据其依赖的响应式数据进行缓存,只有当依赖变化时才会重新计算;而方法在每次调用时都会重新执行函数。因此,对于复杂的计算逻辑,使用计算属性可以提高性能。

5.3 计算属性的 setter

计算属性默认只有 getter,但我们也可以为其设置 setter,使其支持双向数据绑定。

vue

computed: {

fullName: {

// getter

get: function () {

return this.firstName + ' ' + this.lastName

},

// setter

set: function (newValue) {

var names = newValue.split(' ')

this.firstName = names[0]

this.lastName = names[names.length - 1]

}

}

}

当我们对fullName进行赋值时,setter 会被调用,从而更新firstName和lastName的值。

5.4 计算属性的应用场景

计算属性适用于以下场景:

对现有数据进行格式化处理,如日期格式化、字符串拼接等。

根据多个数据的组合计算出一个新的值。

处理需要缓存的复杂逻辑,避免重复计算。

例如,在一个购物车页面中,我们可以使用计算属性来计算商品的总价:

vue

computed: {

totalPrice: function () {

return this.cartItems.reduce((total, item) => {

return total + item.price * item.quantity

}, 0)

}

}

六、成绩案例

为了更好地理解 Vue 的核心知识点,我们通过一个 "成绩案例" 来进行实战演练。这个案例主要实现一个学生成绩的录入、展示和统计功能,涉及到数据绑定、计算属性、表单处理等知识点。

6.1 需求分析

可以录入学生的姓名和各科成绩(数学、语文、英语)。

实时计算每个学生的总分和平均分。

可以删除学生信息。

统计所有学生的各科总分、平均分以及整体的总分和平均分。

6.2 代码实现

vue

<div id="app">

<h2>学生成绩管理系统</h2>

<form @submit.prevent="addStudent">

<div class="form-group">

<label>姓名:</label>

<input type="text" v-model="newStudent.name" placeholder="请输入姓名" required>

</div>

<div class="form-group">

<label>数学:</label>

<input type="number" v-model.number="newStudent.math" placeholder="请输入数学成绩" min="0" max="100" required>

</div>

<div class="form-group">

<label>语文:</label>

<input type="number" v-model.number="newStudent.chinese" placeholder="请输入语文成绩" min="0" max="100" required>

</div>

<div class="form-group">

<label>英语:</label>

<input type="number" v-model.number="newStudent.english" placeholder="请输入英语成绩" min="0" max="100" required>

</div>

<button type="submit">添加学生</button>

</form>

<table border="1" cellpadding="10" cellspacing="0">

<thead>

<tr>

<th>姓名</th>

<th>数学</th>

<th>语文</th>

<th>英语</th>

<th>总分</th>

<th>平均分</th>

<th>操作</th>

</tr>

</thead>

<tbody>

<tr v-for="(student, index) in students" :key="index">

<td>{{ student.name }}</td>

<td>{{ student.math }}</td>

<td>{{ student.chinese }}</td>

<td>{{ student.english }}</td>

<td>{{ student.total }}</td>

<td>{{ student.average }}</td>

<td><button @click="deleteStudent(index)">删除</button></td>

</tr>

</tbody>

<tfoot v-if="students.length > 0">

<tr>

<td>总计</td>

<td>{{ totalMath }}</td>

<td>{{ totalChinese }}</td>

<td>{{ totalEnglish }}</td>

<td>{{ totalAll }}</td>

<td>{{ averageAll }}</td>

<td></td>

</tr>

</tfoot>

</table>

</div>

<script>

new Vue({

el: '#app',

data: {

students: [],

newStudent: {

name: '',

math: 0,

chinese: 0,

english: 0

}

},

computed: {

totalMath: function () {

return this.students.reduce((total, student) => total + student.math, 0)

},

totalChinese: function () {

return this.students.reduce((total, student) => total + student.chinese, 0)

},

totalEnglish: function () {

return this.students.reduce((total, student) => total + student.english, 0)

},

totalAll: function () {

return this.totalMath + this.totalChinese + this.totalEnglish

},

averageAll: function () {

return (this.totalAll / (this.students.length * 3)).toFixed(2)

}

},

methods: {

addStudent: function () {

// 计算总分和平均分

const total = this.newStudent.math + this.newStudent.chinese + this.newStudent.english

const average = (total / 3).toFixed(2)

// 将新学生对象添加到students数组中

this.students.push({

...this.newStudent,

total: total,

average: average

})

// 清空表单

this.newStudent = {

name: '',

math: 0,

chinese: 0,

english: 0

}

},

deleteStudent: function (index) {

this.students.splice(index, 1)

}

}

})

</script>

<style>

.form-group {

margin-bottom: 10px;

}

label {

display: inline-block;

width: 50px;

}

input {

width: 150px;

padding: 5px;

}

button {

padding: 5px 10px;

cursor: pointer;

}

table {

margin-top: 20px;

}

</style>

6.3 代码解析

数据绑定:通过v-model实现表单元素与newStudent对象的双向绑定,方便数据的录入。

计算属性:使用计算属性来计算每个学生的总分、平均分以及所有学生的各科总计、整体平均分,这样当学生数据发生变化时,这些统计数据会自动更新。

列表渲染:通过v-for指令遍历students数组,展示每个学生的成绩信息。

事件处理:使用@submit.prevent阻止表单的默认提交行为,通过@click事件实现删除学生的功能。

这个案例综合运用了 Vue 的多个核心知识点,展示了如何将理论知识应用到实际项目中,实现一个具有实用功能的小应用。

七、watch 监视器 - 简写 - 语法

watch是 Vue 中用于监听数据变化的选项,它可以让我们在数据发生变化时执行相应的操作。除了完整的对象语法外,Vue 还提供了简写的语法,让代码更加简洁。

7.1 基本用法(简写)

当我们只需要在数据变化时执行一个函数,而不需要其他配置(如deep、immediate等)时,可以使用简写语法,直接将监听的属性名作为键,对应的处理函数作为值。

vue

<div id="app">

<input v-model="message">

<p>消息长度:{{ messageLength }}</p>

</div>

<script>

new Vue({

el: '#app',

data: {

message: '',

messageLength: 0

},

watch: {

// 简写语法,监听message的变化

message: function (newVal, oldVal) {

this.messageLength = newVal.length

}

}

})

</script>

在上面的例子中,当message的值发生变化时,watch中的处理函数会被调用,更新messageLength的值。

7.2 与计算属性的区别

watch和计算属性都可以用于处理数据变化,但它们的适用场景有所不同:

计算属性:适用于根据已有数据计算出一个新的数据,并且这个新数据会被多次使用的场景。它是响应式的,会自动更新。

watch:适用于数据变化时需要执行异步操作(如发送请求)、执行复杂的业务逻辑或需要获取数据变化前后的值的场景。

例如,当我们需要根据用户的输入去请求后端数据时,使用watch更为合适:

vue

watch: {

searchKeyword: function (newVal) {

// 发送异步请求

axios.get('/api/search', {

params: { keyword: newVal }

}).then(response => {

this.searchResults = response.data

})

}

}

7.3 注意事项

简写语法只能监听顶层属性的变化,对于嵌套对象或数组中的属性变化,需要使用完整的对象语法并设置deep: true。

在简写语法中,处理函数的第一个参数是新值(newVal),第二个参数是旧值(oldVal)。

八、watch 完整版

虽然简写语法在很多场景下已经足够使用,但在一些复杂的场景中,我们需要使用watch的完整版语法,来配置更多的选项,如deep(深度监听)、immediate(立即执行)等。

8.1 完整语法的结构

vue

watch: {

// 要监听的属性名

propertyName: {

// 处理函数,newVal是新值,oldVal是旧值

handler: function (newVal, oldVal) {

// 处理逻辑

},

// 是否深度监听(对于对象或数组,监听其内部属性的变化)

deep: Boolean,

// 是否在初始化时立即执行一次处理函数

immediate: Boolean

}

}

8.2 深度监听(deep)

当我们需要监听一个对象或数组内部属性的变化时,需要设置deep: true。

vue

<div id="app">

<input v-model="user.name">

<input v-model="user.age">

<p>用户信息:{{ user }}</p>

</div>

<script>

new Vue({

el: '#app',

data: {

user: {

name: '张三',

age: 20

}

},

watch: {

user: {

handler: function (newVal, oldVal) {

console.log('用户信息发生变化', newVal, oldVal)

},

deep: true // 深度监听,监听user对象内部属性的变化

}

}

})

</script>

在上面的例子中,无论是user.name还是user.age发生变化,watch的处理函数都会被触发。

8.3 立即执行(immediate)

默认情况下,watch的处理函数只会在数据发生变化时执行。如果我们需要在组件初始化时就立即执行一次处理函数,可以设置immediate: true。

vue

watch: {

message: {

handler: function (newVal) {

console.log('消息变为:', newVal)

},

immediate: true // 初始化时立即执行一次

}

}

这样,在组件创建时,即使message的值还没有变化,处理函数也会执行一次,打印出初始的message值。

8.4 监听多个属性

如果需要监听多个属性的变化,并执行同一个处理函数,可以将这些属性的监听配置合并。

vue

watch: {

'user.name': {

handler: function (newVal) {

console.log('用户名变化:', newVal)

},

immediate: true

},

'user.age': {

handler: function (newVal) {

console.log('用户年龄变化:', newVal)

},

immediate: true

}

}

或者,也可以通过一个函数来处理多个属性的变化:

vue

methods: {

handleUserChange: function (newVal, oldVal, propName) {

console.log(`用户${propName}变化:`, newVal)

}

},

watch: {

'user.name': function (newVal, oldVal) {

this.handleUserChange(newVal, oldVal, 'name')

},

'user.age': function (newVal, oldVal) {

this.handleUserChange(newVal, oldVal, 'age')

}

}

九、水果购物车

为了进一步巩固 Vue 的知识,我们来实现一个 "水果购物车" 案例。这个案例将涉及到组件化、状态管理(简单版)、事件通信等知识点,是一个比较综合的实战项目。

9.1 需求分析

展示水果列表,包含水果名称、价格和图片。

可以将水果添加到购物车,选择购买数量。

购物车中可以修改水果数量,也可以删除水果。

实时计算购物车中水果的总价。

9.2 代码实现

我们将项目拆分为两个组件:FruitList(水果列表组件)和ShoppingCart(购物车组件),以及一个父组件App来管理整体数据和状态。

9.2.1 FruitList 组件

vue

<template>

<div class="fruit-list">

<h3>水果列表</h3>

<div class="fruit-item" v-for="fruit in fruits" :key="fruit.id">

<img :src="fruit.image" alt="fruit.image">

<div class="fruit-info">

<h4>{{ fruit.name }}</h4>

<p>价格:{{ fruit.price }}元/斤</p>

<button @click="addToCart(fruit)">加入购物车</button>

</div>

</div>

</div>

</template>

<script>

export default {

name: 'FruitList',

props: {

fruits: {

type: Array,

default: () => []

}

},

methods: {

addToCart(fruit) {

this.$emit('add-to-cart', fruit)

}

}

}

</script>

<style scoped>

.fruit-list {

float: left;

width: 60%;

margin-right: 20px;

}

.fruit-item {

display: flex;

margin-bottom: 20px;

border: 1px solid #eee;

padding: 10px;

border-radius: 5px;

}

.fruit-item img {

width: 100px;

height: 100px;

object-fit: cover;

margin-right: 10px;

}

.fruit-info button {

background-color: #42b983;

color: white;

border: none;

padding: 5px 10px;

border-radius: 3px;

cursor: pointer;

}

</style>

9.2.2 ShoppingCart 组件

vue

<template>

<div class="shopping-cart">

<h3>购物车</h3>

<div v-if="cartItems.length === 0">购物车为空</div>

<table v-else border="1" cellpadding="10" cellspacing="0">

<thead>

<tr>

<th>水果名称</th>

<th>单价</th>

<th>数量</th>

<th>小计</th>

<th>操作</th>

</tr>

</thead>

<tbody>

<tr v-for="(item, index) in cartItems" :key="index">

<td>{{ item.name }}</td>

<td>{{ item.price }}</td>

<td>

<button @click="decreaseQuantity(index)" :disabled="item.quantity <= 1">-</button>

{{ item.quantity }}

<button @click="increaseQuantity(index)">+</button>

</td>

<td>{{ item.price * item.quantity }}</td>

<td><button @click="removeItem(index)">删除</button></td>

</tr>

</tbody>

<tfoot>

<tr>

<td colspan="3">总计</td>

<td>{{ totalPrice }}</td>

<td></td>

</tr>

</tfoot>

</table>

</div>

</template>

<script>

export default {

name: 'ShoppingCart',

props: {

cartItems: {

type: Array,

default: () => []

}

},

computed: {

totalPrice() {

return this.cartItems.reduce((total, item) => {

return total + item.price * item.quantity

}, 0)

}

},

methods: {

decreaseQuantity(index) {

this.$emit('decrease-quantity', index)

},

increaseQuantity(index) {

this.$emit('increase-quantity', index)

},

removeItem(index) {

this.$emit('remove-item', index)

}

}

}

</script>

<style scoped>

.shopping-cart {

float: left;

width: 35%;

}

table button {

width: 20px;

height: 20px;

padding: 0;

cursor: pointer;

}

</style>

9.2.3 App 父组件

vue

<template>

<div id="app">

<h2>水果购物车</h2>

<fruit-list :fruits="fruits" @add-to-cart="handleAddToCart"></fruit-list>

<shopping-cart

:cartItems="cartItems"

@decrease-quantity="handleDecreaseQuantity"

@increase-quantity="handleIncreaseQuantity"

@remove-item="handleRemoveItem"

></shopping-cart>

</div>

</template>

<script>

import FruitList from './components/FruitList.vue'

import ShoppingCart from './components/ShoppingCart.vue'

export default {

name: 'App',

components: {

FruitList,

ShoppingCart

},

data() {

return {

fruits: [

{ id: 1, name: '苹果', price: 5, image: 'https://images.unsplash.com/photo-1567306301408-9b74779a11af?ixlib=rb-4.0.3\&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fDE2OTg1NTA1ODl8\&auto=format\&fit=crop\&w=1170\&q=80' },

{ id: 2, name: '香蕉', price: 3, image: 'https://images.unsplash.com/photo-1571902943202-507ec2618e8f?ixlib=rb-4.0.3\&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fDE2OTg1NTA2MjN8\&auto=format\&fit=crop\&w=1170\&q=80' },

{ id: 3, name: '橙子', price: 6, image: 'https://images.unsplash.com/photo-1567306301408-9b74779a11af?ixlib=rb-4.0.3\&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fDE2OTg1NTA1ODl8\&auto=format\&fit=crop\&w=1170\&q=80' }

],

cartItems: []

}

},

methods: {

handleAddToCart(fruit) {

const existingItem = this.cartItems.find(item => item.id === fruit.id)

if (existingItem) {

existingItem.quantity++

} else {

this.cartItems.push({

...fruit,

quantity: 1

})

}

},

handleDecreaseQuantity(index) {

this.cartItems[index].quantity--

if (this.cartItems[index].quantity === 0) {

this.cartItems.splice(index, 1)

}

},

handleIncreaseQuantity(index) {

this.cartItems[index].quantity++

},

handleRemoveItem(index) {

this.cartItems.splice(index, 1)

}

}

}

</script>

<style>

#app {

max-width: 1200px;

margin: 0 auto;

padding: 20px;

}

</style>

9.3 代码解析

组件化:将页面拆分为FruitList和ShoppingCart两个组件,分别负责水果列表的展示和购物车的功能,提高了代码的可维护性和复用性。

数据传递:父组件App通过 props 向子组件传递数据(如fruits和cartItems),子组件通过自定义事件(如@add-to-cart)向父组件传递操作(如添加商品到购物车)。

状态管理:在父组件中管理购物车的状态(cartItems),子组件通过修改父组件的状态来实现购物车的功能。

计算属性:在ShoppingCart组件中使用计算属性totalPrice来实时计算购物车的总价。

通过这个 "水果购物车" 案例,我们可以看到 Vue 在实战中的强大能力,它能够帮助我们快速构建出交互丰富、功能完整的 Web 应用。

总结

本文对 Vue 的核心知识点进行了全面的总结,从指令修饰符、v-bind、v-model到计算属性、watch监视器,再到两个实战案例(成绩管理和水果购物车),涵盖了 Vue 从基础到进阶的主要内容。

学习 Vue,关键在于理解其响应式原理和组件化思想,通过不断的实践来巩固和深化对知识的理解。希望本文能够为大家的 Vue 学习之旅提供有益的参考,帮助大家在前端开发的道路上不断进步。

相关推荐
一只小阿乐3 小时前
vue3 中实现父子组件v-model双向绑定 总结
前端·javascript·vue.js·vue3·组件·v-model语法糖
星光一影3 小时前
快递比价寄件系统技术解析:基于PHP+Vue+小程序的高效聚合配送解决方案
vue.js·mysql·小程序·php
qq_338032923 小时前
Vue 3 的<script setup> 和 Vue 2 的 Options API的关系
前端·javascript·vue.js
擦拉嘿3 小时前
Days.js实时更新时间格式文案在切换全局语言之后的方案
vue.js·days.js·动态更新时间
lumi.3 小时前
Vue Router页面跳转指南:告别a标签,拥抱组件化无刷新跳转
前端·javascript·vue.js
yeyuningzi3 小时前
VUE 运行npm run dev命令提示error Missing script: “dev“
前端·vue.js·npm
Mintopia3 小时前
🧠 一文吃透 Next.js 中的 JWT vs Session:底层原理+幽默拆解指南
前端·javascript·全栈
葛小白13 小时前
Winform控件:Combobox
前端·ui·c#·combobox
政采云技术3 小时前
前端设计模式详解
前端·设计模式