mobx

作者: 林ze宏 | 来源:发表于2018-01-22 16:33 被阅读0次
    安装:
    • npm install mobx --save
    • npm install mobx-react --save
    image.png
    解决:在根目录新增 .babelrc文件,添加相应的插件,然后再npm 安装 babel-plugin-syntax-decorators 和 babel-plugin-transform-decorators-legacy

    npm install babel-plugin-syntax-decorators --save
    npm install babel-plugin-transform-decorators-legacy --save

    image.png image.png

    如果项目用 create-react-app 脚手架生成的项目,它会把babelrc: false禁用掉


    image.png

    如果 @observable selected = 0; 报错,则要安装es7 stage
    ES7不同阶段语法提案的转码规则(共有4个阶段),选装一个
    $ npm install --save-dev babel-preset-stage-0
    $ npm install --save-dev babel-preset-stage-1
    $ npm install --save-dev babel-preset-stage-2
    $ npm install --save-dev babel-preset-stage-3


    image.png image.png

    核心概念:
    Observable state(可观察的状态)
    Actions(动作)

    Computed values(计算值)

    class User {
      @observable name
    }
    
    class Profile extends React.Component {
      @computed get name() {
        // 正确的; 计算属性会追踪 `user.name` 属性
        return this.props.user.name
      }
    
      render() {
        return <div>{this.name}</div>
      }
    }
    

    实用函数:

    参考:http://cn.mobx.js.org/refguide/autorun-async.html

    1:toJS

    import React from 'react';
    import mobx, { observable, transaction, action, map } from 'mobx';
    import {
      Row, Col, Button, Input, Icon,
      Avatar
    } from 'antd';
    import { withRouter } from 'react-router-dom';
    import { observer, inject } from 'mobx-react';
    
    
      componentDidMount() {
    
        var obj = mobx.observable({
          x: 1
        });
    
        var clone = mobx.toJS(obj); // 递归地将一个(observable)对象转换为 javascript 结构
        console.log(clone); // {x: 1}
    
        console.log(mobx.isObservableObject(obj)); // true
        console.log(mobx.isObservableObject(clone)); // false
    
      }
    

    2:Reactions(反应)

    参考:http://cn.mobx.js.org/refguide/reaction.html

    import { observable, reaction} from 'mobx';
    
     @observable persion = {
            firstName: 'Matt',
            lastName: 'Ruby',
            age: 1
      }
      
      componentDidMount() {
        /*
          reaction:接受两个函数,第一个函数返回值作为第二个参数的入参;
          只有第一个函数中的observable变量发生变化,才会触发reactin,
          第二个函数中的observable变量发生变化,不会触发reaction
        */
        reaction(
          () => (this.persion.firstName + ' ' + this.persion.age ),
          (fnameAndAge) => {
            console.log(fnameAndAge + ' ' + this.persion.lastName);
          }
        )
    
        let i = 0;
       // 第一个函数中,observable变量firstName 、age发生变化,会触发reaction函数
        var t = setInterval(
          ()=>{
            this.persion.age = Math.random(40);
            i++
            if(i == 10){
              clearInterval(t);
            }
          }
        ,400)
    
    // lastName 是属于第二个函数,不会触发reaction函数
        var t = setInterval(
          ()=>{
            this.persion.lastName = Math.random(40);
            i++
            if(i == 10){
              clearInterval(t);
            }
          }
        ,400)
    
      }
    
    
    
    
    // 使用严格模式:改变observable变量,必须在使用action,则将需要改变的observable通过方法,用action修饰
    
    import mobx, {observable, action, runInAction, autorun} from 'mobx';
    import {observer, inject} from 'mobx-react';
    
    mobx.useStrict(true);  // 不允许在动作之外进行状态修改
    @observable persion = {
            firstName: 'Matt',
            lastName: 'Ruby',
            age: 1
      }
    
      @action cc = () => {
        this.persion.age = Math.random(40)
      }
    
      componentDidMount() {
        reaction(
          () => (this.persion.firstName + ' ' + this.persion.age ),
          (fnameAndAge) => {
            console.log(fnameAndAge + ' ' + this.persion.lastName);
          }
        )
    
        let i = 0;
        var t = setInterval(
          ()=>{
            this.cc();
            i++;
            if(i == 5){
              clearInterval(t);
            }
          }
        ,400)
    
      }
    

    3:transaction

    import React from 'react';
    import { observable, reaction,  transaction, autorun, action } from 'mobx';
    import {
      Row, Col, Button, Input, Icon,
      Avatar
    } from 'antd';
    import { withRouter } from 'react-router-dom';
    import { observer, inject } from 'mobx-react';
    
    const Search = Input.Search;
    
    @inject("stores")
    @observer
    class antTempate extends React.Component {
    
      constructor(props) {
        super(props);
        this.store = this.props.stores;
        this.state = {
          isShowListInfo: true
        }
    
      }
    
      @observable numbers = observable([]);
    
      @action dd = (d) => {
        this.numbers.push(d);
      }
      
      componentDidMount() {
    
        autorun(() => console.log(this.numbers.length, "numbers!"));
    
        /*
         注意 transaction 完全是同步运行的。 
         Transactions 可以嵌套。
         只有在完成最外面的 transaction 后,其他等待的 reaction 才会运行
        */
        transaction(() => {
            transaction(() => {
              this.dd(1);
              this.dd(2);
            });
            this.dd(3); // 最外层的transaction执行完,才触发autorun
        });
        // 输出: '3 numbers!'
    
      }
    
    

    4:when

    when方法是第一个参数(说参数不太准确)为true的时候,执行以下自定义的方法,但是好像只执行一次;
    和autorun方法有点像,但是autorun方法可以持续触发,只要满足条件了,但是when方法只触发一次,暂时没有想到很好的应用when方法的场景

    import {Component} from 'react'
    import {Button, Modal,Tree} from 'antd'
    import {observable, action,toJS, when} from 'mobx'
    import {observer} from 'mobx-react'
    
    @observer
    export default class Home extends Component {
        @observable test = false;
        constructor(props) {
            super(props);
    
            when(
              ()=> this.test,
              ()=> this.dispose()
            );
        }
    
        dispose(){
            alert('this is dispose');
        }
    
        @action trick = () => {
            this.test = !this.test;
            console.log('set true');
        };
    
        render() {
            return (
              <div>
                  <Button onClick={this.trick} > 测试 </Button>
              </div>
            );
        }
    }
    测试结果:
    when方法是第一个参数(说参数不太准确)为true的时候,执行以下自定义的方法,但是好像只执行一次;
    和autorun方法有点像,但是autorun方法可以持续触发,只要满足条件了,但是when方法只触发一次,暂时没有想到很好的应用when方法的场景
    

    永远只传递拥有 observable 属性的对象

    Array.isArray(observable([1,2,3])) === false
    在 ES5 中没有继承数组的可靠方法,因此 observabl e数组继承自对象,
    这意味着一般的库没有办法识别出 observable 数组就是普通数组(像 lodash,或 Array.concat 这样的内置操作符)。 这个问题很容易解决,在把 observable 数组传递给其它库之前先调用 observable.toJS() 或 observable.slice() 将其转化为普通数组。

    7.3:编写异步 Actions (动作)

    http://cn.mobx.js.org/best/actions.html

    class Store {
        @observable githubProjects = []
        @observable state = "pending" // "pending" / "done" / "error"
    
        @action
        fetchProjects() {
            this.githubProjects = []
            this.state = "pending"
            fetchGithubProjectsSomehow().then(this.fetchProjectsSuccess, this.fetchProjectsError)
    
        }
    
        @action.bound // 回调动作
        fetchProjectsSuccess(projects) {
            const filteredProjects = somePreprocessing(projects)
            this.githubProjects = filteredProjects
            this.state = "done"
        }
        @action.bound // 回调动作
            fetchProjectsError(error) {
                this.state = "error"
            }
        }
    

    7.4:在专用组件中渲染列表

    不好的
    在下面的示例中,当 user.name 改变时,React 会不必要地协调所有的 TodoView 组件。尽管TodoView 组件不会重新渲染,但是协调的过程本身是非常昂贵的。

    @observer class MyComponent extends Component {
        render() {
            const {todos, user} = this.props;
            return (<div>
                {user.name}
                <ul>
                    {todos.map(todo => <TodoView todo={todo} key={todo.id} />)}
                </ul>
            </div>)
        }
    }
    

    好的

    @observer class MyComponent extends Component {
        render() {
            const {todos, user} = this.props;
            return (<div>
                {user.name}
                <TodosView todos={todos} />
            </div>)
        }
    }
    
    @observer class TodosView extends Component {
        render() {
            const {todos} = this.props;
            return <ul>
                {todos.map(todo => <TodoView todo={todo} key={todo.id} />)}
            </ul>)
        }
    }
    

    注意

    • 不要把store中的值赋值给其他变量,然后,再使用改变量,这边,mobx中的属性是不会被追踪的。
    不好的:
    this.microData = this.store.getMicroData;
    <span>{this.microData.appKey}</span>
    
    好的:
    <span>{this.store.getMicroData.appKey}</span>
    
    • Link 路由传递数据
    <Route path="/app/AppStep/:type" component={AppStep}></Route>
    
     <Link to={{
               pathname: '/app/AppStep/edit',
               search: '?microAppId='+microAppId
     }}>
    
    参数获取:
    let params = (this.props.match || {})['params'];
    let type = (params || {})['type'];
    

    相关文章

      网友评论

          本文标题:mobx

          本文链接:https://www.haomeiwen.com/subject/vasfaxtx.html