资讯专栏INFORMATION COLUMN

简单讲讲mobx的observable和autoRun

mrli2016 / 609人阅读

摘要:今天想简单聊聊的和函数。的作用是使一个普通的对象,变得可观察。下面来看看的简单实现,这里不考虑对象的嵌套。一旦任何值发生了修改,就去执行传入的方法。有点简单粗暴,是不是。并且把设为,表示需要收集依赖了。

今天想简单聊聊mobx的observable和autoRun函数。不了解es6的proxy和reflect的伙伴,需要先看看这方面的知识点。

1、observable
observable的作用是使一个普通的对象,变得可观察。也就是说当一个对象变得可观察了之后,当你改变对象里的一个值的时候,就会去触发对应的有这个引用的autoRun函数。
下面来看看observable的简单实现,这里不考虑对象的嵌套。就假设它只有一层。方便理解概念。

var globalID = 0
function observable(obj) {
    var oID = ++globalID
    return new Proxy(obj, {
        get: function (target, key, receiver) {
            collect.startCollect(oID + "" +key)
            return Reflect.get(target, key, receiver)
        },
        set: function (target, key, value, receiver) {
            Reflect.set(target, key, value, receiver)
            collection[oID + "" + key] && collection[oID + "" + key].forEach(c => {
                c()
            });
        }
    })
}

observable的解释在此:引用阮一峰的es6教程里的话
Proxy 可以理解成,在目标对象之前架设一层“拦截”,外界对该对象的访问,都必须先通过这层拦截,因此提供了一种机制,可以对外界的访问进行过滤和改写。Proxy 这个词的原意是代理,用在这里表示由它来“代理”某些操作,可以译为“代理器”。
这里用Proxy是因为当你在可观察对象上加入新的属性时,就不会像Object.defineProperty那样新的属性没法监听了。

像上面代码那样,咱们就成功的拦截了一个对象的getter和setter了。
每次当你obj.a或者obj.b的时候都会进入get方法。咱们在返回obj.a,之前都会去收集依赖。至于到底要不要收集依赖,我这里是由collect.startCollect去判断的。
每当你obj.a = "balabala"的时候,咱们也拦截了set方法。在写入值的之后,就要搞事情了,偷偷地去把收集来的依赖相应的依赖,给全部执行一遍(如果确实有的话)。

2、autoRun
一旦任何值发生了修改,就去执行传入autoRun的方法。

function autorun(handler) {
    collect.begin(handler)
    handler()
    collect.end()
}

有点简单粗暴,是不是。开始收集依赖了,我先发个信号。然后把autoRun里的handler给执行一遍。最后,打声招呼:小朋友你已经兑过奖了,回家吧。执行collect.end()。

3、collect
看了上面两个,心里在想那个collect到底是个什么鬼?

var collection = {}
var collect = {
    begin: function(handler) {
        collection.handler = handler
        collection.now = true
    },
    startCollect: function(oIDKey) {
        if (collection.now) {
            if (collection[oIDKey]) {
                collection[oIDKey].push(collection.handler)
            } else {
                collection[oIDKey] = [collection.handler]
            }
        }
    },
    end: function() {
        collection.now = false
    }
}

这里的collection我也就写在全局了,简单粗暴。
在autoRun里,我们先begin,我把handler赋给了collection.handler,嗯简单粗暴。并且把collection.now设为true,表示需要收集依赖了。
然后执行handler(),就会到get里去执行collect.startCollect。
当startCollect的时候,开始干正经活了,先判断一下是不是now。前面我们劫持了getter,如果不判断collection.now,那么collect.startCollect(oID + "" +key)总是会执行。那就出大事情了。之后,咱们就可以放心的去收集handler了。
完事之后吧collection.now设为false。要不然你每每obj.a取值的时候都会反复的收集依赖。

好了,我想mobx的思路大概是这样的。这是我的理解,有心的同学帮我纠纠错,蟹蟹~

最后放上完整的本人的(cuo)dai照ma。

var globalID = 0
function observable(obj) {
    var oID = ++globalID
    return new Proxy(obj, {
        get: function (target, key, receiver) {
            collect.startCollect(oID + "" +key)
            return Reflect.get(target, key, receiver)
        },
        set: function (target, key, value, receiver) {
            Reflect.set(target, key, value, receiver)
            collection[oID + "" + key] && collection[oID + "" + key].forEach(c => {
                c()
            });
        }
    })
}
var collection = {}
var collect = {
    begin: function(handler) {
        collection.handler = handler
        collection.now = true
    },
    startCollect: function(oIDKey) {
        if (collection.now) {
            if (collection[oIDKey]) {
                collection[oIDKey].push(collection.handler)
            } else {
                collection[oIDKey] = [collection.handler]
            }
        }
    },
    end: function() {
        collection.now = false
    }
}

function autorun(handler) {
    collect.begin(handler)
    handler()
    collect.end()
}

var obj = observable({
    a: 1,
    b: 2
})

autorun(() => {
    console.log("obj.a test1", obj.a)
})
autorun(() => {
    console.log("obj.a test2", obj.a)
})

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

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

相关文章

  • mobx学习总结

    摘要:原理分析的核心就是通过观察某一个变量,当该变量产生变化时,对应的内的回调函数就会发生变化。回调函数若依赖外部环境,则无法进行收集很好理解,的回调函数在预执行的时候无法到达那一行代码,所以收集不到。 Mobx解决的问题 传统React使用的数据管理库为Redux。Redux要解决的问题是统一数据流,数据流完全可控并可追踪。要实现该目标,便需要进行相关的约束。Redux由此引出了dispa...

    roundstones 评论0 收藏0
  • 【用故事解读 MobX源码(一)】 autorun

    摘要:随后,执行官给出一张当张三存款发生变化之时,此机构的运作时序图的确,小机构靠人力运作,大机构才靠制度运转。第一条语句创建观察员第一条语句张三我们调用的时候,就创建了对象,对象的所有属性都将被拷贝至一个克隆对象并将克隆对象转变成可观察的。 ================前言=================== 初衷:网上已有很多关于 MobX 源码解读的文章,但大多阅读成本甚高。...

    qieangel2013 评论0 收藏0
  • MobX

    摘要:建议将它们用于修改可观察量或具有副作用的任何函数中。这意味着在一些定时器或者网络请求,异步处理的情况下,它们的回调函数无法对状态做成改变。这些回调函数都应该有包裹,如果例子里面的一样。 1. 介绍 1.1. 原理 React的render是 状态 转化为树状结构的渲染组件的方法 而MobX提供了一种存储,更新 状态 的方法 React 和 MobX都在优化着软件开发中相同的问题。 ...

    Alliot 评论0 收藏0
  • Mobx4.X状态管理入门

    摘要:前言原本说接下来会专注学但是最新工作又学习了一些有意思的库於是就再写下来做个简单的入门之前我写过一篇文章这个也算是作為一个补充吧这次无非就是类似笔记把认为的一些关键点记下来有些地方还没用到就衹是描述一下代码有些自己写的有些文档写的很好就搬下 前言 原本说接下来会专注学nodejs,但是最新工作又学习了一些有意思的库,於是就再写下来做个简单的入门,之前我写过一篇文章,这个也算是作為一个补...

    CKJOKER 评论0 收藏0
  • 高效Mobx模式(Part 2 - 掌握数据变更方法)

    摘要:有了这个,下一步就是开始对变化作出反应。请注意,此延迟通知仅适用于当前函数范围中的。最快的方法是提供功能。只有当返回的数据发生变化时,才会执行副作用。最棒的部分是它会在运行后自动处理副作用。构建可观察数据掌握数据变更方法高阶应用实例 在上一部分中,我们研究了如何设置MobX状态树并使其可观察。 有了这个,下一步就是开始对变化作出反应。 坦率地说,这就是有趣的开始! MobX保证只要您的...

    xinhaip 评论0 收藏0

发表评论

0条评论

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