资讯专栏INFORMATION COLUMN

【Vue项目总结】组件通信处理方案

TerryCai / 3023人阅读

摘要:组件之间的通信是我们在项目中常常碰到的,而选择合适的通信方式尤为重要,这里总结下作者在实际项目中所运用到的通信方案,如有遗漏,请大家见谅。示例效果如下兄弟组件同级别组件相互间的通信,我们可以使用或着。

Vue组件之间的通信是我们在项目中常常碰到的,而选择合适的通信方式尤为重要,这里总结下作者在实际项目中所运用到的通信方案,如有遗漏,请大家见谅。文章代码具体见DEMO;文章首发于imondo.cn

父子组件

Vue中常见的是父与子组件间的通信,所要用到的关键字段是props$emit

props接受父组件传给子组件信息的字段,它的类型:Array | Object;详细解释可以参考文档

$emit由子组件触发事件向上传播给父级消息。

示例:

// Parent




// Child


效果如下:

祖孙组件

有时候我们可能会碰到组件间的无限嵌套,这是我们使用props时无法向下无限极传递数据的,这是我们可以用到provide/injectprovide可以向其子孙组件传递数据,而不关子孙组件的层级有多深,使用inject都可以拿到数据。详细解释可以参考文档

示例:

// Grand




// Parent

效果如下:

provideinject 绑定并不是可响应的。我们可以通过传递祖父级的实例this或着使用observable来使传递的数据是响应的。
// Grand



// Child


效果如下:

使用observable让一个对象可响应。Vue 内部会用它来处理 data 函数返回的对象。

示例:

// Grand
provide() {
  this.read = Vue.observable({
    msg: ""
  })
  return {
    read: this.read
  };
}

效果如下:

兄弟组件

同级别组件相互间的通信,我们可以使用EventBus或着Vuex

简单的EventBus示例:

// Bus.js
import Vue from "vue";
export default new Vue();

// Child

我是子组件一

// ChildOne

我是子组件二

兄弟叫我:{{ msg }}

效果如下:

v-modelsync

v-model是我们用ElementUI常见的表单绑定值方式;可以直接修改子组件修改父组件传入的值,简化了我们组件通信的逻辑。

示例:

// ModelCom
// Home

效果如下:

sync修饰符也可以是我们的prop进行双向绑定

它需要我们在子组件内触发this.$emit("update:prop", val)事件

// ModelCom

...
props: ["value"],
methods: {
  handleChange(e) {
    const value = e.target.value;
    // 触发更新
    this.$emit("update:value", value);
  }
}

// Home

效果如下:

$children$parent

我们可以在组件中通过当前的实例对象访问到组件的$children$parent来找到各自组件的父级组件或子级组件实例。

示例:

// Child

我是子组件

来自父组件的msg: {{ msg }}

...

$attrs$listeners

$attrs可以通过 v-bind="$attrs" 将组件上的特新都(class 和 style 除外)传入内部组件;传入的值与inheritAttrs的设置有关,通常封装高级组件。

当我们inheritAttrs 设置 true;组件渲染DOM时写在组件的特性会渲染上去;

$listeners包含了父作用域中的 (不含 .native 修饰器的) v-on 事件监听器。它可以通过 v-on="$listeners" 传入内部组件。

具体详细可见文档

示例:

// Attr

Attr

这是$attrs:{{ placeholder }}

这是$listeners:{{ test }}

... // Home

效果如下:

通过封装查找组件
通过封装函数来向上或向下派发事件

参考见Vue.js组件精讲

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

        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) {
            let parent = this.$parent || this.$root;
            let name = parent.$options.name;

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

                if (parent) {
                    name = parent.$options.name;
                }
            }
            if (parent) {
                parent.$emit.apply(parent, [eventName].concat(params));
            }
        },
        broadcast(componentName, eventName, params) {
            broadcast.call(this, componentName, eventName, params);
        }
    }
};
通过封装函数来查找指定任意组件

参考见Vue.js组件精讲

// 由一个组件,向上找到最近的指定组件
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;
}
export { findComponentUpward };

// 由一个组件,向上找到所有的指定组件
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 [];
    }
}
export { findComponentsUpward };

// 由一个组件,向下找到所有指定的组件
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);
    }, []);
}
export { findComponentsDownward };

// 由一个组件,找到指定组件的兄弟组件
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;
}
export { findBrothersComponents };
总结

项目中组件的通信方式大概常用的是上面几种方案,我们可以通过不同的方式来实现组件通信,但是选择合适组件通信方式可以使我们事半功倍。写的不当之处,望指正~

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/104274.html

相关文章

  • 关于Vue2一些值得推荐的文章 -- 五、六月份

    摘要:五六月份推荐集合查看最新的请点击集前端最近很火的框架资源定时更新,欢迎一下。苏幕遮燎沈香宋周邦彦燎沈香,消溽暑。鸟雀呼晴,侵晓窥檐语。叶上初阳乾宿雨,水面清圆,一一风荷举。家住吴门,久作长安旅。五月渔郎相忆否。小楫轻舟,梦入芙蓉浦。 五、六月份推荐集合 查看github最新的Vue weekly;请::点击::集web前端最近很火的vue2框架资源;定时更新,欢迎 Star 一下。 苏...

    sutaking 评论0 收藏0
  • 关于Vue2一些值得推荐的文章 -- 五、六月份

    摘要:五六月份推荐集合查看最新的请点击集前端最近很火的框架资源定时更新,欢迎一下。苏幕遮燎沈香宋周邦彦燎沈香,消溽暑。鸟雀呼晴,侵晓窥檐语。叶上初阳乾宿雨,水面清圆,一一风荷举。家住吴门,久作长安旅。五月渔郎相忆否。小楫轻舟,梦入芙蓉浦。 五、六月份推荐集合 查看github最新的Vue weekly;请::点击::集web前端最近很火的vue2框架资源;定时更新,欢迎 Star 一下。 苏...

    khs1994 评论0 收藏0
  • Vue项目总结】基于饿了么组件封装

    摘要:项目中,组件是项目的基石,每个页面都是组件来组装起来,我司没有自己的组件库,选用的是组件库,在它的基础上再次封装。部分代码三级效果如下总结组件是项目的积木条,公用组件的封装成功与否其实是对项目的开发效率有直接影响。 vue项目中,组件是项目的基石,每个页面都是组件来组装起来,我司没有自己的组件库,选用的是ElementUI组件库,在它的基础上再次封装。 可编辑表格 由于是后台管理项目,...

    YPHP 评论0 收藏0
  • vue组件通信六种方式(完整版)

    摘要:本文总结了组件间通信的几种方式,如和,以通俗易懂的实例讲述这其中的差别及使用场景,希望对小伙伴有些许帮助。状态改变提交操作方法。 前言 组件是 vue.js最强大的功能之一,而组件实例的作用域是相互独立的,这就意味着不同组件之间的数据无法相互引用。一般来说,组件可以有以下几种关系:showImg(https://segmentfault.com/img/remote/146000001...

    frontoldman 评论0 收藏0

发表评论

0条评论

TerryCai

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<