导言

在 React 中,首推的是单向数据流以及单向数据绑定。

什么是单向数据流?VS. 双向数据流

什么是单向数据绑定? VS. 双向数据绑定

利用 Hooks 实现页面级响应式数据管理

  1. // useReactiveData.ts
  2. import { useMemo, useRef, useState } from 'react';
  3. export function useReactiveData<T = any>(ininialState: any) {
  4. const [, setRefresh] = useState({});
  5. const innerDataRef = useRef(ininialState || {});
  6. const dataProxy = useMemo(() => {
  7. return new Proxy(ininialState || {}, {
  8. set(target, prop, value) {
  9. innerDataRef.current[prop] = value;
  10. // console.log(target, prop, value, receiver);
  11. setRefresh({});
  12. return true;
  13. },
  14. get(target, prop) {
  15. return innerDataRef.current[prop];
  16. },
  17. });
  18. }, []);
  19. return dataProxy;
  20. }

使用Controller,拆分 UI 与 业务逻辑

  1. // userController
  2. import { useMemo, useRef, useState } from 'react';
  3. type ControllerBaseOptions = {
  4. changeHandler: () => void;
  5. };
  6. export class ControllerBase {
  7. data: any;
  8. changeHandler!: () => void;
  9. $innerData: object = {};
  10. // eslint-disable-next-line
  11. __init(options: ControllerBaseOptions) {
  12. this.$innerData = this.data || {};
  13. this.changeHandler = options.changeHandler || function name() {};
  14. const innerData = this.$innerData;
  15. const { changeHandler } = this;
  16. this.data = new Proxy(this.$innerData, {
  17. set(target, prop, value) {
  18. innerData[prop] = value;
  19. changeHandler();
  20. return true;
  21. },
  22. get(target, prop) {
  23. return innerData[prop];
  24. },
  25. });
  26. return this;
  27. }
  28. }
  29. export function useController<T extends ControllerBase>(Ctrl: {
  30. new (): { __init(options: ControllerBaseOptions): any };
  31. }) {
  32. const [, setRefresh] = useState({});
  33. const ctrl = useMemo(() => {
  34. // eslint-disable-next-line
  35. return new Ctrl().__init({
  36. changeHandler() {
  37. setRefresh({});
  38. },
  39. });
  40. }, []);
  41. return ctrl;
  42. }

用法

  1. import { ControllerBase } from '@/hooks/userController';
  2. // Logic
  3. export class MarketingActivityController extends ControllerBase {
  4. data = {
  5. listLoading: false,
  6. activityList: [],
  7. };
  8. queryActivityList = () => {
  9. };
  10. }
  11. // UI
  12. export default () => {
  13. const ctrl = useController<MarketingActivityController>(MarketingActivityController);
  14. useEffect(() => {
  15. ctrl.queryActivityList();
  16. }, []);
  17. return <div>12345</div>
  18. }