1. 程式人生 > 其它 >VUE3 之 元件間事件通訊 - 這個系列的教程通俗易懂,適合新手

VUE3 之 元件間事件通訊 - 這個系列的教程通俗易懂,適合新手

1. 概述

相關定律告訴我們:這個世界上的任何事物之間都會存在一定聯絡,“城門失火,殃及池魚”就是一個很好的例子。因此如果我們能夠儘早發現這些看不見的聯絡,就能很好的解決更多遇見的難題。

言歸正傳,之前我們聊過如何在子元件中去修改主元件傳遞的引數的值,當時是在子元件中重新宣告一個新資料,初始值為父元件傳參的值,然後對子元件的資料進行計算。

今天我們使用事件的方式來實現對父元件的傳參進行修改。

2. 元件間事件通訊

2.1 子元件接收引數並實現自增

<body>
    <div id="myDiv"></div>
</body>
<script
> const app = Vue.createApp({ data() { return { num : 1 } }, template:` <div> <test :num="num" /> </div> ` }); app.component("test", { props:['num'], methods : { incrNum() {
this.num++; } }, template:` <div @click="incrNum" >{{num}}</div> ` }); const vm = app.mount("#myDiv");

這個例子咱們之前聊過,父元件有一個數據 num,父元件將這個引數傳給 test 子元件,子元件使用 props:['num'] 的方式接收後,在事件方法中對其自增

很明顯,自增時會報錯,因為父元件傳過來的 num 是隻讀的,子元件不能對其進行修改。

2.2 子元件中宣告新的資料,將父元件的num作為初始值

    const app = Vue.createApp({
        data() {
            return {
                num : 1
            }
        },
        template:`
            <div>
                <test :num="num" />
            </div>
        `
    });
    app.component("test", {
        props:['num'],
        data() {
            return {
                myNum : this.num
            }
        },
        methods : {
            incrNum() {
                // this.num++;
                this.myNum++;
            }
        },
        template:`
            <div @click="incrNum" >{{myNum}}</div>
        `
    });

這是我們上節課的解決方案,在子元件中宣告 myNum,把num當做初始值,然後自增 myNum,顯示時也顯示 myNum

很明顯,這樣做是可以的

2.3 子元件呼叫父元件的方法

既然子元件無權修改父元件傳過來的引數,那我們就讓父元件自己去修改這個引數

    const app = Vue.createApp({
        data() {
            return {
                num : 1
            }
        },
        methods : {
            handleIncr() {
                this.num++;
            }
        },
        template:`
            <div>
                <test :num="num" @incrNum="handleIncr" />
            </div>
        `
    });
    app.component("test", {
        props:['num'],
        methods : {
            incrNum() {
                this.$emit('incrNum')
            }
        },
        template:`
            <div @click="incrNum" >{{num}}</div>
        `
    });

這個例子中,父元件在使用子元件時,綁定了一個事件 incrNum,這個事件會呼叫父元件的 handleIncr 方法,這個方法中對資料 num 進行了自增。

子元件在自己的 incrNum 方法中使用this.$emit('incrNum') 觸發了父元件的 incrNum 事件,然後該事件呼叫父元件的handleIncr 方法,對父元件的資料 num 進行修改。

父元件修改了資料 num,這個資料 num 修改後的值會傳遞給子元件,從而實現對 num 引數的修改。

說了這麼一大堆,簡單看就是子元件通過某種手段呼叫了父元件的方法。

經試驗,完全沒用問題,可以修改 num 的值

2.4 子元件呼叫父元件的方法,且傳參

光呼叫還不行,我們還要傳參

    const app = Vue.createApp({
        data() {
            return {
                num : 1
            }
        },
        methods : {
            handleIncr(param1) {
                this.num += param1;
            }
        },
        template:`
            <div>
                <test :num="num" @incrNum="handleIncr" />
            </div>
        `
    });
    app.component("test", {
        props:['num'],
        methods : {
            incrNum() {
                this.$emit('incrNum', 2)
            }
        },
        template:`
            <div @click="incrNum" >{{num}}</div>
        `
    });

這個例子中,我們根據傳參的值,決定自增多少。

在this.$emit('incrNum', 2) 這句程式碼中,除了指明觸發的事件,還傳了一個引數,父元件的handleIncr(param1) 這個方法,就可以接收這個引數,並使用

2.5子元件呼叫父元件的方法,且傳多個引數

這次我們要傳多個引數,當然也是可以的

    const app = Vue.createApp({
        data() {
            return {
                num : 1
            }
        },
        methods : {
            handleIncr(param1, param2) {
                this.num += param2;
            }
        },
        template:`
            <div>
                <test :num="num" @incrNum="handleIncr" />
            </div>
        `
    });
    app.component("test", {
        props:['num'],
        methods : {
            incrNum() {
                this.$emit('incrNum', 2, 3)
            }
        },
        template:`
            <div @click="incrNum" >{{num}}</div>
        `
    });

這麼傳:this.$emit('incrNum', 2, 3),這麼收:handleIncr(param1, param2),以此類推

2.6 計算邏輯放在子元件中

自增本來是子元件的業務,我們不想把這個邏輯放到父元件中,耦合性太強了,我們可以這麼寫

    const app = Vue.createApp({
        data() {
            return {
                num : 1
            }
        },
        methods : {
            handleIncr(param1) {
                this.num = param1;
            }
        },
        template:`
            <div>
                <test :num="num" @incrNum="handleIncr" />
            </div>
        `
    });
    app.component("test", {
        props:['num'],
        methods : {
            incrNum() {
                this.$emit('incrNum', this.num + 1)
            }
        },
        template:`
            <div @click="incrNum" >{{num}}</div>
        `
    });

其實就是傳參時在子元件中計算好了,然後父元件直接賦值就好

2.7 通過 v-model 的方式,修改父元件資料的值

上面的例子中,我們通過子元件呼叫父元件的方法去修改父元件資料的值,耦合性還是有點強,父元件需要去為子元件寫一個方法。

其實還有一個更簡潔的辦法,就是通過 v-model 的方式,來看下面的例子

    const app = Vue.createApp({
        data() {
            return {
                num : 1
            }
        },
        template:`
            <div>
                <test v-model="num" />
            </div>
        `
    });
    app.component("test", {
        props:['modelValue'],
        methods : {
            incrNum() {
                this.$emit('update:modelValue', this.modelValue + 1);
            }
        },
        template:`
            <div @click="incrNum" >{{modelValue}}</div>
        `
    });

這個例子中,父元件使用 test 子元件時,使用v-model="num" 的方式來傳參。

test 子元件接收時,使用 props:['modelValue'] 的方式接收,注意:modelValue 是一個固定寫法。

在子元件的自增方法中使用this.$emit('update:modelValue', this.modelValue + 1); 的形式去修改 modelValue 的值,注意:update:modelValue 是固定寫法。

2.8 使用 num 替換 modelValue

上面的例子有點不好理解,無緣無故蹦出個modelValue,父元件明明傳的是 num,為啥我接受要用modelValue,太奇怪了

下面的例子更易於我們的理解

    const app = Vue.createApp({
        data() {
            return {
                num : 1
            }
        },
        template:`
            <div>
                <test v-model:num="num" />
            </div>
        `
    });
    app.component("test", {
        props:['num'],
        methods : {
            incrNum() {
                this.$emit('update:num', this.num + 1);
            }
        },
        template:`
            <div @click="incrNum" >{{num}}</div>
        `
    });

這個例子就好理解多了,首先父元件使用 test 子元件時,使用v-model:num="num" 進行傳參。

子元件接收時,接收的就是 num,使用 props:['num'] 接收。

最後使用this.$emit('update:num', this.num + 1); 程式碼對接收到的 num 進行修改。

顯示時顯示的也是 num,{{num}}

這樣寫就清爽很多,父元件沒有 method,子元件相當於自己對接收到的引數 num 進行操作,耦合度降低了很多。

3. 綜述

今天聊了一下 VUE3 的 元件間事件通訊,希望可以對大家的工作有所幫助,下一節我們繼續講元件的相關知識,敬請期待

歡迎幫忙點贊、評論、轉發、加關注 :)

關注追風人聊Java,每天更新Java乾貨。

4. 個人公眾號

追風人聊Java,歡迎大家關注