目录
官方文档链接:https://cn.vuejs.org/api/composition-api-setup.html
一、setup的使用
1.介绍:
新的option,所有的组合API函数都在此使用,只在初始化时执行一次;
函数如果返回对象,对象中的属性或方法,模板中可以直接使用。
2.使用方法:
<template>
<div>
<h1>{{ num }}</h1>
</div>
</template>
<script lang="ts">
import { defineComponent } from "vue";
export default defineComponent({
name: "App",
setup() {
let num = 10;
return {
num,
};
},
});
</script>
3.运行结果:
二、案例
1.需求:
在之前的代码中添加一个点击事件,点击按钮,数字自增+1.
<template>
<div>
<h1>{{num}}</h1>
<button @click="add">点击+1</button>
</div>
</template>
<script lang="ts">
import { defineComponent } from 'vue';
export default defineComponent({
name: 'App',
setup(){
let num=10
const add=()=>{
num++
console.log(num);
}
return{
num,
add
}
}
});
</script>
2.结果:
3.分析:
点击之后发现页面的数字并没有变化,但是控制台显示数字自增+1,这是因为为实现数据的双向绑定,此时就需要ref.
三、ref的使用
1.介绍:
ref是一个函数,定义一个数据的响应式,返回一个ref对象,对象中有vlaue属性;
const xxx=ref(initValue);
创建一个包含响应式数据的引用(reference)对象;
js中操作数据:xxx.value
模板中操作数据:不需要 .value;
一般用来定义一个基本类型的响应式数据
2.使用方法:
<template>
<div>
<h1>{{num}}</h1>
<button @click="add">点击+1</button>
</div>
</template>
<script lang="ts">
// 注意引入ref
import { defineComponent,ref } from 'vue';
export default defineComponent({
name: 'App',
setup(){
let num=ref(10)
const add=()=>{
num.value++
console.log(num);
}
return{
num,
add
}
}
});
</script>
3.结果:
4.分析:
此时数据就变成了响应式数据,实现了双向绑定。
四、reactive的使用
1.介绍:
定多个数据的响应式;
const proxy=reactive(obj):接收一个普通对象然后返回该普通对象的响应式代理对象;
响应式转换“深层的”,会影响对象内部所有嵌套的属性;
内部基于ES6的proxy实现,通过代理对象操作源对象内部数据都是响应式的。
2.使用方法:
<template>
<div>
<button @click="updateData">点击更新</button>
</div>
</template>
<script lang="ts">
import { defineComponent } from 'vue';
export default defineComponent({
name:'App',
setup(){
const obj={
name:'tom',
age:20,
hobby:["吃饭","睡觉","下棋"],
friend:{
name:'kitty',
age:19,
sex:"女"
}
}
const updateData=()=>{
obj.age++,
obj.friend.age+=2,
console.log(obj);
}
return{
obj,
updateData
}
}
})
</script>
3.结果:
同ref一样,未实现双向绑定。
4.解决办法:
把数据变成响应式的数据,返回一个proxy的代理对象,被代理的目标对象就是obj
完整代码为:
<template>
<div>
<button @click="updateData">点击更新</button>
</div>
</template>
<script lang="ts">
import { defineComponent, reactive } from 'vue';
export default defineComponent({
name:'App',
setup(){
const obj={
name:'tom',
age:20,
hobby:["吃饭","睡觉","下棋"],
friend:{
name:'kitty',
age:19,
sex:"女"
}
}
// 把数据变成响应式的数据,返回一个proxy的代理对象,被代理的目标对象就是obj
// statea对象的类型为proxy
const statea=reactive(obj)
const updateData=()=>{
// obj.age++,
// obj.friend.age+=2,
// console.log(obj);
statea.age++,
statea.friend.age+=2,
console.log(statea);
}
return{
// obj,
statea,
updateData
}
//此写法不可行
// function updateData(obj:any) {
// return obj.age++,
// // obj.friend.age+=2,
// console.log(obj);
// }
}
})
</script>
5.ref和reactive的区别:
1.ref是处理基本数据类型的(数字、字符串),reactive是处理复杂数据类型的(对象);
2.ref返回的是ref对象,reactive返回的是proxy代理对象;
3.ref内部:通过给value属性添加getter/setter来实现对数据的劫持;
4.reactive内部:通过使用Proxy来实现对对象内部所有数据的劫持,并通过Reflct操作对象内部数据;
5.使用ref处理对象,内部会经过reactive处理,value形成了一个proxy类型的对象;但是reactive不能处理基本数据类型;
6.ref的数据操作:在js中要 .value,在模板中不需要(内部解析模板时会自动添加 .value);
五、V2和V3响应式的区别*****
1.V2的响应式
核心:
对象:通过defineProperty对对象的已有属性值的读取和修改进行劫持(监视/拦截);
数组:通过重写数组更新数组一系列更新元素的方法来实现元素修改的劫持
代码:
object.defineProperty(data,'count',{ get(){}, set(){} })
问题:
对象直接新添加的属性或删除已有属性,界面不会自动更新;
直接通过下标替换元素或更新length,界面不会自动更新 arr[1]={}
2.V3的响应式
核心:
通过proxy代理:拦截对data任意属性的任意操作,包括属性值的读写,属性的添加、删除等...
通过reflect反射:动态对被代理对象的相应属性进行特定的操作。
使用案例
代码:
<!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>
</head>
<body>
<script>
// 目标对象
const user={
name:'tom',
age:20,
wife:{
name:'小红',
age:18
}
}
// 把目标参数变成代理对象
/*
参数1:user -----》 target目标对象
参数2:handler-----> 处理器对象,用来监视数据,以及对数据的操作
*/
const proxyUser=new Proxy(user,{
get(target,prop){
console.log("get方法被调用了");
console.log(target);
console.log(prop);
return Reflect.get(target,prop)
},
set(target,prop,value){
console.log("set方法被调用了");
// console.log(target);
// console.log(prop);
// console.log(value);
return Reflect.set(target,prop,value)
},
deleteProperty(target,prop){
console.log('deleteProperty方法被调用了');
return Reflect.deleteProperty(target,prop)
}
})
console.log(proxyUser.name);
proxyUser.name="张三"
console.log(user);
console.log(proxyUser.name);
proxyUser.sex="男"
console.log(user);
console.log(proxyUser.sex);
</script>
</body>
</html>
输出结果: