前端Vue日常工作中--computed计算属性
Vue.js 中的计算属性是一种方便的属性,它允许你基于响应式数据进行动态计算,值会根据其依赖的数据动态计算而来,并且会被缓存,只有相关依赖发生改变时才会重新计算。
1.基本语法
Vue 组件的 computed
选项中,你可以定义计算属性,并提供一个函数来计算属性的值。计算属性会被视为响应式依赖,只有当计算属性内部依赖的数据发生变化时,计算属性才会重新计算。
vue
<template>
<div>
<p>Radius: {{ radius }}</p>
<p>Area: {{ area }}</p>
</div>
</template>
<script>
export default {
data() {
return {
radius: 5
};
},
computed: {
area() {
return Math.PI * Math.pow(this.radius, 2);
}
}
};
</script>
area
是一个计算属性,它基于 radius
计算圆的面积。每当 radius
变化时,area
会自动重新计算。
1.1计算属性的 getter 和 setter
计算属性还可以包含 getter 和 setter,使其更灵活。
vue
<template>
<div>
<p>First Name: {{ firstName }}</p>
<p>Last Name: {{ lastName }}</p>
<input v-model="fullName">
</div>
</template>
<script>
export default {
data() {
return {
firstName: 'WW',
lastName: 'BB'
};
},
computed: {
fullName: {
// getter
get() {
return this.firstName + ' ' + this.lastName;
},
// setter
set(value) {
const names = value.split(' ');
this.firstName = names[0];
this.lastName = names[names.length - 1];
}
}
}
};
</script>
fullName
计算属性包含了 getter 和 setter。当你读取 fullName
时,它会返回 firstName
和 lastName
的组合,当你设置 fullName
时,会解析输入的值并更新 firstName
和 lastName
。
1.2在父子组件中使用计算属性:
父组件
html
<template>
<div>
<child-component :first-name="firstName" :last-name="lastName"></child-component>
<p>{{ fullName }}</p>
</div>
</template>
<script>
import ChildComponent from './ChildComponent.vue';
export default {
components: {
ChildComponent
},
data() {
return {
firstName: 'WW',
lastName: 'BB'
};
},
computed: {
fullName() {
return this.firstName + ' ' + this.lastName;
}
}
};
</script>
子组件
html
<template>
<div>
<p>{{ childFullName }}</p>
</div>
</template>
<script>
export default {
props: ['firstName', 'lastName'],
computed: {
childFullName() {
return this.firstName + ' ' + this.lastName;
}
}
};
</script>
父组件通过 props 将 firstName
和 lastName
传递给子组件。子组件使用这些 props 来计算自己的 childFullName
计算属性。每当父组件的 firstName
或 lastName
改变时,子组件的 childFullName
也会随之更新。
2.一些计算属性的使用场景
-
数据转换: 用于对已有的数据进行计算,生成新的数据。
-
过滤和排序: 在显示列表时,可以使用计算属性对数据进行过滤或排序。
-
表单处理: 对表单输入进行实时验证或处理时,计算属性提供了方便的方式。
-
复杂逻辑的封装: 当有复杂的逻辑需要基于多个响应式数据进行计算时,使用计算属性可以使代码更清晰。
1. 数据转换:
商店中,每个产品都有一个价格和折扣。现希望计算每个产品的实际价格,即价格减去折扣。
vue
<template>
<div>
<ul>
<li v-for="product in products" :key="product.id">
{{ product.name }} - Original Price: {{ product.price }} - Discounted Price: {{ discountedPrice(product) }}
</li>
</ul>
</div>
</template>
<script>
export default {
data() {
return {
products: [
{ id: 1, name: 'Product A', price: 100, discount: 20 },
{ id: 2, name: 'Product B', price: 150, discount: 30 },
// ... other products
]
};
},
computed: {
discountedPrices() {
return this.products.map(product => this.discountedPrice(product));
}
},
methods: {
discountedPrice(product) {
return product.price - product.discount;
}
}
};
</script>
discountedPrice
是一个计算属性,用于计算每个产品的折扣后价格。discountedPrices
计算属性则用于获取所有产品的折扣后价格。
2. 过滤和排序:
任务列表中,每个任务有一个状态(已完成、进行中、未开始),现希望能够根据状态过滤和排序任务列表。
vue
<template>
<div>
<select v-model="selectedStatus">
<option value="all">All</option>
<option value="completed">Completed</option>
<option value="inProgress">In Progress</option>
<option value="notStarted">Not Started</option>
</select>
<ul>
<li v-for="task in filteredTasks" :key="task.id">
{{ task.name }} - Status: {{ task.status }}
</li>
</ul>
</div>
</template>
<script>
export default {
data() {
return {
tasks: [
{ id: 1, name: 'Task A', status: 'completed' },
{ id: 2, name: 'Task B', status: 'inProgress' },
// ... other tasks
],
selectedStatus: 'all'
};
},
computed: {
filteredTasks() {
if (this.selectedStatus === 'all') {
return this.tasks;
} else {
return this.tasks.filter(task => task.status === this.selectedStatus);
}
}
}
};
</script>
filteredTasks
是一个计算属性,用于根据选定的状态过滤任务列表。用户通过下拉选择框选择任务状态,filteredTasks
计算属性会根据选择的状态动态更新任务列表。
3. 表单处理:
表单中包含两个输入框,分别用于输入用户名和邮箱。在用户输入时进行实时验证,并根据验证结果决定是否显示提交按钮。
vue
<template>
<div>
<label for="username">Username:</label>
<input v-model="username" id="username">
<label for="email">Email:</label>
<input v-model="email" id="email">
<button :disabled="!isFormValid">Submit</button>
</div>
</template>
<script>
export default {
data() {
return {
username: '',
email: ''
};
},
computed: {
isFormValid() {
return this.username.length > 0 && this.isValidEmail(this.email);
}
},
methods: {
isValidEmail(email) {
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
return emailRegex.test(email);
}
}
};
</script>
isFormValid
是一个计算属性,它根据输入的用户名和邮箱实时验证表单的有效性。如果用户名不为空且邮箱格式有效,则启用提交按钮。
4. 复杂逻辑的封装:
一个在线问卷调查,其中有一些问题需要根据先前问题的回答进行逻辑判断。如果用户选择 "有",那么显示下一个问题;如果选择 "无",则跳过下一个问题。
vue
<template>
<div>
<label>Have you used our product before?</label>
<select v-model="usedProduct">
<option value="yes">Yes</option>
<option value="no">No</option>
</select>
<div v-if="usedProduct === 'yes'">
<label>How satisfied are you with our product?</label>
<select v-model="satisfactionLevel">
<option value="verySatisfied">Very Satisfied</option>
<option value="satisfied">Satisfied</option>
<option value="neutral">Neutral</option>
<option value="dissatisfied">Dissatisfied</option>
<option value="veryDissatisfied">Very Dissatisfied</option>
</select>
</div>
<p v-if="showFeedbackMessage">Thank you for your feedback!</p>
</div>
</template>
<script>
export default {
data() {
return {
usedProduct: '',
satisfactionLevel: '',
};
},
computed: {
showFeedbackMessage() {
// 复杂的逻辑判断
return this.usedProduct === 'yes' && this.satisfactionLevel === 'verySatisfied';
}
}
};
</script>
showFeedbackMessage
是一个计算属性,它根据用户的回答进行复杂的逻辑判断。只有在用户使用过产品并且非常满意时,才显示感谢反馈的信息。