尼采般地抒情

尼采般地抒情

尼采般地抒情

音乐盒

站点信息

文章总数目: 316
已运行时间: 1570

父传子(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 =&gt; 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 =&gt; 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变化,所使用到的组件也会响应式更新,不做详细记录。

评论区