🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
## 1.shallowReactive与shallowRef * shallowReactive:只处理对象最外层属性的响应式(浅响应式)只考虑第一层数据的响应式。 * shallowRef:只处理基本数据类型的响应式,不进行对象的响应式处理,传递基本数据类型的话跟ref没有任何区别,ref是可以进行对象的响应式处理的 **我们正常的ref创建的数据,里面的.value是一个proxy,而shallowRef创建的数据 .value里面是一个object数据类型,所以不会响应式数据** * 什么时候使用?: * 如果有一个对象数据,结构比较深,但变化时只是外层属性变化 ===> shallowReactive * 如果有一个对象数据,后续功能不会修改对象中的属性,而是生新的对象来替换 ===> shallowRef ## 2.readonly与shallowReadonly * readonly:让一个响应式的数据变成只读的(深只读) * shallowReadonly: 让一个响应式数据变成只读的(浅只读) * 应用场景:不希望数据被修改的时候 ``` <script> import { reactive,readonly,shallowReadonly } from 'vue' export default { name: 'test9', setup(){ let person = reactive({ name: '张三', job:{ salary: '20k', } }) person = readonly(person) //这个时候修改人的信息就不会改变了,所有的都不能改 /** * 页面不进行响应式的改变,一般存在两种情况: * 1.setup里面定义的数据改变了,但是vue没有检测到,这个时候是不会改变的 * 2.setup里面定义的数据压根儿就不让你改,这个时候也没法响应式 */ person = shallowReadonly(person) //只有最外层不能修改是只读的,但是job还是可以改的 return { person } }, } </script> ``` ## 3.toRaw与markRaw toRaw 作用:将一个由reactive生成的响应式对象转换为普通对象 使用场景:用于读取响应式对象对应的普通对象,对这个普通对象的所有操作,不会引起页面更新 markRow: 作用:标记一个对象,使其永远不会再成为响应式对象 使用场景: 1.有些值不应被设置成响应式的,例如复杂的第三方类库等 2.当渲染具有不可变数据的大列表时候,跳过响应式转换可以提高性能 ``` import {reactive,toRaw,markRaw} from 'vue' setup(){ let person = reactive({ name: '张三', }) function showRawPerson(){ const p = toRaw(person) p.age++ console.log(p) } function addCar(){ let car = {name: '奔驰'} person.car = markRaw(car) //一旦这么做时候,他就永远不能当成响应式数据去做了 } } ``` ## 4.customRef * 创建一个自定义的ref,并对其依赖项跟踪和更新触发进行显示控制 * 实现防抖效果: ``` <template> <input type="text" v-model="keyword"> <h3>{{keyword}}</h3> </template> <script> import { customRef, ref } from 'vue' export default { name: 'test10', setup(){ let timer; //自定义一个ref——名为: myRef function myRef(value){ return customRef((track,trigger)=>{ return { get(){ console.log(`有人读取我的值了,要把${value}给他`); //两次输出: v-model读取 h3里面的插值语法调了一次 track() //追踪一下改变的数据(提前跟get商量一下,让他认为是有用的) return value }, set(newValue){ console.log(`有人把myRef这个容器中数据改了:${newValue}`); clearTimeout(timer) timer = setTimeout(()=>{ value = newValue trigger() //通知vue去重新解析模板,重新再一次调用get() },500) } } }) } // let keyword = ref('hello') //使用内置提供的ref let keyword = myRef('hello') //使用自定义的ref return { keyword, } }, } </script> ``` ## 5.provide与inject:依赖注入 * 作用:实现祖孙组件间的通信 * 套路:父组件有一个provide选项提供数据,子组件有一个inject选项来开始使用这些数据 * 具体写法: ``` //父组件 <script setup> import { ref,reactive,toRefs,provide } from 'vue'; import ChildVue from './components/Child.vue'; let car = reactive({ name: '奔驰', price: '40w' }) provide('car',car) //给自己的后代组件传递数据 const {name, price} = toRefs(car) </script> <template> <div class="app"> <h3>我是父组件, {{name}}--{{price}}</h3> <ChildVue></ChildVue> </div> </template> ``` ``` //子组件 <script setup> import { ref } from '@vue/reactivity'; import SonVue from './Son.vue'; </script> <template> <div class="app2"> <h3>我是子组件</h3> <SonVue></SonVue> </div> </template> ``` ``` //孙组件 <script setup> import { ref,inject } from 'vue'; let car = inject('car') //拿到父组件的数据 const {name, price} = car </script> <template> <div class="app3"> <h3>我是孙组件</h3> <p>{{name}}-{{price}}</p> </div> </template> ``` ## 6.响应式数据的判断 isRef:检查一个值是否为ref对象 isReactivce:检查一个对象是否是由reactive创建的响应式代理 isReadonly:检查一个对象是否由readonly创建的只读代理 isProxy:检查一个对象是否由reactive或者readonly方法创建的代理