2021-10-10 vue笔记-组件化开发(二) 组件通信:父传子,子传父

0.组件间传值(组件通信)纲要
为什么要组建通信

每个组件之间具有一定的独立性,
但是在实际工作中使用组件的时候有互相之间传递数据的需求,
此时就得考虑进行组件间传值

组件通信的分类

组件通信分为 2 种:父子组件之间的通信、非父子组件之间的通信;

父子组件通信

父组件通过props向子组件传值,
子组件通过$emit将数据发送给父组件;

非父子组件通信又分为兄弟组件、隔代关系组件等
  • 通信方式一:事件总线
通过eventBus(事件总线)实现跨组件传输,
原理:将eventBus作为连接组件之间的桥梁,
所有组件共用相同的事件中心,
向事件中心发送或接收事件,并可以通知其他组件;
eventBus使用步骤:

1、初始化,创建一个事件总线并导出,以便其他模块可以使用并监听它;

// eventBus.js
import Vue from 'vue'
//通过一个空的Vue实例作为中央事件总线(事件中心)
export const EventBus = new Vue() 

2、导入eventBus,使用$emit发送数据;
3、导入$on,使用$on接收数据;
4、如果想移除事件,可以先导入eventBus,通过$off移除;(eventBus.$off ( 'add', {} ))

  • 通信方式二:ref 和 $refs;
如果 ref 在普通DOM上,那么它的引用指向的就是DOM元素;
如果用到子组件上,那么它的引用就指向组件实例,
可以通过实例直接调用组件上的方法和数据
1.父传子
步骤

父组件以自定义属性的形式绑定值到子组件身上
子组件通过使用属性props接收

props
  • props是单向绑定的(只读属性)
    当父组件的属性变化时,将传导给子组件,但是反过来不会
  • 父组件的数据需要通过props把数据传给子组件,子组件需要显式地用props选项声明"props"
  • props属性支持两种常见的写法形式
1.数组(推荐):书写简单,不能设置默认值、数据类型
2.对象:写法复杂,可以设置数据默认值与数据类型
例子:父(root)=>子(navbar)
代码
<body>
    <div id="app">
        <!-- myname是自定义属性(不能用驼峰命名法) -->
        <navbar myname="home" v-bind:myshow="true"></navbar>
        <!-- 使用v-bind动态绑定属性(简写为一个冒号) -->
        <navbar myname="login" :myshow="true"></navbar>
        <navbar myname="list" :myshow="false"></navbar>
        <navbar :myname="parentpath" :myshow="true"></navbar>
    </div>
</body>
<script>
    Vue.component('navbar', {
        // 调用自定义属性myname和myshow
        template: `<div>返回{{myname}}页:<span v-show="myshow">显示</span></div>`,
        // 接收父组件传来的属性(数组)
        props: ["myname", "myshow"]
    })
    new Vue({
        el: "#app",
        data: {
            // 父组件root的属性
            parentpath: "user"
        }
    })
</script>
结果

返回home页:显示
返回login页:显示
返回list页:
返回user页:

总结
1.此处的父组件是指系统默认的根组件root
2.在子组件navbar中,使用props接收父组件传来的属性构成的对象,
该属性已在navbar的调用中,定义成自定义属性
3.动态绑定可以让自定义属性中的值不被看成是字符串,而是js的语法内容
4.props写在template后面而不是{}外面
2.使用props属性的对象写法来进行属性验证
示例:接上例,其他代码不变
  // 接收父组件传来的属性(数组)
  // props: ["myname", "myshow"]
  // 接收父组件传来的属性,并验证(对象)
  props: {
      myname: String,
      myshow: Boolean
  }
3.子传父
步骤
  • 子组件模版内容中.用 $emit() 定义自定义事件
  • 父组件模板内容中.子组件占位标签上.用v-on(或@)绑定子组件定义的自定义事件名,监听子组件的事件来实现通信
$emit()

$emit() 方法有2个参数:

第一个参数为自定义的事件名称
第二个参数为需要传递的数据(可选)
子传父例子一:点击button,p标签字体变大
<body>
    <div id="app">
        <!-- step2:父组件模板内容中.子组件占位标签上.用v-on绑定子组件定义的自定义事件名myclick -->
        <!-- bigger不用带括号 -->
        <child @myclick="bigger"></child>
        <p :style="{fontSize:fontSize+'px'}">hello</p>
    </div>
</body>
<script>
    Vue.component("child", {
        //step1:子组件模版内容中.用 $emit() 定义自定义事件myclick 
        //$emit()的两个参数:自定义的事件名称 需要传递的数据
        template: `<button @click="$emit('myclick',10)">点击</button>`
    });
    new Vue({
        el: "#app",
        data: {
            fontSize: 12
        },
        methods: {
            bigger: function(n) {
                this.fontSize += n//效果:点击button,p标签字体变大
            }
        }
    })
</script>
子传父例子二:(实际应用)点击实现侧边栏的显示和隐藏
<body>
    <div id="app">
        <navbar @myclick="handleEvent"></navbar>
        <sidebar v-show="isShow"></sidebar>
    </div>
</body>
<script>
    Vue.component('navbar', {
        // template: `<button @click="$emit('myclick')">点击</button>`,,与下面代码效果一样
        template: `<button @click="handleClick">点击</button>`,
        methods: {
            handleClick() {
                this.$emit("myclick");
            }
        }
    });
    Vue.component('sidebar', {
        template: `<ul><li>111</li><li>222</li><li>333</li></ul>`
    });
    new Vue({
        el: "#app",
        data: {
            isShow: false
        },
        methods: {
            handleEvent: function() {
                this.isShow = !this.isShow;
            }
        }
    })
</script>
总结
1.父传子是用属性向下传,子传父是用事件向上传
2.子传父的步骤:
	step1:在父组件模板内容的子组件占位符<child>上使用@绑定子组件自定义事件名
	step2:在子组件模板内容的template``,使用$emit()定义自定义事件
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

前端OnTheRun

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值