你不知道的<srcipt setup>不完全攻略(一)

494 阅读4分钟

序言

因为vite极快的打包运行速度对我太具有吸引力了,于是根据vite官网的初始化项目的方法搭建了一个项目,网速不好的小伙伴可以直接复制我下面的命令:

# npm 6.x
npm init @vitejs/app my-vue-app --template vue

# npm 7+, 需要额外的双横线:
npm init @vitejs/app my-vue-app -- --template vue

# yarn
yarn create @vitejs/app my-vue-app --template vue

然后就创建好我们的项目了,当我迫不及待,满心欢喜的打开项目看代码的时候一行代码映入我的眼帘:

<script setup>

我当时的表情应该是一脸黑人问号脸???
我记得vue官网上写的还是:

<script>
setup(){}
</script>

怎么突然setup跑到了script标签上,然后我花了不少的时间学习了网上关于vue3+vite搭建项目的视频,发现大家基本上还是上面第二种写法,算了,秉承着吃螃蟹的想法,就姑且一试这个东西吧。


我们将 "script setup"写法称作写法一,"setup(){}"写法称作写法二,一下内容由写法一,写法二替代

1.响应式数据

根据手册我们知道在vue3中定义数据有两种新的写法分别是reactive和ref
而在写法二中我们需要在setup(){}中定义数据,具体写法如下:

<script>
import { reactive, ref } from "vue"
export default{
        setup(){
        const data = reactive({
            msg:"hello world",
            obj:{
                name:"xiaoming",
                age:18
            }
        });
        const msg2 = ref("hello vite");

        return { data, msg2 }
    }
}


</script>

那在写法一中我们没有了setup(){}还怎么写呢,既然setup已经融入了script标签中,那代表直接写就可以了啊,直接上代码:

<script setup>
import { reactive, ref } from "vue"
    const data = reactive({
        msg:"hello world",
        obj:{
            name:"xiaoming",
            age:18
        }
    });
    const msg2 = ref("hello vite");
</script>

相信小伙伴们发现我这里已经没有return了,那有小伙伴可能会想那我还能在模板里直接使用数据吗?我可以很负责任的告诉你可以直接使用的,但是无论是写法一还是写法二我们想要使用msg和obj都需要data.,那这样每次都data.msg,data.obj.name就会显得很冗余,而且如果是对象里的数据就会显得层级过深,尤大既然发布出来了那肯定有解决的方法,请大家看下一条。

toRefs

在上一条中我们说到了在reactive中定义的数据是个对象,想在模板上使用就得xxx.xxx,这样就会显得很代码冗余,那聪明的小伙伴就想,既然如此那我们不就可以...解构出来用吗,如果只是单纯的展示数据不做任何操作的话那的确看上去没有什么问题,但是既然是reactive定义出来的数据肯定是响应式数据,我们...解构出来不就破坏了他的响应式了吗,如此不妥。官方贴心的给我们提供了toRefs语法用来解构reactive中数据的同时保持了数据的响应式。举个栗子:

<script setup>
import { reactive, toRefs } from "vue"
    const data = reactive({
        msg:"hello world",
        obj:{
            name:"xiaoming",
            age:18
        }
    });
    const { msg, obj } = toRefs(data);
</script>

这样就可以直接在模板中使用了。

如何使用及改变响应式数据

在上面代码中我们我们已经通过toRefs解构出来了data中的数据。那我们假如要给后端传递数据需要用到这些数据怎么办呢,举个栗子:

<script setup>
import { reactive, toRefs } from "vue"
    const data = reactive({
        msg:"hello world",
        obj:{
            name:"xiaoming",
            age:18
        }
    });
    const { msg, obj } = toRefs(data);
    const config = {
        userName:????,
        userAge:????,
    }
</script>

如果没有预习或者预习不仔细的小伙伴可能会在????直接写obj.name和obj.age,既然我说出来了肯定不能这么写了啊,因为toRefs解构出来的数据都是isRef:true的响应式数据,所以想要使用就不能简单的msg或者obj.name,而是msg.value或者obj.value.name。那小伙伴就想这么麻烦有什么更好的办法吗,我暂时也没有特别好的方法,但是可以直接使用data.msg不需要.value,那就有小伙伴发出疑问:那这个toRefs不是很鸡肋吗?非也非也,我们换个角度思考,我们如果没有这个那在模板上使用数据是不是全部都要data.xxx,那不更麻烦吗,所以存在即有一定的合理性。

数据的传递

在vue2.x的版本中,子组件接受父组件传递过来的数据使用的是props,那在写法二中依然可以使用props,那在写法一中没有了export defalut自然也用不了props了,上帝关上了一扇门,也会为你打开一扇窗,上代码:

<script setup>
import { reactive, toRefs, defineProps } from "vue"
defineProps({
    msg3:{
        type:String,
        defalut:()=>{
            return ""
        }
    }
})
    const data = reactive({
        msg:"hello world",
        obj:{
            name:"xiaoming",
            age:18
        }
    });
    const { msg, obj } = toRefs(data);
</script>

在vue3中尤大给我们提供了defineProps去接受父组件的值,那我们怎么去使用这个接收到的值呢或者说我们这个把这个值通过console.log()打印出来呢,我尝试过console.log(msg3),console.log(defineProps.msg3)发现都不可以,网上一通搜索都没找到想要的答案,终于在尤大的github的讨论区找到了我想要的答案,
在上述代码中只要稍加改造就可以了:

<script setup>
import { reactive, toRefs, defineProps } from "vue"
const props = defineProps({
    msg3:{
        type:String,
        defalut:()=>{
            return ""
        }
    }
})
    const data = reactive({
        msg:"hello world",
        obj:{
            name:"xiaoming",
            age:18
        }
    });
    const { msg, obj } = toRefs(data);
    onMounted(()=>{console.log(props.msg3)})
</script>

攻略一就先到这里,我会尽快更新后续的,欢迎大家留言讨论,多多点赞关注。 ---wy白菜