随着React Hooks 普及起来,组件逻辑写法变成函数式;逻辑函数声明、函数代码结构,随着逻辑增加复杂,代码组织混乱,函数声明散乱;
最关键的一点,每个人对代码理解不一样,有的喜欢在一个function
写大段逻辑,有的喜欢拆分逻辑很细,
就会使在项目维护时**,代码风格、代码结构,越来越不统一,难以维护**。
针对上述情况,需要可以组织代码结、梳理逻辑的方法,从而达到项目维护性高、代码结构统一、逻辑清晰
在编写代码的过程中,发现可以抽象出公共代码结构;
- 声明可变数据/共享变量声明、state 声明/let xxx= xxx/useState
- 方法声明/function xx () {} /action/dispatch
- 方法调用 / xx() / action()/dispatch()
通过上图,可以把常见组件内部逻辑,分成3个部分,其中3、4属于相同部分:
- :**主要是声明数据,**有useState/let xxx = 11;
- :声明函数、方法,会涉及修改数据
**setcounts**
、使用数据**sendLogcount**
;- 其中修改与使用里会有一些辅助方法
fetch
来执行对应逻辑;
- 其中修改与使用里会有一些辅助方法
- 调用方法,3与4部分都在视图中使用函数与方法,统一称为调用方法。
把代码结构拆分、分析之后;其实在日常的开发过程中大部分代码复杂逻辑都在**1与2部分,而2部分里有相互调用的逻辑,各种辅助函数相互杂糅在一起,**慢慢的使得代码越来越复杂,难以阅读。
我们可以把1与2部分复杂封装起来,定义好规范干净的结构如
根据上图可知,把原先1、2、3 部分统一封装在一个hooks.js
文件里;
- 原先1与2部分代码通过调用
**polymerAction**
给聚合起来,把state与actions/方法声明给放在一起;再通过**const [state, actions, shareVars] = usePolymerActionState(countActions)**
对外暴露数据与acions/方法。 - 原先3部分封装hooks使用
**usePolymerActionState**
暴露方法调用,走正常调用逻辑。 - 在视图里,正常使用hooks 封装方法,
**return**
出**usePolymerActionState**
暴露数据与方法,正常调用逻辑。
可以看出核心部分,就是把state与action封装在一起高内聚,通过对象组织代码结构,而对象可以进行**组合方式,**来组织更大复杂的代码逻辑与结构。
从视图上来看,只调用暴露出来的方法。
总结一下,按照上述方式,可以提高项目可维护性,代码结构统一。
/** @jsx createElement */
import { createElement, useEffect, useState, useRef, useMemo } from 'rax';
import { moduleInit } from './utils';
export default function Whrealtimetrendinghotels(props) {
const { gdc, mds, pageUtils } = props;
moduleInit({
gdc,
mds,
pageUtils
})(useState, useEffect, useRef,useMemo);
return (<CustomComponent
/>);
}
入口文件需要在moduleInit
传入useMemo,注意传入位置,直接按照上述位置传入即可。
ps:为了兼容小程序,在小程序里,库不能直接引入import { createElement, useEffect, useState, useRef, useMemo } from 'rax';
import {initHooksAction} from './hooks';
function CustomComponent(props) {
const [
count, {setCounts, sendLog}
] = initHooksAction();
return (
<View style={{width: 100, height: 100, backgroundColor: 'red'}} onClick={() => {
setCounts('参入数据了');
}}>
<Text>{count}</Text>
</View>
);
}
initHooksAction
可以拿到数据、方法;走正常逻辑;
const countActions = polymerAction({
count: 0
}, {
setCounts({state, setState}, params) {
setState({
count: ++state.count
})
console.log(params)
},
fetch({state, setState}, count) {
console.log(`接口请求埋点${
count}`)
},
sendLog({state, setState, actions}, count) {
actions.fetch(count)
console.log(`发送相关埋点${
count}`)
},
}, {});
function initHooksAction() {
const [state, actions, shareVars] = usePolymerActionState(countActions);
useEffect(() => {
sendLog(state.count);
}, [state.count])
return [state.count, actions, shareVars]
}
- polymerAction:声明state、actions、shareVar;
- usePolymerActionState:底层会重写actions方法,shareVar数据,
- 返回数据是对应
polymerAction
里声明的数据、方法
- 返回数据是对应
- initHooksAction:封装hooks 逻辑
const infiniteScrollAction = polymerAction({
isLoadingShow: false,
isLoadingError: false,
isEmptyData: false,
}, {
showLoading({ state, setState, shareVars, actions }) {
setState({
isLoadingShow: true,
isLoadingError: false,
isEmptyData: false
});
},
closeLoading({ state, setState, shareVars, actions }) {
setState({
isLoadingShow: false
});
shareVars.throttleTarget = true;
},
...,
}, {
throttleTarget: true,
});
const handleAction = polymerAction({},{
/**
* 刷新接口
*/
onRefreshList({ state, setState, shareVars, actions }) {
....
},
},{})
const scrollListAction = polymerAction({
cityList: [],
recommendList: [],
isCityListShow: false,
}, {
initListParam({ state, setState, shareVars, actions }) {
shareVars.pageNo = 0;
shareVars.dataVersion = 0;
},
exp({ state, setState, shareVars, actions }, data) {
const {cityName, cityCode} = shareVars.cityData;
let shidsArr = [];
if (data[0] && data[0].hotHotelList) {
shidsArr = hotCityListShids(data);
sendUT.exp(cityName, shidsArr[0].join('/'), shidsArr[1].join('/'));
} else {
shidsArr = shids(data);
sendUT.exp(cityName, '', shidsArr.join('/'));
}
},
...,
}, {
pageNo: 0,
dataVersion: 0,
cityData: {
cityName: '',
cityCode: '',
}
});
function initEffect(param) {
const [state, action] = usePolymerActionState(mergePolymerAction(scrollListAction,infiniteScrollAction,handleAction));
...
...
return [state, action]
}
通过**mergePolymerAction**
可以把多个action,scrollListAction
、infiniteScrollAction
** 、handleAction
合并;这样就可以任意拆分action。**
管理 object 类型 state 的 Hooks,用法与 class 组件的 this.setState 基本一致。
const [state,setState] = useSetState({
hehe:1,
aaa:1
});
// 修改
setState({
aaa:2
})
从polymerAction里,获取actions
const handleAction = polymerAction({},{
/**
* 刷新接口
*/
onRefreshList({ state, setState, shareVars, actions }) {
....
},
},{});
const handle = getAction(handleAction);
console.log(handle);
,{
/**
* 刷新接口
*/
onRefreshList({ state, setState, shareVars, actions }) {
....
},
}
生成action 集合
const scrollListAction = polymerAction({
cityList: [],
recommendList: [],
isCityListShow: false,
}, {
initListParam({ state, setState, shareVars, actions }) {
shareVars.pageNo = 0;
shareVars.dataVersion = 0;
},
...,
}, {
pageNo: 0,
dataVersion: 0,
cityData: {
cityName: '',
cityCode: '',
}
});
const [state,actions,shareVal] = polymerAction(stateObj,actionObj,shareValObj)
Params
参数 | 说明 | 类型 | 默认值 |
---|---|---|---|
stateObj | 必传,声明state | object |
{} |
actionObj | 必传,声明方法、函数 | object |
{} |
shareValObj | 可选项,传入默认的状态值 | boolean |
{} |
Result
参数 | 说明 | 类型 |
---|---|---|
state | 状态值 | object |
actions | 操作集合 | Actions |
shareVal | 共享变量 | object |
actionObj
const handleAction = polymerAction({},{
/**
* 刷新接口
*/
onRefreshList({ state, actions,shareVars,setState,setShareVars },param) {
...
},
/**
* 接口报错,刷新接口
*/
onRefreshListError({ state, setState, shareVars, actions }) {
actions.getList(true);
},
},{});
参数 | 说明 | 类型 |
---|---|---|
state | 获取 stateObj | **object** |
actions | 获取 actionObj | **object** |
shareVars | 获取 shareValObj | **object** |
setState | 设置 state | **({}) => void** |
setShareVars | 设置 shareVal | **({}) => void** |
根据传入
action
,转换成能改变页面的**PolymerActionState**
function initEffect(param) {
const [state, actions] = usePolymerActionState(scrollListAction);
...
...
return [state, action]
}
const [state, actions,shareVal] = usePolymerActionState(polymerAction);
Params
参数 | 说明 | 类型 |
---|---|---|
polymerAction | 必传,声明polymerActionState 集合 |
**Array** |
Result
参数 | 说明 | 类型 |
---|---|---|
state | 状态值 | **object** |
actions | 操作集合 | **object** |
shareVal | 共享变量 | **object** |
合并多个
**polymerAction**
mergePolymerAction(scrollListAction,infiniteScrollAction,handleAction)
使用rax 体系,需要从外手动传
newUseState, newUseRef, newUseMemo
,是为了兼容小程序不报错
injectState(useState,useRef,useMemo);