共计 7526 个字符,预计需要花费 19 分钟才能阅读完成。
背景
随着 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 逻辑
高级用法
拆分 / 合并 action
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。API
useSetState
治理 object 类型 state 的 Hooks,用法与 class 组件的 this.setState 基本一致。
const [state,setState] = useSetState({
hehe:1,
aaa:1
});
// 批改
setState({aaa:2})
getAction
从 polymerAction 里,获取 actions
const handleAction = polymerAction({},{
/**
* 刷新接口
*/
onRefreshList({state, setState, shareVars, actions}) {....},
},{});
const handle = getAction(handleAction);
console.log(handle);
,{
/**
* 刷新接口
*/
onRefreshList({state, setState, shareVars, actions}) {....},
}
polymerAction
生成 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** |
usePolymerActionState
依据传入
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** |
mergePolymerAction
合并多个
**polymerAction**
mergePolymerAction(scrollListAction,infiniteScrollAction,handleAction)
injectState
应用 rax 体系,须要从外手动传
newUseState, newUseRef, newUseMemo
, 是为了兼容小程序不报错
injectState(useState,useRef,useMemo);
代码
let useState = null;
let useRef = null;
let useMemo = null;
function useSetState(initData) {const [state, setState] = useState(initData);
const dispatch = (next) => {if ( typeof next === 'object') {setState((pre) => Object.assign({}, pre, next));
}
else {setState(next);
}
};
return [state, dispatch];
}
function polymerAction(state, action = {}, shareVar = {}) {return [state, action, shareVar];
}
function newActionData(actions, states, shareVars, setState) {let newAction = {};
Object.keys(actions)
.forEach((name) => {const old = actions[name];
if (typeof old === 'function') {
// 从新写 actions 办法
newAction[name] = function(...arg) {
return old.call(null, {
state: states,
shareVars,
actions: newAction,
setState(param, fn = () => {}) {setState(param);
fn(param);
},
setShareVars(param) {shareVars = Object.assign(shareVars, param);
},
}, ...arg);
};
}
});
return newAction;
}
// 与 hooks 关联
function usePolymerActionState(param) {const [state, action = {}, shareVar = {}] = param;
const actions = action;
// Object.assign({}, xxx) 多个加载反复组件生成对应数据, 避免数据互相笼罩状况
const [states, setState] = useSetState(Object.assign({}, state));
// 生成新共享变量
const shareVars = useMemo(() => (Object.assign({}, shareVar)), []) ;
shareVars.updateAfterState = states;
const newAction = useMemo(() => (newActionData(actions, states, shareVars, setState)), [action, states, shareVars])
return [states, newAction, shareVars];
}
function getAction(polymer) {return polymer[1];
}
function mergePolymerAction(action1, ...res) {const actions = action1.map(function (val, index) {let resAction = {};
res.forEach((action) => {Object.assign(resAction, action[index]);
});
return Object.assign({}, val, resAction);
});
return actions;
}
function injectState(newUseState, newUseRef, newUseMemo) {if (!newUseState || !newUseMemo) {
console.warn(` 请在模块中的 moduleInit 传入 useState、useMemo,如:moduleInit({gdc,mds,pageUtils})
(useState, useEffect, useRef, useMemo);`);
return
}
useState = newUseState;
useRef = newUseRef;
useMemo = newUseMemo;
}
export {
useSetState,
getAction,
polymerAction,
usePolymerActionState,
mergePolymerAction,
injectState
};
github
https://github.com/NoahsDante…
如果对你有帮忙请点 start 🙏