第一节、傻瓜组件 & 聪明组件 区别
1、傻瓜组件也叫展示组件: 负责根据props显示页面信息
2、聪明组件也叫容器组件: 负责数据的获取、处理、组合、下传给展示组件
3、容器组件+展示组件的优势
3.1、逻辑和展示相分离
3.2、提高组件复用性
3.3、提高组件可用性和可阅读性
3.4、便于测试+后续维护
第二节、函数式组件(没有Hook前的)基础使用
1、函数式组件是一种无状态组件,是为了创建纯展示组件,这种组件只根据传入的props来展示,不涉及state状态的操作。
2、组件不会被实例化,整体渲染性能得到提升。
3、组件不能访问this对象。
4、组件无法访问生命周期的方法。
5、无状态组件只能访问传入的props,同样的props会得到同样的渲染结果,不会有副作用。
6、官方:大部分的React代码中,大多数组件被写成无状态组件,通过简单组合构建成其他组件。通过多个简单合并成一个大应用的设计模式被提倡。
7、具体写法如下:
import React from 'react'
export default function Button(props) {
return <div>
<p>函数式组件</p>
<IsLogo isLogo={props.isLogo} btnText={props.btnText}></IsLogo>
</div>
}
// 这种写法直供组件内部使用,不提供给外部
function IsLogo({ isLogo, btnText }) {
let result = <button>{btnText}</button>
if (isLogo) {
result = <button>¥{btnText}</button>
}
return result;
}
第三节、class组件基础使用
1、React.createClass是react刚开始推荐的创建组件写法(es6前),现在基本上看不到了。
2、React.Component是以ES6的形式来创建react组件的,是React目前极为推荐的创建有状态组件的方式
2.1、里面可以写生命周期、状态、构造函数等
2.2、具体展示如下
import React, { Component } from 'React';
export default class ConditionLoop extends Component {
render(){
return <div>
</div>
}
}
3、React Hooks 更为推荐的函数式变成。以后会更多
第四节、高阶组件初体验
1、高阶组件-HOC(Higher-Order Components)。
2、高阶组件是为了提高组件的复用率而出现的,抽离出具有相同逻辑或者相同展示的组件。
3、高阶组件其实是一个函数,接收一个组件作为入参,返回一个新的组件。返回的这个组件可以对属性进行包装,或者重写部分生命周期。
4、高阶组件默认命名规则:以with开头。
// 创建 withLearnReact的高阶组件。传递一个组件进去,返回一个新的组件NewComponent
const withLearnReact = (Comp) => {
const NewComponent = (props) => {
const extendName = "leranReact高阶组件";
return <Comp {...props} name={extendName} />
}
return NewComponent
}
export default withLearnReact(XXX);
5、LearnReact.js
import React, { Component } from 'react'
// 1、使用函数式组件
// function LearnReact(props) {
// return (
// <div>
// <p>{props.title}</p>
// <p>传入的值:{props.name}</p>
// <p>原始的值:learnReact原始组件</p>
// </div>
// )
// }
// const withLearnReact = (Comp) => {
// const NewComponent = (props) => {
// const extendName = "leranReact高阶组件";
// return <Comp {...props} name={extendName} />
// }
// return NewComponent
// }
// 2、使用class组件
class LearnReact extends Component {
render() {
return (
<div>
<p>{this.props.title}</p>
<p>传入的值:{this.props.name}</p>
<p>原始的值:learnReact原始组件</p>
</div>
)
}
}
const withLearnReact = (Comp) => {
class newComponent extends Component {
render() {
const extendName = "learnReact高阶组件";
return <Comp {...this.props} name={extendName}></Comp>
}
}
return newComponent;
}
export default withLearnReact(LearnReact);
App.js
import LearnReact from './hoc/LearnReact';
...
<LearnReact title="高阶组件-标题"></LearnReact>
第五节、高阶组件链式调用
1、使用情况如下:
1.1、编写一个高阶组件属性的添加。
1.2、编写一个高阶组件重写生命周期。
1.3、然后两个高阶组件进行链式调用。
2、Chain.js
import React, { Component } from 'react'
class LearnReact extends Component {
render() {
return (
<div>
<p>{this.props.title}</p>
<p>传入的值:{this.props.name}</p>
<p>原始的值:learnReact原始组件</p>
</div>
)
}
}
const withLearnReact1 = (Comp)=>{
class newCompoent extends Component {
componentDidMount(){
console.log('w1','didMount');
}
render() {
const extendName = "learnReact高阶组件";
return (
<Comp {...this.props} name={extendName}></Comp>
)
}
}
return newCompoent
}
const withLearnReact2 = (Comp)=>{
class newCompoent extends Component {
componentDidMount(){
console.log('w2','didMount');
}
render() {
return (
<Comp {...this.props}></Comp>
)
}
}
return newCompoent
}
export default withLearnReact2(withLearnReact1(LearnReact));
第六节、高阶组件装饰器写法
1、替换链式调用,ES7专门出现这种装饰器的语法,解决链式调用的不美观。(java里面是叫注解)
2、安装支持装饰器语法的babel插件。
2.1、 npm install --save-dev @babel/plugin-proposal-decorators
or yarn add --dev @babel/plugin-proposal-decorators
2.2、更改配置文件根目录下的 config-overrides.js
const { override, fixBabelImports, addBabelPlugin } = require('customize-cra');
module.exports = override(
// 配置antd按需加载
fixBabelImports('import', {
libraryName: 'antd',
libraryDirectory: 'es',
style: 'css',
}),
// 配置支持高阶组件装饰器写法
addBabelPlugin(["@babel/plugin-proposal-decorators", { "legacy": true }])
);
3、Decorator.js
import React, { Component } from 'react'
const withLearnReact2 = (Comp) => {
class newCompoent extends Component {
componentDidMount() {
console.log('WD2', 'didMount');
}
render() {
return (
<Comp {...this.props}></Comp>
)
}
}
return newCompoent
}
const withLearnReact1 = (Comp) => {
class newCompoent extends Component {
componentDidMount() {
console.log('WD1', 'didMount');
}
render() {
const extendName = "learnReact高阶组件";
return (
<Comp {...this.props} name={extendName}></Comp>
)
}
}
return newCompoent
}
@withLearnReact2
@withLearnReact1
class LearnReact extends Component {
render() {
return (
<div>
<p>{this.props.title}</p>
<p>传入的值:{this.props.name}</p>
<p>原始的值:learnReact原始组件</p>
</div>
)
}
}
export default LearnReact;
第七节、高阶组件通信-context
1、vue 中的组件通信中的一种:provide/inject ,这种借鉴于React的context上下文中的2个对象:
1.1、Provider : 提供者。
1.2、Consumer :消费者。
1.3、解决问题就是:多层组件嵌套的props、跨层级使用数据。
2、使用context可以避免通过中间元素传递props,context的设计目的是为了共享对于一个组件树而言的的 “全局数据”。
3、不使用context的代码需要多层使用{...props}。
import React, { Component } from 'react'
const store = {
name: '周芷若',
age: 23,
}
// 不使用context
function Info(props) {
return (
<div>
<p>{props.title}</p>
<p>姓名:{props.name}</p>
<p>年龄:{props.age}</p>
</div>
)
}
function ToolBar(props) {
return (
<Info {...props}></Info>
)
}
export default class UseContext extends Component {
render() {
return (
<div>
<ToolBar {...this.props} name={store.name} age={store.age}></ToolBar>
</div>
)
}
}
4、使用context
4.1写法一
import React, { Component } from 'react'
const store = {
name: '周芷若',
age: 23,
}
// 使用context
const context = React.createContext();
class Info extends Component {
render() {
return (
<context.Consumer>{
store => {
return (
<div>
<p>{store.title}</p>
<p>姓名:{store.name}</p>
<p>年龄:{store.age}</p>
</div>
)
}
}</context.Consumer>
)
}
}
class ToolBar extends Component {
render() {
return (
<Info></Info>
)
}
}
export default class UseContext extends Component {
render() {
return (
<div>
<context.Provider value={store}>
<ToolBar></ToolBar>
</context.Provider>
</div>
)
}
}
\
4.2写法二 + 合并props
import React, { Component } from 'react'
const store = {
name: '周芷若',
age: 23,
}
// 使用context
const { Provider, Consumer } = React.createContext();
class Info extends Component {
render() {
return (
<Consumer>{
store => {
return (
<div>
<p>{store.title}</p>
<p>姓名:{store.name}</p>
<p>年龄:{store.age}</p>
</div>
)
}
}</Consumer>
)
}
}
function ToolBar() {
return <Info />
}
export default class UseContext extends Component {
render() {
return (
<div>
<Provider value={{ ...store, ...this.props }}>
<ToolBar />
</Provider>
</div>
)
}
}