关于Vue3的Composition API(2)

251 阅读2分钟

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

接下来继续总结Vue3的Composition API的剩余内容。

computed计算属性

具体使用如下demo:通过点击div标签,count值发生改变。而computed监听到count发生改变后,会执行我们想让他做的业务。

<script>
    const app = Vue.createApp({
        template:`
             <div @click="handle">{{count}}---{{countAdd3}}  </div>
        `,
        setup(props,context){
            const {ref,computed} = Vue;
            const handle=()=>{
                count.value+=1;
            }
            const countAdd3=computed(()=>{
                return count.value+=3;
            })
            /*也可以使用以下写法:
            const countAdd3=computed(()=>{
                get:()=>{
                    return count.value+=3;
                },
                set:()=>{
                    count.value=10;
                }
            })
            */
            return {
                count,handle,countAdd3
            }
        }
    });
    const vm = app.mount("#root");
</script>

watch侦听器/watchEffect

  • watch侦听器

    具备一定的惰性(可通过属性immediate设置为true设置为可立即执行)

    其参数可以拿到当前和原始值。

    也可以侦听多个数据的变化,用一个侦听器去完成。

    watch([()=>name,()=>age],([newName,oldName],[newAge,oldAge])=>{ console.log(newName,oldName,'---',newAge,oldAge) }

  • watchEffect

    立即执行,没有惰性的(immediate)

    不需要传递你要侦听的内容,自动会感知代码依赖,不需要传递很多参数,只需要一个回调函数。

    但是不像watch,watchEffect无法获取到原始值。

以上两个属性均可停止侦听,如下设置四秒后停止侦听。

const stop = watchEffect(()=>{

console.log(name);

setimeout(()=>{

stop();},4000)

})

watch也如上。

具体关于watch和watchEffect使用如下demo:通过input标签改变name的值,则可以监听到name的值发生了改变。

<script>
    const app = Vue.createApp({
        template:`
             <input v-model='name'/>
             <div>{{name}}</div>
        `,
        setup(props,context){
            const {ref,watch} = Vue;
            const name = ref("vivi")
            watch(name,(newValue,oldValue))=>{
                console.log(newValue,oldValue)
            }
            watchEffect(()=>{
                console.log(name);
            })
            return {
                name
            }
        }
    });
    const vm = app.mount("#root");
</script>

生命周期新写法

因为setup执行介于beforeCreate和create之间,所以不需要用到这两个生命周期函数

其他的,在setup中使用生命周期,需要改写如下

beforeMount ===> onBeforeMount

mounted ===> onMounted

beforeUpdate ===>onBeforeUpdate

updated ===> onUpdated

beforeUnmount ===>onBeforeUnmount

unmounted ===> onUnmounted

同时还提供了onRenderTracked,onRenderTriggered

  • onRenderTracked:每次渲染后重新收集响应式依赖
  • onRenderTriggered:每次触发页面重新渲染的时候自动执行
<script>
    const app = Vue.createApp({
        template:`
             <div>{{name}}</div>
        `,
        setup(props,context){
            const {ref,onMounted} = Vue;
            const name = ref("vivi")
            onMounted(()=>{
                console.log('onMounted');
            })
            return {
                name
            }
        }
    });
    const vm = app.mount("#root");
</script>

Provide,inject

在父组件中使用provide将属性或者方法传递给子组件,子组件使用inject接收。

如下demo:父组件的name可以通过ref设置响应式,然后传递给子组件,子组件如果想要修改父组件的name,有些人会直接使用name.value="小新"去更改,但这样违反了vue的单向传递原则,子组件最好不要去改变父组件的值,于是建议可以给name变量加上一个readonly属性,一旦有人直接更改,则会报错。最优的做法是触发父组件的changeName方法去改变name的值。

<script>
    const app = Vue.createApp({
        setup(){
            const {provide,ref,readonly} = Vue;
            const name = ref("vivi");
            provide("name":readonly(name));
            provide("changeName",(value)=>{
                name.value=value;
            })
            return {}
        },
        template:`
             <child />
        `
     });
     app.component("child",{
         setup(){
           const {inject} = Vue;
           const name = inject("name");
           const changeName = inject("changeName");
           const handle(()=>{
               //name.value="小新";
               changeName("小新");
           })
           return {name}
         },
         template:`<div @click="handle">{{name}}</div>`
     })
    const vm = app.mount("#root");
</script>

模板Ref的使用

Composition API提供的获取真实DOM节点的ref方法。

<script>
    const app = Vue.createApp({
        template:`
             <div ref="hello">{{name}}</div>
        `,
        setup(props,context){
            const {ref,onMounted} = Vue;
            const hello = ref(null)
            onMounted(()=>{
                console.log(hello.value);//可以获取到hello真实的dom节点
            })
            return {
                hello
            }
        }
    });
    const vm = app.mount("#root");
</script>

\