vue常见的通信(2)

1.父子组件之间的通信 props 和 $emit

父组件通过 prop 给子组件下发数据,子组件通过$emit触发事件给父组件发送消息,即 prop 向下传递,事件向上传递。

父组件:parents

<template>
  <div>
    <children :msg="msg" @say="childrenSay"></children>
  </div>
</template>
<script>
  import Children from './children'
export default {
  name: "parents",
  components:{
    children:Children
  },
  data(){
    return{
      msg:'亲爱的小孩 !',

    }
  },
  methods:{
    childrenSay(msg){
      console.log(msg)
    }
  }
}
</script>

子组件 :children

<template>
  <div>
    <p v-text="'父组件对我说:'+msg"></p>
    <p @click="say" style="border:1px solid #eee;">我对父组件说的话</p>
  </div>
</template>
<script>
export default {
  name: "children",
  props:{
    msg:{
      type:String,
      default: () => {
        return ''
      }
    }
  },
  data(){
    return{
      childrenSay: '亲爱的父亲 !'
    }
  },
  methods:{
    say(){
      this.$emit('say' , this.childrenSay);
    }
  }
}
</script>

效果如下:
在这里插入图片描述

2. a t t r s 和 attrs和 attrslisteners 的使用

A组件

<template>
  <div>
    <child-dom
      :foo="foo"
      :coo="coo"
      v-on:upRocket="reciveRocket">
    </child-dom>
  </div>
</template>
<script>
  import childDom from "./childDom";
  export default {
    name:'demoNo',
    data() {
      return {
        foo:"Hello, world",
        coo:"Hello,rui"
      }
    },
    components:{childDom},
    methods:{
      reciveRocket(){
        console.log("reciveRocket success")
      }
    }
  }
</script>

B组件

<template>
  <div>
    <p class="childDom">foo:{{foo}}</p>
    <p class="childDom">attrs:{{$attrs}}</p>
    <childDomChild v-bind="$attrs" v-on="$listeners"></childDomChild>
  </div>
</template>
<script>
  import childDomChild from './childDomChild';
  export default {
    components:{childDomChild},
    name:'child-dom',
    props:["foo"],
    inheritAttrs:false,
  }
</script>

c组件

<template>
  <div>
    <p>coo:{{coo}}</p>
    <button @click="startUpRocket">我要发射火箭</button>
  </div>
</template>
<script>
  export default {
    name:'childDomChild',
    props:['coo'],
    methods:{
      startUpRocket(){
        this.$emit("upRocket");
      }
    }
  }
</script>

总结
a t t r s 包 含 了 父 作 用 域 中 不 被 认 为 ( 且 不 预 期 为 ) p r o p s 的 特 性 绑 定 ( c l a s s 和 s t y l e 除 外 ) 。 当 一 个 组 件 没 有 声 明 任 何 p r o p s 时 , 这 里 会 包 含 所 有 父 作 用 域 的 绑 定 ( c l a s s 和 s t y l e 除 外 ) , 并 且 可 以 通 过 v − b i n d = ” attrs 包含了父作用域中不被认为 (且不预期为) props 的特性绑定 (class 和 style 除外)。当一个组件没有声明任何 props 时,这里会包含所有父作用域的绑定 (class 和 style 除外),并且可以通过 v-bind=” attrs()props(classstyle)props(classstyle)vbind=attrs” 传入内部组件——在创建更高层次的组件时非常有用。
$listeners

包含了父作用域中的 (不含 .native 修饰器的) v-on 事件监听器。它可以通过 v-on=”$listeners” 传入内部组件——在创建更高层次的组件时非常有用。
inheritAttrs
默认情况下父作用域的不被认作 props 的特性绑定 (attribute bindings) 将会“回退”且作为普通的 HTML 特性应用在子组件的根元素上。当撰写包裹一个目标元素或另一个组件的组件时,这可能不会总是符合预期行为。通过设置 inheritAttrs 到 false,这些默认行为将会被去掉。而通过 (同样是 2.4 新增的) 实例属性 $attrs 可以让这些特性生效,且可以通过 v-bind 显性的绑定到非根元素上。
上述特性的使用完全可以降低在不使用Vuex以及事件总线的情况下,组件跨级props以及事件传递的复杂度。

3.中央事件总线

一个中央事件总线bus,可以作为一个简单的组件传递数据,用于解决跨级和兄弟组件通信问题,那么我们将使用这种思想,将bus封装为一个Vue的插件,可以在所有的组件间任意使用,而不需要导入bus。
首先在src目录下新建vue-bus.js

const install = function (Vue) {
  const Bus = new Vue({
    methods: {
      emit (event, ...args) {
        this.$emit(event, ...args);
      },
      on (event, callback) {
        this.$on(event, callback);
      },
      off (event, callback) {
        this.$off(event, callback);
      }
    }
  });
  Vue.prototype.$bus = Bus;
};

export default install;

其次在main.js中引用

import VueBus from './vue-bus';
Vue.use(VueBus); //加载插件VueBus

然后新建一个counter组件

<template>
  <div>
    {{ number }}
    <button @click="handleAddRandom">随机增加</button>
  </div>
</template>
<script>
  export default {
    props: {
      number: {
        type: Number
      }
    },
    methods: {
      handleAddRandom () {
        // 随机获取 1-100 中的数
        const num = Math.floor(Math.random () * 100 + 1);
        this.$bus.emit('add', num);
      }
    }
  };
</script>

说明
1)定义一个按钮,组件有个属性名称是number;

2)组件定义了一个方法,随机去一个数据,会调用bus定义的一个时间,并将数据传递过去;

最后index.vue

<template>
    <div>
        <h1>首页</h1>
        随机增加:
        <Counter :number="number"></Counter>
    </div>
</template>
<script>
    import Counter from './counter.vue';
 
    export default {
        components: {
            Counter
        },
        computed: {
           .....
        },
        methods: {
            .......
            handleAddRandom (num) {
                this.number += num;
            }
        },
        data () {
            return {
                number: 0
            }
        },
        created () {
            this.$bus.on('add', this.handleAddRandom);
        },
        beforeDestroy () {
            this.$bus.off('add', this.handleAddRandom);
        }
    }
</script>

效果如下
在这里插入图片描述

说明
1)导入自定义的组件,计数器;
2)组件创建和销毁后,分别绑定和基础自定义的事件add,即对add事件进行监听
3)接受触发add事件后,接受到传递过来的数据;
//
使用vue-bus有两点需要注意,第一是 b u s . o n 应 该 在 c r e a t e d 钩 子 内 使 用 , 如 果 在 m o u n t e d 使 用 , 它 可 能 接 收 不 到 其 他 组 件 来 自 c r e a t e d 钩 子 内 发 出 的 事 件 ; 第 二 点 是 使 用 了 bus.on应该在created钩子内使用,如果在mounted使用,它可能接收不到其他组件来自created钩子内发出的事件;第二点是使用了 bus.oncreated使mounted使created使bus.on在beforeDestory钩子里应该需要使用$bus.off解除,因为组件销毁后,就没有必要把监听的句柄存储在vue-bus里面了

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值