vue组件通信(触发事件、注册事件)详解

组件事件

组件之间经常都会发生消息的传递,我们称之为组件通信

prop是组件通信的一种,消息从父组件传递到子组件

但还有一些场景,就是子组件中发生了一件事,可是它没有能力处理这件事,需要使用它的人来处理,此时,就需要事件 event

例如,倒计时组件停止了,可是停止之后干嘛呢?在不同的场景要做不同的事情,可能什么也不做,可能在页面上显示倒计时结束了,也可能把计时器组件销毁掉,也可能另一个组件会变化?

无论是哪种情况,都超出了计时器组件的控制能力

所以,计时器组件在计时结束后,抛出一个事件,事件可以让父组件收到通知,于是父组件可以站在更高的层面来处理这个问题

在这里插入图片描述

子组件中抛出一个事件,称之为触发事件

在父组件中为子组件设置事件处理程序,称之为注册事件
子组件Timer.js

var template = `
    <div>
        <h1>{{ value }}</h1>  
    </div>
`;
export default{
  template,
  props:["value"],
  // data(){
  //   return{
  //     n: 5
  //   };
  // },
  created() {
    // this.$emit("number-change",this.n);
    //开启定时器
    var timer = setInterval(()=>{
      //子组件表达了一个愿望,希望父组件更新数据
        this.$emit("input",this.value-1);
        // this.value--;
        
        if(this.value === 0){
            clearInterval(timer);//停止
            console.log("计时器停止了");
            //触发事件
            // this.$emit("事件名",额外参数)
            // this.$emit("timer-over",this.n);    
        }
    },1000)
  },
};

父组件

// // 新建一个组件
// import MovieContainer from "./components/MovieContainer.js";
// var template = `
// <MovieContainer/>
// `;

// // 导出一个组件配置对象
// export default {
//   components: {
//     MovieContainer
//   },
//   template
// };

import Timer from "./components/test/Timer.js";

var template = `<div>
  <Timer v-model="n" />
  
  <h2>
    目前的数字:{{n}}
  </h2>
</div>`;

export default {
  components: {
    Timer
  },
  data() {
    return {
      n: 5
    };
  },
  template
};

触发事件的代码

this.$emit("事件名", 额外参数)

注册事件的代码

<my-comp 事件名="处理函数">

属性和事件是组件间最常见的通信方式,除此之外,组件之间还有很多其他的通信方式,用于解决一些特殊问题

v-model

如果一个计时器组件,它当前显示的数字,需要被外部控制,那么显示的数字就不能作为状态,而要作为属性,因为状态外部控制不了。

而这样一来,该计时器组件如何实现计时更新呢?

正确的方式是,让该组件希望更新属性时,抛出一个事件,让父组件处理

var Timer = {
  props:["value"],
  data(){
    return {
      timerId: null
    }
  },
  created(){
    this.timerId = setTimeout(()=>{
      this.$emit("input", this.number - 1);
      //是否计时完成
    }, 1000)
  },
  template: `<h1>{{}}</h1>`
}

父组件可以处理该事件,并给予新的属性

var Parent = {
  components:{Timer},
  data(){
    return {
      n:10
    }
  },
  template: `<Timer :value="n" @input="n=$event"/>`
}

在这里插入图片描述
在这里插入图片描述

实际上这是一个非常简单的流程,即:

  1. 子组件想更新数据,通知父组件
  2. 父组件直接更新数据

为了简化这一流程,只要子组件的属性是value,事件是input,父组件可以用使用v-model直接实现数据绑定

<Timer v-model="n"/>
<!-- 完全等同于 -->
<Timer :value="n" @input="n=$event"/>

插槽

有的时候,组件中某一部分内容不知道要显示什么,它可能什么也不显示,也可能要显示另一个组件,又或者要显示一个标签,又或者要显示一个文本

例如,一个朦层组件,它仅仅是提供一个朦层,在朦层中间显示什么并不确定

在这里插入图片描述
此时,就可以使用插槽

// 朦层组件
var Modal = {
  template: `
    <div class="modal">
      <!-- 朦层中间区域 -->
      <div class="center">
        <!-- 不知道要显示什么,使用插槽 -->
        <slot>插槽默认值</slot>
      </div>
    </div>
  `
}

在使用朦层组件时,如果元素内部的内容将传递给slot

<modal>
  加载中...
</modal>

如果没有传递元素内容,则会使用slot的默认值

发布了75 篇原创文章 · 获赞 16 · 访问量 1万+
App 阅读领勋章
微信扫码 下载APP
阅读全文

没有更多推荐了,返回首页

©️2019 CSDN 皮肤主题: 技术工厂 设计师: CSDN官方博客

分享到微信朋友圈

×

扫一扫,手机浏览