vue3对比vue2新增特性

发布于:2025-03-30 ⋅ 阅读:(26) ⋅ 点赞:(0)

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

如有误欢迎指正,后续会继续补充。


网站公告

今日签到

点亮在社区的每一天
去签到