React学习笔记-汇总

272 阅读4分钟

React 全家桶

React 基础 React-Router PubSub Redux Ant-Design

React 介绍

做什么

React 主要是用来操作 DOM 呈现页面(将数据渲染成 HTML 的开元 JavaScript 库)

谁开发

Facebook

为什么学

  1. 原生 JS 操作 DOM 繁琐且效率低(DOM-API)
  2. 使用 JS 直接操作 DOM,浏览器会打大量的重绘重排
  3. 原生 JS 没有组件化编码方案,代码复用率很低

React 的特点

  1. 采用组件化模式,声明式代码,提高开发效率及组件复用率
  2. 在 React Native 中可以使用 React 语法进行移动端开发
  3. 使用虚拟 DOM+优秀的 diff 算法,尽量减少与真是 DOM 的交互

学习 React 之前要掌握的 JS 基础知识

  1. this
  2. class
  3. ES6
  4. npm
  5. 原型及原型链
  6. 数组常用方法
  7. 模块话

babel

ES6 ---> ES5 JSX ---> JS

React 学习

复习

01-类的基本知识

<!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>01-函数式组件</title>
  </head>
  <body>
    <script type="text/JavaScript">
      /**
       * 总结
       * 1. 类的实例不是必须写的,需要对实例进行一些初始化操作挥着添加属性的属性需要写
       * 2. 如果A类继承了B类,且A类写了构造器,那么A类构造器中 super() 必须要调用
       * 3. 类中所定义的方法,都是放在类的原型对象上,供实例去使用
       */
      class person {
        // 构造器方法
        constructor(name, age) {
          // 构造器中的this-->类的实例对象(也就是谁new的)
          this.name = name;
          this.age = age;
        }
        // 一般方法
        speak() {
          // speak 方法放在了--->类的原型对象上; 供实例使用
          // 通过person实例调用时候,speak的this就是person实例
          console.log("我叫", this.name, "我年龄是", this.age);
        }
      }
      const p1 = new person("小张", 100);
      const p2 = new person("小红", 101);
      console.log(p1);  // person {name: '小张', age: 100}
      console.log(p2);  // person {name: '小红', age: 101}
      console.log(p1.speak()); //我叫 小张 我年龄是 100
      //   创建一个student类继承于person
      class student extends person {
        constructor(name, age, grade) {
          super(name, age);
          this.grade = grade;
        }
        speak() {
          console.log(
            "我叫",
            this.name,
            "我年龄是",
            this.age,
            "我上年纪",
            this.age
          );
        }
        study() {
          // study 方法放在了--->类的原型对象上; 供实例使用
          // 通过 student 实例调用时候, study 的 this 就是 student 实例
        }
      }
      const s1 = new student("小白", 10, "六年级");
      const s2 = new student("小黑", 11, "五年级");
      s1.speak(); // 我叫 小白 我年龄是 10 我上年纪 10
      console.log(s1);  // student {name: '小白', age: 10, grade: '六年级'}
      console.log(s2);  // student {name: '小黑', age: 11, grade: '五年级'}
    </script>
  </body>
</html>

02-原生事件绑定

<!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>Document</title>
  </head>
  <body>
    <button id="btn1">按钮1</button>
    <button id="btn2">按钮2</button>
    <button id="btn3" onclick="demo3()">按钮3</button>
    <script>
      const btn1 = document.getElementById("btn1");
      const btn2 = document.getElementById("btn2");
      const btn3 = document.getElementById("btn3");
      btn1.addEventListener("click", () => {
        alert("点击了按钮1");
      });
      btn2.onclick = () => {
        alert("点击了按钮2");
      };
      function demo3(params) {
        alert("点击了按钮3");
      }
    </script>
  </body>
</html>

03-类中方法 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>Document</title>
  </head>
  <body>
    <script type="text/javascript">
      class person {
        constructor(name, age) {
          this.name = name;
          this.age = age;
        }
        speak() {
          console.log(this);
        }
      }
      const p1 = new person("tom", 18);
      const x = p1.speak;
      x(); // undefined
      p1.speak(); // person {name: 'tom', age: 18}

      //   function demo(params) {
      //     "use strict"; // this就undefined了
      //     console.log(this); // window
      //   }
      //   demo();
    </script>
  </body>
</html>

04-展开运算符

<!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>Document</title>
  </head>

  <body>
    <script>
      let arr1 = [1, 3];
      let arr2 = [2, 4];

      // 应用1:展开数组
      console.log(...arr1); // 1 3

      // 应用2: 连接数组
      let arr3 = [...arr1, ...arr2];
      console.log(arr3); // (4) [1, 3, 2, 4]

      // 应用3: 配合函数使用
      function sum(...numbers) {
        console.log(numbers); // [1]
        let sum = numbers.reduce((pre, cur) => {
          return pre + cur;
        }, 0);
        return sum;
      }
      console.log(sum(1, 2, 3, 4, 5)); // 15

      // 应用4: 构造字面量对象的时候使用展开语法
      let person = { name: "123", value: "456" };
      let person2 = { ...person }; // 这个写法 {...} 是ES6字面量形式,是被允许的
      // console.log(...person2);    // 展开运算符不能展开对象
      console.log(person2); // {name: '123', value: '456'}

      // 应用4: 合并对象
      let person3 = { ...person, address: "999" };
      console.log(person3); // {name: '123', value: '456', address: '999'}
    </script>
  </body>
</html>

05-高阶函数和函数柯里化

<!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>01-函数式组件</title>
  </head>

  <body>
    <!-- 准备好容器 -->
    <div id="test"></div>
    <div id="test1"></div>
    <!-- 引入React核心库. -->
    <script src="../React-js/react.development.js"></script>
    <!-- 引入React-dom,用于支持操作DOM -->
    <script src="../React-js/react-dom.development.js"></script>
    <!-- 引入babel,用于将jsx转为js -->
    <script src="../React-js/babel.min.js"></script>
    <!-- 写这个type的意义是为了让他知道我写的是jsx -->
    <script type="text/babel">
      /**
       * 高阶函数: 如果一个函数符合下面两个规范中的任何一个,那么该函数就是高阶函数
       *      1. 若A函数,接收的参数是一个函数,那么A函数就称为高阶函数
       *      2. 若A函数,调用的返回值依然是一个函数,那么A函数就称为高阶函数
       * 常见的高阶函数
       *      1. Promise    new Promise(()=>{})
       *      2. setTimeout
       *      3. arr.map 等等
       *
       *
       * 函数的柯里化: 通过函数调用继续返回函数的方式,实现多次接收参数最后统一处理的函数编码方式
       */
      // 1. 创建函数式组件
      class MyComponent extends React.Component {
        state = {
          username: "",
          password: "",
        };
        // 提交表单
        handleSubmit = (event) => {
          event.preventDefault(); // 可以阻止表单的默认跳转
          const { username, password } = this.state;
          console.log(username, password);
        };
        // 保存表单项的数据到状态中
        saveFormData = (dataType) => {
          return (event) => {
            this.setState({ [dataType]: event.target.value });
          };
        };
        render() {
          return (
            <form onSubmit={this.handleSubmit}>
              用户名:{" "}
              <input
                onChange={this.saveFormData("username")}
                type="text"
                name="username"
              />
              密码: <input
                onChange={this.saveFormData("password")}
                type="password"
                password="password"
              />
              <button>登录</button>
            </form>
          );
        }
      }
      // 2.渲染组件到页面
      ReactDOM.render(<MyComponent />, document.getElementById("test1"));
    </script>
  </body>
</html>

06-对象相关的知识

<!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>Document</title>
  </head>

  <body>
    <script>
      let a = "name";
      let obj = {};
      obj[a] = a;
    </script>
  </body>
</html>

07-演示函数柯里化

<!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>Document</title>
  </head>

  <body>
    <script>
      // function sum(a, b, c) {
      //     return a + b + c
      // }
      // const result = sum(1, 2, 3)

      // 函数柯里化
      function sum(a) {
        return (b) => {
          return (c) => {
            return a + b + c;
          };
        };
      }
      const result = sum(1)(2)(3);
      console.log(result);
    </script>
  </body>
</html>

React 入门

01-hello_react

demo

<!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>01_hello_react</title>
  </head>
  <body>
    <!-- 准备好容器 -->
    <div id="test"></div>
    <!-- 引入React核心库. -->
    <script src="../React-js/react.development.js"></script>
    <!-- 引入React-dom,用于支持操作DOM -->
    <script src="../React-js/react-dom.development.js"></script>
    <!-- 引入babel,用于将jsx转为js -->
    <script src="../React-js/babel.min.js"></script>
    <!-- 写这个type的意义是为了让他知道我写的是jsx -->
    <script type="text/babel">
      // 1. 创建虚拟dom
      const VDOM = <h1>01_hello_react</h1>; // 此处不写引号,因为是jsx可以混着写
      // 2. 渲染虚拟dom到页面
      ReactDOM.render(VDOM, document.getElementById("test"));
    </script>
  </body>
</html>

02-虚拟 dom 的两种创建方式

2.1-使用 js 创建虚拟 dom

<!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>01_使用js创建虚拟dom</title>
  </head>
  <body>
    <!-- 准备好容器 -->
    <div id="test"></div>
    <!-- 引入React核心库. -->
    <script src="../React-js/react.development.js"></script>
    <!-- 引入React-dom,用于支持操作DOM -->
    <script src="../React-js/react-dom.development.js"></script>
    <!-- 写这个type的意义是为了让他知道我写的是jsx -->
    <script type="text/javascript">
      // 1. 创建虚拟dom (使用这个方法仅限于简单的dom结构)
      const VDOM = React.createElement(
        "h1",
        { id: "title" },
        React.createElement("span", {}, "01_使用js创建虚拟dom")
      );
      // 2. 渲染虚拟dom到页面
      ReactDOM.render(VDOM, document.getElementById("test"));
    </script>
  </body>
</html>

2.2-使用 jsx 创建虚拟 dom

<!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>02_使用jsx创建虚拟dom</title>
  </head>
  <body>
    <!-- 准备好容器 -->
    <div id="test"></div>
    <!-- 引入React核心库. -->
    <script src="../React-js/react.development.js"></script>
    <!-- 引入React-dom,用于支持操作DOM -->
    <script src="../React-js/react-dom.development.js"></script>
    <!-- 引入babel,用于将jsx转为js -->
    <script src="../React-js/babel.min.js"></script>
    <!-- 写这个type的意义是为了让他知道我写的是jsx -->
    <script type="text/babel">
      // 1. 创建虚拟dom
      const VDOM = (
        <h1 id="title">
          <span>02_使用jsx创建虚拟dom</span>
        </h1>
      ); // 此处不写引号,因为是jsx可以混着写
      // 2. 渲染虚拟dom到页面
      ReactDOM.render(VDOM, document.getElementById("test"));
    </script>
  </body>
</html>

2.3-虚拟 DOM 和真实 DOM

<!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>03_虚拟DOM和真实DOM</title>
  </head>
  <body>
    <!-- 准备好容器 -->
    <div id="test"></div>
    <!-- 引入React核心库. -->
    <script src="../React-js/react.development.js"></script>
    <!-- 引入React-dom,用于支持操作DOM -->
    <script src="../React-js/react-dom.development.js"></script>
    <!-- 引入babel,用于将jsx转为js -->
    <script src="../React-js/babel.min.js"></script>
    <!-- 写这个type的意义是为了让他知道我写的是jsx -->
    <script type="text/babel">
      // 1. 创建虚拟dom
      const VDOM = (
        <h1 id="title">
          <span>03_虚拟DOM和真实DOM</span>
        </h1>
      );
      /**
       * 1. VDOM本质就是 Object 对象
       * 2. 虚拟DOM比较轻, 属性很少,虚拟DOM仅仅React内部使用,无需那么多的属性
       * 3. 真实DOM比较重, 属性很多
       * 4. 虚拟DOM最终会被React转为真实dom呈现到页面上
       */
      console.log("虚拟DOM", VDOM); //虚拟DOM Object
      const TDOM = document.getElementById("test");
      console.log("真实DOM", TDOM); //真实DOM <div id="test"></div>
      console.log(VDOM instanceof Object); // true
      // 2. 渲染虚拟dom到页面
      ReactDOM.render(VDOM, TDOM);
    </script>
  </body>
</html>

03-JSX

全名 JavaScript XML

3-1.JSX 语法规则


1. 定义虚拟 dom 的使用不要使用引号
2. 标签重混入 js 表达式的时候要用{}
 一定要区分JS语句和JS表达式
 1. 表达式: 一个表达式会产生一个值,可以放在任何一个需要值的地方
  下面这些是表达式
    1. a
    2. a+b
    3. demo(1)
    4. arr.map()
    5. function test(){}
 2. 语句(代码)
  下面这些是语句(代码)
    1. if(){}
    2. for(){}
    3. switch(){}
3. 样式的类名不要用 class,要用 className
4. 内联样式要用 style={{}} 的形式,并且需要大驼峰 fontSize
5. 只能有一个根标签
6. 标签必须要闭合
7. 标签首字母
   7.1 如果是小写字母开头,则就转为 html 的同名元素,如果没有对应的就会报错
   7.2 如果是大写字母开头,React 就去渲染对应的组件,如果组件没有定义那么就报错
<!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>03_JSX语法规则</title>
    <style>
      .title {
        width: 200px;
        height: 200px;
        background-color: yellow;
      }
    </style>
  </head>
  <body>
    <!-- 准备好容器 -->
    <div id="test"></div>
    <!-- 引入React核心库. -->
    <script src="../React-js/react.development.js"></script>
    <!-- 引入React-dom,用于支持操作DOM -->
    <script src="../React-js/react-dom.development.js"></script>
    <!-- 引入babel,用于将jsx转为js -->
    <script src="../React-js/babel.min.js"></script>
    <!-- 写这个type的意义是为了让他知道我写的是jsx -->
    <script type="text/babel">
      /**
       * JSX语法规则
       * 1. 定义虚拟dom的使用不要使用引号
       *    一定要区分JS语句和JS表达式
       *    1. 表达式: 一个表达式会产生一个值,可以放在任何一个需要值的地方
       *     下面这些是表达式
       *       1. a
       *       2. a+b
       *       3. demo(1)
       *       4. arr.map()
       *       5. function test(){}
       *    2. 语句(代码)
       *     下面这些是语句(代码)
       *       1. if(){}
       *       2. for(){}
       *       3. switch(){}
       * 2. 标签重混入js表达式的时候要用{}
       * 3. 样式的类名不要用class,要用className
       * 4. 内联样式要用 style={{}} 的形式,并且需要大驼峰 fontSize
       * 5. 只能有一个根标签
       * 6. 标签必须要闭合
       * 7. 标签首字母
       *  7.1 如果是小写字母开头,则就转为html的同名元素,如果没有对应的就会报错
       *  7.2 如果是大写字母开头,React就去渲染对应的组件,如果组件没有定义那么就报错
       */
      const id = "id";
      const data = "03_JSX语法规则";
      // 1. 创建虚拟dom
      const VDOM = (
        <div>
          <h1 id={id.toLowerCase()} className="title">
            <span>{data.toLowerCase()}</span>
          </h1>
          <input type="text"></input>
        </div>
      );
      // 2. 渲染虚拟dom到页面
      ReactDOM.render(VDOM, document.getElementById("test"));
    </script>
  </body>
</html>

3-2.jsx 练习

<!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>jsx练习</title>
    <style>
      .title {
        width: 200px;
        height: 200px;
        background-color: yellow;
      }
    </style>
  </head>
  <body>
    <!-- 准备好容器 -->
    <div id="test"></div>
    <!-- 引入React核心库. -->
    <script src="../React-js/react.development.js"></script>
    <!-- 引入React-dom,用于支持操作DOM -->
    <script src="../React-js/react-dom.development.js"></script>
    <!-- 引入babel,用于将jsx转为js -->
    <script src="../React-js/babel.min.js"></script>
    <!-- 写这个type的意义是为了让他知道我写的是jsx -->
    <script type="text/babel">
      /**
       * 一定要区分JS语句和JS表达式
       *  1. 表达式: 一个表达式会产生一个值,可以放在任何一个需要值的地方
       *   下面这些是表达式
       *     1. a
       *     2. a+b
       *     3. demo(1)
       *     4. arr.map()
       *     5. function test(){}
       * 2. 语句(代码)
       *   下面这些是语句(代码)
       *     1. if(){}
       *     2. for(){}
       *     3. switch(){}
       */
      const data = ["angular", "react", "vue"];
      const data2 = data.map((el) => <li key={el}>{el}</li>);
      // 1. 创建虚拟dom
      const VDOM = (
        <div>
          <h1>前端框架</h1>
          <ul>{data2}</ul>
        </div>
      );
      // 2. 渲染虚拟dom到页面
      ReactDOM.render(VDOM, document.getElementById("test"));
    </script>
  </body>
</html>

React 面向组件编程

1-基本理解和使用

1.1-函数式组件

<!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>01-函数式组件</title>
  </head>
  <body>
    <!-- 准备好容器 -->
    <div id="test"></div>
    <!-- 引入React核心库. -->
    <script src="../React-js/react.development.js"></script>
    <!-- 引入React-dom,用于支持操作DOM -->
    <script src="../React-js/react-dom.development.js"></script>
    <!-- 引入babel,用于将jsx转为js -->
    <script src="../React-js/babel.min.js"></script>
    <!-- 写这个type的意义是为了让他知道我写的是jsx -->
    <script type="text/babel">
      // 1. 创建函数式组件
      function MyComponent(params) {
        console.log(this); // undefined ---> 是因为 babel 编译后是严格模式,那么this就不能指向window了,
        return <h2>我是用函数定义的组件(适用于简单组件的定义)</h2>;
      }
      // 2. 渲染组件到页面
      ReactDOM.render(<MyComponent />, document.getElementById("test"));
      /**
       * 执行了 ReactDOM.render(<MyComponent />, document.getElementById("test"));
       * 1. React会解析组件标签,找MyComponent组件
       * 2. 发现组件是函数定义的,那么就调用这个函数,
       * 3. 将返回的虚拟dom转换成真实dom.呈现在页面上
       */
    </script>
  </body>
</html>

1.2-类式组件

<!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>01-函数式组件</title>
  </head>
  <body>
    <!-- 准备好容器 -->
    <div id="test"></div>
    <!-- 引入React核心库. -->
    <script src="../React-js/react.development.js"></script>
    <!-- 引入React-dom,用于支持操作DOM -->
    <script src="../React-js/react-dom.development.js"></script>
    <!-- 引入babel,用于将jsx转为js -->
    <script src="../React-js/babel.min.js"></script>
    <!-- 写这个type的意义是为了让他知道我写的是jsx -->
    <script type="text/babel">
      // 1. 类式组件
      class MyComponent extends React.Component {
        render() {
          // render 方法放在了--->类 MyComponent 的原型对象上; 供实例使用
          // render 的this是谁 ---> MyComponent 的实例对象
          console.log(this); // MyComponent {props: {…}, context: {…}, refs: {…}, updater: {…}, _reactInternalFiber: FiberNode, …}
          return <h1>我是类定义的组件,适用于复杂组件</h1>;
        }
      }
      // 2. 渲染组件到页面
      ReactDOM.render(<MyComponent />, document.getElementById("test"));
      /**
       * 执行了 ReactDOM.render(<MyComponent />, document.getElementById("test"));
       * 1. React会解析组件标签,找MyComponent组件
       * 2. 发现组件是函数定义的,那么就new出来该类的实例,并通过该实例调用到原型的render方法,
       * 3. 将返回的虚拟dom转换成真实dom.呈现在页面上
       */
    </script>
  </body>
</html>

02-state

2.1-state 基础使用

<!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="test"></div>
    <!-- 引入React核心库. -->
    <script src="../React-js/react.development.js"></script>
    <!-- 引入React-dom,用于支持操作DOM -->
    <script src="../React-js/react-dom.development.js"></script>
    <!-- 引入babel,用于将jsx转为js -->
    <script src="../React-js/babel.min.js"></script>
    <!-- 写这个type的意义是为了让他知道我写的是jsx -->
    <script type="text/babel">
      // 1. 创建组件
      class Weather extends React.Component {
        // constructor 构造器执行几次?-->new 几次就会执行几次
        constructor(props) {
          super(props);
          // 初始化状态
          this.state = {
            isHot: true,
            wind: "微风",
          };
          // 这样处理是为了解决静态方法内无法拿到类的this,解决this指向的问题
          this.changeWeather = this.changeWeather.bind(this);
        }
        /**
         * changeWeather放在哪里?---Watcher的原型对象上,供实例使用
         * 由于changeWeather方法作为onClick的回调,所以不是实例调用的而是直接调用的
         * 类中的方法默认开启了严格模式,所以changeWeather里面的this是undefined
         *
         */
        //  changeWeather 执行几次?--->点几次调用几次
        changeWeather() {
          const isHot = this.state.isHot;
          // state里面的状态里面的数据要修改需要使用 setState 方法
          // this.state.isHot = !isHot   // 错误的写法
          this.setState({
            isHot: !isHot,
          });
        }
        // render 执行几次?--> 执行 n+1 次, n 是状态更新的次数,每次 state 更新, render 都会执行
        render() {
          // 读取状态
          const { isHot, wind } = this.state;
          return (
            <div>
              <button onClick={this.changeWeather}>改变天气</button>
              <h1>
                今天的天气好: {isHot ? "热" : "冷"},{wind}
              </h1>
            </div>
          );
        }
      }
      // 2. 渲染组件到页面
      ReactDOM.render(<Weather />, document.getElementById("test"));
    </script>
  </body>
</html>

2.2-state 简写

<!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="test"></div>
    <!-- 引入React核心库. -->
    <script src="../React-js/react.development.js"></script>
    <!-- 引入React-dom,用于支持操作DOM -->
    <script src="../React-js/react-dom.development.js"></script>
    <!-- 引入babel,用于将jsx转为js -->
    <script src="../React-js/babel.min.js"></script>
    <!-- 写这个type的意义是为了让他知道我写的是jsx -->
    <script type="text/babel">
      class Weather extends React.Component {
        // 初始化状态
        state = { isHot: true, wind: "微风" };

        /**
         * 自定义方法:---以后都成 赋值语句的形式+箭头函数
         * this执行就会到了watcher了
         * 这样的写法就是把 changeWeather 放在自身,而不是放在原型函数上
         */
        changeWeather = () => {
          console.log(this); // Weather {props: {…}, context: {…}, refs: {…}, updater: {…}, state: {…}, …}
          const isHot = this.state.isHot;
          this.setState({ isHot: !isHot });
        };
        render() {
          const { isHot, wind } = this.state;
          return (
            <div>
              <h1 onClick={this.changeWeather}>
                今天的天气好: {isHot ? "热" : "冷"},{wind}
              </h1>
            </div>
          );
        }
      }
      // 2. 渲染组件到页面
      ReactDOM.render(<Weather />, document.getElementById("test"));
    </script>
  </body>
</html>

03-props

3.1-props 基本使用

<!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>01-函数式组件</title>
  </head>

  <body>
    <!-- 准备好容器 -->
    <div id="test"></div>
    <!-- 引入React核心库. -->
    <script src="../React-js/react.development.js"></script>
    <!-- 引入React-dom,用于支持操作DOM -->
    <script src="../React-js/react-dom.development.js"></script>
    <!-- 引入babel,用于将jsx转为js -->
    <script src="../React-js/babel.min.js"></script>
    <!-- 写这个type的意义是为了让他知道我写的是jsx -->
    <script type="text/babel">
      // 1. 创建函数式组件
      class MyComponent extends React.Component {
        render() {
          return (
            <ul>
              <li>姓名{this.props.name}</li>
              <li>年龄{this.props.age}</li>
              <li>性别{this.props.sex}</li>
            </ul>
          );
        }
      }
      // 2. 渲染组件到页面
      ReactDOM.render(
        <MyComponent name="tom" age="12" sex="男" />,
        document.getElementById("test")
      );
    </script>
  </body>
</html>

3.2-对 props 进行限制

<!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>01-函数式组件</title>
  </head>

  <body>
    <!-- 准备好容器 -->
    <div id="test"></div>
    <div id="test1"></div>
    <!-- 引入React核心库. -->
    <script src="../React-js/react.development.js"></script>
    <!-- 引入React-dom,用于支持操作DOM -->
    <script src="../React-js/react-dom.development.js"></script>
    <!-- 引入babel,用于将jsx转为js -->
    <script src="../React-js/babel.min.js"></script>
    <!-- 引入prop-types,用于对组件标签属性进行限制 -->
    <script src="../React-js/prop-types.js"></script>

    <!-- 写这个type的意义是为了让他知道我写的是jsx -->
    <script type="text/babel">
      // 1. 创建函数式组件
      class MyComponent extends React.Component {
        // props是只读的
        render() {
          return (
            <ul>
              <li>姓名{this.props.name}</li>
              <li>年龄{this.props.age}</li>
              <li>性别{this.props.sex}</li>
            </ul>
          );
        }
      }
      // 对标签属性进行必要性的限制
      MyComponent.propTypes = {
        name: PropTypes.string.isRequired, // 限制姓名为字符串且必填
        name: PropTypes.string, // 限制必须字符串
        age: PropTypes.number, // 限制必须数字
        speak: PropTypes.func, // 限制必须为函数
      };
      // 指定属性的默认值
      MyComponent.defaultProps = {
        sex: "不男不女",
        age: 18,
      };
      const info = { name: "123", age: 13 };
      ReactDOM.render(
        <MyComponent {...info} speak={speak} />,
        document.getElementById("test1")
      );
      function speak(params) {
        console.log("我说话了");
      }
    </script>
  </body>
</html>

3.3-props 简写

<!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>01-函数式组件</title>
  </head>

  <body>
    <!-- 准备好容器 -->
    <div id="test"></div>
    <div id="test1"></div>
    <!-- 引入React核心库. -->
    <script src="../React-js/react.development.js"></script>
    <!-- 引入React-dom,用于支持操作DOM -->
    <script src="../React-js/react-dom.development.js"></script>
    <!-- 引入babel,用于将jsx转为js -->
    <script src="../React-js/babel.min.js"></script>
    <!-- 引入prop-types,用于对组件标签属性进行限制 -->
    <script src="../React-js/prop-types.js"></script>

    <!-- 写这个type的意义是为了让他知道我写的是jsx -->
    <script type="text/babel">
      // 1. 创建函数式组件
      class MyComponent extends React.Component {
        // 对标签属性进行必要性的限制
        static propTypes = {
          name: PropTypes.string.isRequired, // 限制姓名为字符串且必填
          name: PropTypes.string, // 限制必须字符串
          age: PropTypes.number, // 限制必须数字
          speak: PropTypes.func, // 限制必须为函数
        };
        // 指定属性的默认值
        static defaultProps = {
          sex: "不男不女",
          age: 18,
        };
        // props是只读的
        render() {
          return (
            <ul>
              <li>姓名{this.props.name}</li>
              <li>年龄{this.props.age}</li>
              <li>性别{this.props.sex}</li>
            </ul>
          );
        }
      }

      const info = { name: "123", age: 13 };
      ReactDOM.render(
        <MyComponent {...info} speak={speak} />,
        document.getElementById("test1")
      );
      function speak(params) {
        console.log("我说话了");
      }
    </script>
  </body>
</html>

3.4-props 在构造函数中情况

<!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>01-函数式组件</title>
  </head>

  <body>
    <!-- 准备好容器 -->
    <div id="test"></div>
    <div id="test1"></div>
    <!-- 引入React核心库. -->
    <script src="../React-js/react.development.js"></script>
    <!-- 引入React-dom,用于支持操作DOM -->
    <script src="../React-js/react-dom.development.js"></script>
    <!-- 引入babel,用于将jsx转为js -->
    <script src="../React-js/babel.min.js"></script>
    <!-- 引入prop-types,用于对组件标签属性进行限制 -->
    <script src="../React-js/prop-types.js"></script>

    <!-- 写这个type的意义是为了让他知道我写的是jsx -->
    <script type="text/babel">
      // 1. 创建函数式组件
      class MyComponent extends React.Component {
        // props是只读的
        render() {
          return (
            <ul>
              <li>姓名{this.props.name}</li>
              <li>年龄{this.props.age}</li>
              <li>性别{this.props.sex}</li>
            </ul>
          );
        }
      }
      const info = { name: "123", age: 13 };
      ReactDOM.render(
        <MyComponent {...info} speak={speak} />,
        document.getElementById("test1")
      );
      function speak(params) {
        console.log("我说话了");
      }
    </script>
  </body>
</html>

3.5-props 在函数值组件中使用

<!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>01-函数式组件</title>
  </head>

  <body>
    <!-- 准备好容器 -->
    <div id="test"></div>
    <div id="test1"></div>
    <!-- 引入React核心库. -->
    <script src="../React-js/react.development.js"></script>
    <!-- 引入React-dom,用于支持操作DOM -->
    <script src="../React-js/react-dom.development.js"></script>
    <!-- 引入babel,用于将jsx转为js -->
    <script src="../React-js/babel.min.js"></script>
    <!-- 引入prop-types,用于对组件标签属性进行限制 -->
    <script src="../React-js/prop-types.js"></script>

    <!-- 写这个type的意义是为了让他知道我写的是jsx -->
    <script type="text/babel">
      // 1. 创建函数式组件
      function MyComponent(props) {
        const { name, age, sex } = props;
        return (
          <ul>
            <li>姓名{name}</li>
            <li>年龄{age}</li>
            <li>性别{sex}</li>
          </ul>
        );
      }
      // 对标签属性进行必要性的限制
      MyComponent.propTypes = {
        name: PropTypes.string.isRequired, // 限制姓名为字符串且必填
        name: PropTypes.string, // 限制必须字符串
        age: PropTypes.number, // 限制必须数字
        speak: PropTypes.func, // 限制必须为函数
      };
      // 指定属性的默认值
      MyComponent.defaultProps = {
        sex: "不男不女",
        age: 18,
      };
      const info = { name: "123", age: 13 };
      ReactDOM.render(
        <MyComponent {...info} />,
        document.getElementById("test1")
      );
    </script>
  </body>
</html>

04-refs

4.1-字符串形式 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>01-函数式组件</title>
  </head>

  <body>
    <!-- 准备好容器 -->
    <div id="test"></div>
    <div id="test1"></div>
    <!-- 引入React核心库. -->
    <script src="../React-js/react.development.js"></script>
    <!-- 引入React-dom,用于支持操作DOM -->
    <script src="../React-js/react-dom.development.js"></script>
    <!-- 引入babel,用于将jsx转为js -->
    <script src="../React-js/babel.min.js"></script>
    <!-- 写这个type的意义是为了让他知道我写的是jsx -->
    <script type="text/babel">
      /**
       * 字符串的refs存在效率上的问题,不推荐使用
       */
      // 1. 创建函数式组件
      class MyComponent extends React.Component {
        // 展示左侧输入框的数据
        showData = () => {
          const { input1 } = this.refs;
          let value1 = input1.value;
          console.log(value1);
        };
        // 展示右侧输入框的数据
        showData2 = () => {
          const { input2 } = this.refs;
          let value2 = input2.value;
          console.log(value2);
        };
        render() {
          return (
            <div>
              <input
                ref="input1"
                type="text"
                placeholder="点击按钮提示数据"
              ></input>
              <button onClick={this.showData}>点我提示左侧的数据</button>
              <input
                ref="input2"
                onBlur={this.showData2}
                type="text"
                placeholder="失去焦点提示数据"
              ></input>
            </div>
          );
        }
      }
      // 2.渲染组件到页面
      ReactDOM.render(<MyComponent />, document.getElementById("test1"));
    </script>
  </body>
</html>

4.2-回调形式 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>01-函数式组件</title>
  </head>

  <body>
    <!-- 准备好容器 -->
    <div id="test"></div>
    <div id="test1"></div>
    <!-- 引入React核心库. -->
    <script src="../React-js/react.development.js"></script>
    <!-- 引入React-dom,用于支持操作DOM -->
    <script src="../React-js/react-dom.development.js"></script>
    <!-- 引入babel,用于将jsx转为js -->
    <script src="../React-js/babel.min.js"></script>
    <!-- 写这个type的意义是为了让他知道我写的是jsx -->
    <script type="text/babel">
      /**
       * 字符串的refs存在效率上的问题,不推荐使用
       */
      // 1. 创建函数式组件
      class MyComponent extends React.Component {
        // 展示左侧输入框的数据
        showData = () => {
          const { input1 } = this;
          let value1 = input1.value;
          alert(value1);
        };
        // 展示右侧输入框的数据
        showData2 = () => {
          const { input2 } = this;
          let value2 = input2.value;
          alert(value2);
        };
        render() {
          return (
            <div>
              <input
                ref={(c) => (this.input1 = c)}
                type="text"
                placeholder="点击按钮提示数据"
              ></input>
              <button onClick={this.showData}>点我提示左侧的数据</button>
              <input
                ref={(c) => (this.input2 = c)}
                onBlur={this.showData2}
                type="text"
                placeholder="失去焦点提示数据"
              ></input>
            </div>
          );
        }
      }
      // 2.渲染组件到页面
      ReactDOM.render(<MyComponent />, document.getElementById("test1"));
    </script>
  </body>
</html>

4.3-回调形式 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>01-函数式组件</title>
  </head>

  <body>
    <!-- 准备好容器 -->
    <div id="test"></div>
    <div id="test1"></div>
    <!-- 引入React核心库. -->
    <script src="../React-js/react.development.js"></script>
    <!-- 引入React-dom,用于支持操作DOM -->
    <script src="../React-js/react-dom.development.js"></script>
    <!-- 引入babel,用于将jsx转为js -->
    <script src="../React-js/babel.min.js"></script>
    <!-- 写这个type的意义是为了让他知道我写的是jsx -->
    <script type="text/babel">
      /**
       * 字符串的refs存在效率上的问题,不推荐使用
       */
      // 1. 创建函数式组件
      class MyComponent extends React.Component {
        state = { isHot: true };
        // 展示左侧输入框的数据
        showData = () => {
          const { input1 } = this;
          let value1 = input1.value;
          alert(value1);
        };
        changeWeather = () => {
          const { isHot } = this.state;
          this.setState({
            isHot: !isHot,
          });
        };
        saveInput = (c) => {
          this.input1 = c;
          console.log(c);
        };
        render() {
          const { isHot } = this.state;
          return (
            <div>
              <h2>今天天气很{isHot ? "热" : "冷"}</h2>
              {/*这种写法有个问题,就是更新时候,这个console.log(c)会执行两次,第一次c是null,第二才是这个dom结构*/}
              {/*<input ref={c => { this.input1 = c; console.log(c); }} type="text" placeholder="点击按钮提示数据"></input>*/}

              {/*这种写法是做好的,只会执行一次,但是没必要*/}
              <input
                ref={this.saveInput}
                type="text"
                placeholder="点击按钮提示数据"
              ></input>
              <button onClick={this.showData}>点我提示左侧的数据</button>
              <button onClick={this.changeWeather}>点我切换天气</button>
            </div>
          );
        }
      }
      // 2.渲染组件到页面
      ReactDOM.render(<MyComponent />, document.getElementById("test1"));
    </script>
  </body>
</html>

4.4-createRef 形式 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>01-函数式组件</title>
  </head>

  <body>
    <!-- 准备好容器 -->
    <div id="test"></div>
    <div id="test1"></div>
    <!-- 引入React核心库. -->
    <script src="../React-js/react.development.js"></script>
    <!-- 引入React-dom,用于支持操作DOM -->
    <script src="../React-js/react-dom.development.js"></script>
    <!-- 引入babel,用于将jsx转为js -->
    <script src="../React-js/babel.min.js"></script>
    <!-- 写这个type的意义是为了让他知道我写的是jsx -->
    <script type="text/babel">
      // 1. 创建函数式组件
      class MyComponent extends React.Component {
        /**
         * React.createRef调用后返回䘝容器,该容器可以存储被ref所标识的节点
         * 该容器是专人专用,只能存一个节点
         */
        myRef1 = React.createRef();
        myRef2 = React.createRef();
        // 展示左侧输入框的数据
        showData = () => {
          alert(this.myRef1.current.value);
        };
        // 展示右侧输入框的数据
        showData2 = () => {
          alert(this.myRef2.current.value);
        };
        render() {
          return (
            <div>
              <input
                ref={this.myRef1}
                type="text"
                placeholder="点击按钮提示数据"
              ></input>
              <button onClick={this.showData}>点我提示左侧的数据</button>
              <input
                ref={this.myRef2}
                onBlur={this.showData2}
                type="text"
                placeholder="失去焦点提示数据"
              ></input>
            </div>
          );
        }
      }
      // 2.渲染组件到页面
      ReactDOM.render(<MyComponent />, document.getElementById("test1"));
    </script>
  </body>
</html>

4.5-.事件处理

<!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>01-函数式组件</title>
  </head>

  <body>
    <!-- 准备好容器 -->
    <div id="test"></div>
    <div id="test1"></div>
    <!-- 引入React核心库. -->
    <script src="../React-js/react.development.js"></script>
    <!-- 引入React-dom,用于支持操作DOM -->
    <script src="../React-js/react-dom.development.js"></script>
    <!-- 引入babel,用于将jsx转为js -->
    <script src="../React-js/babel.min.js"></script>
    <!-- 写这个type的意义是为了让他知道我写的是jsx -->
    <script type="text/babel">
      // 1. 创建函数式组件
      class MyComponent extends React.Component {
        /**
         * 1. 通过 onXxx 属性指定事件处理函数(注意大小写)
         *   1.1 React 使用的是自定义(合成)事件,而不是使用的原生DOM的事件 --- 为了更好的兼容性
         *   1.2 React 中的事件是通过事件委托方式处理的(委托给组件的最外层) --- 为了高效
         * 2. 通过 event.target 得到发生事件的 DOM 元素 --- 不要过度使用 ref
         */

        //创建ref容器
        myRef1 = React.createRef();
        // 展示左侧输入框的数据
        showData = () => {
          alert(this.myRef1.current.value);
        };
        // 展示右侧输入框的数据
        showData2 = (event) => {
          alert(event.target.value);
        };
        render() {
          return (
            <div>
              <input
                ref={this.myRef1}
                type="text"
                placeholder="点击按钮提示数据"
              ></input>
              <button onClick={this.showData}>点我提示左侧的数据</button>
              <input
                onBlur={this.showData2}
                type="text"
                placeholder="失去焦点提示数据"
              ></input>
            </div>
          );
        }
      }
      // 2.渲染组件到页面
      ReactDOM.render(<MyComponent />, document.getElementById("test1"));
    </script>
  </body>
</html>

5-React 中收集表单数据

5.1-非受控组件

<!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>01-函数式组件</title>
  </head>

  <body>
    <!-- 准备好容器 -->
    <div id="test"></div>
    <div id="test1"></div>
    <!-- 引入React核心库. -->
    <script src="../React-js/react.development.js"></script>
    <!-- 引入React-dom,用于支持操作DOM -->
    <script src="../React-js/react-dom.development.js"></script>
    <!-- 引入babel,用于将jsx转为js -->
    <script src="../React-js/babel.min.js"></script>
    <!-- 写这个type的意义是为了让他知道我写的是jsx -->
    <script type="text/babel">
      // 1. 创建函数式组件
      class MyComponent extends React.Component {
        handleSubmit = (e) => {
          const { username, password } = this;
          e.preventDefault(); // 可以阻止表单的默认跳转
          console.log(username.value, password.value);
        };
        render() {
          return (
            <form onSubmit={this.handleSubmit}>
              用户名:{" "}
              <input
                ref={(c) => (this.username = c)}
                type="text"
                name="username"
              />
              密码: <input
                ref={(c) => (this.password = c)}
                type="password"
                password="password"
              />
              <button>登录</button>
            </form>
          );
        }
      }
      // 2.渲染组件到页面
      ReactDOM.render(<MyComponent />, document.getElementById("test1"));
    </script>
  </body>
</html>

5.2-受控组件

<!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>01-函数式组件</title>
  </head>

  <body>
    <!-- 准备好容器 -->
    <div id="test"></div>
    <div id="test1"></div>
    <!-- 引入React核心库. -->
    <script src="../React-js/react.development.js"></script>
    <!-- 引入React-dom,用于支持操作DOM -->
    <script src="../React-js/react-dom.development.js"></script>
    <!-- 引入babel,用于将jsx转为js -->
    <script src="../React-js/babel.min.js"></script>
    <!-- 写这个type的意义是为了让他知道我写的是jsx -->
    <script type="text/babel">
      /**
       * 手控组件的好处就是省掉了过多的ref
       */
      // 1. 创建函数式组件
      class MyComponent extends React.Component {
        state = {
          username: "",
          password: "",
        };
        handleSubmit = (e) => {
          e.preventDefault(); // 可以阻止表单的默认跳转
          const { username, password } = this.state;
          console.log(username, password);
        };
        // 保存用户名到state
        changeUsername = (e) => {
          this.setState({ username: e.target.value });
        };
        // 保存密码到state
        changePassword = (e) => {
          this.setState({ password: e.target.value });
        };
        render() {
          return (
            <form onSubmit={this.handleSubmit}>
              用户名:{" "}
              <input
                onChange={this.changeUsername}
                type="text"
                name="username"
              />
              密码: <input
                onChange={this.changePassword}
                type="password"
                password="password"
              />
              <button>登录</button>
            </form>
          );
        }
      }
      // 2.渲染组件到页面
      ReactDOM.render(<MyComponent />, document.getElementById("test1"));
    </script>
  </body>
</html>

6-高阶函数与函数柯里化

6.1-高阶函数和函数柯里化

<!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>01-函数式组件</title>
  </head>

  <body>
    <!-- 准备好容器 -->
    <div id="test"></div>
    <div id="test1"></div>
    <!-- 引入React核心库. -->
    <script src="../React-js/react.development.js"></script>
    <!-- 引入React-dom,用于支持操作DOM -->
    <script src="../React-js/react-dom.development.js"></script>
    <!-- 引入babel,用于将jsx转为js -->
    <script src="../React-js/babel.min.js"></script>
    <!-- 写这个type的意义是为了让他知道我写的是jsx -->
    <script type="text/babel">
      /**
       * 高阶函数: 如果一个函数符合下面两个规范中的任何一个,那么该函数就是高阶函数
       *      1. 若A函数,接收的参数是一个函数,那么A函数就称为高阶函数
       *      2. 若A函数,调用的返回值依然是一个函数,那么A函数就称为高阶函数
       * 常见的高阶函数
       *      1. Promise    new Promise(()=>{})
       *      2. setTimeout
       *      3. arr.map 等等
       *
       *
       * 函数的柯里化: 通过函数调用继续返回函数的方式,实现多次接收参数最后统一处理的函数编码方式
       */
      // 1. 创建函数式组件
      class MyComponent extends React.Component {
        state = {
          username: "",
          password: "",
        };
        // 提交表单
        handleSubmit = (event) => {
          event.preventDefault(); // 可以阻止表单的默认跳转
          const { username, password } = this.state;
          console.log(username, password);
        };
        // 保存表单项的数据到状态中
        saveFormData = (dataType) => {
          return (event) => {
            this.setState({ [dataType]: event.target.value });
          };
        };
        render() {
          return (
            <form onSubmit={this.handleSubmit}>
              用户名:{" "}
              <input
                onChange={this.saveFormData("username")}
                type="text"
                name="username"
              />
              密码: <input
                onChange={this.saveFormData("password")}
                type="password"
                password="password"
              />
              <button>登录</button>
            </form>
          );
        }
      }
      // 2.渲染组件到页面
      ReactDOM.render(<MyComponent />, document.getElementById("test1"));
    </script>
  </body>
</html>

6.2-不用高阶函数和函数柯里化

<!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>01-函数式组件</title>
  </head>

  <body>
    <!-- 准备好容器 -->
    <div id="test"></div>
    <div id="test1"></div>
    <!-- 引入React核心库. -->
    <script src="../React-js/react.development.js"></script>
    <!-- 引入React-dom,用于支持操作DOM -->
    <script src="../React-js/react-dom.development.js"></script>
    <!-- 引入babel,用于将jsx转为js -->
    <script src="../React-js/babel.min.js"></script>
    <!-- 写这个type的意义是为了让他知道我写的是jsx -->
    <script type="text/babel">
      // 1. 创建函数式组件
      class MyComponent extends React.Component {
        state = {
          username: "",
          password: "",
        };
        // 提交表单
        handleSubmit = (event) => {
          event.preventDefault(); // 可以阻止表单的默认跳转
          const { username, password } = this.state;
          console.log(username, password);
        };
        // 保存表单项的数据到状态中
        saveFormData = (dataType, event) => {
          this.setState({ [dataType]: event.target.value });
        };
        render() {
          return (
            <form onSubmit={this.handleSubmit}>
              用户名:{" "}
              <input
                onChange={(event) => {
                  this.saveFormData("username", event);
                }}
                type="text"
                name="username"
              />
              密码: <input
                onChange={(event) => {
                  this.saveFormData("password", event);
                }}
                type="password"
                password="password"
              />
              <button>登录</button>
            </form>
          );
        }
      }
      // 2.渲染组件到页面
      ReactDOM.render(<MyComponent />, document.getElementById("test1"));
    </script>
  </body>
</html>

7-组件的生命周期

7-1.引出生命周期

<!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>01-函数式组件</title>
  </head>

  <body>
    <!-- 准备好容器 -->
    <div id="test"></div>
    <div id="test1"></div>
    <!-- 引入React核心库. -->
    <script src="../React-js/react.development.js"></script>
    <!-- 引入React-dom,用于支持操作DOM -->
    <script src="../React-js/react-dom.development.js"></script>
    <!-- 引入babel,用于将jsx转为js -->
    <script src="../React-js/babel.min.js"></script>
    <!-- 写这个type的意义是为了让他知道我写的是jsx -->
    <script type="text/babel">
      // 生命周期回调函数 === 生命周期钩子函数 === 生周期函数 === 生命周期钩子
      // 1. 创建函数式组件
      class MyComponent extends React.Component {
        state = { opacity: 1 };
        death = () => {
          // 卸载组件
          ReactDOM.unmountComponentAtNode(document.getElementById("test1"));
        };
        // 组件挂在完毕时候调用
        componentDidMount() {
          this.timer = setInterval(() => {
            let { opacity } = this.state;
            opacity -= 0.1;
            if (opacity <= 0) {
              opacity = 1;
            }
            this.setState({ opacity });
          }, 200);
        }
        // 组件将要卸载时候调用
        componentWillUnmount() {
          clearInterval(this.timer);
        }
        // 初始化渲染, 状态更新之后
        render() {
          return (
            <div>
              <h2 style={{ opacity: this.state.opacity }}>
                React学不会怎么办?
              </h2>
              <button onClick={this.death}>不活了!</button>
            </div>
          );
        }
      }
      // 2.渲染组件到页面
      ReactDOM.render(<MyComponent />, document.getElementById("test1"));
    </script>
  </body>
</html>

7-2.生命周期-挂载(旧)

<!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>01-函数式组件</title>
  </head>

  <body>
    <!-- 准备好容器 -->
    <div id="test1"></div>
    <!-- 引入React核心库. -->
    <script src="../React-js/react.development.js"></script>
    <!-- 引入React-dom,用于支持操作DOM -->
    <script src="../React-js/react-dom.development.js"></script>
    <!-- 引入babel,用于将jsx转为js -->
    <script src="../React-js/babel.min.js"></script>
    <!-- 写这个type的意义是为了让他知道我写的是jsx -->
    <script type="text/babel">
      // 生命周期回调函数 === 生命周期钩子函数 === 生周期函数 === 生命周期钩子
      // 1. 创建函数式组件
      class MyComponent extends React.Component {
        // 构造器 (第一步)
        constructor(props) {
          super(props);
          // 初始化状态
          this.state = { count: 0 };
          console.log("挂载 第一步--->constructor");
        }
        death = () => {
          ReactDOM.unmountComponentAtNode(document.getElementById("test1"));
        };
        // 组件将要挂载时候调用 (第二步)
        componentWillMount() {
          console.log("挂载 第二步--->componentWillMount");
        }
        // 初始化渲染, 状态更新之后
        render() {
          console.log("挂载 第三步--->render");
          return (
            <div>
              <h2>当前求和为: {this.state.count}</h2>
              <button onClick={this.death}>卸载组件</button>
            </div>
          );
        }
        // 组件挂载完毕时候调用
        componentDidMount() {
          console.log("挂载 第四步--->componentDidMount");
        }
        // 组件将要卸载时候调用
        componentWillUnmount() {
          console.log("挂载 第五步--->componentWillUnmount");
        }
      }
      // 2.渲染组件到页面
      ReactDOM.render(<MyComponent />, document.getElementById("test1"));
    </script>
  </body>
</html>

7-3.生命周期-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>01-函数式组件</title>
  </head>

  <body>
    <!-- 准备好容器 -->
    <div id="test1"></div>
    <!-- 引入React核心库. -->
    <script src="../React-js/react.development.js"></script>
    <!-- 引入React-dom,用于支持操作DOM -->
    <script src="../React-js/react-dom.development.js"></script>
    <!-- 引入babel,用于将jsx转为js -->
    <script src="../React-js/babel.min.js"></script>
    <!-- 写这个type的意义是为了让他知道我写的是jsx -->
    <script type="text/babel">
      // 生命周期回调函数 === 生命周期钩子函数 === 生周期函数 === 生命周期钩子
      // 1. 创建函数式组件
      class MyComponent extends React.Component {
        // 构造器 (第一步)
        constructor(props) {
          super(props);
          // 初始化状态
          this.state = { count: 0 };
        }
        add = () => {
          const { count } = this.state;
          this.setState({
            count: count + 1,
          });
          console.log("更新 第一步--->setState");
        };
        // 控制组件更新的开关
        shouldComponentUpdate() {
          console.log("更新 第二步--->shouldComponentUpdate");
          return true;
        }
        componentWillUpdate() {
          console.log("更新 第三步--->componentWillUpdate");
        }
        // 初始化渲染, 状态更新之后
        render() {
          console.log("更新 第四步--->render");
          return (
            <div>
              <h2>当前求和为: {this.state.count}</h2>
              <button onClick={this.add}>点我+1</button>
            </div>
          );
        }
        componentDidUpdate() {
          console.log("更新 第五步--->componentDidUpdate");
        }
      }
      // 2.渲染组件到页面
      ReactDOM.render(<MyComponent />, document.getElementById("test1"));
    </script>
  </body>
</html>

7-4.生命周期-forceUpdate 更新(旧)

<!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>01-函数式组件</title>
  </head>

  <body>
    <!-- 准备好容器 -->
    <div id="test1"></div>
    <!-- 引入React核心库. -->
    <script src="../React-js/react.development.js"></script>
    <!-- 引入React-dom,用于支持操作DOM -->
    <script src="../React-js/react-dom.development.js"></script>
    <!-- 引入babel,用于将jsx转为js -->
    <script src="../React-js/babel.min.js"></script>
    <!-- 写这个type的意义是为了让他知道我写的是jsx -->
    <script type="text/babel">
      // 生命周期回调函数 === 生命周期钩子函数 === 生周期函数 === 生命周期钩子
      // 1. 创建函数式组件
      class MyComponent extends React.Component {
        // 构造器 (第一步)
        constructor(props) {
          super(props);
          // 初始化状态
          this.state = { count: 0 };
        }
        // 强制更新按钮(不会走到shouldComponentUpdate)
        force = () => {
          this.forceUpdate();
          console.log("更新 第一步--->forceUpdate");
        };
        componentWillUpdate() {
          console.log("更新 第二步--->componentWillUpdate");
        }
        // 初始化渲染, 状态更新之后
        render() {
          console.log("更新 第三步--->render");
          return (
            <div>
              <h2>当前求和为: {this.state.count}</h2>
              <button onClick={this.force}>不更新数据强制更新页面</button>
            </div>
          );
        }
        componentDidUpdate() {
          console.log("更新 第四步--->componentDidUpdate");
        }
      }
      // 2.渲染组件到页面
      ReactDOM.render(<MyComponent />, document.getElementById("test1"));
    </script>
  </body>
</html>

7-5.生命周期-父组件 render 更新(旧)

<!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>01-函数式组件</title>
  </head>

  <body>
    <!-- 准备好容器 -->
    <div id="test1"></div>
    <!-- 引入React核心库. -->
    <script src="../React-js/react.development.js"></script>
    <!-- 引入React-dom,用于支持操作DOM -->
    <script src="../React-js/react-dom.development.js"></script>
    <!-- 引入babel,用于将jsx转为js -->
    <script src="../React-js/babel.min.js"></script>
    <!-- 写这个type的意义是为了让他知道我写的是jsx -->
    <script type="text/babel">
      // 生命周期回调函数 === 生命周期钩子函数 === 生周期函数 === 生命周期钩子
      // 父组件A
      class A extends React.Component {
        state = { carName: "奔驰" };
        changeCar = () => {
          this.setState({ carName: "奥迪" });
        };
        render() {
          return (
            <div>
              <h1>A</h1>
              <button onClick={this.changeCar}>换车</button>
              <B carName={this.state.carName} />
            </div>
          );
        }
      }
      // 子组件B
      class B extends React.Component {
        // 这个钩子第一次传的不算
        componentWillReceiveProps(props) {
          console.log("子组件更新 第一步--->componentWillReceiveProps");
          console.log(props);
        }
        // 控制组件更新的开关
        shouldComponentUpdate() {
          console.log("子组件更新 第二步--->shouldComponentUpdate");
          return true;
        }
        componentWillUpdate() {
          console.log("子组件更新 第三步--->componentWillUpdate");
        }
        render() {
          console.log("子组件更新 第四步--->render");
          return <div>B -- {this.props.carName}</div>;
        }
        componentDidUpdate() {
          console.log("子组件更新 第五步--->componentDidUpdate");
        }
      }
      // 2.渲染组件到页面
      ReactDOM.render(<A />, document.getElementById("test1"));
    </script>
  </body>
</html>

7-6.生命周期总结(旧)

/**
  * 常用:
  *      1. componentDidMount() 一般做一些初始化的事儿,例如开始定制器或者发送网络请求或者订阅消息
  *      2. componentWillUnmount() 一般做一些收尾的事儿,例如取消定时器
  *
  * 1. 初始化阶段: 由 ReactDOM.render() 触发---初次渲染
  *      1. constructor()
  *      2. componentWillMount()
  *      3. render()
  *      4. componentDidMount()
  * 2. 更新阶段: 由组件内部 setState() 或者父组件 render() 触发
  *      1. shouldComponentUpdate()
  *      2. componentWillUpdate()
  *      3. render()
  *      4. componentDidMount()
  * 3. 更新阶段: 由组件内部 forceUpdate() 触发
  *      1. componentWillUpdate()
  *      2. render()
  *      3. componentDidMount()
  * 4. 父组件Props更新: 由父组件Props更新导致子组件更新
  *      1. componentWillReceiveProps()
  *      2. shouldComponentUpdate()
  *      3. componentWillUpdate()
  *      4. render()
  *      5. componentDidMount()
  * 5. 卸载组件: 由 ReactDOM.unmountComponentAtNode() 触发
  *      1. componentWillUnmount()
  */
<!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>01-函数式组件</title>
  </head>

  <body>
    <!-- 准备好容器 -->
    <div id="test1"></div>
    <!-- 引入React核心库. -->
    <script src="../React-js/react.development.js"></script>
    <!-- 引入React-dom,用于支持操作DOM -->
    <script src="../React-js/react-dom.development.js"></script>
    <!-- 引入babel,用于将jsx转为js -->
    <script src="../React-js/babel.min.js"></script>
    <!-- 写这个type的意义是为了让他知道我写的是jsx -->
    <script type="text/babel">
      // 生命周期回调函数 === 生命周期钩子函数 === 生周期函数 === 生命周期钩子
      // 1. 创建函数式组件
      class MyComponent extends React.Component {
        // 构造器 (第一步)
        constructor(props) {
          super(props);
          // 初始化状态
          this.state = { count: 0 };
          console.log("挂载 第一步--->constructor");
        }
        death = () => {
          ReactDOM.unmountComponentAtNode(document.getElementById("test1"));
        };
        // 组件将要挂载时候调用 (第二步)
        componentWillMount() {
          console.log("挂载 第二步--->componentWillMount");
        }
        // 初始化渲染, 状态更新之后
        render() {
          console.log("挂载 第三步--->render");
          return (
            <div>
              <h2>当前求和为: {this.state.count}</h2>
              <button onClick={this.death}>卸载组件</button>
            </div>
          );
        }
        // 组件挂载完毕时候调用
        componentDidMount() {
          console.log("挂载 第四步--->componentDidMount");
        }
        // 组件将要卸载时候调用
        componentWillUnmount() {
          console.log("挂载 第五步--->componentWillUnmount");
        }
      }
      // 2.渲染组件到页面
      ReactDOM.render(<MyComponent />, document.getElementById("test1"));
    </script>
  </body>
</html>

props

props

props

props

props

props

props

props

props

props

props

props

props

props

props

props

props

props

props

props

props

props

props

props

props

props

props

props

props

props

props

props

props

props

props

props