29.9React课程

第02节:react组件化

第2节:02课react组件化

(02课react组件化&)

02课react组件化

初始化显示constructor构造函数,要使用super(),否则没法在内部使用this

React组件化一_API

2与3之间要对组件进行渲染

React组件化一_组件化_02

componentWillReceiverProps父组件传递的属性发生变化时执行

React组件化一_ide_03

React组件化一_组件化_04

接收新的props和新的state

React组件化一_组件化_05

React组件化一_组件化_06

React组件化一_API_07

state发生更新,shouldComponentUpdate才会被激活,接收当前最新的props和state默认返回值是true

执行完render之后执行DidUpdate

React组件化一_组件化_08

React组件化一_ide_09

React组件化一_组件化_10

如果为true返回后面内容,如果为false不展示child要执行willunMount

React组件化一_其他_11

React组件化一_组件化_12

import React, { Component } from "react";

class Child extends React.Component {
  componentWillReceiveProps(nextProps, nextState) {
    // 父组件传递的属性有变化,做相应响应
    console.log(nextProps, nextState, "4.将要接收属性传递");
  }
  componentWillUnmount() {
    // 组件将要卸载, 可做清理工作
    console.log("8.组件将要卸载");
  }
  render() {
    return <div>hello child</div>;
  }
}

export default class Lifecycle extends Component {
  constructor(props) {
    super(props);
    // 常用于初始化状态
    this.state = {
      counter: 0,
      isShow: true
    };
    console.log("1.组件构造函数执行");
  }
  componentWillMount() {
    // 此时可以访问状态和属性,可进行api调用等
    console.log("2.组件将要挂载");
  }
  componentDidMount() {
    // 组件已挂载,可进行状态更新操作
    console.log("3.组件已挂载");
    setTimeout(() => {
      this.setState({
        isShow: false
      });
    }, 3000);
  }
  componentWillReceiveProps(nextProps, nextState) {
    // 父组件传递的属性有变化,做相应响应
    console.log("4.将要接收属性传递");
  }
  shouldComponentUpdate(nextProps, nextState) {
    // 组件是否需要更新,需要返回布尔值结果,优化点
    console.log("5.组件是否需要更新?");
    return true;
  }
  componentWillUpdate() {
    // 组件将要更新,可做更新统计
    console.log("6.组件将要更新");
  }
  componentDidUpdate() {
    // 组件更新
    console.log("7.组件已更新");
  }
  componentWillUnmount() {
    // 组件将要卸载, 可做清理工作
    console.log("8.组件将要卸载");
  }
  add = () => {
    this.setState({
      counter: this.state.counter + 1
    });
  };
  render() {
    console.log("组件渲染");
    return (
      <div onClick={this.add}>
        生命周期探究
        {this.state.isShow && <Child num={this.state.counter} />}
      </div>
    );
  }
}

16.4新版本的API

React组件化一_其他_13

(context实现状态共享&)

context实现状态共享&

React组件化一_react_14

React组件化一_其他_15

创建context,接收一个参数作为context的默认值

React组件化一_ide_16

组件想要使用状态需要用conuser进行包裹,接收参数value就是privider提供的状态

...value以属性展开的方式获取counter值

React组件化一_react_17

React组件化一_API_18

消费provider提供的状态

React组件化一_组件化_19

传递add方法

React组件化一_其他_20

一个值发生了变化其他的值一块变化

React组件化一_其他_21

创建上下文给的默认值,如果没有Provider提供属性值使用默认值

React组件化一_API_22

consumer获取共享状态

React组件化一_其他_23

定义多个组件不会产生冲突

React组件化一_ide_24

child组件可以接收name属性了,相互独立互不影响

consumer接收的都是provider提供的值

React组件化一_API_25

React组件化一_API_26

import React, { Component } from "react";

//创建 Context
const Context = React.createContext({ counter: 0 });
// const Context2 = React.createContext({ name: "davy" });
// const Provider2 = Context2.Provider;
// const Consumer2 = Context2.Consumer;

const { Provider, Consumer } = Context;

//withConsumer是高阶组件工厂,他可以根据配置返回一个高阶组件

//Es5写法
function withConsumer(Consumer) {
  return function(Comp) {
    return function(props) {
      return <Consumer>{value => <Comp {...value} />}</Consumer>;
    };
  };
}

const Child = withConsumer(Consumer)(function(props) {
  return (
    <div
      onClick={() => {
        props.add();
      }}
    >
      {props.counter}
      {props.name}
    </div>
  );
});

// function Child(props) {
//   return (
//     <div
//       onClick={() => {
//         props.add();
//       }}
//     >
//       {props.counter}
//       {props.name}
//     </div>
//   );
// }

class ContextTest extends Component {
  constructor(props) {
    super(props);
    this.state = {
      counter: 0
    };
  }
  add = () => {
    this.setState({
      counter: this.state.counter + 1
    });
  };
  render() {
    return (
      <div>
        <Provider value={{ counter: this.state.counter, add: this.add }}>
          {/* consumer 接收一个函数 当没有provider 会接收context默认值*/}
          <Child />
          {/* <Consumer2>{value => <Child {...value} />}</Consumer2> */}
          <Child />
          <Child />
        </Provider>
      </div>
    );
  }
}

// // <div>
// <div>
//     <Provider2 value={{ name: "han" }}>
//         <div>
//             <Consumer2>{value => <Child {...value} />}</Consumer2>
//         </div>
//     </Provider2>
// </div>
//           </div >
export default ContextTest;

React组件化一_ide_27

(高阶组件&)

高阶组件&

本质是工厂函数,接收组件做为参数返回一个新的组件就是高阶组件

为了提升组件的复用率

React组件化一_其他_28

 

保证Lession产生新组件,传递index索引根据索引,新的组件展示里面的stage和title

接收一个组件Comp,返回一个新的组件props=>{}

使用的时候LessWidthContent传递进idx索引

React组件化一_组件化_29

最后展示reat - 核心API

React组件化一_ide_30

高阶组件变形,容易理解

React组件化一_API_31

React组件化一_ide_32

使用高阶组件保证consumer

React组件化一_API_33

箭头函数演变,接收一个组件,返回一个组件

React组件化一_react_34

React组件化一_ide_35

(链式调用&)

链式调用&

类组件才有生命周期钩子,传入的所有属性以this.props接收展示

组件设计哲学,一定要把一个ui抽象为最小颗粒度去实现,再通过高阶组件拓展

React组件化一_组件化_36

(装饰器写法&)

装饰器写法&

装饰器不支持函数式组件,

React组件化一_API_37

React组件化一_react_38

import React, { Component } from "react";

// Lesson保证功能单一,它不关心数据来源,只负责显示
function Lesson(props) {
  return (
    <div>
      {props.stage} - {props.title}
    </div>
  );
}

// 模拟数据
const lessons = [
  { stage: "React", title: "核心API" },
  { stage: "React", title: "组件化1" },
  { stage: "React", title: "组件化2" }
];

//高阶组件withContent 负责包装这个Lesson
// 包装后的组件具备根据传入的索引,渲染课程

//hoc接收一个组件作为参数,返回一个新的组件

// function withConetnt(Comp) {
//   return function(props) {
//     const content = lessons[props.idx];
//     return <Comp {...content} />;
//   };
// }

const withConetnt = Comp => props => {
  const content = lessons[props.idx];
  return <Comp {...content} />;
};

//高阶组件withlog负责包装传入的组件,具备挂载到Dom上可以输出日志

const withlog = Comp => {
  return class extends React.Component {
    componentDidMount() {
      console.log("has did mount", this.props);
    }
    render() {
      return <Comp {...this.props} />;
    }
  };
};
//包装Lesson
const LessWidthContent = withlog(withConetnt(Lesson));

// @withlog
@withConetnt
class EndTest extends React.Component {
  render() {
    return (
      <div>
        {this.props.stage} - {this.props.title}
      </div>
    );
  }
}

class HocTest extends Component {
  constructor(props) {
    super(props);
    this.state = {};
  }
  render() {
    return <EndTest idx={0} />;
  }
}

export default HocTest;
import React from "react";
// import Lifecycle from "./Lifecycle";
// import ContextTest from "./ContextTest";
import HocTest from "./HocTest.tsx";
import CompositionTest from "./CompositionTest";
import ContextTest2 from "./ContextTest2";

class App extends React.Component {
  render() {
    return (
      <div>
        <h1>hello react</h1>
        {/* 生命周期 */}
        {/* <Lifecycle /> */}
        {/* context 上下文 达到状态共享 */}
        {/* <ContextTest /> */}
        <HocTest />
        {/* <CompositionTest /> */}
        {/* <ContextTest2 /> */}
      </div>
    );
  }
}

export default App;

(组件复合&)

组件复合&

React组件化一_ide_39

组件只赋值展示,内容外部调用的时候传入,props.children也是jsx是一个对象

React组件化一_ide_40

React组件化一_组件化_41

React组件化一_ide_42

作用域插槽,动态传进来的内容不是当前组件作用域而是父组件的作用域,值是内部提供的

()语法糖返回一个对象

props.children变为一个函数可以直接执行,调用来传递参数

通过函数解构出titile和content属性值,并把title和content返回过去

React组件化一_API_43

Dialog接收一个返回过来的title和content

React组件化一_ide_44

调用children函数,children就是Dialog内部的内容,传递什么children就是什么,传递对象props.children就是对象

React组件化一_其他_45

children也可以以属性的方式传递,同时组件内部有内容

React组件化一_ide_46

组件内部props.children优先解析组件内部内容,如果内部没有内容就是test

React组件化一_react_47

React组件化一_API_48

​
import React, { Component } from "react";

// Dialog定义组件外观和行为
function Dialog(props) {
  const messages = {
    foo: { title: "foo", content: "foo~" },
    bar: { title: "bar", content: "bar~" }
  };
  console.log(props.children);
  const { title, content } = props.children(messages[props.msg]);

  return (
    <div style={{ border: "1px solid blue" }}>
      <div>{title}</div>
      <span>---------------</span>
      <div>{content}</div>
    </div>
  );
}
//props.children 什么是Children
//组件的内容部分
class CompositionTest extends Component {
  constructor(props) {
    super(props);
    this.state = {};
  }
  render() {
    return (
      <div>
        <Dialog msg={"bar"} children={"test"}>
          {({ title, content }) => ({
            title: <h1>{title}</h1>,
            content: <p>{content}</p>
          })}

          {/* jsx
          {{
            title: <h1>标题2</h1>,
            content: <p>内容2</p>
          }} */}
        </Dialog>
      </div>
    );
  }
}

export default CompositionTest;

​

(Context API&)

Context API&

React组件化一_其他_49

import React, { Component } from "react";

const Context = React.createContext({ counter: 30 });

class Child extends Component {
  static contextType = Context;
  render() {
    return <div>{this.context.counter}</div>;
  }
}

// Child.contextType = Context;

class ContextTest2 extends Component {
  constructor(props) {
    super(props);
    this.state = {};
  }
  render() {
    return (
      // <Context.Provider value={{ counter: 0 }}>
      //   <Context.Consumer>{value => <Child {...value} />}</Context.Consumer>
      // </Context.Provider>
      <div>
        <Child />
      </div>
    );
  }
}

export default ContextTest2;
import React, { Component } from "react";

// Lesson保证功能单一,它不关心数据来源,只负责显示
function Lesson(props) {
  return (
    <div>
      {props.stage} - {props.title}
    </div>
  );
}

// 模拟数据
const lessons = [
  { stage: "React", title: "核心API" },
  { stage: "React", title: "组件化1" },
  { stage: "React", title: "组件化2" }
];

//高阶组件withContent 负责包装这个Lesson
// 包装后的组件具备根据传入的索引,渲染课程

//hoc接收一个组件作为参数,返回一个新的组件

// function withConetnt(Comp) {
//   return function(props) {
//     const content = lessons[props.idx];
//     return <Comp {...content} />;
//   };
// }

const withConetnt = Comp => props => {
  const content = lessons[props.idx];
  return <Comp {...content} />;
};

//高阶组件withlog负责包装传入的组件,具备挂载到Dom上可以输出日志

const withlog = Comp => {
  return class extends React.Component {
    componentDidMount() {
      console.log("has did mount", this.props);
    }
    render() {
      return <Comp {...this.props} />;
    }
  };
};
//包装Lesson
const LessWidthContent = withlog(withConetnt(Lesson));

// @withlog
@withConetnt
class EndTest extends React.Component {
  render() {
    return (
      <div>
        {this.props.stage} - {this.props.title}
      </div>
    );
  }
}

class HocTest extends Component {
  constructor(props) {
    super(props);
    this.state = {};
  }
  render() {
    return <EndTest idx={0} />;
  }
}

export default HocTest;