Vue3基础知识-setup()、ref()和reactive()
一、完整代码
1. 组件文件(App.vue)
<template><!--Vue3组件可以没有跟标签--><!--直接写school。模板解析ref对象自动调用.value--><h1>{{school}}</h1><h1>{{student.name}}</h1><h1>{{student.age}}</h1><button @click="changeInfo">修改信息</button><hr><h1>{{school2}}</h1><h1>{{student2.name}}</h1><h1>{{student2.age}}</h1><button @click="changeInfo2">修改信息</button>
</template><script>import {reactive, ref} from "vue";export default {name: 'App',created() {console.log(this)},/*setup():作用:为组件准备所需资源(数据、方法、依赖等),替代了Vue2中data、methods、computed 等分散的选项执行时机:beforeCreate生命周期钩子之前执行,其内部的this是undefined(不能通过this访问组件实例)注:setup()不能是async函数。因为返回值再是return对象,而是promise,模板看不到return对象中的属性*/setup(){//知识点1:ref()。加工生成ref引用对象//ref传入基础数据类型:ref对象的原型有value属性(值为传入值)及其响应式set和getlet school = ref("北京大学")//ref传入对象数据类型:ref对象的原型有value属性(值为传入值)及其响应式set和get//传入的对象也需实现响应式,继续加工生成Proxy对象(reactive函数实现)而非ref对象//即:student.value拿到的是Proxy对象let student = ref({name:"张三",age:18})function changeInfo(){//注1:无需this.school.value。//注2:写法 school = "清华大学" 表示school值为string类型的,不触发响应式school.value = "清华大学"//注:写法不是:student.value.name.value = "李四"。student.value.name = "李四"student.value.age = 19}//知识点2:reactive()。加工生成Proxy对象(可监听属性增删改查);即解决了Vue2直接增删属性和数组下标响应式问题(参考ch01-10)//需传入对象类型数据,基本数据类型不会实现响应式let school2 = reactive("北京大学")//无响应式let student2 = reactive({name:"张三",age:18})function changeInfo2(){school2 = "清华大学"student2.name = "李四"student2.age = 19}//返回的对象可在模板中使用return{school,student,changeInfo,school2,student2,changeInfo2,}}
}
</script><style></style>
2. 入口文件(main.js)
//引入不是Vue的构造函数,是一个名为createApp的工厂函数
import { createApp } from 'vue'
import App from './App.vue'
//创建实例对象app,比vm更轻量级
createApp(App).mount('#app')
二、核心知识点解析
1. ref:处理响应式的「万能工具」
ref
的设计初衷是处理所有数据类型的响应式,无论是基础类型还是对象类型,核心是生成一个ref包装对象。
1.1 工作原理
传入基础类型(如
school = ref("北京大学")
):
生成的ref原型结构为{ value: "北京大学", get value(), set value() }
,通过value
的getter/setter
触发响应式(追踪依赖、更新视图)。传入对象类型(如
student = ref({ name: "张三" })
):
生成的ref 内部会自动调用reactive
,将对象转成Proxy
,此时student.value
拿到的是 Proxy 对象,确保嵌套属性(如name
、age
)也能响应式。
1.2 注意事项
ref对象使用
.value
时机:
模板会自动对 ref 数据「解包」(直接写{{ school }}
即可),但在 setup 函数内部,必须通过school.value
访问 / 修改,否则无法触发响应式。响应式的错误写法:
若写school = "清华大学"
(而非school.value = "清华大学"
),会导致school
从「ref 包装对象」变成「普通字符串」,不是响应式(模板不会更新)。
2. reactive:处理对象的「专属工具」
reactive
是专门为对象类型设计的响应式 API,核心是生成 Proxy
对象,可以监听对象属性的增删改查(解决了 Vue2 中「对象增删属性无响应」「数组通过下标修改内容无响应」的问题)。
2.1 工作原理
传入对象后,
reactive
会返回一个Proxy
代理对象,所有对对象属性的操作(如student2.name = "李四"
)都会被 Proxy 拦截,从而触发响应式。不支持基础类型:
若传入基础类型(如reactive("北京大学")
),Vue 会给出警告,且数据无响应式(因为 Proxy 无法代理基础类型)。
2.2 注意事项
无需
.value
:
reactive 生成的是 Proxy 对象,直接修改属性即可(如student2.age = 19
),无需像 ref 那样加.value
。避免「响应式丢失」:
不要将 reactive 对象解构赋值(如const { name } = student2
),解构后name
会变成普通变量,修改时无响应式;若需解构,可配合toRefs
工具。
3. ref 与 reactive区别
对比维度 | ref | reactive |
---|---|---|
支持数据类型 | 所有类型(基础 / 对象) | 仅对象类型(数组 / 对象) |
访问方式 | setup 中需 .value ,模板自动解包 | 直接访问属性(无需 .value ) |
返回值类型 | ref包装对象(含 value 属性) | Proxy 对象 |
适用场景 | 基础类型、单个对象属性 | 复杂对象 / 数组(多属性) |
三、如何选择 ref 和 reactive?
优先用 ref 的场景:
- 处理基础数据类型(string/number/boolean);
- 只需响应式管理单个对象属性(如
count = ref(0)
); - 模板中使用更简洁(无需嵌套访问)。
优先用 reactive 的场景:
- 处理复杂对象 / 数组(如用户信息、列表数据);
- 需要频繁操作对象的多个属性(如
user.name
、user.age
一起修改); - 避免频繁写
.value
(setup 中操作更简洁)。