RN

初识 MobX + React-Native + React R

2019-03-18  本文已影响27人  jevons_lee_

MobX

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


使用:

安装: npm install mobx --save

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

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


Api

observable



什么是 observable ?

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

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

如何用 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())

对于 todolist 的 demo 来讲

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;

总结:

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的区别在于并没有额外的颜色变化,更适于一般场景)

TouchableHighlight

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

Text

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

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

TextInput

输入框组件

ScrollView

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 能够使得路由的匹配更严格一些。

注意: 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 中文网


上一篇下一篇

猜你喜欢

热点阅读