系列文章目录
内容 | 链接 |
---|---|
从Vue2到Vue3【零】 | Vue3简介 |
从Vue2到Vue3【一】 | Composition API(第一章) |
从Vue2到Vue3【二】 | Composition API(第二章) |
从Vue2到Vue3【三】 | Composition API(第三章) |
从Vue2到Vue3【四】 | Composition API(第四章) |
文章目录
前言
随着Vue 3的发布,我们迎来了一套强大且令人兴奋的组合式API,这为开发者带来了更多灵活性和可维护性。Vue 3的组合式API不仅改变了我们编写Vue组件的方式,还引入了一些新的组件和一些小的但实用的改变。在这篇文章中,我们将深入探讨Vue 3的组合式API,并介绍一些引人注目的新组件和改变,让我们一起开始这个令人兴奋的学习之旅吧!
一、shallowReactive 与 shallowRef
-
shallowReactive:
- shallowReactive函数用于创建一个浅响应式对象,它只会对对象的第一层属性进行响应式处理,而不会递归地对嵌套的属性进行深层次响应式处理。
- 这在某些情况下可以提高性能和减少内存消耗,特别是当对象的嵌套层次很深或者对象非常大时。
- 适用场景:当需要对一个大型对象进行响应式处理,但只关心对象的第一层属性变化时,可以使用shallowReactive来避免深层次的响应式处理。
import {shallowReactive} from 'vue'
export default {
name: 'App',
setup(){
let data = ({
name: 'John',
age: 25,
address: {
street: 'Main St',
city: 'New York'
}
})
let data1 = shallowReactive(data)
return {
data1
}
}
}
由于shallowReactive函数创建的是一个浅响应式对象,所以当改变data1.name
时,会触发响应
但当修改data1.address.street
时,就不会触发响应 (shallowReactive:只处理对象最外层属性的响应式)
-
shallowRef:
- shallowRef函数用于创建一个浅响应式引用,它只会对值的第一层进行响应式处理,而不会递归地对嵌套的值进行深层次响应式处理 ===》
只处理基本数据类型的响应式, 不进行对象的响应式处理
- 类似于shallowReactive,这在某些情况下可以提高性能和减少内存消耗。
- 适用场景:当需要对一个值进行响应式处理,但只关心值的第一层变化时,可以使用shallowRef来避免深层次的响应式处理。
- shallowRef函数用于创建一个浅响应式引用,它只会对值的第一层进行响应式处理,而不会递归地对嵌套的值进行深层次响应式处理 ===》
<template>
{{name1}}
<button @click="name1 = '前端百草阁'">点我修改name</button>
<br>
{{ data1.address.street }}
<button @click="data1.address.street = '前端百草阁'">点我修改stree</button>
</template>
<script>
import {shallowRef} from 'vue'
export default {
name: 'App',
setup(){
let name = 'John'
let data = ({
age: 25,
address: {
street: 'Main St',
city: 'New York'
}
})
let data1 = shallowRef(data)
let name1 = shallowRef(name)
console.log(data1.value,name1.value); // 在setup中操作数据时 要加.value
return {
data1,
name1
}
}
}
</script>
这里小伙伴们注意一个点,无论是操作数据还是使用数据都和ref、reactive一样,ref在操作数据时要加.value才能拿到对应的值
二、readonly 与 shallowReadonly
- readonly
- 让一个响应式数据变为只读的(深只读)
- 将整个对象及其嵌套的属性设置为只读的场景,保护某些数据不被修改。
<script>
import { ref, reactive, toRefs,readonly } from "vue";
export default {
name: "deMO",
setup() {
//数据
let sum = ref(0);
let person = reactive({
name: "张三",
age: 18,
job: {
j1: {
salary: 20,
},
},
});
person = readonly(person);
sum = readonly(sum)
return {
sum,
...toRefs(person),
};
},
};
</script>
由于这里使用的是readonly深只读,所以sum以及person的每一个属性都无法被修改
- shallowReadonly
- 让一个响应式数据变为只读的(浅只读)
- 将对象数据的第一层属性设置为只读
<script>
import { ref, reactive, toRefs,shallowReadonly } from "vue";
export default {
name: "deMO",
setup() {
//数据
let sum = ref(0);
let person = reactive({
name: "张三",
age: 18,
job: {
j1: {
salary: 20,
},
},
});
person = shallowReadonly(person)
sum = shallowReadonly(sum)
return {
sum,
...toRefs(person),
};
},
};
</script>
由于person设置了浅只读,所以person中的name属性值不能改变,但是person中的j1里的属性是可以修改的
- 如果有一个对象数据,结构比较深, 但变化时只是外层属性变化 ===> shallowReactive。
- 如果有一个对象数据,后续功能不会修改该对象中的属性 ===> shallowRef。
举个例子,大家注意看
setup() {
let car = reactive({ name: "奔驰", price: "40W" });
let car1 = readonly(car)
car.name = '宝马'
// car1.name = '劳斯莱斯' car1的值为只读不能修改
console.log(car1,car);
return { };
},
};
这里car1是car的只读数据,当car的值发生变化时,car1的值对应着也会变化,但是car1的值不能直接修改
car1 的值直接修改不起作用,并且会报错
三、toRaw 与 markRaw
-
toRaw函数:
- 作用:将一个由
reactive
生成的响应式对象转为普通对象 - 使用场景:用于读取响应式对象对应的普通对象,对这个普通对象的所有操作,不会引起页面更新。
- 作用:将一个由
<script>
import {ref,reactive,toRaw} from 'vue'
export default {
name: 'Demo',
setup(){
//数据
let person1 = ref({
name:'张三',
age:18,
job:{
j1:{
salary:20
}
}
})
let person = reactive({
name:'张三',
age:18,
job:{
j1:{
salary:20
}
}
})
const p = toRaw(person) // person是reactive生成的响应式对象
p.age++ // 普通对象的值可以改变 但是不再引起页面更新
console.log(p) // 转换完后的p就是一个普通对象
const p1 = toRaw(person1.value)
p1.age++
console.log(p) // 转换完后的p就是一个普通对象
return {
sum,
person
}
}
}
</script>
这得透过问题看本质,ref定义一个响应式对象内部求助了reactive,所以person1.value实质上也是一个Proxy对象,所以在转换成普通对象时,要toRaw(person1.value)
实验才能出真知,由于好奇大家才在不停的进步,尝试后发现响应式对象转换为普通对象时,并不会影响先前的响应式对象,换句话说就是person依然是响应式对象,修改它,页面依旧会发生变化
还有一个点
setup() {
let car = reactive({ name: "奔驰", price: "40W" });
let car2 = toRaw(car)
// car.name = '宝马'
car2.name = '劳斯莱斯'
console.log(car,car2);
}
修改car 会改变car的值,修改car2的值同时car的值也会变
- markRaw:
- 作用:标记一个对象,使其
永远不会再成为响应式对象
。 - 应用场景:
- 有些值不应被设置为响应式的,例如复杂的第三方类库等。
- 当渲染具有不可变数据源的大列表时,跳过响应式转换可以提高性能。
- 作用:标记一个对象,使其
<script>
<script>
import { ref, reactive, toRefs, markRaw } from "vue";
export default {
name: "deMo",
setup() {
let person = reactive({
name: "张三",
age: 18,
job: {
j1: {
salary: 20,
},
},
});
let car = { name: "奔驰", price: 40 };
person.car = markRaw(car); // 将一个标记过的对象添加到person的属性中
person.car.price++; // 数据会变化 但是页面不再更新(没有响应式)
console.log(person.car.price);
return {
person,
...toRefs(person), // 普通对象被标记过后 再也无法变成响应式的
};
},
};
</script>
let car = { name: "奔驰", price: 40 };
person.car = car; // 将一个普通对象添加到person的属性中
person.car.price++; // 数据会变化 页面会更新(有响应式)
console.log(person.car.price);
总结
本文讲解了vue3组合式API中的 shallowReactive 与 shallowRef、readonly 与 shallowReadonly、toRaw 与 markRaw的用法以及注意事项,欢迎大家订阅本系列文章,干货满满!