ThinkChat2.0新版上线,更智能更精彩,支持会话、画图、阅读、搜索等,送10W Token,即刻开启你的AI之旅 广告
[TOC] >[success] # 父子组件间如何通过事件进行通信 **需求** :封装一个 **计数器组件** ,**父给子传一个数字,子组件中每次点击数字时,数字自增 +1** ,这样就涉及到了需要**修改父组件传入的值** ,我们之前讲过 **vue** 是 **单向数据流** ,**子组件不可以修改父组件传递的数据** ,之前的 **解决办法是复制一份副本修改副本** ,那么我们今天讲一下另外一种解决办法, **我们在子组件通过事件告诉父组件来修改这个值** 。 1. **子传父** ~~~ <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>父子组件间如何通过事件进行通信</title> <!-- 通过cdn方式引入vue --> <script src="https://unpkg.com/vue@next"></script> </head> <body> <div id="root"></div> </body> <script> // 父组件 const app = Vue.createApp({ data(){ return { count: 1 } }, methods: { handleAddOne(param){ this.count += param } }, template: ` <div> <counter :count="count" @add-one="handleAddOne" /> </div> ` }) // 子组件 app.component('counter', { props: ['count'], methods: { handleClick(){ this.$emit('addOne', 2) } }, template: ` <div @click="handleClick">{{count}}</div> ` }) const vm = app.mount('#root') </script> </html> ~~~ 子组件 **$emit('addOne')** 时, **事件名**可以是 **驼峰式命名** ,但是 **在标签上使用时应该是中划线方式@add-one="handleAddOne"** 。 上面的计算方式是 **子组件通过事件来告知父组件,父组件计算后传给子组件** ,也可以**在子组件中计算完成后,传入给父组件,父组件再回传回来** ,如下: ~~~ <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>父子组件间如何通过事件进行通信</title> <!-- 通过cdn方式引入vue --> <script src="https://unpkg.com/vue@next"></script> </head> <body> <div id="root"></div> </body> <script> // 父组件 const app = Vue.createApp({ data(){ return { count: 1 } }, methods: { handleAddOne(param){ this.count = param } }, template: ` <div> <counter :count="count" @add-one="handleAddOne" /> </div> ` }) // 子组件 app.component('counter', { props: ['count'], methods: { handleClick(){ this.$emit('addOne', this.count + 2) } }, template: ` <div @click="handleClick">{{count}}</div> ` }) const vm = app.mount('#root') </script> </html> ~~~ >[success] # emits 如果一个 **子组件向外部触发事件** ,可以写一个 **emits** 的 **对象或数组** ,来 **存放$emit定义的事件**。 **emits的作用** : 为了 **方便易于维护,写在emits中,一眼就能看到组件中向外传递了哪些事件**,很方便, 还可以 **校验$emit回传的值的格式** ~~~ <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>父子组件间如何通过事件进行通信</title> <!-- 通过cdn方式引入vue --> <script src="https://unpkg.com/vue@next"></script> </head> <body> <div id="root"></div> </body> <script> // 父组件 const app = Vue.createApp({ data(){ return { count: 1 } }, methods: { handleAddOne(param){ this.count = param } }, template: ` <div> <counter :count="count" @add-one="handleAddOne" /> </div> ` }) // 子组件 app.component('counter', { props: ['count'], // emits: ['addOne'], // 数组形式 emits: { // 对象形式 addOne: (count) => { // count参数:this.$emit('addOne', 对应这个count) if(count < 0){ // 如果参数大于0,同意事件往外传值 return true } // 如果小于0,不允许往外传,并且给予警告 return false } }, // 对象形式 methods: { handleClick(){ this.$emit('addOne', this.count + 2) } }, template: ` <div @click="handleClick">{{count}}</div> ` }) const vm = app.mount('#root') </script> </html> ~~~