摘要
在vue3直接定义变量不是响应式数据
在vue3中定义变量更改变量页面是显示不出来的
在按钮中绑定一个函数,当我点击它的时候发生改变str值
点击前
点击后
点击后控制台显示更改数据,而页面中不显示数据,这就是vue3没触发响应式
使用ref和reactive可以完美结局,以下文章讲述如何使用ref和reactive来进行响应式操作
一、ref
ref是一个函数,是vue组合式api中的一个方法,主要作用就是定义一个响应式的数据、
<template>
<div>
<p>
{{ msg }}
</p>
<button @click="handleClick">更新数据</button>
</div>
</template>
<script lang="ts" setup>
import { ref } from 'vue';
// 定义变量
let msg: any = ref("你好世界")
// 绑定点击事件
let handleClick = () => {
console.log(msg);
}
</script>
当我们点击更新变量得到是是一个ref对象
更改值操作-----------------------------(页面同步)
我们要获取value值,这样才能响应式
<template>
<div>
<p>
{{ msg }}
</p>
<button @click="handleClick">更新数据</button>
</div>
</template>
<script lang="ts" setup>
import { ref } from 'vue';
// 定义变量
let msg: any = ref("你好世界")
// 绑定点击事件
let handleClick = () => {
// 修改数据必须加上value,因为被ref包裹的变量是一个ref对象
msg.value = "你好地球"
console.log(msg.value, ".value方法")
}
</script>
当我再次点击更新数据
直接发生响应式变化
l另外补充
// unref可以直接提取ref定义的value值
console.log(unref(msg), "unref方法")
// isRef判断是不是一个ref定义的数据,是就返回true不是就返回false
console.log(isRef(msg), "isRef方法")
以后使用ref尽量使用.value
二、reactive
*reactive定义多个数据的响应式,返回的是一个proxy代理对象,被代理的对象叫做目标对象
reactive内部是通过es6的proxy实现的,通过代理对象将目标对象转为响应式数据
<template>
<div>
<p>
名字:{{ msg.name }}<br>
年龄:{{ msg.age }}<br>
性别:{{ msg.sex }}
</p>
<button @click="handleClick">更新数据</button>
</div>
</template>
<script lang="ts" setup>
import { ref, reactive } from 'vue';
// 定义变量
let msg: any = reactive({
name: "张三",
age: 20,
sex: "男"
})
// 绑定点击事件
let handleClick = () => {
console.log(msg, 'proxy代理对象')
}
</script>
页面输出
更改值操作-----------------------------(页面同步)
<template>
<div>
<p>
名字:{{ msg.name }}<br>
年龄:{{ msg.age }}<br>
性别:{{ msg.sex }}<br>
爱好:{{ msg.pin }}
</p>
<button @click="handleClick">更新数据</button>
</div>
</template>
<script lang="ts" setup>
import { ref, reactive } from 'vue';
// 定义变量
let msg: any = reactive({
name: "张三",
age: 20,
sex: "男",
})
// 绑定点击事件
let handleClick = () => {
msg.name = "李四"
//在vue2中不先定义直接添加属性会导致视图不更新,解决办法this.$set
// 在vue3中使用reactive可以
msg.pin = "健身"
console.log(msg, 'proxy代理对象')
}
</script>
使用reactive可以直接修改数据而且可以添加没定义的数据
三、ref与reactive区别?
1、ref区别
通过ref定义的基本数据类型
<template>
<div>
<p>
{{ m1 }}
</p>
<button @click="handleClick">更新数据</button>
</div>
</template>
<script lang="ts" setup>
import { ref, reactive } from 'vue';
// 定义变量
// 通过ref定义的基本数据类型
let m1 = ref("我是张三");
// 绑定点击事件
let handleClick = () => {
// 只要通过ref定义的基本数据类型,是一个ref对象,修改数据必须加上.value
m1.value = "我是李四";
}
</script>
通过ref定义的复杂数据类型
<template>
<div>
<p>
{{ m2.wifi.title }}
</p>
<button @click="handleClick">更新数据</button>
</div>
</template>
<script lang="ts" setup>
import { ref, reactive } from 'vue';
// 定义变量
// 通过ref定义的复杂的数据类型
let m2 = ref({
name: "小鸟",
wifi: {
title: "苹果",
},
});
// 绑定点击事件
let handleClick = () => {
// 只要通过ref定义的复杂数据类型,是一个ref对象,只是内部会自动变成reactive代理对象的形式
m2.value.wifi.title = "香蕉";
console.log(m2);
}
</script>
2、reactive区别
reactive不能定义基本数据类型,只能定义复杂的数据类型
<template>
<div>
<p>
{{ m3.wifi.title }}
</p>
<button @click="handleClick">更新数据</button>
</div>
</template>
<script lang="ts" setup>
import { ref, reactive } from 'vue';
// 定义变量
// 通过reactive定义的复杂的数据类型,注意reactive不能定义基本数据类型
let m3 = reactive({
name: "猴子",
wifi: {
title: "香蕉",
},
});
// 绑定点击事件
let handleClick = () => {
// 只要通过reactive定义的复杂的数据类型,是一个proxy代理对象
m3.name = "蜜蜂";
m3.wifi.title = "糖水";
console.log(m3);
}
</script>
3、reactive小问题
reactive弊端:赋值一一对应赋值页面可以响应式,页面更新
而整体赋值页面会渲染不上,只有控制台会有变化,而页面中无法更新
将数据obj对象可以直接赋值给reactive定义的m3中,但是不是响应式的(ref是可以的)
ref可以这样整体赋值,但是到后面得加.value
reactive整体赋值解决方法
方法一
创建这个arr[]对象可以是空对象!!
方法二
使用****Object.assign(原数据, 新数据)、
对象中添加多个新属性,则通过 **Object.assign(原数据, 新数据)**创建新对象
Object.assign(m3, obj)
方法三
使用forEach
使用forEach必须是数组形式
总结
ref和reactive是vue3组合式api中最重要的响应式api
ref是用来处理基本数据类型,reactive是用来处理复杂的数据类型
如果用ref处理复杂的数据类型,那么内部会自动将复杂的数据类型转为reactive代理对象的形式
ref内部:通过value属性添加getter,setter来实现数据的响应式
reactive内部:通过es6中的proxy来实现对对象内部所有的数据进行劫持
注意:ref定义的数据修改数据的时候需要加上.value,reactive不需要