父传子(Props)
利用props传值
- 组件默认值的写法
- 点标记写法就相当于组件作为一个对象值
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} />
</>
);
};
爷传后代
爷传孙
- 第一种方式就是利用剩余参数爷传子,子再传孙,不过这种方式繁琐且不便维护
- 利用下面的透传方式
透传(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
事件总线的方式,其实这属于前端通用的一种设计模式,在线编辑器常用的一种代码设计模式
- 事件封装:只封装了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;
- 使用
- Daughter组件定义,Son组件触发
- 有注册就要有注销,不然内存中会出现重复事件逻辑多次执行的问题
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变化,所使用到的组件也会响应式更新,不做详细记录。
评论区