vue3.x
computed函数
与vue2中computed配置功能一致
import { computed } from "vue";
setup(){
//简写
let test = computed(()=>{
return 1+1
})
//完整
let demo =computed({
get(){
return 1+1
},
set(value){
value+1
}
})
}
watch函数
与Vue2.x中的watch配置功能一致
监视的是属性(结构),而不是属性值,所以监视ref定义的数据,不用加.value
两个‘小坑’:
1. 监视reactive定义的响应式数据时:oldValue无法正确获取,强制开启了深度监视(deep:false配置失效)
2.监视reactive定义的响应式数据中某个属性(对象)时,deep配置有效
<template>
<div>
<h2>求和结果:{{ sum }}</h2>
<button @click="sum++">+1</button>
<hr />
<p>信息:{{ msg }}</p>
<button @click="msg += '!'">hi</button>
<hr />
<p>姓名:{{ obj.name }}</p>
<p>年龄:{{ obj.age }}</p>
<p>工作:{{ obj.job.job1.name }}</p>
<p>薪资:{{ obj.job.job1.salary }}K</p>
<button @click="obj.name += '-'">修改姓名</button>
<button @click="obj.age++">修改年龄</button>
<button @click="obj.job.job1.salary++">加薪</button>
</div>
</template>
<script>
import { ref, watch, reactive } from "vue";
export default {
// vue2的watch,vue3也可以用
/* watch: {
// 简写
// sum(newVal, oldVal) {
// console.log("sum的值改变了");
// },
// 完整——可以配置属性
sum: {
// 立即监听
immediate: true,
// 深度监视
deep: true,
handler(newVal, oldVal) {
// console.log("sum的值改变了");
},
},
}, */
setup() {
// sum是基本数据类型,所以用ref
let sum = ref(0);
let msg = ref("hello");
let obj = reactive({
name: "张三",
age: 22,
job: {
job1: {
name: "web工程师",
salary: 20,
},
},
});
// 情况一:监视ref所定义的一个响应式数据
/* watch(sum, (newVal, oldVal) => {
console.log("sum的值改变了");
},{immediate:true}); */
// 情况二:监视ref所定义的多个响应式数据
/* watch([sum, msg], (newVal, oldVal) => {
console.log("值改变了");
},{immediate:true}); */
// 情况三:监视reactive所定义的一个响应式数据的全部属性,
// 注意:1.此处无法正确的获取oldVal;2.强制开启了深度监视(deep:false配置无效)
/* watch(obj, (newVal, oldVal) => {
console.log("sum的值改变了");
},{deep:false}); */
// 情况四:监视reactive所定义的一个响应式数据的某个属性
/* watch(()=>obj.age, (newVal, oldVal) => {
console.log("sum的值改变了");
}); */
// 情况五:监视reactive所定义的一个响应式数据的某些属性
/* watch([()=>obj.age,()=>obj.name], (newVal, oldVal) => {
console.log("sum的值改变了");
}); */
// 特殊情况
watch(
() => obj.job,
(newVal, oldVal) => {
console.log("job里面的值改变了");
},
{ deep: true }//由于此处监视的是reactive所定义的对象中的某个属性,所以deep配置有效
);
return { sum, msg, obj };
},
};
</script>
<style>
</style>
监视ref定义的数据的问题
<template>
<div>
<h2>求和结果:{{ sum }}</h2>
<button @click="sum++">+1</button>
<hr />
<p>信息:{{ msg }}</p>
<button @click="msg += '!'">hi</button>
<hr />
<p>姓名:{{ obj.name }}</p>
<p>年龄:{{ obj.age }}</p>
<p>工作:{{ obj.job.job1.name }}</p>
<p>薪资:{{ obj.job.job1.salary }}K</p>
<button @click="obj.name += '-'">修改姓名</button>
<button @click="obj.age++">修改年龄</button>
<button @click="obj.job.job1.salary++">加薪</button>
</div>
</template>
<script>
import { ref, watch, reactive } from "vue";
export default {
setup() {
// sum是基本数据类型,所以用ref
let sum = ref(0);
let msg = ref("hello");
let obj = ref({
name: "张三",
age: 22,
job: {
job1: {
name: "web工程师",
salary: 20,
},
},
});
// sum是ref定义的数据,是RefImpl对象
watch(sum, (newVal, oldVal) => {
console.log("监视到sum的值改变了,");
});
/* watch(obj, (newVal, oldVal) => {
console.log("监视到obj内的值改变了,");
}); 监视不到*/
// obj是ref定义的数据,是RefImpl对象,但是obj里面的value是reactive定义的,是Proxy对象
// 方式一:
/* watch(obj.value, (newVal, oldVal) => {
console.log("监视到obj内的值改变了,");
}); */
watch(
obj,
(newVal, oldVal) => {
console.log("监视到obj内的值改变了,");
},
{ deep: true }
);
return {
sum,
msg,
obj,
};
},
};
</script>
<style>
</style>
watchEffect函数
watch的套路是:既要指明监视的属性,也要指明监视的回调
watchEffect的套路是:不用指明监视哪个属性,监视的回调中用到哪个属性,那就监视哪个属性
watchEffect有点像computed:
但computed注重的计算出来的值(回调函数的返回值),所以必须要写返回值
而watchEffect更注重的是过程(回调函数的函数体),所以不用写返回值
//watchEffect所指定的回调中用到的数据只要发生变化,则直接重新执行回调
watchEffect(()=>{
const x1=sum.value;
const x2=obj.job.job1.salary
console.log('watchEffect所指定的回调执行了');
})
生命周期
<template>
<div>
<h2>求和结果:{{ sum }}</h2>
<button @click="sum++">+1</button>
</div>
</template>
<script>
// 组合式API
import {
ref,
onBeforeMount,
onMounted,
onBeforeUpdate,
onUpdated,
onBeforeUnmount,
onUnmounted,
} from "vue";
export default {
// setup先执行再到beforeCreate
// 在setup里面没有beforeCreate和created这两个组合API
setup() {
let sum = ref(0);
console.log("setup");
onBeforeMount(() => {
console.log("onBeforeMount");
}),
onMounted(() => {
console.log("onMounted");
}),
onBeforeUpdate(() => {
console.log("onBeforeUpdate");
}),
onUpdated(() => {
console.log("onUpdated");
}),
onBeforeUnmount(() => {
console.log("onBeforeUnmount");
}),
onUnmounted(() => {
console.log("onUnmounted");
});
return {
sum,
};
},
// 若setuo里面的组合式API的生命周期钩子时期比配置项的生命周期钩子快一点
// 通过配置项的形式使用生命周期钩子
//#region
beforeCreate() {
console.log("beforeCreate");
},
created() {
console.log("created");
},
beforeMount() {
console.log("beforeMount");
},
mounted() {
console.log("mounted");
},
beforeUpdate() {
console.log("beforeUpdate");
},
updated() {
console.log("updated");
},
beforeUnmount() {
console.log("beforeUnmount");
},
unmounted() {
console.log("unmounted");
},
//#endregion
};
</script>
<style>
</style>
自定义hooks函数
什么是hooks?:本质是一个函数,把setup函数中使用的CompositionApi 进行了封装
类似于Vue2.x中的mixin
自定义hook的优势:复用代码,让setup中的逻辑更清楚易懂
toRef
作用:创建一个ref对象,其value值指向另一个对象中的某个属性
语法:
const newName = toRef(obj,'name')
应用:要将响应式对象中的某个属性单独提供给外部使用时,还不想丢失响应式,就可以使用toRef
扩展:toRefs与toRef功能一致,但可以批量创建多个ref对象,语法:toRefs(obj),返回的是一个对象,需要定义一个变量接收,或者在return直接使用**…toRefs(obj)**
<template>
<div>
<p>{{obj}}</p>
<p>姓名:{{ name }}</p>
<p>年龄:{{ age }}</p>
<p>工作:{{ job.job1.name }}</p>
<p>薪资:{{ job.job1.salary }}K</p>
<button @click="name += '-'">修改姓名</button>
<button @click="age++">修改年龄</button>
<button @click="job.job1.salary++">加薪</button>
</div>
</template>
<script>
import { reactive, toRef, toRefs } from "vue";
export default {
setup() {
let obj = reactive({
name: "张三",
age: 22,
job: {
job1: {
name: "web工程师",
salary: 20,
},
},
});
// 页面可以显示相关的信息,但是修改不了,不是响应式数据
/* return {
// obj,
name:obj.name,//'张三
age:obj.age,//22
job:obj.job.job1.name,//'web工程师'
salary:obj.job.job1.salary//20
}; */
return {
obj,
// 下面几个属性常用
// toRef只能处理一个属性
/* name:toRef(obj,'name'),
age:toRef(obj,'age'),
jobName:toRef(obj.job.job1,'name'),
salary:toRef(obj.job.job1,'salary') */
// toRefs可以处理多个属性,返回一个对象,所以需要接收
// ...:在一个对象使用...展开另外一个对象,只能展开到该对象的第一层,深层的展开不了
...toRefs(obj)
}
},
};
</script>
<style>
</style>