vue3其他Composition api
shallowReactive 与 shallowRef
- shallowReactive : 只处理了对象内最外层属性的响应式(也就是浅响应式)
- shallowRef: 只处理了 value 的响应式, 不进行对象的 reactive 处理什么时候用浅响应式呢? - 一般情况下使用 ref 和 reactive 即可
- 如果有一个对象数据, 结构比较深, 但变化时只是外层属性变化 ===> shallowReactive
- 如果有一个对象数据, 后面会产生新的对象来替换 ===> shallowRef
 1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51<template> 
 <h2>shallowReactive 与 shallowRef</h2>
 <h3>m1:{{ m1 }}</h3>
 <h3>m2:{{ m2 }}</h3>
 <h3>m3:{{ m3 }}</h3>
 <h3>m4:{{ m4 }}</h3>
 <hr />
 <button @click="handleUpdata">更新数据</button>
 </template>
 <script lang="ts">
 import {
 defineComponent,
 reactive,
 ref,
 shallowReactive,
 shallowRef,
 } from "vue";
 export default defineComponent({
 name: "",
 setup() {
 // m1 reactive 深度劫持,深度响应式
 const m1 = reactive({ a: 1, b: { c: 2 } })
 const m2 = shallowReactive({ a: 1, b: { c: 2 } })
 const m3 = ref({ a: 1, b: { c: 2 } })
 const m4 = shallowRef({ x: 1, y: { c: '2' } })
 const handleUpdata = () => {
 // m1.b.c += 1
 // m2.b.c += 1
 // m3.value.a += 1
 // m3.value.b.c += 1
 // m4.value.y.c += 1
 console.log(m3);
 console.log(m4);
 
 // 为什么reactive或ref在使用时,shallowRef和shallowReactive的数据会变成响应式?
 // 数据处于同一环境,都被同一个Fragment包着,Fragment是一种VNode的类型,m1.b.c触发改变
 // 对应的模板领域会进行更新,所以会发生改变
 }
 return {
 m1,
 m2,
 m3,
 m4,
 handleUpdata,
 };
 },
 });
 </script>
readonly 与 shallowReadonly
- readonly 深度只读数据   shallowReadonly: 浅只读数据应用场景: 
 在某些特定情况下, 我们可能不希望对数据进行更新的操作, 那就可以包装生成一个只读代理对象来读取数据, 而不能修改或删除1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39<template> 
 <h2>readonly 与 shallowReadonly</h2>
 <h3>state:{{ state2 }}</h3>
 <hr />
 <button @click="handleUpdata">更新数据</button>
 </template>
 <script lang="ts">
 import { defineComponent, reactive, readonly, ref, shallowReadonly } from "vue";
 export default defineComponent({
 name: "",
 setup(props, { attrs, emit, slots }) {
 const state = reactive({
 name:'he',
 age:20,
 car:{
 name:'红旗'
 }
 })
 // 只读数据---深度只读 对象的属性不能修改,对象的对象的属性也不能修改
 // const state2 = readonly(state)
 // 只读数据---浅度只读 对象的属性不能修改,对象的对象的属性可以修改
 const state2 = JSON.parse(JSON.stringify(shallowReadonly(state)))
 // 问题:state对象里的属性改变,也会影响state2对象里的属性(浅拷贝)
 // 解决:JSON.parse(JSON.stringify(shallowReadonly(state))) 进行深拷贝
 const handleUpdata = ()=>{
 // state2.name += '=='
 state2.car.name += '--'
 console.log(state.car,state2.car);
 }
 return {
 state2,
 state,
 handleUpdata
 };
 },
 });
 </script>
toRaw 与 markRaw
- toRaw:把代理对象变成普通对象,数据变化,界面不变化
- toRaw:返回由 reactive 或 readonly 方法转换成响应式代理的普通对象
- markRaw:markRaw标记的对象,不能成为代理对象,数据不能在页面更新
markRaw应用场景:
有些值不应被设置为响应式的,例如复杂的第三方类实例或 Vue 组件对象。
当渲染具有不可变数据源的大列表时,跳过代理转换可以提高性能。
| 1 | <template> | 
toRef
- 为源响应式对象上的某个属性创建一个 ref 对象, 二者内部操作的是同一个数据值, 更新时二者是同步的
- const age = toRef(state, "age")
- 区别ref : 拷贝了一份新的数据值单独操作, 更新时相互不影响
- 应用: 当要将 某个 prop 的 ref 传递给复合函数时,toRef 很有用App.vue 1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45<template> 
 <h2>toRef</h2>
 <h3>state:{{ state }}</h3>
 <h3>age:{{ age }}</h3>
 <h3>name:{{ name }}</h3>
 <hr />
 <button @click="handleUpdata">toRaw</button>
 <Child :age='age'></Child>
 </template>
 <script lang="ts">
 import { defineComponent, reactive, toRef, ref } from "vue";
 import Child from './components/Child.vue'
 export default defineComponent({
 name: "",
 components:{
 Child
 },
 setup() {
 const state = reactive({
 name: "he",
 age: 20,
 car: {
 name: "红旗",
 },
 });
 // 把响应式数据state的属性age变成ref对象
 const age = toRef(state, "age");
 // 把响应式数据state的属性name,使用ref进行包装,变成ref对象
 const name = ref(state.name);
 console.log(age,name);
 
 const handleUpdata = () => {
 state.age += 2
 // name.value += 3
 };
 return {
 state,
 age,
 name,
 handleUpdata,
 };
 },
 });
 </script>Child.vue 1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34<template> 
 <h2>Child组件,子组件</h2>
 <h3>age:{{ age }}</h3>
 <h3>length:{{ length }}</h3>
 </template>
 <script lang="ts">
 import { computed, defineComponent, Ref, ref, toRef } from "vue";
 // 参数必须是一个Ref类型的数据
 function useGetLength(age:Ref) {
 return computed(() => {
 return age.value.toString().length;
 });
 }
 export default defineComponent({
 name: "",
 // props: {
 // age: {
 // type: Number,
 // required: true,
 // },
 // },
 props: ["age"],
 setup(props, { attrs, emit, slots }) {
 //把一个对象里的属性,变成ref对象
 const length = useGetLength(toRef(props, "age"));
 console.log(length);
 console.log(props);
 return {
 length,
 };
 },
 });
 </script>
customRef
- 创建一个自定义的 ref,并对其依赖项跟踪和更新触发进行显式控制
需求: 使用 customRef 实现 debounce 的示例
get: 告诉vue追踪数据:track() set: 告诉Vue更新页面:trigger()
| 1 | <template> | 
provide 与 inject:父组件与孙子组件之间的通信
provide和inject提供依赖注入,功能类似 2.x 的provide/inject
实现跨层级组件(祖孙)间通信
App.vue(父组件)
| 1 | <template> | 
Child.vue(子组件)
| 1 | <template> | 
Grandson.vue(孙组件)
| 1 | <template> | 
响应式数据的判断
isRef: 检查一个值是否为一个 ref 对象
isReactive: 检查一个对象是否是由 reactive 创建的响应式代理
isReadonly: 检查一个对象是否是由 readonly 创建的只读代理
isProxy: 检查一个对象是否是由 reactive 或者 readonly 方法创建的代理
| 1 | <template> |