這邊文章主要目的呢。是搭建一個react和mobx的demo。可以瞭解mobx在react應用中如何使用的。我會用大白話的形式寫這個文章; 文末有react 和react-native 的兩個集成mobx的項目demo。react-native的實現思路和下面同樣。react
#####1.create-react-app建立react項目 腳手架命令生成一個項目:webpack
1.create-react-app react_mobx
//建立好腳手架安裝mobx和mobx-react 包
2. npm install mobx mobx-react --save
3. npm install react-router --save
複製代碼
安裝好上面依賴。咱們修改下項目結構----你們能夠自行修改下; git
#####2.實現react-router功能 你們都知道mobx能夠解跨頁面共享數據的問題。那咱們先實現跳轉頁面功能;咱們先修改下下面幾個文件-- 1.home.jsx
github
import React, { Component } from "react";
class Home extends Component {
constructor(props) {
super(props);
this.state = {};
}
render() {
return (
<div>
<h1>首頁</h1>
<button onClick={() => { this.props.history.push("/one");}}>
跳轉到第一個頁面
</button>
</div>
);
}
}
export default Home
複製代碼
2.one.jsx
web
import React, { Component } from "react";
class One extends Component {
constructor(props) {
super(props);
this.state = {};
}
render() {
return (
<div>
<h1>頁面一</h1>
<button onClick={() => { this.props.history.push("/");}}>
跳轉到首頁
</button>
</div>
);
}
}
export default One
複製代碼
3.router.jsx
npm
import React, { Component, Fragment } from "react";
import { HashRouter,Route } from "react-router-dom";
import Home from '../page/home';
import One from '../page/one';
class Router extends Component {
render() {
return (
<HashRouter>
<Fragment>
<Route exact path={`/`} component={Home} />
<Route path={`/one`} component={One} />
</Fragment>
</HashRouter>
);
}
}
export default Router;
複製代碼
4.index.js 文件入口
redux
import React from 'react';
import ReactDOM from 'react-dom';
import Router from './router/router';
ReactDOM.render(<Router />, document.getElementById('root'));
複製代碼
好了文件修改完畢~ npm start
一下,頁面是否是能夠自由跳轉了呢~ 好了 實現了這個咱們就進行下一步吧react-native
重要提醒--MobX採用的是ES7的裝飾器語法,目前仍是一種實驗性的語法,使用 create-react-app 腳手架默認建立的項目是沒有開啓裝飾器語法的。須要一些額外的配置查看下這篇文章:
create-react-app配置修飾器 可能這個方法比較麻煩-----我如今解決方案是這個--有好的辦法 我會及時更新的~bash
#####3.mobx和mobx-react的使用 3.1須要項目結構src下增長一個store文件夾 --這個文件夾的做用。咱們理解爲專門存放和管理數據源的地方; react-router
建立3個js文件- homeStore.js、oneStore.js、index.js 下面對每一個文件夾進行添加代碼 homeStore.js: 存放一個頁面數據源的類
import { observable} from "mobx";
class HomeStore {
@observable homeNum = 0;
}
export default HomeStore;
複製代碼
oneStore.js: 存放一個頁面數據源的類
import { observable} from "mobx";
class OneStore {
@observable oneNum = 3333;
}
export default OneStore;
複製代碼
index.js: 將多個store融合到一個對象裏面
import HomeStore from "./homeStore";
import OneStore from "./oneStore";
let oneStore = new OneStore();
let homeStore = new HomeStore();
const stores = {
oneStore,
homeStore
};
/// 默認導出接口
export default stores;
複製代碼
這些文件夾建立的意義是什麼呢。其實一個xxxStore的話 就是一個數據源的地方。每一個類裏面能夠定義咱們須要用到的數據-就和咱們react中state同樣;index.js的做用呢 就是把全部數據整合到一塊去-- 其實也是爲了下面一部作鋪墊的;
3.2 項目入口index.js部分代碼修改 index.js
import React from "react";
import ReactDOM from "react-dom";
import Router from "./router/router";
import { Provider } from "mobx-react";
import stores from "./store";
ReactDOM.render(
<Provider {...stores}>
<Router />
</Provider>,
document.getElementById("root")
);
複製代碼
這邊咱們引入 Provider 和上面說起到的store 。這邊其實就是一個數據容器,也是mobx這一類數據流框架實現數據共享的基礎。
咱們子組件放在這個數據容器當中。mobx才能夠作到跨組件數據共享Provider 這個其實不陌生了。其實就是react中context 中的屬性--本身寫的關於react Context的文章 不瞭解的同窗能夠學習一下。
3.3 page/home.jsx 的代碼修改 既然Provider是數據容器。咱們子組件在容器裏面。那咱們子組件是如何使用容器裏面的數據呢--看一下下面代碼
import React, { Component } from "react";
+ import { observer, inject } from "mobx-react";
+ @inject("homeStore")
+ @observer
class Home extends Component {
constructor(props) {
super(props);
this.state = {};
}
render() {
return (
<div>
+ <h1>首頁數據源的number爲:{this.props.homeStore.homeNum}</h1>
<button onClick={() => { this.props.history.push("/one") }}>
跳轉到第一個頁面
</button>
</div>
);
}
}
export default Home;
複製代碼
代碼中+
就是新添加的代碼 。下面介紹一下咱們用到的幾個熟悉吧 observer:
將你的組件變成響應式組件。就是數據改變時候能夠出發從新的渲染。 inject(homeStore):
和redux的connect做用同樣,將數據註冊到組件。homeStore其實就咱們store/index中 new出來的實例名稱; this.props.homeStore.xxx
:這個就是如何使用數據源中的值.就和組件透傳同樣
3.4 數據源如何修改? 既然上文咱們實現了數據的展現,那麼固然少不了操做數據的操做-咱們就進行下一個操做 @action:
請求的意思-在嚴格模式下。這是惟一操做store的操做; +表明新增代碼
修改數據源
//homeStore.js
import { observable,action} from "mobx";
class HomeStore {
@observable homeNum = 0;
+ @action addNum() {
+ this.homeNum += 1;
+ }
+ @action lessNum() {
+ this.homeNum -= 1;
+ }
}
export default HomeStore;
複製代碼
展現增長操做按鈕
store裏面定義的@action這邊就用this.props.home.addNum()
操做就能夠了render() {
return (
//代碼自行添加。。。。。。
+ <div>
+ <h1>首頁數據源的number爲:{this.props.homeStore.homeNum}</h1>
+ <button onClick={() => {this.props.homeStore.addNum()}} >
+ 點擊添加
+ </button>
+ <button onClick={() => {this.props.homeStore.lessNum()}}>
+ 點擊刪除
+ </button>
+ </div>
//代碼自行添加。。。。。。
);
}
}
export default Home;
複製代碼
3.5 共享的數據怎麼使用? 展現和修改的操做都完成了--那麼咱們下一步應該是mobx共享數據了。如何實現數據共享呢。其實很簡單 咱們直接看代碼-在咱們須要用到的數據源頁面上加上@inject("homeStore")
就能夠了---固然修改共享數據 也是
import React, { Component } from "react";
import { observer, inject } from "mobx-react";
@inject("homeStore")
@inject("oneStore")
@observer
class One extends Component {
constructor(props) {
super(props);
this.state = {};
}
render() {
return (
<div>
<h1>頁面一</h1>
<h1>首頁數據源的number爲:{this.props.homeStore.homeNum}</h1>
<h1>oneStore的number爲:{this.props.oneStore.oneNum}</h1>
<button onClick={() => { this.props.history.push("/");}}>
跳轉到首頁
</button>
</div>
);
}
}
export default One
複製代碼
去第二個頁面查看一下數據展現:
這樣一套流程結束啦~
#####4.嚴格模式的設置 若是咱們不適用嚴格模式的話。你能夠有這麼一個騷操做;在頁面中使用下放代碼:
this.props.homeStore.homeNum = 33;
複製代碼
你會發現你的數據源數據被修改過了~很方便對吧。but這是很危險的操做
數據源就變得不可追溯了~ 那麼如何設置的-也是很簡單的啦~ 項目入口index.js
+ import { configure } from "mobx";
//代碼自行增長
render(
<div>
<Provider {...stores}>
<XXX />
</Provider>
</div>,
document.getElementById("root")
);
//5.x版本嚴格模式開啓方式
+ configure({
+ enforceActions: "observed"
+ });
複製代碼
這樣開啓嚴格模式就能夠了---這樣的好處呢就是操做數據源的惟一操做就是經過action。數據流變得可追溯了~
todo:代碼仍是有不少須要優化的地方 1.@observer不能放置在export default前 2.對於create-react-react 修飾器的支持感受有點麻煩了
好了文章處處結束了; 寫的比較簡單。若是有寫的不對的地方歡迎指正-- 下面給一下git地址-- 本身寫了2個demo 一個是本身手動搭建webpack的demo 一個是腳手架生成的demo 本身手動webpack-mobx項目 create-react-app項目 react-native 集成mobx項目