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,歡迎大家關注


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM