初识 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

 要显示的文字 
  • 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";
...

    
    

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

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

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

  • 如果你写h5,你应该安装 react-router-dom;

API


basename: string
getUserConfirmation: func
forceRefresh: bool
keyLength: number
children: node

basename: string
getUserConfirmation: func
hashType: string
children: node

to: string
to: object
replace: bool
innerRef: function
innerRef: RefObject
others

activeClassName: string
activeStyle: object
exact: bool
strict: bool
isActive: func
location: object
aria-current: string


initialEntries: array
initialIndex: number
getUserConfirmation: func
keyLength: number
children: node

to: string
to: object
push: bool
from: string
exact: bool
strict: bool

Route render methods
Route props
component
render: func
children: func
path: string | string[]
exact: bool
strict: bool
location: object
sensitive: bool

history: object
children: node

basename: string
location: string
location: object
context: object
children: node

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";
...

    
...
  • 如果你写 React Native 应用,你应该安装 react-router-native;

API:


children


to: string
to: object
replace: bool
component: func

getUserConfirmation: func
keyLength: number
children: node

initialEntries: array
initialIndex: number
getUserConfirmation: func
keyLength: number
children: node

to: string
to: object
push: bool
from: string
exact: bool
strict: bool

Route render methods
Route props
component
render: func
children: func
path: string | string[]
exact: bool
strict: bool
location: object
sensitive: bool

history: object
children: node

basename: string
location: string
location: object
context: object
children: node

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";
...

    
    

参考:

react-router 文档

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


更多参考: react native 中文网


你可能感兴趣的:(初识 MobX + React-Native + React Router dom/native)