React(三)

戳这里

一.受控元素(组件)

一个标签(组件)受react中控制,受数据,受函数,等等(其实,就是一个标签(组件)里用了react里的东西)

表单的value受控,受数据控制,

<input type="text" value={this.state.数据名}  /> //model 控制 view。
<input type="text" onChange={this.方法} />   //view 控制 model

1.1双向绑定

 class Books extends React.Component {
      constructor(props) {
        super();
        this.state = {
          username: "",
          sex: "女",
          hobby: ["打羽毛球"],
          profession: "计算机科学与技术",
        };
      }
      //  文本框: 修改用户名
      changeName = (ev) => {
        this.setState({
          username: ev.target.value,
        });
      };
      // 单选按钮
      changeSex = (ev) => {
        this.setState({
          sex: ev.target.value,
        });
      };
      // 复选框
      changeHobby = (ev) => {
        let arr;
        if (ev.target.checked) {
          // 当选中复选框时,则将选中的数据添加到数组中
          // 添加到数组中
          arr = [...this.state.hobby, ev.target.value];
        } else {
          // 删除
          let index = this.state.hobby.indexOf(ev.target.value);
          arr = this.state.hobby;
          arr.splice(index, 1);
        }
        this.setState({
          hobby: arr,
        });
      };
      // 下拉框
      changeProfession = (ev) => {
        this.setState({
          profession: ev.target.value,
        });
      };
      render() {
        return (
          <div>
            {/*react中的onChange事件就是在用户输入的同时,就会被触发,相当于原生中的input*/}
            用户名:
            <input
              type="text"
              value={this.state.username}
              onChange={this.changeName}
            />
            <br />
            性别:
            <label htmlFor="nv">
              <input
                type="radio"
                name="sex"
                id="nv"
                value="女"
                checked={this.state.sex == "女"}
                onChange={this.changeSex}
              />
              女
            </label>
            <label htmlFor="nan">
              <input
                type="radio"
                name="sex"
                id="nan"
                value="男"
                checked={this.state.sex == "男"}
                onChange={this.changeSex}
              />
              男
            </label>
            <br />
            请选择你的爱好: <br />
            <input
              type="checkbox"
              value="singing"
              checked={this.state.hobby.indexOf("singing") != -1}
              onChange={this.changeHobby}
            />
            singing
            <input
              type="checkbox"
              value="打羽毛球"
              checked={this.state.hobby.indexOf("打羽毛球") != -1}
              onChange={this.changeHobby}
            />
            打羽毛球
            <input
              type="checkbox"
              value="舞蹈"
              checked={this.state.hobby.indexOf("舞蹈") != -1}
              onChange={this.changeHobby}
            />
            舞蹈
            <input
              type="checkbox"
              value="篮球"
              checked={this.state.hobby.indexOf("篮球") != -1}
              onChange={this.changeHobby}
            />
            篮球
            <br />
            请选择您的专业:
            <select
              value={this.state.profession}
              onChange={this.changeProfession}
            >
              <option value="网络工程">网络工程</option>
              <option value="计算机科学与技术">计算机科学与技术</option>
              <option value="数学与应用数学">数学与应用数学</option>
            </select>
          </div>
        );
      }
    }
    ReactDOM.render(
      <div>
        <Books />
      </div>,
      document.getElementById("app")
    );

在这里插入图片描述

1.2 处理多个输入元素(双向绑定的封装)

可以为每个元素添加一个 name 属性(通常和数据名一致),处理函数根据 event.target.name 的值来选择要做什么

 class Books extends React.Component {
      constructor(props) {
        super();
        this.state = {
          username: "",
          sex: "女",
          hobby: ["打羽毛球"],
          profession: "计算机科学与技术",
        };
      }
      // 封装文本框,单选框,下拉框的双向绑定
     changeVal=(ev)=>{
       this.setState({
         [ev.target.name]:ev.target.value
       })
     }
      render() {
        return (
          <div>
          
          用户名:
            <input
              type="text" name="username"
              value={this.state.username}
              onChange={this.changeVal}
            />
            <br />
            性别:
            <label htmlFor="nv">
              <input
                type="radio"
                name="sex"
                id="nv"
                value="女"
                checked={this.state.sex == "女"}
                onChange={this.changeVal}
              />
              女
            </label>
            <label htmlFor="nan">
              <input
                type="radio"
                name="sex"
                id="nan"
                value="男"
                checked={this.state.sex == "男"}
                onChange={this.changeVal}
              />
              男
            </label>
            <br />
            请选择您的专业:
            <select
              value={this.state.profession}
              onChange={this.changeVal}
              name="profession"
            >
              <option value="网络工程">网络工程</option>
              <option value="计算机科学与技术">计算机科学与技术</option>
              <option value="数学与应用数学">数学与应用数学</option>
            </select><br />
           </div>
        );
      }
    }
    ReactDOM.render(
      <div>
        <Books />
      </div>,
      document.getElementById("app")
    );

在这里插入图片描述

二. 非受控元素(组件)

​ 要编写一个非受控组件,而不是为每个状态更新都编写数据处理函数,你可以 使用 ref 来从 DOM 节点中获取表单数据

<input type="text" value="哈哈"  ref="xx" />

2.1默认值

​ 表单元素上的 value 将会覆盖 DOM 节点中的值,在非受控组件中,你经常希望 React 能赋予组件一个初始值,但是不去控制后续的更新,指定一个 defaultValue 属性,而不是 value

2.2可选案例:增删改查

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
    <style>
      table {
        width: 800px;
        margin: 20px auto;
        background-color: #ccc;
        border-collapse: collapse;
      }
      th {
        background-color: green;
      }
      tr {
        text-align: center;
        height: 30px;
      }
      th,
      td {
        vertical-align: middle;
      }
      input[type="button"] {
        outline: none;
        margin-right: 5px;
      }
      .addBox {
        position: fixed;
        margin: auto;
        top: 0;
        left: 0;
        right: 0;
        bottom: 0;
        width: 300px;
        height: 200px;
        background-color: #f5f5f5;
        border: 1px solid #999;
        padding: 10px 20px;
      }
      .addBox input {
        margin-bottom: 10px;
        outline: none;
      }
    </style>
  </head>
  <body>
    <div id="app"></div>
  </body>
  <script src="./js/react.js"></script>
  <script src="./js/react-dom.js"></script>
  <script src="./js/babel.min.js"></script>
  <script src="./js/prop-types.js"></script>

  <script type="text/babel">
    // 学生管理系统
    class Students extends React.Component {
      constructor(props) {
        super();
        this.state = {
          isShowAddBox: "none",
          users: [
            {
              id: "01001",
              username: "张三疯",
              profession: "计算机科学与技术",
              faculty: "数学与计算机应用学院",
              classes: "1803班",
            },
            {
              id: "01002",
              username: "李四",
              profession: "统计专业",
              faculty: "数计院",
              classes: "1702班",
            },
            {
              id: "01003",
              username: "王五",
              profession: "思政",
              faculty: "马克思主义学院",
              classes: "1603班",
            },
            {
              id: "01004",
              username: "语文",
              profession: "电科",
              faculty: "电信院",
              classes: "1603班",
            },
          ],
          newUser: {
            id: "",
            username: "",
            profession: "",
            faculty: "",
            classes: "",
          },
        };
      }
      // 显示添加窗口
      showAddBox = () => {
        this.setState({
          isShowAddBox: this.state.isShowAddBox == "block" ? "none" : "block",
        });
      };
      //添加里面的数据实现双向绑定
      changeVal = (ev) => {
        let obj = { ...this.state.newUser, [ev.target.name]: ev.target.value };
        this.setState({
          newUser: obj,
        });
      };
      // 保存按钮,将表单中的数据添加到表格中,并清空内容
      addSave = () => {
        this.state.users.push(this.state.newUser);
        this.setState({
          isShowAddBox: "none",
          newUser: {
            id: "",
            username: "",
            profession: "",
            faculty: "",
            classes: "",
          },
        });
      };
      render() {
        return (
          <div>
            <input type="button" value="添加" onClick={this.showAddBox} />
            <table border="1">
              <thead>
                <tr>
                  <th>学号</th>
                  <th>姓名</th>
                  <th>学院</th>
                  <th>专业</th>
                  <th>班级</th>
                  <th>操作</th>
                </tr>
              </thead>
              <tbody>
                {this.state.users.map((user, index) => (
                  <tr key={index}>
                    <td>{user.id}</td>
                    <td>{user.username}</td>
                    <td>{user.faculty}</td>
                    <td>{user.profession}</td>
                    <td>{user.classes}</td>
                    <td>
                      <input type="button" value="修改" />
                      <input type="button" value="删除" />
                    </td>
                  </tr>
                ))}
              </tbody>
            </table>

            <div
              className="addBox"
              style={{ display: this.state.isShowAddBox }}
            >
              学号:
              <input
                type="text"
                value={this.state.newUser.id}
                name="id"
                onChange={this.changeVal}
              />
              <br />
              姓名:
              <input type="text" 
              value={this.state.newUser.username}
                name="username"
                onChange={this.changeVal}/>
              <br />
              学院:
              <input type="text" 
              value={this.state.newUser.faculty}
                name="faculty"
                onChange={this.changeVal}/>
              <br />
              专业:
              <input type="text" 
              value={this.state.newUser.profession}
                name="profession"
                onChange={this.changeVal}/>
              <br />
              班级:
              <input type="text" 
              value={this.state.newUser.classes}
                name="classes"
                onChange={this.changeVal}/>
              <br />
              <input type="button" value="保存" onClick={this.addSave} />
              <input type="button" value="取消" onClick={this.showAddBox}/>
            </div>
          </div>
        );
      }
    }
    ReactDOM.render(
      <div>
        <Students></Students>
      </div>,
      document.getElementById("app")
    );
  </script>
</html>

在这里插入图片描述在这里插入图片描述
在这里插入图片描述
小括号错写成大括号,找了好几个小时,还是换人换马~

三.生命周期及其钩子函数

react组件生命周期经历的阶段:初始化阶段 -----> 运行阶段(更新期)-----> 销毁阶段

3 .1 初始化阶段 (挂载):

(在这个阶段完成了vue中数据挂载和模板渲染)

组件实例被创建并插入 DOM 中时,其生命周期钩子函数的调用顺序如下:

1)、constructor:构造函数里,可以做状态的初始化,接收props的传值

2)、componentWillMount: 在渲染前调用,相当于vue中的beforeMount

3)、render:渲染函数,不要在这里修改数据。 vue中也有render函数。

4)、componentDidMount :相当于vue中的 mounted

​ 渲染完毕,在第一次渲染后调用。之后组件已经生成了对应的DOM结构, 如果你想和其他JavaScript框架(swiper)一起使用,可以在这个方法中使用,包括调用setTimeout, setInterval或者发送AJAX请求等操作,相当于vue的mounted

 class Students extends React.Component {
      constructor(props) {
        super();
        this.state = {
          name: "皮卡丘",
        };
        console.log("constructor");
      }
      componentWillMount() {
        console.log("componentWillMount");
      }

      componentDidMount() {
        console.log("componentDidMount");
      }
      render() {
        console.log("render");
        return <div></div>;
      }
    }

    ReactDOM.render(
      <div>
        <Students></Students>
      </div>,
      document.getElementById("app")
    );

在这里插入图片描述

3.2运行中阶段(更新)

(相当于vue中更新阶段)

当组件的 props 或 state 发生变化时会触发更新(严谨的说,是只要调用了setState()或者改变了props时)。组件更新的生命周期调用顺序如下:

1)、shouldComponentUpdate(nextProps, nextState) 是否更新? 需要返回true或者false。如果是false,那么组件就不会继续更新了。

2)、componentWillUpdate,即将更新。相当于vue中的 beforeUpdate

3)、 componentWillReceiveProps(nextProps): 在组件接收到一个新的 prop (更新后)时被调用。这个方法在初始化render时不会被调用。nextProps 是props的新值,而 this.props是旧值。

4)、render

​ 不要在这里修改数据

5)、componentDidUpdate

在组件完成更新后立即调用。在初始化时不会被调用。 相当于vue中的updated

3.3 销毁阶段(卸载)

componentWillUnmount()

即将卸载,可以做一些组件相关的清理工作,例如取消计时器、网络请求等。

注意:

父更新则子更新,子更新父不更新

   class Parent extends React.Component {
      constructor(props) {
        super();
        this.state = {
          name: "张三疯",
        };
        console.log("Parent======constructor");
      }
      //   首次渲染前
      componentWillMount() {
        console.log("Parent======componentWillMount");
      }
      // 首次渲染后
      componentDidMount() {
        console.log("Parent======componentDidMount");
      }
      // 组件更新前
      componentWillUpdate() {
        console.log("Parent======componentWillUpdate");
      }
    //   组件更新后
      componentDidUpdate() {
        console.log("Parent======componentDidUpdate");
      }
      changeName = () => {
        this.setState({
          name: "hahhah",
        });
      };
      render() {
        console.log("Parent======render");
        return (
          <div>
            <h1>父组件</h1>
            <p>{this.state.name}</p>
            <input type="button" value="父组件修改姓名" onClick={this.changeName} />
            <Son />
          </div>
        );
      }
    }
    class Son extends React.Component {
      constructor(props) {
        super();
        console.log("Son======constructor");
      }
      //   首次渲染前
      componentWillMount() {
        console.log("Son======componentWillMount");
      }
      // 首次渲染后
      componentDidMount() {
        console.log("Son======componentDidMount");
      }
      // 组件更新前
      componentWillUpdate() {
        console.log("Son======componentWillUpdate");
      }
    //   组件更新后
      componentDidUpdate() {
        console.log("Son======componentDidUpdate");
      }
           changeName = () => {
        this.setState({
        });
      };
      render() {
        console.log("Son======render");
        return <div>
            <input type="button" value="子组件修改姓名" onClick={this.changeName} /></div>;
      }
    }
    ReactDOM.render(
      <div>
        <Parent />
      </div>,
      document.getElementById("app")
    );

在这里插入图片描述
在这里插入图片描述

react17,不建议使用的钩子函数(面试过程中有问到):

UNSAFE_componentWillMount 不建议用,可以会出现bug,不能初始化因为会受到React16.xFiber的协调算法,函数会执行多次,如果把异步请求放到该钩子函数中,异步请求可能也会执行多次。
UNSAFE_componentWillReceiveProps
UNSAFE_componentWillUpdate

在这里插入图片描述
今天的blog写的有点不满意。。。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值