个人简介
👀个人主页: 前端杂货铺
🙋♂️学习方向: 主攻前端方向,正逐渐往全干发展
📃个人状态: 研发工程师,现效力于中国工业软件事业
🚀人生格言: 积跬步至千里,积小流成江海
🥇推荐学习:🍍前端面试宝典 🎨100个小功能 🍉Vue2 🍋Vue3 🍓Vue2/3项目实战 🥝Node.js实战 🍒Three.js🌕个人推广:每篇文章最下方都有加入方式,旨在交流学习&资源分享,快加入进来吧
文章目录
- 前言
- computed
- watch
- 监听 ref 定义的基本类型数据。
- 监听 ref 定义的对象类型数据
- 监听 reactive 定义的对象类型数据
- 监听 ref 或 reactive 定义的对象类型数据的某个属性
- 监视多个属性
- watchEffect
前言
重拾 Vue3,查缺补漏、巩固基础。
computed
计算属性只读、可修改(getter setter)。
<template>
<div class="person">
<input type="text" v-model="firstName" /><br />
<input type="text" v-model="lastName" /><br />
{{ fullName }} <br />
<button @click="changeName">changeName(computed)</button>
</div>
</template>
<script lang="ts" setup>
import { ref, computed } from "vue";
const firstName = ref("zhang");
const lastName = ref("san");
// 只读计算属性
// const fullName = computed(() => {
// return (
// firstName.value.slice(0, 1).toUpperCase() +
// firstName.value.slice(1) +
// "-" +
// lastName.value
// );
// });
// getter setter
const fullName = computed({
get() {
return (
firstName.value.slice(0, 1).toUpperCase() +
firstName.value.slice(1) +
"-" +
lastName.value
);
},
set(val) {
const [str1, str2] = val.split("-");
firstName.value = str1;
lastName.value = str2;
},
});
function changeName() {
fullName.value = "li-si";
}
</script>
<style scoped>
.person {
background-color: skyblue;
box-shadow: 0 0 10px;
border-radius: 10px;
padding: 20px;
}
button {
margin: 0 5px;
}
</style>
watch
Vue3 中的 watch 只能监视以下四种数据:
- ref 定义的数据
- reactive 定义的数据
- 函数返回一个值(getter函数)
- 一个包含上述内容的数组
监听 ref 定义的基本类型数据。
<template>
<div class="person">
{{ sum }} <br />
<button @click="changeSum">changeSum</button>
</div>
</template>
<script lang="ts" setup>
import { ref, watch } from "vue";
const sum = ref(0);
function changeSum() {
sum.value += 1;
}
// sum 值大于 5 时停止监视
const stopWatch = watch(sum, (newValue, oldVallue) => {
console.log(newValue, oldVallue);
if (newValue > 5) {
stopWatch();
}
});
</script>
<style scoped>
.person {
background-color: skyblue;
box-shadow: 0 0 10px;
border-radius: 10px;
padding: 20px;
}
button {
margin: 0 5px;
}
</style>
监听 ref 定义的对象类型数据
修改的是 ref 定义的对象中的属性,newValue 和 oldValue 都是新值,因为它们是同一个对象。
修改整个 ref 定义的对象,newValue 是新值,oldValue 是旧值,因为不是同一个对象。
<template>
<div class="person">
{{ person.name }} <br />
{{ person.age }} <br />
<button @click="changeName">changName</button>
<button @click="changePerson">changePerson</button>
</div>
</template>
<script lang="ts" setup>
import { ref, watch } from "vue";
const person = ref({
name: "zhangsan",
age: 10,
});
function changeName() {
person.value.name = "lisi";
}
function changePerson() {
person.value = { name: "wangwu", age: 20 };
}
// 深度监听 person
watch(person, (newValue, oldValue) => {
console.log(newValue, oldValue);
},{ deep: true ));
</script>
<style scoped>
.person {
background-color: skyblue;
box-shadow: 0 0 10px;
border-radius: 10px;
padding: 20px;
}
button {
margin: 0 5px;
}
</style>
监听 reactive 定义的对象类型数据
监视 reactive 定义的对象类型数据时,默认开启深度监视,且无法取消。
<template>
<div class="person">
{{ person.name }} <br />
{{ person.age }} <br />
<button @click="changeName">changName</button>
<button @click="changePerson">changePerson</button>
</div>
</template>
<script lang="ts" setup>
import { reactive, watch } from "vue";
const person = reactive({
name: "zhangsan",
age: 10,
});
function changeName() {
person.name = "lisi";
}
function changePerson() {
Object.assign(person, { name: "wangwu", age: 20 });
}
watch(person, (newValue, oldValue) => {
console.log(newValue, oldValue);
});
</script>
<style scoped>
.person {
background-color: skyblue;
box-shadow: 0 0 10px;
border-radius: 10px;
padding: 20px;
}
button {
margin: 0 5px;
}
</style>
监听 ref 或 reactive 定义的对象类型数据的某个属性
- 若该属性值不是对象类型。需要写成函数形式
- 若该属性值是对象类型。可以直接
.
出来,也可以写成函数(推荐)
监视的要是对象里的属性,最好写成函数式。
注意点:若监视的是地址值,需要关注对象内部,需要手动开启深度监听。
<template>
<div class="person">
{{ person.name }} : {{ person.age }}
{{ person.car.c1 }}
{{ person.car.c2 }}
<button @click="changeName">changeName</button>
<button @click="changeC1">changeC1</button>
<button @click="changeC2">changeC2</button>
<button @click="changeCar">changeCar</button>
</div>
</template>
<script lang="ts" setup>
import { reactive, watch } from 'vue'
const person = reactive({
name: '张三',
age: 20,
car: {
c1: '大众',
c2: '小米'
}
})
function changeName() {
person.name = '李四';
}
function changeC1() {
person.car.c1 = '奥迪';
}
function changeC2() {
person.car.c2 = '宝马';
}
function changeCar() {
person.car = {c1: "雅迪", c2: "爱玛"};
}
watch(() => person.name, (newValue, oldValue) => {
console.log('name changed', newValue, oldValue);
})
watch(() => person.car, (newValue, oldValue) => {
console.log(newValue, oldValue);
}, { deep: true})
</script>
<style scoped>
.person {
background-color: skyblue;
box-shadow: 0 0 10px;
border-radius: 10px;
padding: 20px;
}
button {
margin: 0 5px;
}
</style>
监视多个属性
使用数组包裹的形式,实现同时监听多个属性。
<template>
<div class="person">
{{ person.name }} : {{ person.age }}
{{ person.car.c1 }}
{{ person.car.c2 }}
<button @click="changeName">changeName</button>
<button @click="changeC1">changeC1</button>
<button @click="changeC2">changeC2</button>
<button @click="changeCar">changeCar</button>
</div>
</template>
<script lang="ts" setup>
import { reactive, watch } from 'vue'
const person = reactive({
name: '张三',
age: 20,
car: {
c1: '大众',
c2: '小米'
}
})
function changeName() {
person.name = '李四';
}
function changeC1() {
person.car.c1 = '奥迪';
}
function changeC2() {
person.car.c2 = '宝马';
}
function changeCar() {
person.car = {c1: "雅迪", c2: "爱玛"};
}
watch([() => person.name, () => person.car.c1], (newValue, oldValue) => {
console.log('name or car changed', newValue, oldValue);
})
</script>
<style scoped>
.person {
background-color: skyblue;
box-shadow: 0 0 10px;
border-radius: 10px;
padding: 20px;
}
button {
margin: 0 5px;
}
</style>
watchEffect
watchEffect 会立即运行一个函数,同时响应式地追踪其依赖,并在依赖更改时重新执行。
<template>
<div class="person">
<h2>当前求和为:{{ sum }}</h2>
<button @click="changeNum">changeNum</button>
</div>
</template>
<script lang="ts" setup>
import { ref, watchEffect } from 'vue'
const sum = ref(0);
function changeNum() {
sum.value += 1;
}
watchEffect(() => {
if (sum.value < 5) {
console.log('num changed', sum.value)
}
})
</script>
<style scoped>
.person {
background-color: skyblue;
box-shadow: 0 0 10px;
border-radius: 10px;
padding: 20px;
}
button {
margin: 0 5px;
}
</style>
参考资料:
https://www.bilibili.com/video/BV1Za4y1r7KE?spm_id_from=333.788.player.switch&vd_source=f839085517d2b7548b2939bfe214d466&p=23