初识 MobX + React-Native + React Router dom/native

MobX

简单、可扩展的状态管理(可观察的数据)


使用:

安装: npm install mobx --save

React 绑定库: npm install mobx-react --save

引用 : import { observable } from 'mobx';


Api


observable



什么是 observable ?

observable 是一种让数据的变化可观察的方法

哪些数据类型可以被观察 ?

  • 原始类型:string,number,boolean,symbol
  • 对象
  • 数组

如何用 observable 把对象转化为可观察到对象

MobX 对任意变量的处理方式有两种

1.  对于数组纯对象以及 es6 中的 map ,直接把 observable 当作函数来把变量转化为可观察到对象,之后对数组、对象、map 中的内部数据进行合理的操作,都将会被监视

const map = observable(new Map());
map.set('a',1);
console.log(map.has('a'));
map.delete('a');
console.log(map.has('a'));

2.  对于上面没有包含的其他类型,都将调用 observable.box来进行把变量包装为可观察到对象,之后对该变量的直接负值将会被监视

const str = observable.box(2);
const num = observable.box(2);
const bool = observable.box(2);
num.set(3)
console.log('---observable---', str, num.get(), bool.get())
  • .get() - 返回原始类型值。

  • .set(value) - 替换当前存储的值并通知 observable。

对于 todolist 的 demo 来讲

  • 每一次对Todos更改都会触发change(例如:添加,删除)
  • 但是对Todos中的每一条Todo状态更改并不会被监听(不会监听下一级变化)
  • change的object属性代表改变之后的状态
constructor() {
    observe(this.Todos, change => {
        console.log(change,'this.Todos, change')
    })
}

MobX 提供了 decorator 的修饰器

其只可以修饰类和类成员

MobX 为了简化 API 让 @observable 能识别当前是被普通函数调用的还是被当作修饰器调用的,如果是修饰器(@)就自动识别变量类型

spy

用法:
spy(listener) 注册一个全局间谍监听器,用来监听所有 MobX 中的事件。 它类似于同时在所有的 observable 上附加了一个 observe 监听器,而且还通知关于运行中的事务/反应和计算。

spy(event => {
    console.log(event,'spy-event')
});

computed

什么是 computed ?

  • 一般理解为对可观察数据做出的响应

  • 多个可观察数据组合成一个可观察数据

import {observable, computed, autorun} from "mobx";

class Store {
    @observable 
    price = 6;
    @observable 
    amount = 3;
}
const store = new Store()
var total = computed(()=>{
    return store.price * store.amount;
})

total.observe((change)=>{
    console.log(total,'computed---------',change)
})

store.price = 9;

简而言之,你有一个值,该值的结果依赖于其他被观察的值,并且该值也需要被 obserable,那么就使用computed。

autorun

什么是 autorun ?

另一个响应 state 的 api 便是 autorun 。和 computed 类似,每当依赖的值改变时,其都会改变。不同的是, autorun 没有了 computed 的优化(当然,依赖值未改变的情况下也不会重新运行,但不会被自动回收)。因此在使用场景来说, autorun 通常用来执行一些有副作用的。例如打印日志,更新 UI 等等。

官方定义:

当你想创建一个响应式函数,而该函数本身永远不会有观察者时,可以使用 mobx.autorun。 这通常是当你需要从反应式代码桥接到命令式代码的情况,例如打印日志、持久化或者更新UI的代码。 当使用 autorun 时,所提供的函数总是立即被触发一次,然后每次它的依赖关系改变时会再次被触发
相比之下, computed(function) 创建的函数只有当它有自己的观察者时才会重新计算,否则它的值会被认为是不相关的 。 经验法则:如果你有一个函数应该自动运行,但不会产生一个新的值,请使用autorun。 其余情况都应该使用 computed。 Autoruns 是关于 启动效果 (initiating effects) 的 ,而不是产生新的值。 如果字符串作为第一个参数传递给 autorun ,它将被用作调试名。

简而言之:自动追踪其所引用的可观察数据,并在数据发生变化时重新触发

假如你观察了一个数组,你想根据数组的长度变化作出反应,在不使用 computed 时,代码是这样的

var numbers = observable([1, 2, 3]);
autorun(() => console.log(numbers.length));
// 输出 '3'
numbers.push(4);
// 输出 '4'
numbers[0] = 0;
// 输出 '4'

使用 computed 最后一个改变数组内元素内容的改变就不会被触发

const Mobx = require("mobx");
const { observable, autorun, computed } = Mobx;
var numbers = observable([1, 2, 3]);
var sum = computed(() => numbers.length);
autorun(() => console.log(sum.get()));
// 输出 '3'
numbers.push(4);
// 输出 '4'
numbers[0] = 1;

总结:

  • computed 可以当作新的可观察数据看待
  • autorun 引用的可观察数据发生的变化 无论是否修改数据都会先行执行一次

    如果你想响应式的产生一个可以被其它 observer 使用的值,请使用 @computed,如果你不想产生一个新值,而想要达到一个效果(比如上文提到的 打印日志、持久化或者更新UI的代码,请使用 autorun。

when

提供了条件执行逻辑

class Store {
    @observable 
    bool = false;
}
const store = new Store()
when(()=>store.bool, ()=>console.log('when~'));
console.log('-----')
store.bool = true
// -----
// when~

如果一开始 bool 就是 true 那 when 就会立即执行

action

什么是 action ?

action 是任何用来修改状态的东西

在 MobX 中,对于 store 对象中可观察的属性值,在他们改变的时候则会触发观察监听的函数,这里注意两点:

  1. 该属性必须是定义的可观察属性(@observable)
  2. 它的值必须发生改变(和原值是不等的)

何时使用action

应该永远只对修改状态的函数使用 action。

只执行查找,过滤器等函数不应该被标记为动作,以允许 MobX 跟踪它们的调用。

对于 todolist 中的 demo 来讲

@action
createTodo(title:string,content:string) {
    this.Todos.unshift(new Todo(title,content));
}

@action
createTodo(Todo:IINSTodo) {
    this.Todos.remove(Todo)
}

createTodo 和 createTodo 会将 被观察的 Todos 改变


Intercept & Observe

MobX 还提供了很多好用的方法,例如上面代码中的 this.Todos.remove(Todo) 的remove方法可以直接从数组中删除某元素,不用遍历查找再删除


定义数据存储

可以通过在应用中传递属性到组件树中或使用 mobx-react 包中的 Provider 和 inject 来分发 UI 状态 store。

ProviderInject

Provider 是一个组件,可以使用 react 上下文机制将 store (其他东西)传递给子组件。如果你不希望显示传递多层组件请使用 provider

inject 可以获得 store 它是一个更高阶的组件,它接受一个字符串列表并使这些存储可用于被包装的组件。


MobX 学习参考:

https://github.com/ckinmind/mobx-share


React Native 基础了解


常用标签(组件)篇

使用: import { View, Text, TextInput, TouchableOpacity } from "react-native";

View

相当于 html 的 div,块容器

Image

图片展示组件,常用属性如下:

source

source={{uri: "XXX"}}
加载网络图片, 必须设置宽和高才能展示。在展示图片前,最好判断XXX是否存在

source={require("XXX")}
加载本地图片,XXX为本地图片相对地址

TouchableOpacity

用于写按钮的组件。常用属性如下:(此组件与TouchableHighlight的区别在于并没有额外的颜色变化,更适于一般场景)

  • activeOpacity
    指定封装的视图在被触摸操作激活时以多少不透明度显示(通常在 0 到 1 之间)

  • onPress
    类似平时写的 onClick

TouchableHighlight

用于写按钮的组件,常用属性如下:

  • activeOpacity
    指定封装的视图在被触摸操作激活时以多少不透明度显示(通常在 0 到 1 之间)

  • underlayColor
    有触摸操作时显示出来的底层的颜色

  • onPress
    类似平时写的 onClick

Text

显示文字的组件 ( 文字不能直接写在 View 中要嵌套 Text

<View><Text> 要显示的文字 </Text></View>
  • ellipsizeMode

    取值('head', 'middle', 'tail', 'clip')

    • head
      从文本的开头进行截断,并在文本的开头添加省略号,例如:…xyz。
    • middle
      从文本的中间进行截断,并在文本的中间添加省略号,例如:ab…yz。
    • tail
      从文本的末尾进行截断,并在文本的末尾添加省略号,例如:abcd…。
    • clip
      文本的末尾显示不下的内容会被截断,并且不添加省略号,clip只适用于iOS平台。

  • numberOfLines
    限制最多显示的行数

  • onPress
    类似平时写的 onClick

TextInput

输入框组件

  • value

  • onChangeText

  • underlineColorAndroid="transparent"
    TextInput在安卓上默认有一个底边框,同时会有一些padding。如果要想使其看起来和iOS上尽量一致,则需要设置padding: 0,同时设置underlineColorAndroid="transparent"来去掉底边框

  • placeholder
    提示文本

  • placeholderTextColor
    提示文本颜色

  • onBlur
    当文本框失去焦点的时候调用此回调函数。

  • onFocus
    当文本框获得焦点的时候调用此回调函数。

ScrollView

  • horizontal
    当此属性为true的时候,所有的子视图会在水平方向上排成一行,而不是默认的在垂直方向上排成一列。默认值为false。

  • showsHorizontalScrollIndicator
    当此属性为true的时候,显示一个水平方向的滚动条。

StyleSheet

样式定义 StyleSheet.create

style的写法基本就与正常的css相同,只不过用中划线的css名字改用驼峰式写法
例如: margin-top 改为 marginTop

Dimensions

获取屏幕尺寸 :
Dimensions.get('window').height
Dimensions.get('window').width

布局

flex布局

路由

在 App.ts 中定义路由

import { NativeRouter, Route } from "react-router-native";
...
<NativeRouter>
    <Route exact={true} path="/" component={index} />
    <Route path="/Content" component={Content} />
</NativeRouter>

其中 exact 是 Route 下的一条属性,一般而言,react 路由会匹配所有匹配到的路由组价,exact 能够使得路由的匹配更严格一些。

  • exact 的值为 bool 型,为 true 是表示严格匹配,为 false 时为正常匹配。
  • 如在 exact 为 true 时,' /link ' 与 ' / ' 是不匹配的,但是在 false 的情况下它们又是匹配的。

注意: react-router 还分为浏览器端(h5)和 rn应用端

API

<BrowserRouter>
basename: string
getUserConfirmation: func
forceRefresh: bool
keyLength: number
children: node
<HashRouter>
basename: string
getUserConfirmation: func
hashType: string
children: node
<Link>
to: string
to: object
replace: bool
innerRef: function
innerRef: RefObject
others
<NavLink>
activeClassName: string
activeStyle: object
exact: bool
strict: bool
isActive: func
location: object
aria-current: string
<Prompt>
<MemoryRouter>
initialEntries: array
initialIndex: number
getUserConfirmation: func
keyLength: number
children: node
<Redirect>
to: string
to: object
push: bool
from: string
exact: bool
strict: bool
<Route>
Route render methods
Route props
component
render: func
children: func
path: string | string[]
exact: bool
strict: bool
location: object
sensitive: bool
<Router>
history: object
children: node
<StaticRouter>
basename: string
location: string
location: object
context: object
children: node
<Switch>
location: object
children: node
history
history is mutable
location
match
null matches
matchPath
pathname
props
withRouter
Component.WrappedComponent
wrappedComponentRef: func

例子:

import { HashRouter as Router, Route } from "react-router-dom";
...
<Router>
    <div style={{ display: "flex", height: "100%" }}>
        <Route exact={true} path="/" component={xxx} />
        ...
    </div>
</Router>

API:

<BackButton>
children
<DeepLinking>
<Link>
to: string
to: object
replace: bool
component: func
<NativeRouter>
getUserConfirmation: func
keyLength: number
children: node
<MemoryRouter>
initialEntries: array
initialIndex: number
getUserConfirmation: func
keyLength: number
children: node
<Redirect>
to: string
to: object
push: bool
from: string
exact: bool
strict: bool
<Route>
Route render methods
Route props
component
render: func
children: func
path: string | string[]
exact: bool
strict: bool
location: object
sensitive: bool
<Router>
history: object
children: node
<StaticRouter>
basename: string
location: string
location: object
context: object
children: node
<Switch>
location: object
children: node
history
history is mutable
location
match
null matches
matchPath
pathname
props
withRouter
Component.WrappedComponent
wrappedComponentRef: func

例子:

import { NativeRouter, Route } from "react-router-native";
...
<NativeRouter>
    <Route exact={true} path="/" component={xxx} />
    <Route path="/xxx" component={xxx} />
</NativeRouter>

参考:

react-router 文档

REACT ROUTER <- 这个讲的很详细,上述的API在其中有代码演示


更多参考: react native 中文网


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