_
2023/8/31 08:27:411027

前面我们学习vue的单项数据流,在vue中父组件可以使用属性的方式给子组件传递数据,那么如果我们要想在子组件里面传数据给父组件怎么办呢,按照单项数据流原则是不允许我们子组件给父组件逆向传数据的。若想要实现子组件给父组件传数据的话我们可以通过事件通讯的方式。

从计数器开始

我们先写个计数器组件,从一个计数器开始我们今天的课程。

<script>
  const app = Vue.createApp({
    data() {
      return {
        message: "hello world!"
      }
    },
    template: `<div>
        <div>这是一个计数器 点击能加1 </div>
        <Counter/>
      </div>`
  })

  app.component('Counter',{
      data(){
        return{
          count:1
        }
      },
      methods: {
        handelAddCount(){
          this.count++
        }
      },
      template:`<button @click="handelAddCount" >{{count}}</button>`
  })

  const vm = app.mount("#app")
</script>

改改计数器

目前在Counter组件中,count计数变量是在组件内部的定义的,那么假设我们需要在外部定义count变量然后传给Counter组件来使用。

我们肯定先在App根组件中来定义一个的count,在到Counter组件定义一个props来接收传过来的数据,再把数据渲染到组件节点中。

<script>
  const app = Vue.createApp({
    data() {
      return {
        count: 1
      }
    },
    template: `<div>
        <div>这是一个计数器 点击能加1 </div>
        <Counter :count="count" />
      </div>`
  })
  app.component('Counter',{
      props:[count],
      methods: {
        handelAddCount(){
          this.count++
        }
      },
      template:`<button @click="handelAddCount" >{{count}}</button>`
  })
  const vm = app.mount("#app")
</script>

我们改成这样之后,会发现个问题,当点击按钮数值没有加一,控制台还给我们一个警告信息,所以我们不能直接修改props的值。

子组件调用父组件方法

遇到这样的问题,我们可以让父组件去帮我们修改count值,那么怎么做呢在handelAddCount这个方法里面通过this.$emit方法向外抛出一个事件,这个事件我们可以叫它addCount

app.component('Counter',{
      props:["count"],
      methods: {
        handelAddCount(){
          this.$emit("addCount")
        }
      },
      template:`<button @click="handelAddCount" >{{count}}</button>`
  })

然后我们就可以在父组件中来监听这个事件,使用v-on或者@来监听addCount事件,在事件中我们来修改count++

const app = Vue.createApp({
    data() {
      return {
        count: 1
      }
    },
    methods:{
      handelAddCount(){
        this.count++
      }
    },
    template: `<div>
        <div>这是一个计数器 点击能加1 </div>
        <Counter :count="count" @add-count="handelAddCount" />
      </div>`
  })

然后我们到浏览器看一下效果,你会发现当点击按钮的时候,count已经可以增加了。

子组件给父组件传值

通过自定义事件的方式我们让父组件帮我们修改了props的值, 假如在这个计数器里面我们还希望父组件不只是让count加1,我们希望的是可以随时修改的,让它加多少就加多少。比如+2。

 handelAddCount(){
    this.$emit("addCount",2)
 }

this.$emit方法第二个参数就是事件的传值,意思就通过emit方法抛出了一个事件,这个事件传递一个参数值为2,然后父组件监听事件时,就可以获取到这个参数,再让count加上这个值。

methods:{
   handelAddCount(num){
     this.count+=num
   }
}

定义事件

在使用emit抛出自定义事件的时候,我们比较规范的写法是需要在组件中定一个emits。来表示我这个组件会触发那些自定义事件。

app.component('Counter',{
      props:["count"],
      emits:['addCount'],
      methods: {
        handelAddCount(){
          this.$emit("addCount",2)
        }
      },
      template:`<button @click="handelAddCount" >{{count}}</button>`
  })

emits它可以接收一个数组,我们给它定义了一个addCount事件,表示我们会触发addCount事件,这样代码看起会更佳规范。

另外,如果我们触发的事件,并没有在emits里面定义的,vue会给我报一个警告的。

![](file:///Users/apple/Desktop/images/2023-07-13-01-25-49-image.png?msec=1695744987356)

emits它可以接收一个数组,也可以接受对象,在使用对象的方式声明时,它还给我提供一个传值校验的功能。

emits:{
   addCount:(val)=>{
     if(val>20){
        return true
     }else{
        return false
     }
   }
}

val表示我们传的值,当我们返回true时,表示可以把这个值传出去,返回false时表示不可以把这个值传出去,并且vue还会给我们报警告。

![](file:///Users/apple/Desktop/images/2023-07-13-01-31-26-image.png?msec=1695744987357)

好了,节课的知识点我们就学习完了,拜拜~

视频讲解