前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >mobx 能为我们带来哪些改变

mobx 能为我们带来哪些改变

作者头像
腾讯IVWEB团队
发布2020-06-29 11:54:33
6850
发布2020-06-29 11:54:33
举报

介绍

第一印象

首先上一段代码:

代码语言:javascript
复制
import {observable, observe} from 'mobx'
var student = observable({  
    name: 'unknown'
})
observe(student, (change)=>{  
    console.info(change)   
    /*  will print:
    * { type: 'update',
    * object: { name: [Getter/Setter] },
    * oldValue: 'unknown',
    * name: 'name',
    * newValue: 'foo' }
    */
})

student.name = 'foo'

非常直观的,student的属性改变了,监听的方法打印出了所有的变动细节。

简介

mobx是一个状态管理器,用于TFRP(transparently applying functional reactive programming)自发式函数相应式编程。

可以看到,它的核心概念包括action->state->computed value -> reaction

通过action数据(state), 然后state引发的变动触发computed-value变动,最终传给监听器(reaction),如果把react的的render方法也注册为监听器,那么mobx就可以和react配合起来构建一个健全的app架构了。

基本使用

mobx的原理是在对象包裹setter和getter。例如当我们调用一个属性时候:obj.name就会触发name的getter,调用obj.name = 'hello world'的时候,就会触发name属性的setter。第一小节的例子如果自己写,大致是这个样子的:

代码语言:javascript
复制
var student = {
  _name: 'unknown',
  get name(){
      console.info('getter of student.name')
      return this._name;
  },
  set name(val){
      console.info('setter of student.name')
      this._name = val;
  }
}

student.name = 'richcao'  //=> setter of student.name
student.name //=> getter of student.name

特性和局限

很难单独的说mobx带来哪些特性和哪些局限,这里都是结合react,以实际工程使用角度来考量mobx的优劣。

特性

属性变动精确定位

这点特性联系到页面重绘:

代码语言:javascript
复制
var student = observable({
    name: 'richcao',
    age: 28
})

ReactDom.render(
	mobx.observer(()=>(
    	<div>{student.name}<div>
    )),
	document.getElementById('root')
);


student.name = 'foo'  //会引发重绘
student.age = 18  // 不会引发重绘

如果要用redux实现这点,估计需要不计其数的shouldComponentUpdate方法了吧。

视图层缓存

mobx提供了一个computed方法,通过computed方法计算的值如果放到了监听器中,那么这个值会被缓存,state没有变动的情况下,computed的值不会重新计算。

想想我们的react中的render方法, 在方法中创建的中间变量都会被重新计算,例如下面的代码,每render一次,就需要计算一次totalPrice,简单的场景还好,如果计算量偏大,这样的消耗就不该发生。

代码语言:javascript
复制
render(){
    let totalPrice = this.props.price * this.props.num;
    return <div>{totalPirce}</div>
}

可不可以把totalPrice缓存起来,只要props.price和pros.num没有变化,就不用重新计算totalPrice?答案是可以的。mobx提供了一个computed方法,用于将state映射为新的值,这些值常常被用作视图层的渲染。看下面的例子:

代码语言:javascript
复制
const a = observable(1);
const b = observable(2);

const sum = computed(() => {
  console.log("computing");
  return a.get() + b.get();
});

sum.get() // outputs "computing", returns result
sum.get() // outputs "computing", returns result
sum.get() // outputs "computing", returns result

// create an observer (reaction/autorun/render)
const disposeObserver = autorun(() => sum.get()) // outputs "computing", result is cached

sum.get() // outputs nothing, cached value returned
sum.get() // outputs nothing, cached value returned
sum.get() // outputs nothing, cached value returned

// dispose observer
disposeObserver()

sum.get() // outputs "computing", returns result
sum.get() // outputs "computing", returns result
sum.get() // outputs "computing", returns result
}

局限

使用mobx需要妥协的有:

1、内存上的增加:

mobx会将给定对象深拷贝一份作为私有变量,然后再创建一个对象,包含该私有变量所有属性的getter和setter方法。无疑在内存占用上,比单纯的使用plain javascript object占用更多的内存。例如:

代码语言:javascript
复制
var student = {name: 'foo'}
var observableStudent = observable(student);

mobx会深拷贝student,然后创建一个{ name: [Getter/Setter] }返回。实际上就“多了”两个student的副本。

2、所有需要监听的变量都必须挂载到一个上级对象上。

单一的变量无法绑定getter和setter,所以,只有ObjectArrayMap才能够被包裹成observable。除此之外,字面量、函数、有prototype的类等都不能监听变化,看下面的代码:

代码语言:javascript
复制
var age = observable(23);
mobx.observe(age, console.info)
age = 18;   // nothing happened

关于原生变量的情况,mobx返回的是一个observable.box对象,可以去官方文档中查看。其实这一点我们注意避免即可。

3、全局state维持同一对象引用

state维持为同一个对象的引用,这样要做状态回滚(撤销操作)就比较困难了。

我们知道redux的每次store更新,都生成一个新的state引用,可以把旧的state保存下来,需要撤销操作时,将旧的state重新render一遍就好了。

这个特性放到mobx上就不太可能了,因为我们压根儿没有Object.assign一个新的state出来。好在,mobx团队也给出了解决方案:mobx-state-tree。其底层和immutable一样,是一个不可变类型的数据容器,但是在api上比immutablejs容易使用太多太多。我在另一篇文章中讲吧.....

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 介绍
    • 第一印象
      • 简介
      • 基本使用
      • 特性和局限
        • 特性
          • 局限
          相关产品与服务
          容器服务
          腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
          领券
          问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档