fix: 新增react学习

This commit is contained in:
haishan 2021-11-24 13:30:05 +08:00
parent cf4958e806
commit a7ec84e131

View File

@ -14,14 +14,14 @@ group:
世界知名三大框架之一,我认为热度目前为首吧
### 设计原则
### iPhone 上的秒表
设计组件的几个原则:
1. 保持接口小props 数量要少
2. 根据数据边界划分组件,充分利用组合
3. 把 state 往上层组件提取,让下层组件只需要实现为纯函数
举例iPhone 上的秒表:
```jsx
import React, { useState } from 'react';
@ -40,7 +40,7 @@ const MajorClock = ({ ms = 0 }) => {
return result;
};
return <h1>{ms2Time(ms)}</h1>;
return <h1 style={{ textAlign: 'center', color: 'red' }}>{ms2Time(ms)}</h1>;
};
// 返回所有记次jsx
@ -65,18 +65,41 @@ const ControlButton = ({
['normal', '#aaa'],
]);
const contStyle = {
display: 'flex',
justifyContent: 'space-around',
};
const btnStyle = {
width: '64px',
height: '64px',
lineHeight: '64px',
textAlign: 'center',
fontWeight: '300',
borderRadius: '99px',
border: '3px solid #b4a078',
};
if (activated) {
return (
<div>
<button onClick={onSplit}>计次</button>
<button onClick={onPause}>停止</button>
<div style={contStyle}>
<button style={btnStyle} onClick={onSplit}>
计次
</button>
<button style={btnStyle} onClick={onPause}>
停止
</button>
</div>
);
} else {
return (
<div>
<button onClick={onReset}>复位</button>
<button onClick={onStart}>启动</button>
<div style={contStyle}>
<button style={btnStyle} onClick={onReset}>
复位
</button>
<button style={btnStyle} onClick={onStart}>
启动
</button>
</div>
);
}
@ -89,9 +112,9 @@ export default class StopWatch extends React.Component {
state = {
isStarted: false,
startTime: null,
currentTime: null,
spilts: [],
startTime: 0,
currentTime: 0,
splits: [],
};
render() {
@ -99,6 +122,7 @@ export default class StopWatch extends React.Component {
return (
<React.Fragment>
<h2 style={{ textAlign: 'center', color: 'green' }}>秒表</h2>
<MajorClock ms={currentTime - startTime} />
<ControlButton
activated={isStarted}
@ -139,6 +163,22 @@ export default class StopWatch extends React.Component {
}
```
## 无状态组件PureComponent
为了防止相同的 props 多次渲染,可以通过更改为 PureComponent 来实现(函数组件可以使用 memo ),从而减少性能的浪费
```js
// 类组件
class Demo extends React.PureComponent {
render() {
return <div>我是一个无状态组件</div>;
}
}
// 函数组件
const Demo = React.memo(() => <div>我是一个无状态组件</div>);
```
## 高阶组件HOC
高阶组件的几个原则:
@ -147,28 +187,158 @@ export default class StopWatch extends React.Component {
2. 结果必须是一个新的 React 组件,新组件的 JSX 部分包含作为参数的组件
3. 一般需要把传给自己的 props 转手传递给作为参数的组件
> 一般会带 with 前缀
### 普通用法
```jsx
import React from 'react';
class Demo extends React.Component {
constructor() {
super();
}
const getUserId = () => {
return true;
};
render() {
const { store } = this.props;
return <div>艹 {store}</div>;
}
}
const LoginBtn = () => {
return <div>退出登录</div>;
};
const withFuckU = (Component) => {
const ShoppingCar = () => {
return <div>购物车</div>;
};
const withLogin = (Component) => {
const NewComponent = (props) => {
return <Component {...props} store="fuck you" />;
if (getUserId()) {
return <Component {...props} />;
} else {
return null;
}
};
return NewComponent;
};
export default withFuckU(Demo);
const LoginButton = withLogin(LoginBtn);
const LoginCar = withLogin(ShoppingCar);
export default () => (
<div>
<LoginButton />
<LoginCar />
</div>
);
```
### 高级用法
借鉴上文的 withLogin根据用户是否选择登录渲染合适的组件
```js
const withLoginAndLogout = (ComponentForLogin, ComponentForLogout) => {
const NewComponent = (props) => {
if (getUserId()) {
return <ComponentForLogin {...props} />;
} else {
return <ComponentForLogout {...props} />;
}
};
return NewComponent;
};
const LoginBtn = () => {
return <div>登录</div>;
};
const LogoutBtn = () => {
return <div>退出登录</div>;
};
// 通过条件判断 退出(登录)按钮
const TopButtons = withLoginAndLogout(LogoutBtn, LoginBtn);
```
### 链式调用
```js
// 示例 1
const SuperX = withMethod3(withMethod2(withMethod1(x)));
// 示例 2
const compose = (...funcs) {
if (funcs.length === 0) return arg => arg
if (funcs.length === 1) return funcs[0]
return funcs.reduce((a, b) => (...args) => a(b(...args)))
}
const hoc = compose(withMethod3, withMethod2, withMethod1)
const SuperX = hoc(x)
```
## render props 模式
示例:
```js
const Auth = (props) => {
const userName = getUserName();
if (userName) {
const allProps = { userName, ...props };
return <React.Fragment>{props.login(allProps)}</React.Fragment>;
} else {
<React.Fragment>{props.nologin(props)}</React.Fragment>;
}
};
// 调用
<Auth
login={({ userName }) => <h1>Hello {userName}</h1>}
nologin={() => <h1>Please login</h1>}
/>;
```
## 提供者模式
```jsx
import React from 'react';
const ThemeContext = React.createContext();
const ThemeProvider = ThemeContext.Provider;
const ThemeConsumer = ThemeContext.Consumer;
const Title = (props, context) => {
return (
<ThemeConsumer>
{(theme) => <p style={{ color: theme.textColor }}>{props.children}</p>}
</ThemeConsumer>
);
};
const Paragraph = (props, context) => {
return (
<ThemeConsumer>
{(theme) => <p style={{ color: theme.mainColor }}>{props.children}</p>}
</ThemeConsumer>
);
};
const Page = () => {
return (
<div>
<Title>这是标题</Title>
<Paragraph>这是正文</Paragraph>
</div>
);
};
export default (props, context) => {
return (
<ThemeProvider value={{ mainColor: 'green', textColor: 'red' }}>
<Page />
</ThemeProvider>
);
};
```
## 参考资料