ref,reactive
当点击num,和info,去修改它们的值,页面上也会同步修改过来,相当于vue2中在data函数里面声明响应式数据,但是比vue2更加完善。在vue2中使用Object.defineProperty() 来实现响应式,存在一些局限性,比如无法检测对象属性的添加和删除,对于数组的某些操作(如通过索引修改元素)也不能自动触发响应式更新(需要手动触发视图更新)。vue3使用基于js的proxy对象实现响应式,很好的解决了这个问题。
<template>
<div>
<div @click="numAdd">num:{{ num }}</div>
<div @click="changeInfo">info:{{ info }}</div>
</div>
</template>
<script setup>
import { reactive, ref } from "vue";
//ref创建基础数据类型的响应式处理
const num = ref(1);
// reactive创建引用数类型的响应式处理
const info = reactive({ name: "zs", age: 12 });
const numAdd = () => {
num.value++;
};
const changeInfo = () => {
console.log(info);
info.age = 99;
info.name = "张三";
};
</script>
<style></style>
组合式函数
组合式函数是 Vue 3 中一种复用逻辑的方式,通过将相关的逻辑封装到一个函数中,可以在多个组件中复用。
创建tools文件夹,创建文件demoTool.js
import { ref } from 'vue';
function useCounter() {
const count = ref(0);
const increment = () => {
count.value++;
};
return {
count,
increment
};
}
export {useCounter}
<template>
<div>
<div @click="countAdd()"> count:{{count}}</div>
</div>
</template>
<script setup>
import {useCounter} from '@/tools/demoTool'
//解构出count变量,和count+1的方法
const {count,increment}=useCounter();
const countAdd=()=>{
increment();
console.log('count',count.value);
}
</script>
<style>
</style>
provide,inject,defineProps,defineEmits
provide,inject跨组件传参,defineProps,defineEmits父子组件传参。详细可以看下这里,本文就不赘述了。vue3组件传参
shallowReactive,shallowRef
`shallowReactive`与 `reactive` 类似,但仅对对象的顶层属性进行响应式处理,深层嵌套的对象不会被转为响应式。适用于处理大型对象,仅需要对顶层属性进行响应式更新的场景,可减少不必要的响应式转换开销。
`shallowRef`与 `ref` 类似,但仅对 `.value` 的赋值操作进行响应式追踪,而不会对 `.value` 指向的对象内部属性变化进行响应式处理。当只关心引用的变更,而不关心引用对象内部的变化时可以使用。
<template>
<div>
<h2>shallowReactive</h2>
<p>Name: {{ info.name }}</p>
<p>Detail Name: {{ info.detail.name2 }}</p>
<button @click="changeName">Change Names</button>
<button @click="changeName2">Change Names</button>
<br />
<h2>shallowRef</h2>
<p>Name: {{ info2.name }}</p>
<p>Detail Name: {{ info2.detail.name }}</p>
<P>age :{{ info2.detail.age }}</P>
<button @click="changeInfo">Change Names</button>
<button @click="changeInfo2">Change Names</button>
</div>
</template>
<script setup>
import { shallowReactive, shallowRef } from "vue";
const info = shallowReactive({
name: "zs",
detail: {
name2: "ls",
age: 12,
},
});
const info2 = shallowRef({ name: "111", detail: { name: "a111", age: 22 } });
const changeInfo = () => {
info2.value = { name: "222", detail: { name: "a222", age: 33 } };
// info2.value.name = "qqq"; 单独修改根目录属性是不生效的
};
const changeInfo2 = () => {
// 不生效的 不会对内部属性对象进行响应式处理
info2.value.detail.name = "张三";
};
// 视图会更新
const changeName = () => {
info.name = "张三";
};
// 视图不会更新
const changeName2 = () => {
info.detail.name2 = "李四";
};
</script>
针对于shallowReactive还有一种情况,如果在一个方法里面去同时修改第一层和第二层的name,那么视图也是会更新的,这是因为Vue 的响应式系统在更新时会有一个批量处理的机制。当修改第一层响应式属性info.name时,Vue 会开启一个更新队列,在这个队列处理过程中,虽然info.detail.name不是响应式的,但由于更新队列在处理其他更新,会顺带把相关的 DOM 重新渲染了 。演示下:
<template>
<div>
{{ info.name }}-{{ info.detail.name }}
<button @click="changeInfo">修改info</button>
</div>
</template>
<script setup>
import {provide ,reactive ,shallowReactive,isReactive} from 'vue'
const info=shallowReactive({name:'zs',detail:{name:'ls',age:12}});
const changeInfo=()=>{
info.name='张三';
info.detail.name='李四';
console.log(isReactive(info.detail.name));
}
</script>
当点击按钮的时候 info.detail.name视图也更新了,从控制台打印信息看到它不是响应式的。
end
如有误欢迎指正,后续会继续补充。