Vue 组件间通讯

prop、event、ref

经过 Prop 向子组件传递数据

Prop 是你能够在组件上注册的一些自定义特性。当一个值传递给一个 prop 特性的时候,它就变成了那个组件实例的一个属性。为了给博文组件传递一个标题,咱们能够用一个 props 选项将其包含在该组件可接受的 prop 列表中:html

Vue.component('blog-post', {
  props: ['title'],
  template: '<h3>{{ title }}</h3>'
})

一个组件默承认以拥有任意数量的 prop,任何值均可以传递给任何 prop。在上述模板中,你会发现咱们可以在组件实例中访问这个值,就像访问 data 中的值同样。
可使用 v-bind 来动态传递 propvue

<blog-post
  v-for="post in posts"
  v-bind:key="post.id"
  v-bind:title="post.title"
></blog-post>

参考:node


经过事件向父级组件发送消息

Vue 实例提供了一个自定义事件的系统来解决这个问题。咱们能够调用内建的 $emit 方法并传入事件的名字,来向父级组件触发一个事件:git

<button v-on:click="$emit('enlarge-text', 0.1)">
  Enlarge text
</button>

参考:github


访问元素 & 组件

ref 被用来给元素或子组件注册引用信息。引用信息将会注册在父组件的 $refs 对象上。若是在普通的 DOM 元素上使用,引用指向的就是 DOM 元素;若是用在子组件上,引用就指向组件实例:vuex

<!-- `vm.$refs.p` will be the DOM node -->
<p ref="p">hello</p>

<!-- `vm.$refs.child` will be the child component instance -->
<child-component ref="child"></child-component>

$parent 属性能够用来从一个子组件访问父组件的实例。设计模式

$children 用来访问当前实例的直接子组件。api

参考:
访问元素 & 组件
vm.$refs
vm.$parent
vm.$childrenapp


provide、inject

provide / inject 是 vue 2.2.0 新增的 APIiview

这对选项须要一块儿使用,以容许一个祖先组件向其全部子孙后代注入一个依赖,不论组件层次有多深,并在起上下游关系成立的时间里始终生效。若是你熟悉 React,这与 React 的上下文特性很类似。

// 父级组件提供 'foo'
var Provider = {
  provide: {
    foo: 'bar'
  },
  // ...
}

// 子组件注入 'foo'
var Child = {
  inject: ['foo'],
  created () {
    console.log(this.foo) // => "bar"
  }
  // ...
}

参考:


dispatch、broadcast

$dispatch$broadcastVue.js 1.x 中提供的方法。
$dispatch 用于向上级派发事件,只要是它的父级(一级或多级以上),均可以在组件内经过 $on (或 events2.x 已废弃)监听到。
$broadcast 是由上级向下级广播事件的。

参考 $dispatch 和 $broadcast 替换,在 vue2 中已经废弃了这两个 API,不过咱们能够参考 vue1 的源码在 vue2 中实现这两个 API

function broadcast(componentName, eventName, params) {
  this.$children.forEach(child => {
    var name = child.$options.componentName;

    if (name === componentName) {
      child.$emit.apply(child, [eventName].concat(params));
    } else {
      broadcast.apply(child, [componentName, eventName].concat([params]));
    }
  });
}
export default {
  methods: {
    dispatch(componentName, eventName, params) {
      var parent = this.$parent || this.$root;
      var name = parent.$options.componentName;

      while (parent && (!name || name !== componentName)) {
        parent = parent.$parent;

        if (parent) {
          name = parent.$options.componentName;
        }
      }
      if (parent) {
        parent.$emit.apply(parent, [eventName].concat(params));
      }
    },
    broadcast(componentName, eventName, params) {
      broadcast.call(this, componentName, eventName, params);
    }
  }
};

这里给出几个组件库的实现,能够参考:


findComponents

findComponents 系列方法并非 vueAPI,而是自行实现的经过递归、遍历,找到指定组件的 name 选项匹配的组件实例的方法。
有如下场景:

  • 由一个组件,向上找到最近的指定组件;
  • 由一个组件,向上找到全部的指定组件;
  • 由一个组件,向下找到最近的指定组件;
  • 由一个组件,向下找到全部指定的组件;
  • 由一个组件,找到指定组件的兄弟组件。
// 由一个组件,向上找到最近的指定组件
function findComponentUpward (context, componentName) {
    let parent = context.$parent;
    let name = parent.$options.name;

    while (parent && (!name || [componentName].indexOf(name) < 0)) {
        parent = parent.$parent;
        if (parent) name = parent.$options.name;
    }
    return parent;
}

// 由一个组件,向上找到全部的指定组件
function findComponentsUpward (context, componentName) {
    let parents = [];
    const parent = context.$parent;

    if (parent) {
        if (parent.$options.name === componentName) parents.push(parent);
        return parents.concat(findComponentsUpward(parent, componentName));
    } else {
        return [];
    }
}

// 由一个组件,向下找到最近的指定组件
function findComponentDownward (context, componentName) {
    const childrens = context.$children;
    let children = null;

    if (childrens.length) {
        for (const child of childrens) {
            const name = child.$options.name;

            if (name === componentName) {
                children = child;
                break;
            } else {
                children = findComponentDownward(child, componentName);
                if (children) break;
            }
        }
    }
    return children;
}

// 由一个组件,向下找到全部指定的组件
function findComponentsDownward (context, componentName) {
    return context.$children.reduce((components, child) => {
        if (child.$options.name === componentName) components.push(child);
        const foundChilds = findComponentsDownward(child, componentName);
        return components.concat(foundChilds);
    }, []);
}

// 由一个组件,找到指定组件的兄弟组件
function findBrothersComponents (context, componentName, exceptMe = true) {
    let res = context.$parent.$children.filter(item => {
        return item.$options.name === componentName;
    });
    let index = res.findIndex(item => item._uid === context._uid);
    if (exceptMe) res.splice(index, 1);
    return res;
}

eventbus、vuex

EventBus

EventBus 是一种发布订阅设计模式(观察者设计模式)。
EventBus

  • 有一个全局EventBus
  • 全部事件都订阅它
  • 全部组件也发布到它,订阅组件得到更新
  • 全部组件都可以将事件发布到总线,而后总线由另外一个组件订阅,而后订阅它的组件将获得更新
var EventBus = new Vue(); 
Object.defineProperties(Vue.prototype, { 
    $bus: { get: function () { 
            return EventBus 
        }
    }
})

这个特定的总线使用两个方法 $on$emit$emit 用于建立发出的事件;$on 用于订阅。

var EventBus = new Vue();
this.$bus.$emit('nameOfEvent',{
    // code
});
this.$bus.$on('nameOfEvent',($event) => {
    // code
})

参考:
EventBus
事件总线(EventBus)


Vuex

Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。它采用集中式存储管理应用的全部组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。
vuex

参考:

相关文章
相关标签/搜索