个人随笔,主要记录学习react时的个人理解,方便回顾。。
一、context
解决问题:多个嵌套组件中向深层组件传props需要嵌套传递问题。
个人理解:在调用context的组件中,建立一个类似针对该组件为域(包含该组件以及其子孙组件)的变量,这个变量可以被该组件以及其子孙组件访问。
例:
// Context 可以让我们无须明确地传遍每一个组件,就能将值深入传递进组件树。
// 为当前的 theme 创建一个 context(“light”为默认值)。
const ThemeContext = React.createContext('light');
class App extends React.Component {
render() {
// 使用一个 Provider 来将当前的 theme 传递给以下的组件树。
// 无论多深,任何组件都能读取这个值。
// 在这个例子中,我们将 “dark” 作为当前的值传递下去。
return (
<ThemeContext.Provider value="dark">
<Toolbar />
</ThemeContext.Provider>
);
}
}
// 中间的组件再也不必指明往下传递 theme 了。
function Toolbar(props) {
return (
<div>
<ThemedButton />
</div>
);
}
class ThemedButton extends React.Component {
// 指定 contextType 读取当前的 theme context。
// React 会往上找到最近的 theme Provider,然后使用它的值。
// 在这个例子中,当前的 theme 值为 “dark”。
static contextType = ThemeContext;
render() {
return <Button theme={this.context} />;
}
}
二、组合
react中组件重用基本都是用组合。
个人理解:其实就是渲染props中的内容。另一种解决方案是靠继承,不过react官方文档认为组合能解决目前遇到的各种情况。
例:
function Dialog(props) {
return (
<FancyBorder color="blue">
<h1 className="Dialog-title">
{props.title}
</h1>
<p className="Dialog-message">
{props.message}
</p>
</FancyBorder>
);
}
function WelcomeDialog() {
return (
<Dialog
title="Welcome"
message="Thank you for visiting our spacecraft!" />
);
}
拓展:
//父组件
function FancyBorder(props) {
return (
<div className={'FancyBorder FancyBorder-' + props.color}>
{props.children}
</div>
);
}
//爷组件
function WelcomeDialog() {
return (
<FancyBorder color="blue">
<h1 className="Dialog-title">
Welcome
</h1>
<p className="Dialog-message">
Thank you for visiting our spacecraft!
</p>
</FancyBorder>
);
}
/*子组件:
<h1 className="Dialog-title">
Welcome
</h1>
<p className="Dialog-message">
Thank you for visiting our spacecraft!
</p>
在爷组件调用父组件时,将子组件丢入父组件内,react会将子组件传入父组件的props.children
*/
三、render props
一种在 React 组件之间使用一个值为函数的 prop 共享代码的简单技术
个人理解:将高阶组件当做props。在父组件的props传入高阶组件(返回值为组件的函数),然后在父组件中渲染(调用)该props中的高阶组件,且在调用该props时可以传参,参数为高阶组件的实参(如下例中的mouse)。
例:
//子组件
class Cat extends React.Component {
render() {
const mouse = this.props.mouse;
return (
<img src="/cat.jpg" style={{ position: 'absolute', left: mouse.x, top: mouse.y }} />
);
}
}
//父组件
class Mouse extends React.Component {
constructor(props) {
super(props);
this.handleMouseMove = this.handleMouseMove.bind(this);
this.state = { x: 0, y: 0 };
}
handleMouseMove(event) {
this.setState({
x: event.clientX,
y: event.clientY
});
}
render() {
return (
<div style={{ height: '100%' }} onMouseMove={this.handleMouseMove}>
{/*
Instead of providing a static representation of what <Mouse> renders,
use the `render` prop to dynamically determine what to render.
*/}
{this.props.render(this.state)}
</div>
);
}
}
//爷组件
class MouseTracker extends React.Component {
render() {
return (
<div>
<h1>移动鼠标!</h1>
{}/*在父组件的render(props)中传入高阶组件(mouse => (<Cat mouse={mouse}),
返回值为子组件,且Cat组件mouse(props)的值为父组件的this.state
*/}
<Mouse render={mouse => (
<Cat mouse={mouse} />
)}/>
</div>
);
}
}
四、react函数组件防抖+节流
官方文档的示例中只给出了class组件的写法,以下为函数组件写法:
防抖:
//引入防抖方法
import debounce from 'lodash.debounce';
//方法写成 实例方法的形式
const funName = debounce((data) => {
console.log(data)
//other things...
}, 3000)
return(
<div onclick={()=>{funName("我卢本伟没有开挂")}}>click me</div>
)
节流:
//引入节流方法
import throttle from 'lodash.throttle';
//方法写成 实例方法的形式
const funName = throttle((data) => {
console.log(data)
//other things...
}, 3000)
return(
<div onclick={()=>{funName("我卢本伟没有开挂")}}>click me</div>
)