背景
随着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