在上篇文章里# vue3的setup还能这么用?介绍了一下script setup
的基本使用方式,而后这两天在实际用它的过程中,发现在script setup
中...toRefs
很有意思,今天这里就给大家分享分享,如哪里有误欢迎指出,大佬勿喷
script setup
中的...toRefs
大家都知道在setup
的这种写法中,我们可以将定义的响应式对象
通过...toRefs
的方式将这个响应式对象
中的每个属性变为一个响应式数据
<script>
import {reactive,toRefs} from "vue";
export default {
name: "test1",
setup(){
const data = reactive({
name:'inline',
age:18,
fun(){
console.log('我爱掘金!')
}
})
return{
...toRefs(data)
}
}
}
</script>
复制代码
然后我们在模板中就可以直接用通过...toRefs
转换后的响应式数据,具体如下:
<div>
<button>姓名:{{ name }}</button>
<button>年龄:{{ age }}</button>
<button @click="fun">点我</button>
</div>
复制代码
那我们都知道在使用script setup
时,声明的顶层的绑定 (包括声明的变量,函数声明,以及 import 引入的内容) 都能在模板中直接使用,不再需要使用 return
导出。
那要是在script setup
中想使用...toRefs
去将我们的响应式对象
变为一个个响应式数据
呢?怎么做呢 答案是:做不到
小声bb,也可能是我菜,欢迎大佬解惑
可以看我们这里定义了一个响应式的对象,然后想通过...toRefs
去将对象中的属性变为响应式的数据
<script setup>
import {reactive,toRefs} from "vue";
const data = reactive({
name:'inline',
age:18,
fun(){
console.log('我爱掘金~')
}
})k
</script>
复制代码
然后发现在script setup
中没有地方让我们这么写,也写不了return
,写了就会报错,想访问变量和方法只能通过data.xxx
的方式进行访问
<h5>姓名:{{ data.name }}</h5>
<h5>年龄:{{ data.age }}</h5>
<button @click="data.fun">点我</button>
复制代码
那我们有没有什么办法能变相的去解决这个问题呢?我们来试一试
首先想到的是在写script setup
时我们还可以写普通的script
标签
那我们在这个普通的script
标签里写setup
并定义响应式对象
,然后在通过return
暴露给组件模板,这样可不可行
// script setup
<script setup>
import {reactive,toRefs} from "vue";
const data = reactive({
name:'inline',
age:18,
fun(){
console.log('我爱掘金~')
}
})
</script>
// 普通的script
<script>
import {reactive, toRefs} from "vue";
export default {
setup(){
const data = reactive({
name:'inline',
age:18,
fun(){
console.log('我爱掘金~')
}
})
return{
...toRefs(data)
}
}
}
</script>
复制代码
使用
<h5>姓名:{{ name }}</h5>
<h5>年龄:{{ age }}</h5>
<button @click="fun">点我</button>
复制代码
结果我们发现页面没有获取到值,按钮点击也无反应,控制台也没有任何报错
得出结论在
<script setup>
和<script> setup{} </script>
两种模式共存时,在<script> setup{} </script>
中的setup
中定义的任何变量和方法模板都访问不到 此种方式淘汰
同样定义两个script
标签,只不过第二个普通的script
标签我们使用Options Api
<script setup>
import {reactive,toRefs} from "vue";
const data = reactive({
name:'inline',
age:18,
fun(){
console.log('我爱掘金~')
}
})
</script>
<script>
import {reactive, toRefs} from "vue";
export default {
data(){
return{
name:'inline-two',
age:180,
}
},
methods:{
fun(){
console.log('爱大家~~~~')
}
}
}
</script>
复制代码
使用
<h5>姓名:{{ name }}</h5>
<h5>年龄:{{ age }}</h5>
<button @click="fun">点我</button>
复制代码
结果
可行,但好像没有什么太大的意义
这一次我们只用script setup
首先定义一个响应式对象
然后通过toRefs
进行解构
<script setup>
import {reactive,toRefs} from "vue";
const data = reactive({
name:'inline',
age:18,
fun(){
console.log('我爱掘金~')
}
})
const { name,age,fun } = toRefs(data)
</script>
复制代码
使用
<div>
<h5>姓名:{{ data.name }}</h5>
<h5>年龄:{{ data.age }}</h5>
<button @click="data.fun">点我</button>
</div>
<div style="margin-top: 20px">
<h5>姓名2:{{ name }}</h5>
<h5>年龄2:{{ age }}</h5>
<button @click="fun">点我2</button>
</div>
复制代码
结果可行,并且两种方式都可以访问到定义的响应式变量和方法,缺点就是每定义一个变量都需要手动进行解构
似乎在script setup
中没有特别完美的...toRefs
的解决方案,不知道后续vue会不会出相关的API。在实际的业务中,第三种方式应该也足够我们使用。