Web组件通信
Opened this issue · 2 comments
Web组件通信
Web组件是什么
Web Component
- 由W3C制定的Web组件标准
- 是一个将标准的html、css、js封装成组件的一种方案
- 尚未成熟,只有少部分浏览器支持不完全的特性
- 大多数情况下通过polyfill实现
- 没有被广泛投入生产
广义Web组件
- 广义的Web组件没有明确的定义,各个厂商对Web组件都有自己的实现。
- 这些WEB组件通常是一个包含模板页、样式及视图逻辑的某种形式的封装。
- 主要是为解决分块开发以及复用问题而产生的。
- 有不同的封装形式,如封装成类、函数,或使用构建工具将独立的文件打包成组件。如her框架中基于smarty模板的widget,基于标准Web-Component的Polymer-Element,函数式的React-Component,基于ViewModel实例的Vue-Component等。
组件化的特点
- 高度隔离和解耦
- 尽可能少地暴露内部变量和方法
- 数据通信不够自由
组件通信原理
- 利用全局变量或公共作用域
- 暴露组件内部函数
- 使用组件属性传递
- 通过事件触发
- 基于观察者对象
数据流
组件通信会时产生数据传递,这里不讨论数据传递后的视图的更新问题,仅按照数据传递的方向举例了一些可能遇到的情况。
由父组件向下通信
-
通过组件属性继承向下传递
Her框架中,子组件对的父组件中声明的变量有隐式继承,这就意味着,在父组件中声明一个变量或函数,子组件无需进行任何引用就可以调用它。
-
调用子组件的引用
由子组件向上通信
- 调用父组件的引用
- 通过调用继承自父组件的通信方法
子组件间通信
- 通过父组件的属性继承分发各组件的通信方法
跨组件通信
为什么要进行跨组件通信?
-
传统属性继承式的通信模型,随着组件深度的增加,维护成本也会随着大大增加。
假设一个组件有深度为3的A和深度为4的B两个子节点,如果使用传统的属性继承进行通信,那么在维护一个数据流的时候需要包括父组件在内关注8个节点,成本无疑是非常高的。
-
在MVVM的通信模型中,因为具有双向绑定的特性,在组件深度较高时,任何一个变量所发生的变化都会通知与这个变量相关所有继承链上的观察者,造成不必要的资源消耗。
如何进行跨组件通信?
-
事件驱动
在Her框架中,通用登录组件在一定程度上使用了这种组件通信原理。它在登录成功后emit一个事件,通过该事件触发其它组件中监听该事件的回调。
不同点在于,login事件没有在广播事件时传值,仅充当触发器的作用。
-
观察者对象
几种目前主流的跨组件通信方式
Fire
Fire API是Polymer框架对组件通信的一种实现。它的实现方法是component标签上绑定事件,使用原生的CustomEvent类定义事件的回调,通过内置的fire方法触发事件并传递数据。这种实现方式实质上是依赖了document对象的事件命名空间,是最接近原生的实现方式,早期的Vue也使用这种方式做组件通信。
FLUX
Flux是React对组件通信的一种架构**,也通过事件驱动来实现的。
Flux中有Action和Store两个重要概念
- Action是一个事件的集合,它负责收集开发者定义的所有事件,并暴露激活Store的方法。
- Store则是一个存放state、对指定Action的监听器以及对应回调函数的集合,当Store被Action激活时,执行内部的回调。
一个完整的Flux数据流大概是这样:
- 在视图层设置指定对Store的监听
- 在视图层设置Store监听的回调函数
- 在视图层调用Action,发送数据
- Action将事件和数据分发给监听它的Store
- Store调用自身的回调函数,通常情况下要做两件事:
- 更新内部的state
- 将state发送给视图层
- 视图层收到Store同步过来的数据,调用之前设置的回调函数
- 执行回调函数,根据收到的state更新视图
Vuex
在一个完整的MVVM框架中,Vuex扮演了Model层的角色。这里要解释一个误区,很多人认为Vue是一个MVVM框架,其实Vue只是一个ViewModel的构造函数,DOM + Vue + Vuex才是一个完整的MVVM框架。
和Flux类似,Vuex中也有Action和Store的概念。但是因为双向绑定的特点,在ViewModel中直接绑定Store的state,在Action激活Store后,Store更新state会自动的同步到所有的试图模型中,不需要在视图层设置Store的监听,以及手动发送state。
跨组件通信,其实对于小项目,轻量一点,使用事件的方式挺好的。
之前做一个react小项目,仅仅需要跨组件将navbar的下拉菜单状态修改,所以封装了一个简单的时间onfire方式:https://github.com/hustcc/onfire.js.