您现在的位置:首页 >> 前端 >> 内容

html开发redux深入理解

时间:2017/12/6 11:18:52 点击:

  核心提示:html开发redux深入理解学习react的过程中,redux的熟练掌握是一个绕不开并且很难绕过去的坎。接触react已经有一段时间了,甚至连一些小项目都用react做了不少了,但redux的使用上...

html开发redux深入理解

学习react的过程中,redux的熟练掌握是一个绕不开并且很难绕过去的坎。接触react已经有一段时间了,甚至连一些小项目都用react做了不少了,但redux的使用上还是有诸多不理解不熟练的地方。正好有很长一段时间没有更过博客了,就从这里着手,增强一下自己的理解。

先从解决全局事件的问题开始

我们都知道,react的数据流是单向的,这样做是为了保证数据同源。

一般来说,子组件可以直接从父组件提供的props中获取数据放入state或是渲染出来,但是子组件要影响父组件的state的话就比较困难了,一般来说需要从父组件写一个回调函数通过props传入子组件,子组件调用这个回调函数之后,值就能在父组件中获取了。

那么,如何与孙组件传值呢?依据单向数据流的思路,层层props传递,回调函数再层层传递回来,是不是在写法上就有点看不懂了?

那么,跟与这个组件几乎完全没关系的远房亲戚组件传值呢?数据状态管理上就非常混乱了。我们自然而然的会想到,是不是能设计出一种思路,解决多级无关层次属性传递的问题呢?

有计算机基础的同学应该会从设计模式中找到灵感。没错,发布-订阅模式啊,全局订阅一个事件,将监听函数的回调函数置入其中,之后让想要改变数据的操作dispatch一个action的话,会依次激活通知所有订阅了这个事件的组件,这样再也不用辛苦的一级一级传递数据了,岂不是美滋滋?

var EventEmitter = {
  _events: {},
  dispatch: function (event, data) {
    if (!this._events[event]) return;
    for (var i = 0; i < this._events[event].length; i++)
        this._events[event][i](data);
  },
  subscribe: function (event, callback) {
    if (!this._events[event]) 
      this._events[event] = [];
    this._events[event].push(callback);
  },
  unSubscribe: function(event){
    if(this._events && this._events[event]) {
      delete this._events[event];
    }
  }
}

是不是看起来很简单?事实上,redux本身的思路就是这么简单,甚至你可以直接拿这个自己写的“myRedux”中的发布订阅功能投入到react项目的使用中。举个例子:

var MyContainer = React.createClass({
  render: function(){
    return (
      

) } }); var CurItemPanel = React.createClass({ getInitialState: function(){ return { curItem: 'item1' } }, componentDidMount: function(){ var self = this; EventEmitter.subscribe('changeItem', function(newItem){ self.setState({ curItem: newItem }); }) }, componentWillUnmount: function(){ EventEmitter.unSubscribe('changeItem'); }, render: function(){ return (

The curItem is: {this.state.curItem}

) } }); var SelectionButtons = React.createClass({ onClickItem: function(item){ EventEmitter.dispatch('changeItem', item); }, render: function(){ return (

) } });

当点击按钮时,SelectionButtons的兄弟节点CurItemPanel可直接通过订阅的回调函数取得数据啦。

redux本身的思路就是这么简洁明了。

有没有别的方法

如果你的工程的数据流动没有那么繁杂,不想加入redux库来强行增加代码复杂度,但又实在觉得单项数据流的祖先传值太不友好的话,react本身还提供了一个解决办法:Context(上下文)。它同样能解决层次传递的痛点,可以使子组件直接访问祖先组件数据,先写一个示例:

var CurItemWrapper = React.createClass({
  render: function(){
    return (
      

) } }); var CurItemPanel = React.createClass({ contextTypes: { curItem: React.PropTypes.any }, render: function(){ return (

The curItem is: {this.context.curItem}

) } }); var MyContainer = React.createClass({ getInitialState: function(){ …… }, childContextTypes: { curItem: React.PropTypes.any, changeItem: React.PropTypes.any }, getChildContext: function(){ return { curItem: this.state.curItem, changeItem: this.changeItem } }, changeItem: function(item){ this.setState({ curItem: item }); }, render: function(){ return (

) } }); var ListWrapper = React.createClass({ render: function(){ return (

) } }); var List = React.createClass({ contextTypes: { changeItem: React.PropTypes.any }, onClickItem: function(item){ this.context.changeItem(item); }, render: function(){ return (
  • item1
  • item2
) } }); var MyContainer = React.createClass({ getInitialState: function(){ …… }, childContextTypes: { curItem: React.PropTypes.any, changeItem: React.PropTypes.any }, getChildContext: function(){ return { curItem: this.state.curItem, changeItem: this.changeItem } }, changeItem: function(item){ this.setState({ curItem: item }); }, render: function(){ return (

) } });

可以看出,通过指定childContextTypes后,父组件通过getChildContext方法可以直接获取到子孙组件中的context,而子孙组件通过调用context对象也能轻松获取来自祖先的回调函数,省去了中间商赚差价(误

getChildContext 函数将会在每次state或者props改变时调用。为了更新context中的数据,使用 this.setState触发本地状态的更新。这将触发一个的context并且数据的改变可以被子元素收到。

但是!官方似乎并不希望context这个功能被广泛的使用,并声称在日后很可能下架这项功能。以下是原话:

绝大多数的应用程序不需要使用上下文(context)。

如果你希望使用应用程序更加稳定,就不要使用上下文(context)。这只是一个实验性的 API ,并且可能在未来的 React 版本中移除。

如果你不熟悉 Redux 或者 MobX 这类 state 管理库,就不要使用 context 。在许多实际应用中,这些库以及和React 绑定是一个很好的管理 和许多组件相关的 state 。Redux 相比 context 是更好的解决方案。

如果你不是一个经验丰富的 React 开发者,就不要使用 context 。更好的方式是使用 props 和 state 。

如果你不顾这些警告仍然坚持使用 context ,尝试着将 context 的使用隔离在一个将小的范围内,并且在可能的情况下直接使用 context ,以便在API改变的时候进行升级。

emmm,所以呀,我们还是尽情拥抱redux吧,作为一个状态管理flux的react优化版,还是很值得学习一番的。

Tags:HT TM ML L开 
作者:网络 来源:枫之谷