尼采般地抒情

尼采般地抒情

尼采般地抒情

音乐盒

站点信息

文章总数目: 321
已运行时间: 1782

父传子(Props)

利用props传值

  1. 组件默认值的写法
  1. 点标记写法就相当于组件作为一个对象值
const Son = (props: any) => {
  console.log('parent to son: ', props);
  return <div>son</div>;
};
// Son default props
Son.defaultProps = {
  msg: 'son-default-msg',
};

export default () => {
  const [parentMsg, setParentMsg] = useState('parent-msg');
  return (
    <>
      <h1>react-message</h1>
      parent
      <Son msg={parentMsg} />
    </>
  );
};

子传父

在父组件定义响应式变量,同时传递一个回调函数参数给子组件,子组件再利用调用回调函数给便父组件所定义的响应式变量

const Son = (props: any) => {
  console.log('parent to son: ', props.msg);
  const sonToParentClick = () => {
    props.getSonValue('son-to-parent-msg');
  };
  return (
    <div>
      son<button onClick={sonToParentClick}>son-to-parent</button>
    </div>
  );
};
Son.defaultProps = {
  msg: 'son-default-msg',
};

export default () => {
  const [parentToSonMsg, setParentToSonMsg] = useState('parent-to-son-msg');
  const [getSonMsg, setGetSonMsg] = useState('');
  const getSonValue = (msg: string) => {
    console.log('son-to-parent-msg: ', msg);
    setGetSonMsg(msg);
  };
  return (
    <>
      <h1>react-message</h1>
      parent
      <Son msg={parentToSonMsg} getSonValue={getSonValue} />
    </>
  );
};

爷传后代

爷传孙

  1. 第一种方式就是利用剩余参数爷传子,子再传孙,不过这种方式繁琐且不便维护
  2. 利用下面的透传方式

透传(Context)

import { createContext } from 'react';

const Context = createContext({});

const Son = (props: any) => {
  console.log('parent to son: ', props.msg);
  const sonToParentClick = () => {
    props.getSonValue('son-to-parent-msg');
  };
  return (
    <>
      <div>
        son<button onClick={sonToParentClick}>son-to-parent</button>
      </div>
      <GradeSon />
    </>
  );
};
Son.defaultProps = {
  msg: 'son-default-msg',
};

const GradeSon = () => {
  const getGrandFather = useContext(Context);
  console.log('get-grand-father: ', getGrandFather);
  return <div>GradeSon</div>;
};

export default () => {
  const [parentToSonMsg, setParentToSonMsg] = useState('parent-to-son-msg');
  const [parentToGradeSonMsg, setParentToGradeSonMsg] = useState({ a: 11, b: 22 });
  const [getSonMsg, setGetSonMsg] = useState('');
  const getSonValue = (msg: string) => {
    console.log('son-to-parent-msg: ', msg);
    setGetSonMsg(msg);
  };
  return (
    <Context.Provider value={parentToGradeSonMsg}>
      <h1>react-message</h1>
      parent
      <Son msg={parentToSonMsg} getSonValue={getSonValue} />
    </Context.Provider>
  );
};

EventBus

事件总线的方式,其实这属于前端通用的一种设计模式,在线编辑器常用的一种代码设计模式

  1. 事件封装:只封装了on、emit、off事件,实际上封装形式不一,也可以使用三方库等
type StringKeyOf<T> = Extract<keyof T, string>;
type CallbackType<
  T extends Record<string, any>,
  EventName extends StringKeyOf<T>,
> = T[EventName] extends any[] ? T[EventName] : [T[EventName]];
type CallbackFunction<T extends Record<string, any>, EventName extends StringKeyOf<T>> = (
  ...props: CallbackType<T, EventName>
) => any;

export class EventEmitter<T extends Record<string, any>> {
  private callbacks: { [key: string]: Function[] } = {};

  public on<EventName extends StringKeyOf<T>>(
    event: EventName,
    fn: CallbackFunction<T, EventName>,
  ): this {
    if (!this.callbacks[event]) {
      this.callbacks[event] = [];
    }

    this.callbacks[event].push(fn);

    return this;
  }

  public emit<EventName extends StringKeyOf<T>>(
    event: EventName,
    ...args: CallbackType<T, EventName>
  ): this {
    const callbacks = this.callbacks[event];

    if (callbacks) {
      callbacks.forEach(callback => callback.apply(this, args));
    }

    return this;
  }

  public off<EventName extends StringKeyOf<T>>(
    event: EventName,
    fn?: CallbackFunction<T, EventName>,
  ): this {
    const callbacks = this.callbacks[event];

    if (callbacks) {
      if (fn) {
        this.callbacks[event] = callbacks.filter(callback => callback !== fn);
      } else {
        delete this.callbacks[event];
      }
    }

    return this;
  }

  protected removeAllListeners(): void {
    this.callbacks = {};
  }
}

const EventBus = new EventEmitter();
export default EventBus;
  1. 使用
    1. Daughter组件定义,Son组件触发
    2. 有注册就要有注销,不然内存中会出现重复事件逻辑多次执行的问题
import { createContext } from 'react';
import EventBus from '@/utils/eventEmitter';

const Context = createContext({});

const Son = (props: any) => {
  console.log('parent to son: ', props.msg);
  const sonToParentClick = () => {
    props.getSonValue('son-to-parent-msg');
    EventBus.emit('daughterEvent', {
      msg: 'son-to-daughter-msg',
    });
  };
  return (
    <>
      <div>
        son<button onClick={sonToParentClick}>son-to-parent</button>
      </div>
      <GradeSon />
    </>
  );
};
Son.defaultProps = {
  msg: 'son-default-msg',
};

const Daughter = () => {
  useEffect(() => {
    function daughterEvent(data: any) {
      console.warn('daughter event: ', data);
    }
    EventBus.on('daughterEvent', daughterEvent);
    return () => {
      EventBus.off('daughterEvent', daughterEvent);
    };
  }, []);
  return <div>Daughter</div>;
};

const GradeSon = () => {
  const getGrandFather = useContext(Context);
  console.log('get-grand-father: ', getGrandFather);
  return <div>GradeSon</div>;
};

export default () => {
  const [parentToSonMsg, setParentToSonMsg] = useState('parent-to-son-msg');
  const [parentToGradeSonMsg, setParentToGradeSonMsg] = useState({ a: 11, b: 22 });
  const [getSonMsg, setGetSonMsg] = useState('');
  const getSonValue = (msg: string) => {
    console.log('son-to-parent-msg: ', msg);
    setGetSonMsg(msg);
  };
  return (
    <>
      <Context.Provider value={parentToGradeSonMsg}>
        <h1>react-message</h1>
        parent
        <Son msg={parentToSonMsg} getSonValue={getSonValue} />
      </Context.Provider>
      <Daughter />
    </>
  );
};

状态管理

状态管理所定义的Module变化,所使用到的组件也会响应式更新,不做详细记录。

评论区

什么都不舍弃,什么也改变不了