一、计算属性
1.1 计算属性与方法的区别:
- 两种方式在结果上确实是完全相同的,不同之处在于 计算属性值会基于其响应式依赖被缓存;
- 一个计算属性仅会在其响应式依赖更新时才重新计算,这意味着只要所依赖的数据源不改变,无论多少次访问计算属性都会立即返回先前的计算结果,而不用重复执行
getter
函数; - 方法调用总是会在重新渲染发生时再次执行函数;
1.2 组合式API
- 计算属性 - 语法:
- 简易写法:(getter):
- 只是使用计算属性的值不对其进行修改;
import { computed } fro 'vue' const 变量名 = computed(() => { // getter 必须要有return,可以简写成箭头函数 return xxx })
- 完整写法:(setter + getter):
- 既要使用计算属性的值,也要对其进行修改操作;
import { computed } from 'vue' const 变量名 = computed({ // 给计算属性赋值的时候触发 setter // value - 就是给计算属性赋的值 set(value) {}, // 使用计算属性的值的时候触发 getter // getter 中 必须要有 return get() { return xxx } })
- 简易写法:(getter):
- 注意:
- 计算属性默认是只读的,当我们尝试修改一个值的时候,会收到一个运行时警告。只会在某些特殊场景中可能才会需要用到“可写”的属性,可以通过同时提供
getter
和setter
创建; - 计算属性的
getter
应只做计算而没有任何其他的副作用;- 不要在
getter
中做 异步请求 或者 更改DOM;
- 不要在
- 避免直接修改计算属性值;
- 从计算属性返回的值是派生状态。可以把它看作是一个“临时快照”,每当原状态发生变化时,就会创建一个新的快照。更改快照是没有意义的,因此计算属性的返回值应该被视为只读的,并且永远不应该被更改——应该更新它所依赖的原状态以触发新的计算;
- 计算属性默认是只读的,当我们尝试修改一个值的时候,会收到一个运行时警告。只会在某些特殊场景中可能才会需要用到“可写”的属性,可以通过同时提供
- 示例展示:
- 全选 - 反选:
<script setup> import { ref, computed } from 'vue'; const animeArr = ref([ { name: '完美世界', role: '石昊', checked: false }, { name: '不良人', role: '李星云', checked: false }, { name: '遮天', role: '叶尘', checked: false } ]) // TODO 反选 const reverseSelect = () => { animeArr.value.forEach(item => item.checked = !item.checked) } // TODO 计算属性 let chooseAll = computed({ set(value) { animeArr.value.forEach(item => item.checked = value) }, get() { return animeArr.value.every(item => item.checked) } }); </script> <template> <h3>全选 / 反选 - demo</h3> <p> <label> 全选 : <input type="checkbox" v-model="chooseAll" :checked="chooseAll"> | <button @click="reverseSelect">反选</button> </label> </p> <p v-for="item in animeArr" :key="item.name"> <label> {{ `${item.name} ➡ ${item.role}` }} : <input type="checkbox" :checked="item.checked" v-model="item.checked"> </label> </p> </template> <style scoped> p { text-align: left; } </style>
- 根据日期判断星座:
<script setup> import { computed, ref } from 'vue' let birthday = ref('') // 生日 // 计算属性:星座 let constellation = computed(() => { // yyyy-MM-dd -> ['yyyy', 'MM', 'dd'] let birArr = birthday.value.split('-') // 月份 let month = parseInt(birArr[1]) // 日份 let day = parseInt(birArr[2]) // 判断 switch (month) { case 1: if (day <= 19) { return '魔羯座' } else { return '水平座' } case 2: if (day <= 18) { return '水平座' } else { return '双鱼座' } case 3: if (day <= 20) { return '双鱼座' } else { return '白羊座' } case 4: if (day <= 19) { return '白羊座' } else { return '金牛座' } case 5: if (day <= 20) { return '金牛座' } else { return '双子座' } case 6: if (day <= 21) { return '双子座' } else { return '巨蟹座' } case 7: if (day <= 22) { return '巨蟹座' } else { return '狮子座' } case 8: if (day <= 22) { return '狮子座' } else { return '处女座' } case 9: if (day <= 22) { return '处女座' } else { return '天秤座' } case 10: if (day <= 23) { return '天秤座' } else { return '天蝎座' } case 11: if (day <= 22) { return '天蝎座' } else { return '射手座' } case 12: if (day <= 21) { return '射手座' } else { return '魔羯座' } default: return '请选择日期' } }) </script> <template> <div> 生日:<input type="date" v-model="birthday"> <h3>星座:{{ constellation }}</h3> </div> </template>
- 全选 - 反选:
1.3 选项式API
- 选项式计算属性写法:
<script> export default { data: () => ({ test: '' }), computed: { test: () => 'xxx' } } </script>
- 示例展示:
<script> export default { data: () => ({ age: 20, // 年龄 birthday: '' // 生日 }), // 计算属性选项 computed: { // 年龄阶段 ageState() { if (this.age < 18) { return '未成年' } else if (this.age < 35) { return '青年' } else if (this.age < 50) { return '中年' } else { return '老年' } }, // 星座 constellation() { // yyyy-MM-dd -> ['yyyy', 'MM', 'dd'] let birArr = this.birthday.split('-') // 月份 let month = parseInt(birArr[1]) // 日份 let day = parseInt(birArr[2]) // 判断 switch (month) { case 1: if (day <= 19) { return '魔羯座' } else { return '水平座' } case 2: if (day <= 18) { return '水平座' } else { return '双鱼座' } case 3: if (day <= 20) { return '双鱼座' } else { return '白羊座' } case 4: if (day <= 19) { return '白羊座' } else { return '金牛座' } case 5: if (day <= 20) { return '金牛座' } else { return '双子座' } case 6: if (day <= 21) { return '双子座' } else { return '巨蟹座' } case 7: if (day <= 22) { return '巨蟹座' } else { return '狮子座' } case 8: if (day <= 22) { return '狮子座' } else { return '处女座' } case 9: if (day <= 22) { return '处女座' } else { return '天秤座' } case 10: if (day <= 23) { return '天秤座' } else { return '天蝎座' } case 11: if (day <= 22) { return '天蝎座' } else { return '射手座' } case 12: if (day <= 21) { return '射手座' } else { return '魔羯座' } default: return '请选择日期' } } } } </script> <template> <div> 年龄:<input type="number" v-model.lazy="age"> <!-- 简单的表达式 --> <h3>年龄阶段(简单):{{ age < 18 ? '未成年' : '成年' }} </h3> <!-- 计算属性:年龄阶段 --> <h3>年龄阶段(复杂):{{ ageState }} </h3>· </div> <hr> <div> 生日:<input type="date" v-model="birthday"> <!-- 计算属性:星座 --> <h3>星座:{{ constellation }}</h3> </div> </template>
- 示例展示:
在这里插入代码片