1.改写计数器例子:
Vue2
中的代码:
<template>
<p>{{count}}</p>
<button @click="increase">?</button>
</template>
<script lang="ts">
import { defineComponent } from 'vue';
export default defineComponent({
name: 'App',
data(){
return {
count:0
}
},
methods:{
increase(){
this.count++;
}
}
});
</script>
复制代码
使用 vue3
改写后的代码:
setup
:在生命周期之前运行的- 通过代码可以发现,
increase
函数改变count
的值是改变的count
对象的value
,但template
中展示值是直接通过count
展示,而不是count.value
computed
:是一个函数,接收一个参数
:回调函数,回调函数中处理想要返回的值
<template>
<p>{{count}}</p>
<p>{{double}}</p>
<button @click="increase">?</button>
</template>
<script lang="ts">
import { defineComponent } from 'vue';
import {ref,computed} from "vue";
export default defineComponent({
name: 'App',
setup(){
const count = ref(0);
const increase = () => {
count.value ++;
}
const double = computed(()=>{
return count.value * 2;
})
return {
count,increase,double
}
}
});
</script>
复制代码
结果如下:
2.更进一步,reactive
1.使用reactive
实现计数器:
-
reactive
:reactive
是一个函数,参数是一个对象;通过reactive
包装后返回一个响应式的数据data
-
因为
computed
的原因,需要使用interface
去约束下data
的类型,否则如下图:上图的
data
会报错,解决方案就是添加interface
去约束,代码如下:
<template>
<p>{{data.count}}</p>
<p>{{data.double}}</p>
<button @click="data.increase">?</button>
</template>
<script lang="ts">
import { defineComponent } from 'vue';
import {ref,computed,reactive} from "vue";
interface DataProps {
count:number;
double:number;
increase:() => void;
}
export default defineComponent({
name: 'App',
setup(){
const data:DataProps = reactive({
count:0,
increase:()=>{
data.count++;
},
double:computed(()=>{
return data.count * 2
})
})
return {
data
}
}
});
</script>
复制代码
2.无效的优化方案:
这里面看到data.count...
等的很麻烦,想要在return {data}
中对data
进行解构或者es6的"..."展开操作符
,但是解构后发现页面计数器失效
,因为直接通过下面的方式:
//略
//页面点击无反应
return {
...data
}
//或者
//页面点击后依然无反应
return {
count:data.count,
increase:data.increase,
double:data.double
}
复制代码
3.正确使用 toRefs
去优化:
-
toRefs
:使用一个reactive对象
作为参数,返回一个普通的对象
-
通过
toRefs
转化后的refData
如下图,是一个Ref
类型,然后展开refData
即可。 -
代码如下:
<template>
<p>{{count}}</p>
<p>{{double}}</p>
<button @click="increase">?</button>
</template>
<script lang="ts">
import { defineComponent } from 'vue';
import {ref,computed,reactive,toRefs} from "vue";
interface DataProps {
count:number;
double:number;
increase:() => void;
}
export default defineComponent({
name: 'App',
setup(){
const data:DataProps = reactive({
count:0,
increase:()=>{
data.count++;
},
double:computed(()=>{
return data.count * 2
})
})
const refData = toRefs(data);
return {
...refData
}
}
});
</script>
复制代码
3.ref
和reactive
的区别:
上面使用了变量声明、ref、以及reactive
三种方式去定义变量:
用ref
定义的数据,打印结果是一个被对象包裹的响应的数据
,使用reactive
的方式和纯变量声明
的方式打印结果是一样的,这是什么原因呢?
在控制台输出一个警告信息, 提示100
这个值不能被reactive
创建。
官方也推荐我们在定义数据
的时候,reactive
定义复杂的数据类型
的数据,ref
推荐定义基本数据类型
,所以如果要使用reactive
定义基本数据类型
的话,需要在reactive
中将数据包装
一下。
- 但是使用
reactive
定义的数据和ref
定义的数据打印结果有一些差异:
ref
定义的数据打印结果需要.value
才能获取到结果
,而reactive
则不需要
总结:
reactive
和ref
都是用来定义响应式数据
的。reactive
更推荐去定义复杂的数据类型
;ref
更推荐定义基本类型
ref
和reactive
本质可以简单地理解为ref
是对reactive
的二次包装
,ref
定义的数据访问的时候要多一个.value
- 使用
ref
定义基本数据类型
,ref
也可以定义数组
和对象
。
© 版权声明
文章版权归作者所有,未经允许请勿转载。
THE END