资讯专栏INFORMATION COLUMN

动手实现 redux

Barrior / 339人阅读

摘要:动手实现实现这个模块直接创建的函数考虑到要暴露出去的三个函数我们用函数内部的变量来存储我们的数据时候直接返回当前的值就可以了同样用内部变量来存储订阅者订阅者则由函数添加返回取消订阅的函数。则根据返回新的同时通知订阅者执行相关逻辑。

文章地址

实例回顾

假如按钮和界面不在同一组件, 经常用 redux 去实现上面功能, 可以想象到如下代码

    ...
    const Test = ({ colorTheme, authorName }) =>
        
Hello World - { authorName }
const mapStateToProps = state => ({ colorTheme: state.colorTheme, authorName: state.authorName }) ...

用过 mapStateToProps 从顶层拿到属性然后展示, 在另一个组建通过 mapDispatchToProps 去触发 action 改变 state, 那么我们如何自己实现 redux 的功能呢

redux 属性分析

关于我们常用到的内容, 首先我们要考虑 createStore 方法, 使得可以创建出来我们后面要用到的 store , 可以接受 action 去处理改变 state, 并且去触发其他事件,比如组建渲染。 Provider 组建,可以传入一个 store 向下分发我们的 store,使得子组建可以获取到我们 store 内的属性和方法。一个 connect 方法,使得子组建可以获取到 store 里面的内容, 并根据 state 改变及时刷新渲染。

动手实现 redux 实现 createStore
    export default reducer => {
        let state = null
        let listeners = []

        const subscribe = listener => {
            listeners.push(listener)
            return () => {
                listeners = listeners.filter(d => d !== listener)
            }
        }

        const getState = () => state

        const dispatch = action => {
            state = reducer(state, action)
            listeners.forEach(listener => listener())
        }

        dispatch()

        return { getState, dispatch, subscribe }
    }

这个模块直接 export 创建 store 的函数,考虑到要暴露出去的三个函数, 我们用函数内部的变量 state 来存储我们的数据, getState 时候直接返回当前的值就可以了, 同样用内部变量 listeners 来存储订阅者, 订阅者则由 dispatch 函数添加, 返回取消订阅的函数。 dispatch 则根据 action 返回新的 state 同时通知订阅者执行相关逻辑。最后返回包含这三个函数的对象。改对象接受 reducer 作为参数, 内部执行一次 dispatch 则是为了初始化 state

实现 reducer
    const initState = {
        ...
    }

    export default (state, action) => {

        if (!state) return initState

        switch (action.type) {
            ...
        }
    }

关于 reducer 则简单的实现了根据不同的 action, 返回不同的 state, 只是刚开始判断了如果没有 state, 即初始化时候返回设置好的初始化值。

实现 Provider
    class Provider extends Component {
        getChildContext () {
            return {
                store: this.props.store
            }
        }

        ...
    }

这里必须提一下 reactcontext 这个属性, 可以让我们不通过 props 去获取到上层组建的属性, 不过关于写法却有一些特殊的规定而且在后面的版本可能被移除, 具体信息可以参考Context. 我们用 context 把创建的 store 存入顶层组建中, 这样就可以在后序组建中去获取到相关内容了。

实现connect
    const connect = (mapStateToProps, mapDispatchToProps) => (WrappedComponent) => {
        class InnerComponent extends Component{
            constructor (props, context) {
                super(props)
                const { getState, dispatch, subscribe } = context.store

                this.state = {
                    ...props,
                    ...mapStateToProps(getState()),
                    ...mapDispatchToProps(dispatch)
                }

                subscribe(() => this._updateStore())
            }

            _updateStore  = () => {
                const { getState, dispatch } = this.context.store

                const allProps = {
                    ...this.props,
                    ...mapStateToProps(getState()),
                    ...mapDispatchToProps(dispatch)
                }

                this.setState({ ...allProps })
            }

            render () {
                return (
                    
                )
            }
        }

        InnerComponent.contextTypes = { store: PropTypes.object }

        return InnerComponent
    }

高阶组件这个概念我们在官网上也可以看的到 Higher-Order Components, 简单理解就是传入一个组件返回一个新的组件, 它内部做什么事情则有你自己定义, 我们这里实现 connect, 则也算是高阶函数返回一个高阶组件, 接受两个函数作为参数, mapStateToProps mapDispatchToProps 看形参的名字就很熟悉, 我们分别传入当前的 statedispatch 函数, 得到的返回值则通过 props 传递给入参函数, 内部函数则通过 context 获取到顶部的 store, 同时用 subscribe
添加订阅者每次更新 state 时候则重新渲染当前组件。

至此我们的简易得逻辑已经实现, 代码github上有【reacts-ggsddu】, 大家可以下载本地运行感受一下

参考

React.js 小书

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

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

相关文章

  • 动手实现一个最简单的redux

    摘要:原文地址的主要集中在函数返回值中,以下这个迷你的只简单实现方法,如下测试代码运行结果 原文地址:https://github.com/huruji/blog/issues/1 redux的主要API集中在createStore函数返回值中,以下这个迷你的redux只简单实现createStore、dispatch、subscribe、getState方法,如下: const creat...

    xiguadada 评论0 收藏0
  • 写一本关于 React.js 的小书

    摘要:因为工作中一直在使用,也一直以来想总结一下自己关于的一些知识经验。于是把一些想法慢慢整理书写下来,做成一本开源免费专业简单的入门级别的小书,提供给社区。本书的后续可能会做成视频版本,敬请期待。本作品采用署名禁止演绎国际许可协议进行许可 React.js 小书 本文作者:胡子大哈本文原文:React.js 小书 转载请注明出处,保留原文链接以及作者信息 在线阅读:http://huzi...

    Scorpion 评论0 收藏0
  • 动手写个React高阶组件

    摘要:作用是给组件增减属性。如果你的高阶组件不需要带参数,这样写也是很的。那么需要建立一个引用可以对被装饰的组件做羞羞的事情了,注意在多个高阶组件装饰同一个组件的情况下,此法并不奏效。你拿到的是上一个高阶组件的函数中临时生成的组件。 是什么 简称HOC,全称 High Order Component。作用是给react组件增减props属性。 怎么用 为什么不先说怎么写?恩,因为你其实已经用...

    xiaokai 评论0 收藏0
  • redux中间件探秘

    摘要:接下来我们来看看源码中的模块是怎么应用中间件的。如何实现中间件操作的。新的会从第一个中间件开始触发,这样,在我们调用的时候,就会将中间件走一遍了。函数如果存在多个中间件,直接使用方法将各个中间件嵌套起来。 从redux-thunk引出思考 在使用redux-thunk进行异步action书写的时候,我经常好奇redux到底如何运作,让asyncAction成为可能 为了探究,我们必须看...

    Jeff 评论0 收藏0
  • 前端空间 - 收藏集 - 掘金

    摘要:封装手写的方笔记使用检测文件前端掘金副标题可以做什么以及使用中会遇到的坑。目的是帮助人们用纯中文指南实现复选框中多选功能前端掘金作者缉熙简介是推出的一个天挑战。 深入理解 JavaScript Errors 和 Stack Traces - 前端 - 掘金译者注:本文作者是著名 JavaScript BDD 测试框架 Chai.js 源码贡献者之一,Chai.js 中会遇到很多异常处理...

    you_De 评论0 收藏0

发表评论

0条评论

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