关于Vue3的Composition API(1)

148 阅读2分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第21天,点击查看活动详情

Composition API也叫组合式API,是Vue3的新特性。如果是小型项目,可以不使用Composition API。但是如果项目大了,像之前的vue相关代码需要配置到option的指定位置,找起来麻烦,后期维护复杂,复用性不高,则选择Composition API是更好的,几百个组件,共享和重用代码就尤为重要了。 以下会逐一用最简单的语言总结解析vue3的组合式API。

Setup的使用

setup接受两个参数,一个是props,一个是context上下文

使用setup定义变量和方法,不需要在data中定义变量,或者在methods中定义方法,可以直接返回,即可在模板中使用。

setup 为created实例被完全初始化之前被调用,无法调用外部的方法(如下实例methods中的myname函数),也没有this,但是setup可以被外部的方法执行。

<script>
    const app = Vue.createApp({
        template:`
             <div @click="handle">name:{{name}}  </div>
        `,
        methods:{
            myname(){
                console.log('hh');
            }
        }
        mountd(){
          console.log(this.$options.setup());//可以打印出{name:'vivi',handle:f}
       }
        setup(props,context){
            this.myname();//无法执行,报错。
            return {
                name:'vivi',
                handle:()=>{
                    console.log('vivi');
                }
            }
        }
    });
    const vm = app.mount("#root");
</script>
  • props参数:父组件传递过来的属性值

  • context参数:context参数中有attrs,slots,emit

    attrs:是一个None-Props属性,接收到除prop以外的属性

    slots:关于插槽的内容。

    emit:用于触发自定义事件

ref reactive 响应式的引用

setup中返回的数据是没有响应式的。

如下,name两秒后并不会变成小新。

<script>
    const app = Vue.createApp({
        template:`
             <div>name:{{name}}  </div>
        `,
        setup(props,context){
            let name = 'vivi';
            setTimeout(()=>{
                name="小新";
            },2000)
            return {
                name
            }
        }
    });
    const vm = app.mount("#root");
</script>

此时,就需要ref或者reactive进行包装,让其有响应式的引用。

原理:通过proxy对数据进行封装,当数据变化时,触发模板内容的更新

  • ref 处理基础类型数据

    如下,"vivi"变成Proxy({value:"vivi"})

    那么name两秒后就会变成小新

<script>
    const app = Vue.createApp({
        template:`
             <div>name:{{name}}  </div>
        `,
        setup(props,context){
            const {ref} = Vue;
            let name = ref('vivi');
            setTimeout(()=>{
                name.value = "小新";
            },2000)
            return {
                name
            }
        }
    });
    const vm = app.mount("#root");
</script>
  • reactive 处理非基础数据类型

    {name:'vivi'}变成proxy({name:'vivi'})

    那么name两秒后就会变成小新

    <script>
        const app = Vue.createApp({
            template:`
                 <div>name:{{nameObj.name}}  </div>
            `,
            setup(props,context){
                const {reactive} = Vue;
                let nameObj = reactive({name:'vivi'});
                setTimeout(()=>{
                    nameObj.name = "小新";
                },2000)
                return {
                    nameObj
                }
            }
        });
        const vm = app.mount("#root");
    </script>
    

如果不想数据变成响应式,可以使用readonly把响应式变量设置为只读。修改后则会报错。

如引入const {readonly}=Vue后,设置readonly:let name1 = readonly(name)

toRefs/toRef

  • toRefs

    如果想直接解构reactive的值,需要使用toRefs,如果直接解构会失去响应式功能。

    将proxy({name:'vivi',sex:'女'})解构成:

    name:proxy(value:'vivi')和sex:proxy(value:'女')

  • toRef

    对于没有原先没有的属性可以使用toRef,否则也是没有响应式的。(已经有的属性也可以)。

<script>
    const app = Vue.createApp({
        template:`
             <div>name:{{name}}  </div>
             <div>sex:{{sex}}  </div>
             <div>age:{{age}}  </div>
        `,
        setup(props,context){
            const {reactive} = Vue;
            let nameObj = reactive({name:'vivi',sex:'女'});
             const {name,sex} = toRefs(nameObj);
             const {age} = toRef(nameObj,'age');
            setTimeout(()=>{
                name.value = "小新";
                sex.value = "男";
                age.value = '18'
            },2000)
            return {
                name,sex,age
            }
        }
    });
    const vm = app.mount("#root");
</script>