文章目录
前言
上一节我们知道了setup函数的数据不具备响应式,这一节我们来解决这一问题。
响应式引用原理
通过 proxy 对数据进行封装,当数据变化时,触发模板内容更新。
ref
- 作用:接受一个内部值并返回响应式对象;
- 处理:一般用于处理基础数据类型;
- 引用:ref需要从Vue中引入才能使用;
- 使用:通过value属性获取,使用数据时不需要使用value;
// 模板中使用时,vue底层自动调用 .value
template:`<div>{{name}}</div>`,
setup(){
//引入ref
const { ref } = Vue;
// 响应式引用,proxy 将 '张三' 变成 proxy({ value: '张三'})
let name = ref('张三');
// 两秒后修改 name
setTimeout(() => {
// 修改 name 使用 name.value
name.value = '李四';
}, 2000);
return{ name }
}
页面渲染成功渲染出 张三
两秒后更新数据,重新渲染出 李四
reactive
- 作用:接受一个内部值并返回响应式对象;
- 引用:从Vue中引入才能使用;
- 处理:一般用于处理非基础数据类型;
- 解构:数据解构之后的数据不具备响应式;
数据未解构时
template:`<div>{{obj.name}}</div>`,
setup(){
//引入reactive
const { reactive } = Vue;
// 响应式引用,proxy 将 {name: '张三'} 变成 proxy({name: '张三'})
let obj = reactive({name: '张三'});
// 两秒后修改 obj.name
setTimeout(() => {
obj.name = '李四';
}, 2000);
return{ obj }
}
页面渲染成功渲染出 张三
两秒后更新数据,重新渲染出 李四
尝试对数据进行解构
template:`<div>{{name}}</div>`,
setup(){
//引入reactive
const { reactive } = Vue;
// 响应式引用,proxy 将 {name: '张三'} 变成 proxy({name: '张三'})
let obj = reactive({name: '张三'});
// 两秒后修改 obj.name
setTimeout(() => {
obj.name = '李四';
}, 2000);
const { name } = obj;
return{ name }
}
页面渲染成功渲染出 张三
两秒后更新数据,页面没有变化
toRefs
- 作用:使解构后的数据重新获得响应式;
- 引用:从Vue中引入才能使用;
- 封装:封装数据中本身不存在某个数据时,会返回不具备响应式的undefined;
toRefs响应式引用
template:`<div>{{name}}</div>`,
setup(){
//引入reactive
const { reactive, toRefs } = Vue;
// 响应式引用,proxy 将 {name: '张三'} 变成 proxy({name: '张三'})
let obj = reactive({name: '张三'});
// 两秒后修改 obj.name
setTimeout(() => {
obj.name = '李四';
}, 2000);
// 通过toRefs包装后会变为proxy({name:proxy({value:'name'})})
const { name } = toRefs(obj);
return{ name }
}
页面渲染成功渲染出 张三
两秒后更新数据,重新渲染出 李四
toRefs封装不存在数据
template:`<div>{{age}}</div>`,
setup(){
//引入reactive
const { reactive, toRefs } = Vue;
// 响应式引用,proxy 将 {name: '张三'} 变成 proxy({name: '张三'})
let obj = reactive({name: '张三'});
// 通过toRefs包装后会变为proxy({name:proxy({value:'name'})})
const { age } = toRefs(obj);
// 两秒后修改 age.value
setTimeout(() => {
age.value = '18';
}, 2000);
return{ age }
}
控制台报错
toRef
- 作用:封装数据中不存在数据时,不会报错,会返回具备响应式的值;
- 使用:toRef方法不需要解构;
- 参数:两个参数,一个总数据,一个获取的数据。
template:`<div>{{age}}</div>`,
setup(){
//引入reactive
const { reactive, toRef } = Vue;
// 响应式引用,proxy 将 {name: '张三'} 变成 proxy({name: '张三'})
let obj = reactive({name: '张三'});
const age = toRef(obj, 'age');
// 两秒后修改 age.value
setTimeout(() => {
age.value = '18';
}, 2000);
return{ age }
}
页面两秒后渲染出:18
readonly
- 作用:取得一个对象或ref并返回一个只读代理;
- 引用:从Vue中引入才能使用;
template:`
<div>{{obj.name}}</div>
<div>{{copyObj.name}}</div>
`,
setup(){
//引入reactive
const { reactive, readonly } = Vue;
// 响应式引用,proxy 将 {name: '张三'} 变成 proxy({name: '张三'})
let obj = reactive({name: '张三'});
let copyObj = readonly({name: '张三'});
// 两秒后修改 obj.name
setTimeout(() => {
obj.name = '李四';
copyObj.name = '李四';
}, 2000);
return{ obj, copyObj }
}
页面效果
两秒后页面效果,同时控制台给出警告。
完整代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Vue3 -- 响应式引用</title>
<!-- 使用CDN引入Vue -->
<script src="https://unpkg.com/vue@next"></script>
</head>
<body>
<div id="root"></div>
<script>
const app = Vue.createApp({
// ref
// 模板中使用时,vue底层自动调用 .value
// template:`<div>{{name}}</div>`,
// setup(){
// //引入ref
// const { ref } = Vue;
// // 响应式引用,proxy 将 '张三' 变成 proxy({ value: '张三'})
// let name = ref('张三');
// // 两秒后修改 name
// setTimeout(() => {
// // 修改 name 使用 name.value
// name.value = '李四';
// }, 2000);
// return{ name }
// }
// reactive
// 未解构
// template:`<div>{{obj.name}}</div>`,
// setup(){
// //引入reactive
// const { reactive } = Vue;
// // 响应式引用,proxy 将 {name: '张三'} 变成 proxy({name: '张三'})
// let obj = reactive({name: '张三'});
// // 两秒后修改 obj.name
// setTimeout(() => {
// obj.name = '李四';
// }, 2000);
// return{ obj }
// }
// 解构后
// template:`<div>{{name}}</div>`,
// setup(){
// //引入reactive
// const { reactive } = Vue;
// // 响应式引用,proxy 将 {name: '张三'} 变成 proxy({name: '张三'})
// let obj = reactive({name: '张三'});
// // 两秒后修改 obj.name
// setTimeout(() => {
// obj.name = '李四';
// }, 2000);
// const { name } = obj;
// return{ name }
// }
// // toRefs
// template:`<div>{{name}}</div>`,
// setup(){
// //引入reactive
// const { reactive, toRefs } = Vue;
// // 响应式引用,proxy 将 {name: '张三'} 变成 proxy({name: '张三'})
// let obj = reactive({name: '张三'});
// // 两秒后修改 obj.name
// setTimeout(() => {
// obj.name = '李四';
// }, 2000);
// // 通过toRefs包装后会变为proxy({name:proxy({value:'name'})})
// const { name } = toRefs(obj);
// return{ name }
// }
//toRefs封装不存在数据
// template:`<div>{{age}}</div>`,
// setup(){
// //引入reactive
// const { reactive, toRefs } = Vue;
// // 响应式引用,proxy 将 {name: '张三'} 变成 proxy({name: '张三'})
// let obj = reactive({name: '张三'});
// const { age } = toRefs(obj);
// // 两秒后修改 age.value
// setTimeout(() => {
// age.value = '18';
// }, 2000);
// return{ age }
// }
// //toRef
// template:`<div>{{age}}</div>`,
// setup(){
// //引入reactive
// const { reactive, toRef } = Vue;
// // 响应式引用,proxy 将 {name: '张三'} 变成 proxy({name: '张三'})
// let obj = reactive({name: '张三'});
// const age = toRef(obj, 'age');
// // 两秒后修改 age.value
// setTimeout(() => {
// age.value = '18';
// }, 2000);
// return{ age }
// }
// readonly
template:`
<div>{{obj.name}}</div>
<div>{{copyObj.name}}</div>
`,
setup(){
//引入reactive
const { reactive, readonly } = Vue;
// 响应式引用,proxy 将 {name: '张三'} 变成 proxy({name: '张三'})
let obj = reactive({name: '张三'});
let copyObj = readonly({name: '张三'});
// 两秒后修改 obj.name
setTimeout(() => {
obj.name = '李四';
copyObj.name = '李四';
}, 2000);
return{ obj, copyObj }
}
});
const vm = app.mount('#root');
</script>
</body>
</html>
总结
ref
- 作用:接受一个基础数据类型值并返回响应式对象;
- 引用:ref需要从Vue中引入才能使用;
- 使用:通过value属性获取,使用数据时不需要使用value;
reactive
- 作用:接受一个非基础数据类型值并返回响应式对象;
- 引用:从Vue中引入才能使用;
- 解构:数据解构之后的数据不具备响应式;
toRefs
- 作用:使reactive解构后的数据重新获得响应式;
- 引用:从Vue中引入才能使用;
- 封装:封装数据中本身不存在某个数据时,会返回不具备响应式的undefined;
toRef
- 作用:封装数据中不存在数据时,不会报错,会返回具备响应式的值;
- 使用:toRef方法不需要解构;
- 参数:两个参数,一个总数据,一个获取的数据。
readonly
- 作用:取得一个对象或ref并返回一个只读代理;
- 引用:从Vue中引入才能使用;
结语
本小节到此结束,谢谢大家的观看!
如有问题欢迎各位指正