vue 12种通信方式

Vue组件间的通信方式

1. props传递数据

在父组件中使用儿子组件

<template>
 <div>
  父组件:{{mny}}
  <Son1 :mny="mny"></Son1>
 </div>
</template>

<script>
import Son1 from "./Son1";
export default {
 components: {
  Son1
 },
 data() {
  return { mny: 100 };
 }
};
</script>

在子组件中获取父组件的mny值

<template>
  <div>
    子组件:{{subMny}}
  </div>
<template>

<script>
export default {
  props: {
    mny: String
  },
  data() {
    return {
      subMny: this.mny
    }
  }
}
</script>
2.$emit使用

子组件出发父组件的方法

/* 父组件 */
<template>
 <div>
  父组件:{{mny}}
  <Son1 :mny="mny" @input="change"></Son1>
 </div>
</template>
<script>
import Son1 from "./Son1";
export default {
 methods: {
  change(mny) {
   this.mny = mny;
  }
 },
 components: {
  Son1
 },
 data() {
  return { mny: 100 };
 }
};
</script>

子组件触发绑定自身的方法

/* 子组件 */
<template>
 <div>
  子组件1: {{mny}}
  <button @click="$emit('input',200)">更改</button>
 </div>
</template>
<script>
export default {
 props: {
  mny: {
   type: Number
  }
 }
};
</script>
3.sync实现数据双向绑定,从而同步父子组件数据,父组件可以修改子组件,子组件也可以修改父组件
<Son1 :mny.sync="mny"></Son1>
<!-- 触发的事件名 update:(绑定.sync属性的名字) -->
<button @click="$emit('update:mny',200)">更改</button>

<!--等价于-->
<!-- 父组件-->
<Son1 :mny="mny" @update.mny="val => mny = val"></Son1>
<button @click="$emit('update:mny',200)">更改</button>
4.v-model
<Son1 v-model="mny"></Son1>
<!--等价于-->
<Son1 v-bind:value="mny" v-on:input="mmy = $event.target.value"></Son1>

<template>
 <div>
  子组件1: {{value}} // 触发的事件只能是input
  <button @click="$emit('input',200)">更改</button>
 </div>
</template>
<script>
export default {
 props: {
  value: { // 接收到的属性名只能叫value
   type: Number
  }
 }
};
</script>

写自定义组件select的时候发现没有input事件,要如何才是使用v-model?

   Vue.component('vue-select', {
      model: {
        prop: 'checked',
        event: 'change'
      },
      props: {
        checked: Boolean,
        // this allows using the `value` prop for a different purpose
        value: String
      },
      // ...
    })

新增model属性值里面有两个key,分别为prop、event,值分别为checked、change。model属性值里的两个key就是v-model的语法糖所代表的的prop和event,分别表示该单元素的值和改变元素值的触发事件,在input中,这两个值value和input默认值,在checkout中表示checked和change,select中表示selected和change。

<!--父组件-->
<mui-select
  v-bind:selected="parentValue"
  v-on:change="parentValue = arguments[0]">
</mui-select>

<!--子组件-->
<select :value="selected" @change="handleChange($event.target.value">
  <template v-for="item in selectData">
    <option :value="item.value">{{item.text}}</option>
  <template>
<select>

<script>
export default{
  model: {
    prop: "selected",
    event: "change"
  },
  props: {
    selectData: Array,
    selected: {
      type: [String, Number]
    }
  },
  methods: {
    handleChange(val) {
      this.$emit('change', val)
    }
 }
 </script>
5. $parent, $children属性传递
<Grandson1 :value="value"></Grandson1>
<template>
 <div>
  孙子:{{value}}
  <!-- 调用父组件的input事件 -->
  <button @click="$parent.$emit('input',200)">更改</button>
 </div>
</template>
<script>
export default {
 props: {
  value: {
   type: Number
  }
 }
};
</script>
6. $dispatch

既然能向上派发也可以向下派发

Vue.prototype.$dispatch = function $dispatch(eventName, data) {
  let parent = this.$parent;
  while(parent) {
    parent.$emit(eventName, data);
    parent = parent.$parent;
  }
};
7.$broadcast
Vue.prototype.$broadcast = function $broadcast(eventName, data) {
  const broadcase = function() {
    this.$children.forEach(child => {
      child.$emit(eventName, data);
      if(child.$children){
        $broadcast.call(child, eventName, data)
      }
    });
  };
  broadcast.call(this, eventName, data);
};
7. $attr 批量向下传入属性
<Son2 name="小珠峰" age="10"></Son2>

<!-- 可以在son2组件中使用$attrs属性,可以将属性继续向下传递 -->
<div>
  儿子2: {{$attrs.name}}
  <Grandson2 v-bind="$attrs"></Grandson2>
</div>


<template>
 <div>孙子:{{$attrs}}</div>
</template>
8.$listeners批量向下传入方法
<Son2 name="小珠峰" age="10" @click="()=>{this.mny = 500}"></Son2>
<!-- 可以在son2组件中使用listeners属性,可以将方法继续向下传递 -->
<Grandson2 v-bind="$attrs" v-on="$listeners"></Grandson2>

<button @click="$listeners.click()">更改</button>
9. provide&inject

provide 在父组件中注入数据

provide() {
  return { parentMsg: "父亲" };
}

inject 在任意子组件中可以注入父组件数据

inject: ['parentMsg']; // 会将数据挂载在当前实例上
10.Ref获取组件实例
<Grandson2 v-bind="$attrs" v-on="$listeners" ref="grand2"></Grandson2>
mounted() { // 获取组件定义的属性
  console.log(this.$refs.grand2.name);
}
11.eventBus用于跨组件通知
Vue.prototype.$bus = new Vue();

son2组件

mounted() {
  this.$bus.$on('my', data=> {
    console.log(data);
  });
},

grandson1组件

mounted() {
  this.$nextTick(() => {
    this.$bus.$emit('my', '我是grandson1’)
  })
}
12.vuex 状态管理

在这里插入图片描述