React第二篇class类组件

React第二篇class类组件

在这里插入图片描述

简介:React是facebook(现在叫Meta)出的针对视图层的library库,目前最新版本18X
React官网- 点我去官网
通过这篇文章你会学到以下知识:

  1. 你将会学习到
  2. 如何创建和嵌套组件
  3. 如何添加标签和样式
  4. 如何显示数据
  5. 如何渲染条件和列表
  6. 如何对事件做出响应并更新界面
  7. 如何在组件间共享数据

1、首先我们在HML中使用react

我们需要准备三个东西

babel 作用是代码解析何jsx编译
react 核心库
react-dom 是在浏览器种使用react的必备插件

上面的第三方库 可以到NPM去下载(注意版本)
NPM-点我去NPM官网

2、 class类组件定义

class定义的组件,又叫类组件,这种组件可有自己的局部状态和生命周期
class定义的组件都需要继承自Component或者PereComponent(相当于function定义的组件中为组件添加一个memo缓存效果)

每一个class定义的组件都需要一个render方法,这个方法返回当前组件的html内容
在class定义的组件中,如果改变state数据,需要调用setState方法
setState是异步的,其实它可以接收两个参数
参数一 表示要改变的数据
参数二 表示数据改变之后的回调函数

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>class定义组件</title>
  </head>
  <body>
    <div id="app"></div>
    <script src="./libs/babel.min.js"></script>
    <script src="./libs/react.development.js"></script>
    <script src="./libs/react-dom.development.js"></script>
    <script type="text/babel">
      // 两种方式定义的组件是可以嵌套使用的
      class Counter extends React.Component {
        constructor(props) {
          super(props);
          // 可以通过state属性为组件定义状态数据
          this.state = {
            count: 1,
            name: "这是一个计数器",
          };
        }
       
        render() {
          // 每一次数据或者属性改变的时候这个方法会重新执行
          // console.log("render方法执行了");
          return (
            <>
              <h1>这是一个组件---{this.state.name}</h1>
              <h2>count值为:{this.state.count}</h2>
              <button
                onClick={() => {
                  this.setState(
                    {
                      count: this.state.count + 1,
                    },
                    function () {
                      console.log(this.state.count);
                    }
                  );
                  // console.log(this.state.count);
                }}
              >
                +1
              </button>
            </>
          );
        }
      }
      const App = () => {
        return (
          <>
            <Counter />
          </>
        );
      };

      ReactDOM.render(<App />, document.querySelector("#app"));
    </script>
  </body>
</html>

3、 this指向问题

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8" />
  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  <title>组件传参</title>
</head>

<body>
  <div id="app"></div>
  <script src="./libs/babel.min.js"></script>
  <script src="./libs/react.development.js"></script>
  <script src="./libs/react-dom.development.js"></script>
  <script type="text/babel">
    const { Component } = React;
    class Counter extends Component {
      constructor(props) {
        super(props);
        this.state = {
          count: 1,
        };
        // 在class定义的组件中绑定this的时候,建议使用这种方案
        // this.clickHandle3 = this.clickHandle3.bind(this);
      }
      clickHandle() {
        console.log(this);
      }
      clickHandle2() {
        console.log(this);
      }
      clickHandle3() {
        console.log(this);
      }
      render() {
        return (
          <>
            <h1>当前的计数值为:{this.state.count}</h1>
            <button
              onClick={() => {
                console.log(this);
              }}
            >
              改变
            </button>
            <button onClick={this.clickHandle.bind(this)}>改变2</button>
            <button onClick={() => this.clickHandle2()}>改变3</button>
            <button onClick={this.clickHandle3}>改变4</button>
          </>
        );
      }
    }
    const App = () => {
      return (
        <>
          <Counter></Counter>
        </>
      );
    };

    ReactDOM.render(<App />, document.querySelector("#app"));
  </script>
</body>

</html>

4、 class类组件的组件传参(与function组件传参一样)

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>组件传参</title>
  </head>
  <body>
    <div id="app"></div>
    <script src="./libs/babel.min.js"></script>
    <script src="./libs/react.development.js"></script>
    <script src="./libs/react-dom.development.js"></script>
    <script type="text/babel">
      const context = React.createContext(); // 创建
      class Counter extends React.Component {
        constructor(props) {
          super(props);
          this.state = { count: 1 };
        }
        render() {
          console.log(this.context);
          return (
            <>
              <h1>计数器的值为:{this.state.count}</h1>
              <h3>父组件传过来的步长为:{this.props.step}</h3>
              <p>全局context中的数据为:{this.context.name}</p>
              <button
                onClick={() => {
                  this.props.showNum("998");
                }}
              >
                改变
              </button>
            </>
          );
        }
      }
      Counter.contextType = context; // 只需要为组件设置contextType属性
      const App = () => {
        const [step, gaiBianStep] = React.useState(1);
        const showNum = (num) => {
          alert(num);
        };
        return (
          <>
            <input
              type="range"
              min="1"
              max="10"
              step="1"
              defaultValue={step}
              onChange={(e) => {
                gaiBianStep(e.currentTarget.value * 1);
              }}
            />
            <Counter step={step} showNum={showNum} />
          </>
        );
      };

      ReactDOM.render(
        <context.Provider value={{ name: "我是数据" }}>
          <App />
        </context.Provider>,
        document.querySelector("#app")
      );
    </script>
  </body>
</html>

5、PureComponent(缓存一个组件)

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>PureComponent</title>
  </head>
  <body>
    <div id="app"></div>
    <script src="./libs/babel.min.js"></script>
    <script src="./libs/react.development.js"></script>
    <script src="./libs/react-dom.development.js"></script>
    <script type="text/babel">
      // 在项目中建议使用PureComponent实现组件的继承
      class Item extends React.PureComponent {
        constructor(props) {
          super(props);
        }
        render() {
          console.log("组件渲染了");
          return (
            <>
              <h2>{this.props.name}</h2>
            </>
          );
        }
      }
      const App = () => {
        const [list, setList] = React.useState([]);
        return (
          <>
            <input
              type="text"
              placeholder="请输入内容"
              onKeyUp={(e) => {
                if (e.keyCode === 13 && e.currentTarget.value) {
                  setList([
                    ...list,
                    { id: Date.now(), name: e.currentTarget.value },
                  ]);
                }
              }}
            />
            <hr />
            {list.map((item) => (
              <Item key={item.id} {...item} />
            ))}
          </>
        );
      };

      ReactDOM.render(<App />, document.querySelector("#app"));
    </script>
  </body>
</html>

6、组件的生命周期

  1. constructor----构造器
  2. componentWillMount —将要挂载
  3. componentDidMount —挂在完成
  4. componentWillReceiveProps — 将要接受新的属性
  5. shouldComponentUpdate 是否允许更新
  6. componentWillUpdate— 将要更新
  7. componentDidUpdate —更新完成
  8. componentWillUnmount —销毁
  9. render—渲染

当页面初次渲染是执行顺序:

  1. constructor----构造器
  2. componentWillMount —将要挂载
  3. render—渲染
  4. componentDidMount —挂在完成

当页面更新的是执行顺序:
第一种情况

  1. shouldComponentUpdate 是否允许更新 (返回 true -----是)
  2. componentWillUpdate— 将要更新
  3. render—渲染
  4. componentDidUpdate —更新完成

第二种情况

  1. shouldComponentUpdate 是否允许更新 (返回false -----否) 页面不会在更新

组件之间进行嵌套的时候生命周期钩子函数的执行顺序:

  1. 父组件-constructor----构造器
  2. 父组件-componentWillMount —将要挂载
  3. 父组件-render—渲染
  4. 子组件-constructor----构造器
  5. 子组件-componentWillMount —将要挂载
  6. 子组件- render—渲染
  7. 子组件 componentDidUpdate —更新完成
  8. 父组件componentDidUpdate —更新完成
  9. 总结:先执行父组件的构造器,将要挂载,执行到render的时候,开始解析子组件的生命周期钩子函数,当所有的子组件都挂载完成,在执行父组件的挂载完成

两个注意点:
一、属性或者数据改变的时候render会重新执行, 在render中不能改变数据,会引起死循环
二、 非常重要,主要用来做组件性能优化,
那些不需要在页面中展示的数据改变的时候可以返回false
返回false的时候后续的更新阶段不会再执行
返回true那么后续的更新阶段就会执行
这个方法接收两个参数(下一次的属性, 下一次的状态)
shouldComponentUpdate(nextProps, nextState) {
console.log(“shouldComponentUpdate”);
console.log(nextProps);
console.log(nextState);
return false;
}

在这里插入图片描述

7、refs

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>refs</title>
  </head>
  <body>
    <div id="app"></div>
    <script src="./libs/babel.min.js"></script>
    <script src="./libs/react.development.js"></script>
    <script src="./libs/react-dom.development.js"></script>
    <script type="text/babel">
      class App extends React.Component {
        componentDidMount() {
          console.log((this.refs.ppp.style.color = "red"));
        }
        render() {
          return (
            <>
              <h1>这是一个组件</h1>
              <p ref="ppp">我是一段很长的文字</p>
            </>
          );
        }
      }

      ReactDOM.render(<App />, document.querySelector("#app"));
    </script>
  </body>
</html>

8、练习todolist

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>todo-list</title>
  </head>
  <body>
    <div id="app"></div>
    <script src="./libs/babel.min.js"></script>
    <script src="./libs/react.development.js"></script>
    <script src="./libs/react-dom.development.js"></script>
    <script type="text/babel">
      const { PureComponent } = React;
      class TodoInput extends PureComponent {
        constructor(props) {
          super(props);
          this.saveHandle = this.saveHandle.bind(this);
        }
        saveHandle(e) {
          if (e.keyCode === 13 && e.currentTarget.value) {
            this.props.save(e.currentTarget.value);
            e.currentTarget.value = "";
          }
        }
        render() {
          return <input placeholder="请输入内容" onKeyUp={this.saveHandle} />;
        }
      }
      class Todo extends PureComponent {
        constructor(props) {
          super(props);
        }
        render() {
          return (
            <>
              <h3>{this.props.content}</h3>
              {this.props.isEnd ? null : (
                <button
                  onClick={() => {
                    this.props.end(this.props.id);
                  }}
                >
                  完成
                </button>
              )}
              <button>删除</button>
              <hr />
            </>
          );
        }
      }
      class Todos extends PureComponent {
        constructor(props) {
          super(props);
        }
        render() {
          return (
            <>
              {this.props.list.map((item) => (
                <Todo key={item.id} {...item} end={this.props.end} />
              ))}
            </>
          );
        }
      }
      class TodoList extends PureComponent {
        constructor(props) {
          super(props);
          this.state = {
            list: [],
          };
          this.save = this.save.bind(this);
          this.end = this.end.bind(this);
        }
        save(txt) {
          this.setState({
            list: [
              ...this.state.list,
              { id: Date.now(), content: txt, isEnd: false },
            ],
          });
        }
        end(id) {
          this.setState({
            list: this.state.list.map((item) =>
              item.id == id ? { ...item, isEnd: true } : { ...item }
            ),
          });
        }
        render() {
          return (
            <>
              <TodoInput save={this.save} />
              <hr />
              <Todos list={this.state.list} end={this.end} />
            </>
          );
        }
      }
      const App = () => {
        return (
          <>
            <TodoList />
          </>
        );
      };

      ReactDOM.render(<App />, document.querySelector("#app"));
    </script>
  </body>
</html>

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值