不少前端開發者認爲,Vuex
和Redux
是用來解決組件間狀態通訊問題的,因此大部分人僅僅是用於達到狀態共享的目的。可是一般Redux
是用於解決工程性問題的,用於分離業務與視圖,讓結構更加清晰,從而達到易於維護的目的。也就是 Flux
(這裏我以前翻譯的Flux深度解讀)架構所解決的問題。可是絕大多數時候,你們只是想解決的問題是組件嵌套過深的時候,如何將子組件的狀態直接傳遞給父組件。那麼此時Vuex
也好Redux
也好,對於咱們的訴求就過於繁瑣。每次通訊後,咱們還須要清理掉Store
中的狀態。更加惱人的是,咱們該如何選擇哪些狀態應該放入Store
,那些狀態應該放在組建內的state
一直困擾着你們,甚至於社區也是沒有一個定論。所以不少年輕前端工程師所開發的項目,狀態管理極其混亂。以致於不久後就難以維護。前端
針對以上訴求,咱們能不能開發一個簡單的組件間通訊工具來解決目前前端狀態管理的痛點呢?所以我實現了一個無狀態組件通訊工具,這也就是這篇文章的由來。react
無狀態,也就是它並不關注數據內容,它只是起到一個管道的做用,在組件間創建管道,組件能夠經過該管道向管道另外一頭的組件說:「hello world!This is your message。」。git
設計模式,你們都很熟悉,現代前端框架已經使用很是多的設計模式,你們都能耳熟能詳的就是觀察者模式,裝飾器模式,以及發佈訂閱模式(一種將觀察者和通知者融合的設計模式)。github
設計模式,是用於解決特定問題而被你們公認爲最佳實踐的模式。通常最被你們熟知的爲23種設計模式 - 這裏是我用ES2015實現的面向對象方式的設計模式例子。面試
那麼咱們該如何利用設計模式解決咱們的問題呢?上代碼:redux
const listener = {}; // 用於保存訂閱者
// 註冊訂閱者
function subscribe (event, handle) {
// 訂閱者訂閱的信息
if (typeof event !== 'string') {
throw new Error('event must be String!');
}
// 訂閱者的callback函數
if (typeof handle !== 'function') {
throw new Error('handle must be function!');
}
// 將訂閱者添加到訂閱者容器中保存起來
if (!listener[event]) {
listener[event] = [];
listener[event].push(handle);
} else {
var index = listener[event].indexOf(handle);
if (index < 0) {
listener[event].push(handle);
}
}
// 返回用於取消訂閱的接口,這裏是一個高階函數
return function unSubscribe() {
var index = listener[event].indexOf(handle);
if (index > -1) {
listener[event].splice(index, 1);
}
}
}
// 爲通知者提供的發起通知的接口
function dispatch (event, payload) {
if (listener[event]) {
listener[event].forEach(function serviceFunc(handle) {
handle(payload);
})
} else {
throw new Error('No subscriber be registried for serviceName!');
}
}
export {
subscribe,
dispatch
}
複製代碼
這裏主要使用了一下幾種JS語言經常使用的設計模式以及技術知識點:小程序
以上,咱們利用沙盒模式,發佈訂閱模式實現了一個基本的無狀態組件間通訊工具。那麼咱們如何使用它呢?設計模式
下面是咱們要實現的一個例子:前端框架
組件結構是 爺爺包含兒子,兒子包含孫子,兒子和孫子能夠和爺爺直接對話。前端工程師
在根組件(爺爺組件)註冊訂閱者用來訂閱兒子和孫子發來的信息:
import Son from './Son';
import { subscribe } from './utils';
class App extends Component {
constructor(props) {
super(props);
this.state = {
messageFromSon: '',
messageFromGrandson: ''
}
// 在這裏訂閱了兒子的會話和孫子的會話,記得bind(this)這樣才能訪問組件的上下文
this.listenSonHandle = this.listenSonHandle.bind(this);
this.listenGrandsonHandle = this.listenGrandsonHandle.bind(this);
// 咱們須要保留訂閱會話,在不須要的時候取消註冊
this.listenHandle = [
subscribe('son', this.listenSonHandle),
subscribe('grandson', this.listenGrandsonHandle)
]
}
listenSonHandle(payload) {
this.setState({
messageFromSon: payload
});
}
listenGrandsonHandle(payload) {
this.setState({
messageFromGrandson: payload
})
}
componentWillUnmount() {
this.listenHandle.forEach((unSubscribe) => {
unSubscribe();
})
}
render() {
return (
<div style={{background: 'red'}}> <Son /> <div> 兒子來電:{this.state.messageFromSon} </div> <div> 孫子來電:{this.state.messageFromGrandson} </div> </div>
);
}
}
複製代碼
兒子組件須要和爺爺組件直接對話,那麼就須要和爺爺組件創建相同的通訊管道:
import React from 'react';
import { dispatch } from './utils';
import Grandson from './Grandson';
export default class Son extends React.Component {
constructor(props) {
super(props);
this.state = {
message: ''
}
}
render() {
return <div style={{background: 'green'}}> 這裏是兒子: <input value={this.state.message} onChange={(e) => { this.setState({ message: e.target.value }) }}></input> <button onClick={() => { // 利用通知者接口,向爺爺組件發送信息 dispatch('son', this.state.message); }}>告訴老子</button> <Grandson/> </div>
}
}
複製代碼
孫子組件想要向爺爺組件發送信息,若是不使用redux的話就要一層一層的傳遞props。先告訴爸爸,而後爸爸告訴爺爺,可是有了咱們如今構建的無狀態組件通訊工具。就不須要那麼麻煩了:
import React from 'react';
import { dispatch } from './utils';
export default class Son extends React.Component {
constructor(props) {
super(props);
this.state = {
message: ''
}
}
render() {
return <div style={{background: 'yellow'}}> 這裏是孫子: <input value={this.state.message} onChange={(e) => { this.setState({ message: e.target.value }) }}></input> <button onClick={() => { dispatch('grandson', this.state.message); }}>告訴爺爺</button> </div>
}
}
複製代碼
甚至咱們能夠很容易再剝離出一層業務層,實現業務與視圖的隔離。起到和Vuex,Redux一樣的目的。
因爲設計模式是語言無關的,所以這個utils/index.js下的代碼是能夠用於任何前端框架的。
這就是設計模式的強大之處。是否是大家能夠扔掉那惱人的Vuex和Redux了呢?
廣告:咱們團隊招人,途家網,地點在國家會議中心,咱們的團隊很年前,才組件1年多。有不少機會。
別人面試造火箭,進去擰螺絲。咱們面試擰螺絲,進來造火箭。咱們招不起能面試造火箭的人(T_T不知道這麼說老大會不會打我),因此只能招得起面試能擰螺絲的。可是咱們有不少造火箭的需求。
若是你想尋求刺激,就來加入咱們吧