【React一】React基础+组件化编程【ref+props+state】

对照代码查看笔记: 代码详情

  • 有详细的ReadMe文档
  • 欢迎star+fork到自己的仓库
  • 后续将进行todolist案例的详细讲解:vue2,vue3,react

react基础,React-Router,pubsub,redux,ant-design

一、 React基础+组件化编程

  • 发送请求获取数据
  • 处理数据(过滤、整理格式)
  • 操作DOM呈现页面

是一个将数据渲染为HTML视图的开源JavaScript库;由Facebook开发,且开源

  • JS操作DOM繁琐、效率低(DOM-API操作UI)

  • 大量重排重绘

  • 复用率低,要用组件化

1-1 基础

1-1-1 react简介

1-1-1-1 react创建虚拟DOM

组件化+声明式编码

虚拟DOM+diffing算法

react native中使用React语法进行移动端开发

  1. 相关js库

    • react.js:React核心库。
  • react-dom.js:提供操作DOM的react扩展库。
    • babel.min.js:
    • 解析JSX语法代码转为JS代码的库。
      • ES6==> ES5
  1. 创建虚拟DOM的方式

    • 方法一: 原生

    image-20220928165230912

     <script type="text/babel">
            // 1. 创建虚拟DOM
            // const VDOM = <h1>Hello,React</h1>
            const VDOM = React.createElement('h1',{id: 'title'},React.createElement('span',{},'Hello,React'))
            // 2. 渲染虚拟DOM到页面
            ReactDOM.render(VDOM,document.getElementById('test'))
        </script>
    
    • 方法二:jsx【后续介绍,见1-1-2】
1-1-1-2 虚拟DOM与真实DOM
  1. image-20220928171456452

  2. React提供了一些API来创建一种 “特别” 的一般js对象

    const VDOM = React createElement('xx',{id: 'xx'},'xx')

    • 上面创建的就是一个简单的虚拟DOM对象

    • 虚拟DOM对象最终都会被React转换为真实的DOM

    • 我们编码时基本只需要操作react的虚拟DOM相关数据, react会转换为真实DOM变化而更新界面

  3. 关于虚拟DOM:

    • 本质是Object类型的对象(一般对象)
    • 虚拟DOM比较“轻”,真实DOM比较“重”,因为虚拟DOM是React内部在用,无需真实DOM上那么多的属性
    • 虚拟DOM最终会被React转化为真实DOM,呈现在页面上

1-1-2 JSX

1-1-2-1 语法规则【摘自word】
  1. 全称: JavaScript XML

  2. react定义的一种类似于XML的JS扩展语法:

    • JS + XML本质是React.createElement(component, props, ...children)方法的语法糖

    • XML早期用于存储和传输数据

  3. 作用: 用来简化创建虚拟DOM

  4. 写法:var ele = <h1>Hello JSX!</h1>

    • 注意1:它不是字符串, 也不是HTML/XML标签
    • 注意2:它最终产生的就是一个JS对象
    • 标签名任意: HTML标签或其它标签
  5. 标签属性任意: HTML标签属性或其它

  6. 基本语法规则

    • 遇到 <开头的代码, 以标签的语法解析: html同名标签转换为html同名元素, 其它标签需要特别解析
    • 遇到以 { 开头的代码,以JS语法解析: 标签中的js表达式必须用{ }包含
  7. babel.js的作用

    • 浏览器不能直接解析JSX代码, 需要babel转译为纯JS的代码才能运行
    • 只要用了JSX,都要加上type=“text/babel”, 声明需要babel来处理
1-1-2-2 渲染虚拟DOM(元素)
  1. 语法: ReactDOM.render(virtualDOM, containerDOM)

  2. 作用: 将虚拟DOM元素渲染到页面中的真实容器DOM中显示

  3. 参数说明

    • 参数一: 纯js或jsx创建的虚拟dom对象
    • 参数二: 用来包含虚拟DOM元素的真实dom元素对象(一般是一个div)
1-1-2-3 JSX语法规则
    • 定义虚拟DOM时,不要写引号
    • 标签中混入JS表达式要用{}
      • 区分【JS语句(代码)】与【js表达式】
      • 表达式: 一个表达式会产生一个值,可以放在任何一个需要值的地方
        • 下面这些都是表达式
          • a
          • a+b
          • demo(1)
          • arr.map()
          • function test () {}
      • 语句(代码):
        • 下面这些都是语句(代码):
          • if(){}
          • for(){}
          • switch(){}
    • 样式的类名指定不要用class,要用className
    • 内联样式,要用style={{key:value}}的形式去写
    • 只有一个根标签
    • 标签必须闭合
    • 标签首字母
      • 若小写字母开头,则将标签诸位内html中同名元素,若html中无该标签对应的 同名元素,则报错
      • 若大写字母开头,react就去渲染对应的组件,若组件没有定义,则报错
  1. 例子

需要下载react,react-dom,及babel包,代码已上传至Gitee,可翻阅文件夹查看对应代码

在这里插入图片描述


<!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>
    <div id="test"></div>
    <script type="text/javascript" src="./js/react.development.js"></script>
    <script type="text/javascript" src="./js/react-dom.development.js"></script>
    <script type="text/javascript" src="./js/babel.min.js"></script>

    <script type="text/babel">
      const data = ["Angular", "React", "vue"];
      //  const obj = {name1:'Angular', name2: 'React', name3: 'Vue'}
      //
      const VDOM = (
        <div>
          <h1>前端js框架列表</h1>
          <ul>
            {data.map((item, index) => {
              return <li key={index}>{item}</li>;
            })}
          </ul>
        </div>
      );

      // 2. 渲染虚拟DOM到页面
      ReactDOM.render(VDOM, document.getElementById("test"));
    </script>
  </body>
</html>

1-1-2-4 列表例子
  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>Document</title>
  </head>
  <body>
    <div id="test"></div>
    <script type="text/javascript" src="./js/react.development.js"></script>
    <script type="text/javascript" src="./js/react-dom.development.js"></script>
    <script type="text/javascript" src="./js/babel.min.js"></script>

    <script type="text/babel">
      const data = ["Angular", "React", "vue"];
      //  const obj = {name1:'Angular', name2: 'React', name3: 'Vue'}
      //
      const VDOM = (
        <div>
          <h1>前端js框架列表</h1>
          <ul>
            {data.map((item, index) => {
              return <li key={index}>{item}</li>;
            })}
          </ul>
        </div>
      );

      // 2. 渲染虚拟DOM到页面
      ReactDOM.render(VDOM, document.getElementById("test"));
    </script>
  </body>
</html>

    • 给React一个数组能显示,给React一个对象不能显示

1-1- 3 模块与组件

  1. js模块

    • 理解:向外提供特定功能的js程序, 一般就是一个js文件
    • 为什么要拆成模块:随着业务逻辑增加,代码越来越多且复杂。
    • 作用:复用js, 简化js的编写, 提高js运行效率
  2. 组件

    • 理解:用来实现局部功能效果的代码和资源的集合(html/css/js/image等等)
    • 为什么要用组件: 一个界面的功能更复杂
    • 作用:复用编码, 简化项目编码, 提高运行效率
  3. 模块化

    • 当应用的js都以模块来编写的, 这个应用就是一个模块化的应用
  4. 组件化

    • 当应用是以多组件的方式实现, 这个应用就是一个组件化的应用

1-2 React面向组件化编程

1-2-1

1-2-1-1 函数式和类式组件
  1. 函数式组件

    • ReactDOM.render(<Demo/>,document.getElementById('test')), 执行了ReactDOM.render(<MyComponent/>)…之后,发生了什么)

    • React解析组件标签,找到了MyComponent组件

    • 发现组件时使用函数定义的,随后调用该函数,将返回的虚拟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>Document</title>
 </head>
 <body>
   <!-- 准备好一个容器 -->
   <div id="test"></div>

   <script type="text/javascript" src="../../js/react.development.js"></script>
   <script
     type="text/javascript"
     src="../../js/react-dom.development.js"
   ></script>
   <script type="text/javascript" src="../../js/babel.min.js"></script>

   <script type="text/babel">
     // 1. 创建函数式组件
     function Demo() {
       console.log(this); // 此处的this是undefined,因为babel编译后开启了严格模式
       return <h2>我是用函数定义的组件(适用于【简单组件】的定义)</h2>;
     }
     // 2. 渲染组件到页面
     /*  ReactDOM.render(<Demo/>,document.getElementById('test'))
   执行了ReactDOM.render(<MyComponent/>.....之后,发生了什么) 
   1. React解析组件标签,找到了MyComponent组件
   2. 发现组件时使用函数定义的,随后调用该函数,将返回的虚拟DOM转为真实DOM,随后呈现在页面中*/
     ReactDOM.render(<Demo />, document.getElementById("test"));
   </script>
 </body>
</html>
  1. 类式组件

    • 必须继承自component
    • 必须有render()
       class MyComponent extends React.Component {
          render() {
            // render是放在MyComponent的原型对象上,供实例使用
            return <h2>我是用类定义的组件(适用于【复杂组件】的定义)</h2>
          }
        }
    
        // 2. 渲染组件到页面
        ReactDOM.render(<MyComponent/>,document.getElementById('test'))
    
    
  2. 执行了ReactDOM.render(<MyConponent/>,document.getElementById('test'))之后

    • React解析组件标签,找到了MyComponent组件

    • 发现组件时使用类定义的,随后new出来该类的实例,并通过该实例调用到原型上的render方法

    • 将render返回的虚拟DOM转为真实DOM,随后呈现在页面中

  3. render :

    • render是放在哪里?

      • MyComponent的原型对象上,供实例使用
    • render中的this是谁?

      • MyComponent的实例对象

      image-20220930201119335

1-2-1-2 渲染类组件标签的基本流程
  1. React内部会创建组件实例对象

  2. 调用render()得到虚拟DOM, 并解析为真实DOM

  3. 插入到指定的页面元素内部

1-2-2 组件实例的三大属性

  • class
  • hooks玩三大属性
1-2-2-1 state

创建组件时必须写构造器

  • 可以初始化状态
  • 可以解决changeWeather中的this指向问题
1-2-2-1-1 对state的理解
  1. state是组件对象最重要的属性, 值是对象(可以包含多个key-value的组合)

  2. 组件被称为"状态机", 通过更新组件的state来更新对应的页面显示(重新渲染组件)

  3. 严重注意:状态(state)不可直接更改,下面这行就是直接更改!

    • this.state.isHot = !isHot // 错误的写法

    • 严重注意:状态必须通过setState进行更新,且更新是一种合并,不是替换

    this.setState({ isHot: !isHot });

1-2-2-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>Document</title>
  </head>
  <body>
    <div id="test"></div>
    <script
      type="text/javascript"
      src="../../../js/react.development.js"
    ></script>
    <script
      type="text/javascript"
      src="../../../js/react-dom.development.js"
    ></script>

    <script type="text/javascript" src="../../../js/babel.min.js"></script>

    <script type="text/babel">
      let that;
      // 1. 创建组件
      class Weather extends React.Component {
        // 构造器调用几次?    ---- 1次
        constructor(props) {
          super(props);
          this.state = { isHot: true, wind: "微风" };
          // this.changeWeather = this.changeWeather.bind(this);
        }

        // render调用几次?    =----- 1+n次,1是初始化的那次,n是状态更新的次数
        render() {
          // 读取状态
          // console.log(this);
          // 解构赋值
          const { isHot } = this.state;
          return (
            <h1 id="title" onClick={this.changeWeather}>
              今天天气{isHot ? "炎热" : "凉爽"}
            </h1>
          );
          // demo():直接写小括号就调用了函数
        }
        // change..调用几次,点几次调用几次
        // 创建组件时,加了小括号导致函数调用
        changeWeather() {
          // changeWeather放在哪里? ----Weather的原型对象上,供实例使用
          // 通过Weather实例调用changeWeather时,changeWeather中的this就是Weather实例。由于changeWeather是作为onClick的回调,所以不是通过实例调用的,是直接调用的
          // 类中的方法默认开启了局部的严格模式,所以changeWeather中的this为undefined,否则就是window,babel禁止自定义的this指向window
          console.log(this);
          // 获取原来的isHot值
          const isHot = this.state.isHot;
          // 严重注意:状态(state)不可直接更改,下面这行就是直接更改!
          // this.state.isHot = !isHot    // 错误的写法
          // 严重注意:状态必须通过setState进行更新,且更新是一种合并,不是替换
          this.setState({ isHot: !isHot });
        }
      }
      // 2. 渲染组件到页面
      ReactDOM.render(<Weather />, document.getElementById("test"));
    </script>
  </body>
</html>

   
1-2-2-1-3 类中方法this的指向
  1. <script>
        class Person {
            constructor(name, age) {
                this.name = name
                this.age = age
            }
            speak() {
                console.log(this)
            }
        }
        
        const p1 = new Person('tom',19)
        p1.study()    // 通过实例调用study方法
        const x = p1.study
        x()     // 开启严格模式:undefined;未开启严格模式:window
    </script>
    
  2. 类中所有方法都在局部开启了严格模式

    function demo() {
      'user strict'
       console.log(this)
    }
    function demo1() {
        console.log(this)
    }
    
    demo()   // undefined
    demo1()    // window
    
1-2-2-1-4 setState的使用
// 严重注意:状态(state)不可直接更改,下面这行就是直接更改!
     // this.state.isHot = !isHot    // 错误的写法
// 严重注意:状态必须通过setState进行更新,且更新是一种合并,不是替换
     this.setState({ isHot: !isHot });
1-2-2-1-5 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>Document</title>
  </head>
  <body>
    <div id="test"></div>
    <script
      type="text/javascript"
      src="../../../js/react.development.js"
    ></script>
    <script
      type="text/javascript"
      src="../../../js/react-dom.development.js"
    ></script>

    <script type="text/javascript" src="../../../js/babel.min.js"></script>

    <script type="text/babel">
      // 1. 创建组件
      class Weather extends React.Component {
        // 初始化状态
        state = { isHot: false, wind: "微风" };

        render() {
          const { isHot, wind } = this.state;
          return (
            <h1 onClick={this.changeWeather}>
              今天天气{isHot ? "炎热" : "凉爽"},{wind}
            </h1>
          );
        }
        // 箭头函数没有this,自定义方法----要用赋值语句的+箭头函数
        changeWeather = () => {
          const isHot = this.state.isHot;
          this.setState({ isHot: !isHot });
        };
      }
      // 2. 渲染组件到页面
      ReactDOM.render(<Weather />, document.getElementById("test"));
    </script>
  </body>
</html>

1-2-2-1-6 总结state
    • state 是对象最重要的属性,值是对象(可以包含多个key-value的组合)
    • 组件被称为”状态机“,通过更新组件的state来更新对应的页面显示(重新渲染组件)
  1. !!!

    • 组件render方法中的this为组件实例对象
    • 组件自定义的方法中this为undefines,如何解决?
      • 强制绑定this:通过函数对象的bind()
      • 箭头函数
    • 状态数据,不能直接修改或更新
1-2-2-2 props

-----------类式-----------

1-2-2-2-1 效果
  1. 需求:自定义用来显示一个人员信息的组件

    • 姓名必须指定,且为字符串类型
    • 性别为字符串类型,如果性别没有指定,默认为男3
    • 年龄为字符串类型,且为数字类型,默认值为18img
    • 每个组件对象都会有props(properties的简写)属性
    • 组件标签的所有属性都保存在props中
1-2-2-2-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>Document</title>
  </head>
  <body>
    <div id="test"></div>
    <div id="test2"></div>
    <div id="test3"></div>
    <script
      type="text/javascript"
      src="../../../js/react.development.js"
    ></script>
    <script
      type="text/javascript"
      src="../../../js/react-dom.development.js"
    ></script>

    <script type="text/javascript" src="../../../js/babel.min.js"></script>

    <script type="text/babel">
      // 创建组件
      class Person extends React.Component {
        render() {
          const { name, age, sex } = this.props;
          
          return (
            <ul>
              <li>姓名:{name}</li>
              <li>性别: {sex}</li>
              <li>年龄: {age}</li>
            </ul>
          );
        }
      }

      // 渲染组件到页面
      ReactDOM.render(
        <Person name="jerry" age="18" sex="女" />,
        document.getElementById("test")
      );
      ReactDOM.render(
        <Person name="tom" age="18" sex="女" />,
        document.getElementById("test2")
      );

      const p = { name: "老刘", age: 18, sex: "女" };
      // console.log({ ...p });
      ReactDOM.render(<Person {...p} />, document.getElementById("test3"));
    </script>
  </body>
</html>
   
1-2-2-2-3 对props进行限制
  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>Document</title>
  </head>
  <body>
    <div id="test"></div>
    <div id="test2"></div>
    <div id="test3"></div>
    <script
      type="text/javascript"
      src="../../../js/react.development.js"
    ></script>
    <script
      type="text/javascript"
      src="../../../js/react-dom.development.js"
    ></script>
    <script type="text/javascript" src="../../../js/prop-types.js"></script>

    <script type="text/javascript" src="../../../js/babel.min.js"></script>

    <script type="text/babel">
      // 创建组件
      class Person extends React.Component {
        render() {
          const { name, age, sex } = this.props;
          return (
            <ul>
              <li>姓名:{name}</li>
              <li>性别: {sex}</li>
              <li>年龄: {age + 1}</li>
            </ul>
          );
        }
      }

      // 对标签属性进行类型、必要性的限制
      Person.propTypes = {
        // name: React.PropTypes.string
        name: PropTypes.string.isRequired,
        sex: PropTypes.string,
        age: PropTypes.number,
        speak: PropTypes.func,
      };
      Person.defaultProps = {
        sex: "不男不女",
        age: 18,
      };

      // 渲染组件到页面
      ReactDOM.render(
        <Person name="jerry" age="18" sex="女" />,
        document.getElementById("test")
      );
      ReactDOM.render(
        <Person name="tom" age={18} sex="女" />,
        document.getElementById("test2")
      );

      const p = { name: "老刘", age: 18, sex: "女" };
      // console.log({ ...p });
      // 对象没有Iterator接口,不是js的内置对象,只有标签上可以使用
      ReactDOM.render(<Person {...p} />, document.getElementById("test3"));
    </script>
  </body>
</html>

1-2-2-2-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>Document</title>
  </head>
  <body>
    <div id="test"></div>
    <div id="test2"></div>
    <div id="test3"></div>
    <script
      type="text/javascript"
      src="../../../js/react.development.js"
    ></script>
    <script
      type="text/javascript"
      src="../../../js/react-dom.development.js"
    ></script>
    <script type="text/javascript" src="../../../js/prop-types.js"></script>

    <script type="text/javascript" src="../../../js/babel.min.js"></script>

    <script type="text/babel">
      // 创建组件
      class Person extends React.Component {
        // 属性
        static propTypes = {
          // name: React.PropTypes.string
          name: PropTypes.string.isRequired,
          sex: PropTypes.string,
          age: PropTypes.number,
          speak: PropTypes.func,
        };
        static defaultProps = {
          sex: "不男不女",
          age: 18,
        };

        render() {
          const { name, age, sex } = this.props;
          // props是只读的,读出来不能改动
          // this.props.name = "jack"; // 此行代码会报错
          return (
            <ul>
              <li>姓名:{name}</li>
              <li>性别: {sex}</li>
              <li>年龄: {age + 1}</li>
            </ul>
          );
        }
      }

      // 对标签属性进行类型、必要性的限制
      // 指定默认值
      ReactDOM.render(
        // 渲染组件到页面
        <Person name="jerry" age="18" sex="女" />,
        document.getElementById("test")
      );
      ReactDOM.render(
        <Person name="tom" age={18} sex="女" />,
        document.getElementById("test2")
      );

      const p = { name: "老刘", age: 18, sex: "女" };
      // console.log({ ...p });
      // 对象没有Iterator接口,不是js的内置对象,只有标签上可以使用
      ReactDOM.render(<Person {...p} />, document.getElementById("test3"));
    </script>
  </body>
</html>

--------------函数式-------------------------------

1-2-2-2-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>Document</title>
</head>
<body>
  <div id="test1">
    
  </div>
  <div id="test2">
    
  </div>
  <div id="test3">
    
  </div>
  <script type="text/javascript" src="../day1/js/react.development.js"></script>
  <script type="text/javascript" src="../day1/js/react-dom.development.js"></script>
  
  <script type="text/javascript" src="../day1/js/babel.min.js"></script>

  <script type="text/babel">
    function Person (props) {
      console.log(props);
      const {name, age, sex }= props
      return (
        <ul>
          <li>姓名:{name}</li>
          <li>性别: 女</li>
          <li>年龄: 18</li>
        </ul>
      )
    }

    Person.propTypes = {
      name: PropTypes.string.isRequired,
      sex: PropTypes.string,
      age: PropTypes.number, 
    }

    Person.defaultProps = {
      sex: '难',
      age: 18
    }

    // 渲染组件到页面
    ReactDOM.render(<Person name="jerry" sex="女"/>,document.getElementById('test1'))
  </script>
</body>
</html>
1-2-2-3 ref
1-2-2-3-1 ref
    • 字符串形式的ref【不推荐】

      <input ref="input1">

    • 回调形式的ref

      <input ref={(c)=>{this.input1 = c}}>

  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>Document</title>
  </head>
  <body>
    <div id="test"></div>
    <div id="test2"></div>
    <div id="test3"></div>
    <script
      type="text/javascript"
      src="../../../js/react.development.js"
    ></script>
    <script
      type="text/javascript"
      src="../../../js/react-dom.development.js"
    ></script>

    <script type="text/javascript" src="../../../js/babel.min.js"></script>

    <script type="text/babel">
      // 创建组件
      class Demo extends React.Component {
        // 展示左侧输入框的数据
        showData = () => {
          // const input = document.getElementById("input1");
          // alert(input.value);
          console.log(this.refs.input1);
          // debugger;
        };
        // 展示右侧输入框的数据
        showData2 = () => {
          const { input1 } = this.refs;
          alert(input1.value);
        };
        render() {
          return (
            <div>
              <input
                ref="input1"
                id="input1"
                type="text"
                placeholder="点击按钮提示数据"
              />
              <button onClick={this.showData}>点我提示左侧数据</button>
              <input
                onBlur={this.showData2}
                type="text"
                placeholder="失去焦点提示数据"
              />
            </div>
          );
        }
      }
      // 渲染组件到页面
      ReactDOM.render(<Demo />, document.getElementById("test"));
    </script>
  </body>
</html>
  • 回调形式
<!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>
    <div id="test"></div>
    <div id="test2"></div>
    <div id="test3"></div>
    <script
      type="text/javascript"
      src="../../../js/react.development.js"
    ></script>
    <script
      type="text/javascript"
      src="../../../js/react-dom.development.js"
    ></script>

    <script type="text/javascript" src="../../../js/babel.min.js"></script>

    <script type="text/babel">
      // 创建组件
      class Demo extends React.Component {
        // 展示左侧输入框的数据
        showData = () => {
          const { input1 } = this;
          alert(input1.value);
        };
        // 展示右侧输入框的数据
        showData2 = () => {
          const { input2 } = this;
          alert(input2.value);
        };
        render() {
          return (
            <div>
              <input
                ref={(currentNode) => {
                  this.input1 = currentNode;
                }}
                type="text"
                placeholder="点击按钮提示数据"
              />
              <button onClick={this.showData}>点我提示左侧数据</button>
              <input
                type="text"
                onBlur={this.showData2}
                ref={(c) => (this.input2 = c)}
                placeholder="失去焦点提示数据"
              />
            </div>
          );
        }
      }
      // 渲染组件到页面
      ReactDOM.render(<Demo a="1" b="2" />, document.getElementById("test"));
    </script>
  </body>
</html>

  1. 回调函数的ref
    • string的类型存在效率问题,已经过时会在未来版本移除
      -内联的回调和函数式的回调: 关于回调函数形式ref中回调次数的问题
  2. JSX的注释:{/*你好你好*/}
1-2-2-3-2
    • 通过onXxx属性指定事件处理函数(注意大小写)

    • a.React使用的是自定义(合成)事件,而不是使用的原生DOM事件-----为了更好的兼容性

    • b.React中的事件是通过事件委托方式处理的(委托给组件最外层的元素)—为了效

  1. 通过event.target得到发生事件的DOM元素对象—不要过度使用ref

1-2-2-3-4 createRef的使用

最主流的写法

  1. React.createRef调用后可以返回一个容器,该容器可以存储被ref所标识的节点
  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>Document</title>
  </head>
  <body>
    <div id="test"></div>
    <div id="test2"></div>
    <div id="test3"></div>
    <script
      type="text/javascript"
      src="../../../js/react.development.js"
    ></script>
    <script
      type="text/javascript"
      src="../../../js/react-dom.development.js"
    ></script>

    <script type="text/javascript" src="../../../js/babel.min.js"></script>

    <script type="text/babel">
      // 创建组件
      class Demo extends React.Component {
        // React.createRef调用后可以返回一个容器,该容器可以存储被ref所标识的节点
        // 专人专用
        myRef = React.createRef();
        myRef2 = React.createRef();
        // 展示左侧输入框的数据
        showDate = () => {
          console.log(this.myRef.current.value);
          console.log(this.myRef);
        };
        showData2 = () => {
          alert(this.myRef2.current.value);
          alert(this.myRef2);
        };
        render() {
          return (
            <div>
              {/*直接把ref所在的节点存储在容器里面*/}
              <input type="text" ref={this.myRef} />
              <button onClick={this.showDate}>点我提示左侧的数据</button>
              <input type="text" ref={this.myRef2} onBlur={this.showData2} />
            </div>
          );
        }
      }

      ReactDOM.render(<Demo />, document.getElementById("test"));
    </script>
  </body>
</html>

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值