# react-division
**Repository Path**: lingyunruo/react-division
## Basic Information
- **Project Name**: react-division
- **Description**: 拆分react状态逻辑页面
- **Primary Language**: Unknown
- **License**: Not specified
- **Default Branch**: master
- **Homepage**: None
- **GVP Project**: No
## Statistics
- **Stars**: 0
- **Forks**: 0
- **Created**: 2022-01-06
- **Last Updated**: 2022-09-13
## Categories & Tags
**Categories**: Uncategorized
**Tags**: None
## README
## 简介
> 用于组织react代码并分离数据模型,控制器模型,和页面模型。
### 一、主要API
- bindModel
> 数据模型进行实例化,
>
> 使用:
>
> ```js
> class Model1 {
> data = {
> name: 'abc',
> pageInfo: {
> current: 0
> }
> }
> }
>
> bindModel({
> m1: Model1
> });
> ```
>
>
- bindAction
> 逻辑类进行实例化并关联
>
> 使用:
>
> ```js
> class Action1 {
> toggle1 = () => {
> const name = this.models.m1.get('name');
>
> this.models.m1.set({
> name: 'bcd'
> });
> }
> }
>
> class Action2 {
> toggle2 = () => {
> this.models.m1.set({
> 'pageInfo.current': 1
> });
> this.actions.a1.toggle1();
> }
> }
>
> class Action3 {
> toggle = () => {
> this.actions.a2.toggle2();
> this.actions.a1.toggle1();
> }
> }
>
> bindAction({
> a1: Action1,
> a2: Action2
> })
> ```
>
>
- render
> 关联页面数据和逻辑, 只需要关联组件使用到的action和model就行了
>
> 使用:
>
> ```js
> render({
> actions: ['a1', 'a2'],
> models: ['m1']
> })(class Home extends React.Component {
> constructor(props) {
> super(props)
> }
>
> render() {
> return (
>
> {this.props.m1.name}
>
>
> );
> }
> })
> ```
### 二、数据模型
通过class定义一个数据,并且通过bindModel,创建数据模型实例。class内有几个必须属性:
| 名称 | 说明 ||
|-----|------|
| data | 数据结构与初始化,定义数据结构和初始化最初数据 |
数据模型有几个默认方法:
- set:参数为一个或者两个,并且修改会触发两个事件,一个是change事件,另一个是change:\[key\]事件,key为当前更新的属性名称
- 当参数是一个的时候,参数必须是一个对象,对象内为需要更新的数据和属性。且属性如果带‘.’或者'[]'符号,会递归数据找到需要更新的数据。例如 set({'a.b['c']': '9'}')
- 当参数是两个的时候,第一个参数是更新的key,第二个参数是更新的值
- get:接受一个参数,参数可以是一个字符串和一个数组
- 参数为字符串的时候,参数作为属性名,返回该属性值,找不到值时返回null,如:get('a.c[0]')
- 参数为数组的时候,数组作为属性名数组,返回与数组顺序相同的属性值
- getType:返回数据类型,通过Object.prototype.toString.call实现
- has:接受一个字符串作为参数,判断数据内该属性值,是否为undefined或者为null,是返回false,不是返回true
- deepClone:接受最多一个对象作为参数,进行深拷贝,如果不传参数,则默认拷贝data属性,返回拷贝后的值
- previous:接受最多一个字符串作为参数,返回上一次修改的值,如果不传参数,会返回上一次修改的整个对象
- on: 接受两个参数,订阅事件,第一个参数为事件名称,第二个参数为回调函数
- off:取消订阅
- trigger:触发事件
model示例
```js
// ./demo/model.js
export default class {
data = {
name: '姓名不重要'
}
}
```
action里调用model示例
```js
// ./demo/action.js
export default class {
changeName() {
this.models.m1.set({
name: '明天在来'
});
console.log(this.models.m1.get('name'));
}
}
```
组件里使用model内定义的数据示例
```js
// ./demo/Home.js
import React from 'react';
import {render, bindModel, bindAction} from '../src/frame';
import ChildPage from './Child';
import Action1 from './action';
bindAction({
action1: Action1
});
const Home = render({
actions: ['action1'],
models: ['m1']
})((props) => {
const {m1, action} = props;
return (
{m1.name}
);
});
export default Home
```
### 三、控制器
通过class定义一个包含了逻辑处理方法的类,并通过bindAction方法,将控制器类实例化。
类默认的属性
- models:action通过这个属性调用数据模型的方法,models是个对象,存储的是所有创建的数据模型实例。
- actions:同组件引用的其他action,是个对象,属性为组件绑定action的时候指定的属性
- $instance:可以通过这个属性,拿到使用该类的所有组件实例
静态属性
- extends:接收一个数组,数组内是该类需要继承的其他父类,且父类也可以有extends属性,以实现多重继承
action示例
```js
// ./demo/action.js
import Action3 from './action3';
export default class {
static extends = [Action3]
changeName() {
this.models.m1.set({
name: '明天在来'
});
}
initData() {
console.log(this.models);
setTimeout(() => {
this.changeName();
this.models.m1.testName();
this.showAbc();
this.showAbcde();
}, 6000);
console.log(this.models.m1.get('name'));
}
}
```
### 四、渲染API
render函数,是将数据模型和控制器和页面关联起来的函数。render函数被调用两次,第一次调用传入配置参数。第二次调用传入一个组件,组件的props会传入action和绑定的model。
配置参数:
- actions:数组,数组元素为调用bindAction时给定的名称
- models:数组,该组件需要用到的数据模型名称,注意在配置model之前需要确保它被bindModel调用过。
> 注意models在这里只跟组件绑定,与action无关,任意action都可以拿到所有的models。models内的元素可以是字符串和数组,如果是字符串,必须是定义的model名称,如果是数组,数组第一个元素是model名称,剩下元素是要依次要监听的字段,比如 [modelName, rowIndex, colKey]
render方法示例
```js
// ./demo/Child.js
import React from 'react';
import {render, bindModel, bindAction} from '../src/frame';
import Action2 from './action2';
import Model2 from './model2';
bindModel({
m2: Model2
});
bindAction({
a2: Action2
});
const Child = render({
actions: ['a2'],
models: ['m2']
})(({props, state, action}) => {
const {m2} = props;
console.log(props);
return (
{m2.childName}
);
});
export default Child;
```
### 五、完整示例
```js
import React from 'react';
import ReactDom from 'react-dom';
import {bindStore, bindAction, render} from '../index';
class ModelP {
aaa = 0
}
class Model extends ModelP {
data = {
name: '999'
}
}
class ActionP {
aaa = 0
}
class Action {
static extends = [ActionP]
toggle = () => {
}
}
bindStore({
m1: Model
});
bindAction({
a1: Action
})
class Home extends React.Component {
constructor(props) {
super(props);
}
componentDidMount() {
setTimeout(() => {
this.props.models.m1.set({
name: '888'
});
}, 5000);
}
render() {
const {m1} = this.props;
return (
{m1.name}
);
}
}
const Page = render({
actions: ['a1'],
models: ['m1']
})(Home);
ReactDom.render(, document.getElementById('root'));
```