mobx-react 源码阅读笔记(一)

前言

emm 由于实习的项目组只有自己一个人,选型开发都为所欲为了tat,从以redux进行数据流管理的使用,决定尝试一波实战mobx,在使用中不禁在想,mobx是怎么和react连在一起,而mobx又是为什么可以如此高效便捷。react-redux的驱动视图更新是通过connect组件,在外层HOC中订阅store改变触发
setState({})进行更新视图。而mobx-react中的observer呢?

这里可以看到最关键的一点,区别于redux的更新方式,在mobx-react中是直接使用forceUpdate方法进行更新视图,而区别于redux 对store的订阅,mobx-react又是怎么样触发forceUpdate呢?

/**
 *强制更新组件https://github.com/mobxjs/mobx-react/blob/master/src/observer.js#L188
 */
Component.prototype.forceUpdate.call(this)

定位到observer,先了解observer执行的流程


1.png

核心点


2.png

talk is so cheap show you the code

//... 
// https://github.com/mobxjs/mobx-react/blob/master/src/observer.js#L334
mixinLifecycleEvents(target)
//mixin组件的生命周期,将reactiveMixin中的函数mixin到具体的生命周期中.

在mixin中最核心需要关注的就是componentWillMount,
先简单提一下mixinLifecycleEvents区别对待的是shouldComponentUpdate,如果该方法没有定义observer会直接将其重写为PureComponentshouldComponentUpdate的实现

进一步看componentWillMount

//https://github.com/mobxjs/mobx-react/blob/master/src/observer.js#L168
// wire up reactive render
        //保存当前函数的render
        const baseRender = this.render.bind(this)
        let reaction = null
        let isRenderingPending = false

        const initialRender = () => {
            /*绑定reaction,observable属性改变的时候会触发这个(mobx实质是双向绑定,observable更新视图也要更新,这里是数据绑定到视图上的第一步。)
            */
            reaction = new Reaction(`${initialName}#${rootNodeID}.render()`, () => {
                if (!isRenderingPending) {
                    // N.B. Getting here *before mounting* means that a component constructor has side effects (see the relevant test in misc.js)
                    // This unidiomatic React usage but React will correctly warn about this so we continue as usual
                    // See #85 / Pull #44
                    isRenderingPending = true
                    if (typeof this.componentWillReact === "function") this.componentWillReact() // TODO: wrap in action?
                    if (this.__$mobxIsUnmounted !== true) {
                        // If we are unmounted at this point, componentWillReact() had a side effect causing the component to unmounted
                        // TODO: remove this check? Then react will properly warn about the fact that this should not happen? See #73
                        // However, people also claim this migth happen during unit tests..
                        let hasError = true
                        try {
                            isForcingUpdate = true
                            if (!skipRender) Component.prototype.forceUpdate.call(this)
                            hasError = false
                        } finally {
                            isForcingUpdate = false
                            if (hasError) reaction.dispose()
                        }
                    }
                }
            })
            reaction.reactComponent = this
            reactiveRender.$mobx = reaction
            // 重写render
            this.render = reactiveRender
            // 实际的render
            return reactiveRender()
        }
        
        const reactiveRender = () => {
            isRenderingPending = false
            let exception = undefined
            let rendering = undefined
            /**
            * 核心关联部分
            * 追踪数据  
            * https://github.com/mobxjs/mobx/blob/master/src/core/reaction.ts#L112
            * reaction.track(fn: () => void)
            * 实际上
            * trackDerivedFunction<T>(derivation: IDerivation, f: () => T, context)
            * const result = trackDerivedFunction(this, fn, undefined)// this对应reaction,fn对应track中的fn
            *   (https://github.com/mobxjs/mobx/blob/master/src/core/derivation.ts#L131)
            * trackDerivedFunction这个函数有什么作用? 
            * 执行函数f并跟踪那些可观察并且正在f函数中引用的变量,将这些可追踪的变量注册并储存在derivation中即reaction中
            * 
            * f中引用的变量 核心上是通过atom.reportObserved()关联引用
            * 简单例子见   makePropertyObservableReference  中的      
            *       get: function() {
            *        atom.reportObserved() 
            *        return valueHolder
            *    },
            * 
            *  重新到trackDerivedFunction执行中
            * result = f.call(context); 
            *f本身已经是箭头函数了,上下文已经绑定过了. 这里实际上就是执行component的render,
            *实际上就是通过这里收集到observable的引用 (依赖收集)
            *trackDerivedFunction中会derivation进行属性更新,以及通过bindDependencies更新依赖收集的情况。
            **/
            reaction.track(() => {
                if (isDevtoolsEnabled) {
                    this.__$mobRenderStart = Date.now()
                }
                try {
                    rendering = extras.allowStateChanges(false, baseRender)
                } catch (e) {
                    exception = e
                }
                if (isDevtoolsEnabled) {
                    this.__$mobRenderEnd = Date.now()
                }
            })
            if (exception) {
                errorsReporter.emit(exception)
                throw exception
            }
            return rendering
        }

        this.render = initialRender
    },

这一次的阅读之行到此就暂告一段落了,关于derivation原理的进一步理解需要进一步学习mobx的源码。目前只是有较浅的理解,如有不正之处,请大家指出! tat 毕竟只是闭门造车。


注释版源码

学习资料

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,242评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,769评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,484评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,133评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,007评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,080评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,496评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,190评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,464评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,549评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,330评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,205评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,567评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,889评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,160评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,475评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,650评论 2 335

推荐阅读更多精彩内容