class类组件特性

context和contextType

  • context:实现跨层级组件数据传递
  • contextType: 类静态属性,可以不必使用函数就可以消费数据 ```javascript // 创建context上下文提供者 const BatteryContext = createContext();

// 中间的组件 class Middle extends React.Component { render() { return ( ) } } class Leaf extends React.Component { render() { // 消费数据的组件,使用时必须使用.Consumer,并且通过函数调用显示数据 return ( { x =>

context:{x}

} ) } } class App extends React.Component { state = { battery: 20, }; render() { const { battery } = this.state; return ( {/ battery 动态变化 /} ); } }

  1. ```javascript
  2. // 创建context上下文提供者
  3. const BatteryContext = createContext();
  4. // 中间的组件
  5. class Middle extends React.Component {
  6. render() {
  7. return <Leaf />;
  8. }
  9. }
  10. class Leaf extends React.Component {
  11. // 消费数据时更加方便,不必使用函数
  12. // 相当于对上下文提供者 BatteryContext,做了数据接收
  13. static contextType = BatteryContext;
  14. render() {
  15. const battery = this.context;
  16. return <h1>context:{battery}</h1>;
  17. }
  18. }
  19. class App extends React.Component {
  20. state = {
  21. battery: 20,
  22. onLine: false,
  23. };
  24. render() {
  25. const { battery, onLine } = this.state;
  26. return (
  27. <BatteryContext.Provider value={battery}>
  28. {/* battery 动态变化 */}
  29. <button onClick={() => this.setState({ battery: battery + 1 })}>
  30. add
  31. </button>
  32. <Middle />
  33. </BatteryContext.Provider>
  34. );
  35. }
  36. }

lazy和Suspense

  • lazy: 引入组件时,进行懒加载
  • Suspense:在懒加载组件期间,页面内容显示的处理
    1. const About = lazy(() => import("./About.js"));
    2. class App extends React.Component {
    3. render() {
    4. return (
    5. <div>
    6. {/* lazy生成的组件,必须配合 Suspense使用,否则会报错 */}
    7. <Suspense fallback={<div>loading</div>}>
    8. <About></About>
    9. </Suspense>
    10. </div>
    11. );
    12. }
    13. }
    ```javascript import React from “react”;

export default class About extends React.Component { render() { return

about
; } }

  1. <a name="I4tb2"></a>
  2. ### memo
  3. - React.memo 可以对组件进行缓存。进行性能优化;有点类似shouldUpdateComponent或PureComponent的作用。
  4. <a name="TgCMo"></a>
  5. #### 类组件shouldUpdateComponent的使用
  6. ```javascript
  7. class Foo extends React.Component {
  8. shouldComponentUpdate(nextProps, nextState) {
  9. if (nextProps.name === this.props.name) {
  10. // 属性相同,不进行渲染
  11. return false;
  12. }
  13. // 否则进行渲染
  14. return true;
  15. }
  16. render() {
  17. console.log("render");
  18. return <div>Foo</div>;
  19. }
  20. }
  21. class App extends React.Component {
  22. state = {
  23. count: 0,
  24. };
  25. render() {
  26. const { count } = this.state;
  27. return (
  28. <div>
  29. <button onClick={() => this.setState({ count: count + 1 })}>add</button>
  30. <Foo name="foo"></Foo>
  31. </div>
  32. );
  33. }
  34. }

PureComponent的使用

  1. // 只是进行浅比较
  2. class Foo extends PureComponent {
  3. render() {
  4. console.log("render");
  5. return <div>Foo</div>;
  6. }
  7. }

React.memo的使用

  1. function Foo() {
  2. console.log("render");
  3. return <div>Foo</div>;
  4. }
  5. const MemoFoo = React.memo(Foo)
  6. class App extends React.Component {
  7. state = {
  8. count: 0,
  9. };
  10. render() {
  11. const { count } = this.state;
  12. return (
  13. <div>
  14. <button onClick={() => this.setState({ count: count + 1 })}>add</button>
  15. <MemoFoo name="foo"></MemoFoo>
  16. </div>
  17. );
  18. }
  19. }

hooks特性

类组件的不足

hooks的出现,是为了解决类组件中存在的问题,主要有:

  1. 状态逻辑难复用
  2. this的使用问题
  3. 生命周期函数混杂着难以处理的逻辑

为了实现类组件属性的复用,有渲染属性和高阶组件

  1. class Resizable extends React.Component {
  2. state = {
  3. size: [window.innerWidth, window.innerHeight],
  4. };
  5. onSize = () => {
  6. this.setState({ size: [window.innerWidth, window.innerHeight] });
  7. };
  8. componentDidMount() {
  9. window.addEventListener("resize", this.onSize);
  10. }
  11. componentWillUnmount() {
  12. window.removeEventListener("resize", this.onSize);
  13. }
  14. render() {
  15. // 为了解决属性复用,
  16. return this.props.render(this.props.size);
  17. }
  18. }
  19. class Foo extends React.Component {
  20. render() {
  21. const [width, height] = this.props.size;
  22. return (
  23. <div>
  24. {width} X {height}
  25. </div>
  26. );
  27. }
  28. }
  29. // 使用类组件,渲染属性
  30. <Resizable render={(size) => <Foo size={size} />} />;
  1. // 高阶组件
  2. function resizable(Child) {
  3. return class Wrapper extends React.Component {
  4. state = {
  5. size: [window.innerWidth, window.innerHeight],
  6. };
  7. onSize = () => {
  8. this.setState({ size: [window.innerWidth, window.innerHeight] });
  9. };
  10. componentDidMount() {
  11. window.addEventListener("resize", this.onSize);
  12. }
  13. componentWillUnmount() {
  14. window.removeEventListener("resize", this.onSize);
  15. }
  16. render() {
  17. // 为了解决属性复用
  18. const size = this.props.size;
  19. return <Child size={size} />;
  20. }
  21. };
  22. }
  23. class Foo extends React.Component {
  24. render() {
  25. const [width, height] = this.props.size;
  26. return (
  27. <div>
  28. {width} X {height}
  29. </div>
  30. );
  31. }
  32. }
  33. // 包装成高阶组件
  34. const WrapperFoo = resizable(Foo);
  35. // 使用高阶组件
  36. <WrapperFoo />

hooks逻辑复用

  1. function HookResize() {
  2. const size = useSize();
  3. useEffect(() => {
  4. document.title = size.join("x");
  5. });
  6. return (
  7. <div>
  8. {size[0]}x{size[1]}
  9. </div>
  10. );
  11. }
  12. function useSize() {
  13. const [size, setSize] = useState([window.innerWidth, window.innerHeight]);
  14. const onResize = () => {
  15. setSize([window.innerWidth, window.innerHeight]);
  16. };
  17. useEffect(() => {
  18. window.addEventListener("resize", onResize);
  19. return () => {
  20. window.removeEventListener("resize", onResize);
  21. };
  22. });
  23. return size;
  24. }

hooks的优势

  1. 函数组件hooks无this问题
  2. 自定义hook方便复用状态逻辑
  3. 副作用的关注点分离