这是我参与更文挑战的第19天,活动详情查看: 更文挑战
一、ref函数的使用
ref()函数可以将数据转为响应式数据, 一般用于定义一个基本类型的响应式数据.
1.1 新建ref路由
自己写vue3模板页面太麻烦了, vscode自定义代码片段, 搜vue
然后补上这段代码
"vue3": {
"prefix": "vue3",
"body": [
"<template>",
" <div>",
"",
" </div>",
"</template>",
"",
"<script lang=\"ts\">",
"import { defineComponent } from 'vue';",
"",
"export default defineComponent({",
" name: '',",
"});",
"</script>",
"",
"<style scoped>",
"",
"</style>"
],
"description": "vue3初始化"
}
复制代码
然后在vscode中一键生成vue3模板
回归ref, 为什么要用ref, vue3中数据不是响应式的, 需要使用ref函数
新建一个ref路由
home.vue中
<button @click="goPage('/ref')">去ref页</button>
import { useRouter } from 'vue-router';
let router = useRouter()
let goPage = (path:string) => {
router.push(path)
}
复制代码
ref.vue中
<template>
<div>
{{count}} <button @click="incrementCount">+</button>
</div>
</template>
<script lang="ts">
import { defineComponent } from 'vue';
export default defineComponent({
name: '',
setup() {
let count = 0
let incrementCount = () => {
count++
console.log(count);
}
return {
count,
incrementCount,
}
}
});
</script>
<style scoped>
</style>
复制代码
可以看见未使用ref, 数据是自增了, 但是视图未变
使用ref后, 数据就是双向的了
let count =ref(0)
let incrementCount = () => {
count.value++
console.log(count.value);
}
复制代码
二、 reactive函数的使用
reactive()函数和ref()函数类似,也是将数据变成响应式数据,当数据发生改变时,模板视图也会自动更新。不同的是ref()用于基本数据类型,而reactive()用于引用数据类型,比如对象或数组。
例如添加用户列表
不用reactive是非响应式
<template>
<div>
<ul>
<li v-for="(item,index) in userList" :key="index">{{item.name}}</li>
</ul>
<button @click="addUser">添加用户</button>
</div>
</template>
<script lang="ts">
import { defineComponent } from "vue";
export default defineComponent({
name: "reactive",
setup() {
let userList = [
{
id: 1,
name: "张三",
},
{
id: 2,
name: "李四",
},
{
id: 3,
name: "王五",
},
];
let addUser = () => {
let user = {
id: userList.length + 1,
name: '机器人' + userList.length + 1
}
userList.push(user)
console.log(userList);
}
return {
userList,
addUser
}
},
});
</script>
<style scoped>
</style>
复制代码
加了reactive, 数据变成proxy代理,变成响应式了
import { defineComponent,reactive } from "vue";
let userList = reactive([
{
id: 1,
name: "张三",
},
{
id: 2,
name: "李四",
},
{
id: 3,
name: "王五",
},
]) ;
复制代码
ps: 其实ref也可以操作应用类型, 使用ref后数据.value.push就可以了, 因为底层会判断是基础数据类型还是引用数据类型, 如果是引用数据类型的话, 还是会走reactive的方法, 所以官方推荐引用类型使用reactive
三、响应式的原理
Vue3的响应式原理是通过proxy(代理)对对象属性值进行读写、添加、删除进行劫持,通过Reflect(反射)动态对被代理的对象的属性进行特定的操作,由于proxy和Reflect不支持IE浏览器,这也是Vue3不支持IE浏览器的主要原因之一。
新建一个html
<!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>Document</title>
<script>
let user = {
id: 1,
name: '张三'
}
let proxyUser = new Proxy(user,{
// 目标对象 属性名
get(target,prop) {
console.log(target,prop);
}
})
proxyUser.name
</script>
</head>
<body>
</body>
</html>
复制代码
获取里面的值
let proxyUser = new Proxy(user,{
get(target,prop) {
console.log(target,prop);
return target[prop]
}
})
let result = proxyUser.name
console.log(result,'属性值');
复制代码
优化: 建议使用reflect反射获取值
get(target,prop) {
console.log(target,prop);
// return target[prop]
return Reflect.get(target,prop)
}
复制代码
通过set去设置里面的值
// 设置值
set(targe,prop,val) {
// targe[prop] = val // 不推荐
Reflect.set(targe,prop,val)
}
let result = proxyUser.name
console.log(result,'属性值原来');
proxyUser.name = '李四'
let result2 = proxyUser.name
console.log(result2,'属性值改变');
console.log(user,'被代理对象');
复制代码
被代理的对象也改变了.
删除值
// 删除值
deleteProperty(target,prop) {
// delete target[prop] // 不推荐
Reflect.deleteProperty(target,prop)
}
delete proxyUser.name
console.log(user,'删除后被代理对象');
复制代码
完整代码
<!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>Document</title>
<script>
let user = {
id: 1,
name: '张三'
}
let proxyUser = new Proxy(user,{
// 获取值
get(target,prop) {
console.log(target,prop);
// return target[prop]
return Reflect.get(target,prop)
},
// 设置值
set(targe,prop,val) {
// targe[prop] = val // 不推荐
Reflect.set(targe,prop,val)
},
// 删除值
deleteProperty(target,prop) {
// delete target[prop] // 不推荐
Reflect.deleteProperty(target,prop)
}
})
let result = proxyUser.name
console.log(result,'属性值原来');
proxyUser.name = '李四'
let result2 = proxyUser.name
console.log(result2,'属性值改变');
console.log(user,'被代理对象');
delete proxyUser.name
console.log(user,'删除后被代理对象');
</script>
</head>
<body>
</body>
</html>
复制代码
© 版权声明
文章版权归作者所有,未经允许请勿转载。
THE END