背景

随着React Hooks 遍及起来,组件逻辑写法变成函数式;逻辑函数申明、函数代码构造,随着逻辑减少简单,代码组织凌乱,函数申明散乱;
最要害的一点,每个人对代码了解不一样,有的喜爱在一个function 写大段逻辑,有的喜爱拆分逻辑很细,
就会使在我的项目保护时,代码格调、代码构造,越来越不对立,难以保护
针对上述情况,须要能够组织代码结、梳理逻辑的办法,从而达到我的项目维护性高、代码构造对立、逻辑清晰

设计理念

形象代码构造

在编写代码的过程中,发现能够形象出公共代码构造;

  1. 申明可变数据/共享变量申明、state 申明/let xxx= xxx/useState
  2. 办法申明/function xx () {} /action/dispatch
  3. 办法调用 / xx() / action()/dispatch()


通过上图,能够把常见组件外部逻辑,分成3个局部,其中3、4属于雷同局部:

  1. :次要是申明数据,有useState/let xxx = 11;
  2. :申明函数、办法,会波及批改数据**setcounts**、应用数据**sendLogcount**;

    1. 其中批改与应用里会有一些辅助办法fetch来执行对应逻辑;
  3. 调用办法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,scrollListActioninfiniteScrollActionhandleAction合并;这样就能够任意拆分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)

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