通信
props
函数(标签上传递,参数接收)
interface IProps {
name: string
}
interface IState {}
function Comp(props: IProps) {
const [state, setState] = useState<IState>({}) //这属于hooks内容,在函数组件中初始化state
return <h1>my name is {props.name}</h1>
}
const name = 'LLC'
ReacrDOM.render(<Comp name={name} />, document.getElementById('app'))
类(defaultProps传递 / 标签上传递,this.props接收)
class Comp extends React.Component<IProps, IState> {
constructor(props: IProps) {
super(props)
this.state = {}
}
render() {
return <h1>my name is {this.props.name}</h1>
}
}
Comp.defaultProps = {
name: 'LLC'
}
ReacrDOM.render(<Comp/>, document.getElementById('app'))
props传递方法(父向子传递函数,由子触发,从而实现子向父传递数据)
class Father extends React.Component {
state = {
needToDo: ["wash cloth", "do housework"],
};
getTask = (event) => {
const { needToDo } = this.state;
needToDo.unshift(event);
this.setState({ needToDo });
};
render() {
return (
<div>
<h1>老爸需要做的事情:</h1>
<ul>
{this.state.needToDo.map((e, index) => {
return <li key={index}>{e}</li>;
})}
</ul>
<h1>再安排些事情给老爸做:</h1>
<Son assgin={this.getTask} />
</div>
);
}
}
class Son extends React.Component {
assginTask = () => {
this.props.assgin(this.refs.inp.value);
this.refs.inp.value = "";
};
render() {
return (
<div>
<input ref="inp" />
<button onClick={this.assginTask}>安排</button>
</div>
);
}
}
createContext/consumer,对标provider/inject
这和直接import的区别就是,这是可以传响应式数据,import的话,虽然是改了,但是在页面中不是实时渲染的
import { createContext, useState } from "react";
export const aProvider = createContext();
export default function GrandPa() {
const [num, setNum] = useState(10);
return (
<>
<button
onClick={() => {
setNum(110);
}}
>
increment num
</button>
<aProvider.Provider value={{ num, setNum }}>
<Father />
</aProvider.Provider>
;
</>
);
}
const Father = () => <Child />;
// 如果不在同一个文件下,还要再import aProvider from 'xxx/GrandPa'
function Child() {
return (
<>
<h1>I am Child</h1>
<aProvider.Consumer>
{({ num, setNum }) => {
return (
<>
<p>{num}</p>
<button
onClick={() => {
setNum(120);
}}
>
increment num to 120
</button>
</>
);
}}
</aProvider.Consumer>
</>
);
}
useRef + forwardRef 对标 $refs(函数组件没有实例,只能在类组件用)
funtion Father() {
const 拿来吧你= useRef(null)
// 直接拿到了子组件实例,然后就可以为所欲为
return <Kid ref={拿来吧你} />
}
class Kid extends React.Component {
state = {
name: 'kid'
}
render() {
return <h1>{this.state.name}</h1>
}
}
更牛的是,Father中的 “拿来吧你” 竟然可以做props,传递出去,拿其它非子组件的实例(通信能通到哪,就能拿到哪)
funtion 表哥(props) {
return <表哥的大舅 ref={props.拿来吧你} /> // 这就“千里之外”拿到了表哥的大舅的实例
}
class 表哥的大舅 extends React.Component {}
创建自定义事件传值 对标 eventBus
可以把document当成那个bus,但是这很艹蛋,故创建一个不用的伪元素来做事件中心
class EventBus {
constructor() {
this.bus = document.createElement('fakeelement');
}
addEventListener(event, callback) {
this.bus.addEventListener(event, callback);
}
removeEventListener(event, callback) {
this.bus.removeEventListener(event, callback);
}
dispatchEvent(event, detail = {}){
this.bus.dispatchEvent(new CustomEvent(event, { detail }));
}
}
export default new EventBus
import EventBus from './EventBus'
class ComponentA extends React.Component {
componentDidMount() {
EventBus.addEventListener('myEvent', this.handleEvent)
}
componentWillUnmount() {
EventBus.removeEventListener('myEvent', this.handleEvent)
}
handleEvent = (e) => {
console.log(e.detail.log) //i'm zach
}
}
class ComponentB extends React.Component {
sendEvent = () => {
EventBus.dispatchEvent('myEvent', {log: "i'm zach"}))
}
render() {
return <button onClick={this.sendEvent}>Send</button>
}
}