React Hooks之usePolymerAction抽象代码结构设计理念

 

背景

随着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 'react';
\
export default function Realtimetrendinghotels(props) {
const { gdc, mds, pageUtils } = props;
return (<CustomComponent
/>);
}
import { createElement, useEffect, useState, useRef, useMemo } from 'react';`
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必传,声明stateobject{}
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)

代码

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
};

githubhttps://github.com/NoahsDante...

以上就是React Hooks之usePolymerAction抽象代码结构设计理念的详细内容,更多关于React Hooks usePolymerAction的资料请关注编程宝库其它相关文章!

本文为大家分享了微信小程序实现计时器的具体代码,供大家参考。微信小程序点击事件触发计时器1.wxml<view class="button" bindtap="open_modal">开始巡查</vi ...