React 1.0


# 概述

也是单页面应用 (spa),public 下只有一个 index.html,也是数据驱动视图,也是虚拟 dom
React 是一个将数据渲染为 HTML 视图的开源 JavaScript 库 (只 关注于视图 ),是 Facebook 开发的

# 为什么要学

  1. 原生 JavaScript 操作 DOM 繁琐, 效率低
  2. 使用 JavaScript 直接操作 DOM,浏览器会进行大量的 重绘重排
  3. 原生 Javascript 没有 组件化 编码方案,代码复用率低下

# React 特点

  1. 采用 组件化模式 , 声明式编码 ,提高开发效率及组件复用率
  2. 在 React Native (可以让前端人员通过 js 去编写 Android 和 ios 的一门技术) 中可以使用 React 语法 进行移动端开发
  3. 使用 虚拟 DOM 和优秀的 Diff 算法 ,尽量减少与真实 DOM 的交互

# hello_react 案例

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <title>hello_react</title>
  </head>
  <body>
    <!-- 准备好一个“容器” -->
    <div id="test"></div>

    <!-- 引入react核心库 -->
    <script src="../js/react.development.js"></script>
    <!-- 引入react-dom,用于支持react操作DOM -->
    <script src="../js/react-dom.development.js"></script>
    <!-- 引入babel,用于将jsx转为js -->
    <script src="../js/babel.min.js"></script>

    <script type="text/babel">
      /* 此处一定要写babel,将jsx通过babel转换为js */
      /* 不写默认是js */
      //1.创建虚拟DOM
      const VDOM = <h1>Hello,React</h1>;
      /* 此处一定不要写引号,因为不是字符串 */
      const VDOM2 = <h1>Hello,Mrr</h1>;
      //2.渲染虚拟DOM到页面
      /* render(虚拟DOM,容器) */
      // ReactDOM 是因为引入了react-dom.development.js ,React是因为引入了react.development.js
      // 注意这里 ReactDOM 的写法
      ReactDOM.render(VDOM, document.getElementById("test"));
      ReactDOM.render(VDOM2, document.getElementById("test")); //这里会将上边的替换掉
    </script>
  </body>
</html>

# 虚拟 dom 的两种创建方式

  1. 有了 jsx 可以使编码人员 更简单的创建虚拟 dom
  2. jsx 里边的这种写法创建虚拟 dom,其实就是 原始 js 创建虚拟 dom 这种写法的一个 语法糖 (简写的方式)
  3. 虚拟 Dom 本质是一个 Object 类型的对象 (一般对象)
  4. 虚拟 DOM 比较 "轻" , 真实 Dom 比较 "重" ,因为 虚拟 Dom 是 React 内部 在用, 无需真实 Dom 上那么多的属性
  5. 虚拟 Dom 最终会被 React 转换为 真实 Dom ,呈现在页面上
  6. debugger 断点,可以去控制台中的 Sources 查看具体内容
  • 使用 jsx 创建虚拟 dom

    <!DOCTYPE html>
    <html lang="en">
      <head>
        <meta charset="UTF-8" />
        <title>hello_react</title>
      </head>
      <body>
        <div id="test"></div>
        <script src="../js/react.development.js"></script>
        <script src="../js/react-dom.development.js"></script>
        <script src="../js/babel.min.js"></script>
        <script type="text/babel">
          /* 用一个 () 表示是一个整体 */
          const VDOM = (
            <h1 id="title">
              <span>Hello,React</span>
            </h1>
          );
          /* 最终浏览器运行的还是通过babel编译成使用js创建时的样子 */
          /* 但写起来很方便 */
          ReactDOM.render(VDOM, document.getElementById("test"));
        </script>
      </body>
    </html>
  • 使用 js 创建虚拟 dom (肯定不用)

    <!DOCTYPE html>
    <html lang="en">
      <head>
        <meta charset="UTF-8" />
        <title>hello_react</title>
      </head>
      <body>
        <div id="test"></div>
        <script src="../js/react.development.js"></script>
        <script src="../js/react-dom.development.js"></script>
        <script>
          const VDOM = React.createElement(
            "h1",
            { id: "title" },
            React.createElement("span", {}, "Hello,React")
          );
          ReactDOM.render(VDOM, document.getElementById("test"));
        </script>
      </body>
    </html>

# jsx 语法

  1. 定义虚拟 DOM 时, 不要写引号 。
  2. 标签中混入 JS 表达式时 (html 中写 js) 要用 {} 。 注意是表达式!
  3. 标签上样式的类名不要用 class,要用 className 。
  4. 内联样式 ,要用 style={{key:'value'}} 的形式去写。 font-size 这种的要写成 小驼峰 形式
  5. 只有一个根标签
  6. 标签必须闭合
  7. 标签的 for 换成 htmlFor (比如 label 标签的 for)
  8. 标签首字母
    (1). 若小写字母开头 ,则将该标签转为 html 中同名元素,若 html 中无该标签对应的同名元素,则报错。
    (2). 若大写字母开头 ,react 就去渲染对应的组件,若组件没有定义,则报错。
  9. jsx 事件绑定 `onClick (大写的)= 函数名 (不是函数调用)

# jsx 小练习

一定注意区分: js 语句(代码) 与 js 表达式
const x = 表达式 ( 能用变量接收的就是表达式 )

  • 表达式:一个表达式会产生一个值,可以放在任何一个需要值的地方
    下面这些都是表达式:
    (1). a
    (2). a+b
    (3). demo(1)
    (4). arr.map()
    (5). function test () {}

  • 语句 (代码):
    下面这些都是语句 (代码):
    (1).if(){}
    (2).for(){}
    (3).switch()

  • 案例

    <!DOCTYPE html>
    <html lang="en">
      <head>
        <meta charset="UTF-8" />
        <title>jsx小练习</title>
      </head>
      <body>
        <div id="test"></div>
        <script src="../js/react.development.js"></script>
        <script src="../js/react-dom.development.js"></script>
        <script src="../js/babel.min.js"></script>
        <script type="text/babel">
          //模拟一些数据
          const data = ["Angular", "React", "Vue"];
          const VDOM = (
            <div>
              <h1>前端js框架列表</h1>
              <ul>
                {data.map((item, index) => {
                  /* 不建议写 index */
                  return <li key={index}>{item}</li>;
                })}
              </ul>
            </div>
          );
          ReactDOM.render(VDOM, document.getElementById("test"));
        </script>
      </body>
    </html>

# 模块与组件、模块化与组件化的理解

  • 模块

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

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

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

# 组件

组件实例三大属性: state,props,refs
函数式组件 只能用 props , 而 class 类组件才有三大属性

context 也需了解

# 函数式组件

一个函数只能返回一个 html 根节点, 没有生命周期和 state

<script type="text/babel">
  // 1.创建函数式组件
  // 函数式组件,函数名就是组件名
  function MyComponent() {
    console.log(this);
    // 此处的this是 undefined 而不是 window
    // 因为babel编译后开启了严格模式(禁止自定义函数中的this指向window)
    return <h2>我是用函数定义的组件(适用于【简单组件】的定义)</h2>;
    // 函数必须有返回值
  }
  // 2.渲染组件到页面
  // 组件名首字母大写且必须为闭合标签!!!!
  // 这里必须是标签,不能直接写名字
  ReactDOM.render(<MyComponent />, document.getElementById("test"));

  // 执行了ReactDOM.render(<MyComponent/>.......之后,发生了什么?
  // 1.React解析组件标签,找到了MyComponent组件。如果找不到会报错
  // 2.发现组件是使用函数定义的,随后调用该函数,将返回的虚拟DOM转为真实DOM,随后呈现在页面中。
</script>

# class 类组件

有生命周期和 state

<script type="text/babel">
  // 1.创建类式组件
  // 类名就是组件名
  // React 中规定如果要用类式组件必须要继承React中内置的一个类
  class MyComponent extends React.Component {
    render() {
      // render是放在哪里的?—— MyComponent的原型对象上,供实例使用。
      // render中的this是谁?—— MyComponent的实例对象 <=> MyComponent组件实例对象。
      console.log("render中的this:", this);
      return <h2>我是用类定义的组件(适用于【复杂组件】的定义)</h2>;
    }
  }
  // 2.渲染组件到页面
  ReactDOM.render(<MyComponent />, document.getElementById("test"));

  // 执行了ReactDOM.render(<MyComponent/>.......之后,发生了什么?
  // 1.React解析组件标签,找到了MyComponent组件。
  // 2.发现组件是使用类定义的,随后会new出来该类(MyComponent)的实例,并通过该实例调用到原型上的render方法。
  // 是 React 自己做的 new 操作
  // 3.将render返回的虚拟DOM转为真实DOM,随后呈现在页面中。
</script>

# 复习类的概念

# 总结

  • 类中的构造器 不是 必须要写的,要对实例进行一些初始化的操作,如添加指定属性时才写。
  • 如果 A 类继承了 B 类,且 A 类中写了构造器,那么 A 类构造器中的 super 是必须要调用的。
  • 类中所定义的方法,都放在了 类的原型对象上,供实例去使用 。

# 案例

//创建一个Person类
class Person {
  //构造器方法
  constructor(name, age) {
    //构造器中的this是谁?—— 类的实例对象,new的时候执行constructor
    this.name = name;
    this.age = age;
  }
  //一般方法
  speak() {
    // speak方法放在了哪里?——类的原型对象上,供实例使用
    //通过Person实例调用speak时,speak中的this就是Person实例
    console.log(`我叫${this.name},我年龄是${this.age}`);
  }
}

//创建一个Student类,继承于Person类
class Student extends Person {
  constructor(name, age, grade) {
    // 只要这里用了构造器就必须用 super
    // super 是帮你调用父类的构造器,且 super 必须放在所有人之前
    super(name, age);
    this.grade = grade;
    this.school = "清北";
    // 所有由 Student 缔造的实例身上都有一个值为清北的school属性
  }
  //重写从父类继承过来的方法
  speak() {
    console.log(
      `我叫${this.name},我年龄是${this.age},我读的是${this.grade}年级`
    );
    this.study();
  }
  study() {
    //study方法放在了哪里?——类的原型对象上,供实例使用
    //通过Student实例调用study时,study中的this就是Student实例
    console.log("我很努力的学习");
  }
}

class Car {
  constructor(name, price) {
    this.name = name;
    this.price = price;
    // this.wheel = 4
  }
  //类中可以直接写赋值语句,如下代码的含义是:给Car的实例对象添加一个名为a,值为1的属性
  a = 1;
  wheel = 4;
  // 不写 static 是加给了类的实例对象,写的话就是加给了类本身
  static demo = 100;
}
const c1 = new Car("奔驰c63", 199);
console.log(c1); // Car {a: 1, wheel: 4, name: "奔驰c63", price: 199}
console.log(Car.demo); // 100

# 组件实例三大属性之一 state 和事件处理

# 案例一

<script type="text/babel">
  //1.创建组件
  class Weather extends React.Component {
    //构造器调用几次? ———— 1次,因为在ReactDom.render中只写了一次
    constructor(props) {
      super(props);
      //初始化状态
      // 这里是往组件实例中放东西
      this.state = { isHot: false, wind: "微风" };
      //解决changeWeather中this指向问题
      //如果没有这行代码,changeWeather 会指向 undefined
      this.changeWeather = this.changeWeather.bind(this);
    }

    //render调用几次? ———— 1+n次 1是初始化的那次 n是状态更新的次数
    render() {
      //读取状态
      const { isHot, wind } = this.state;
      return (
        <h1 onClick={this.changeWeather}>
          今天天气很{isHot ? "炎热" : "凉爽"},{wind}
        </h1>
      );
    }

    //changeWeather调用几次? ———— 点几次调几次
    changeWeather() {
      //changeWeather放在哪里? ———— Weather的原型对象上,供实例使用
      //由于changeWeather是作为onClick的回调,所以不是通过实例调用的,是直接调用
      //类中的方法默认开启了局部的严格模式!!!!,所以changeWeather中的this为undefined

      //获取原来的isHot值
      const isHot = this.state.isHot;
      //严重注意:状态必须通过setState进行更新,且更新是一种合并,不是替换。
      this.setState({ isHot: !isHot });
      console.log(this);

      //严重注意:状态(state)不可直接更改,下面这行就是直接更改!!!
      //this.state.isHot = !isHot //这是错误的写法
    }
  }
  //2.渲染组件到页面
  ReactDOM.render(<Weather />, document.getElementById("test"));
</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>
      );
    }

    //自定义方法————要用赋值语句的形式+箭头函数
    changeWeather = () => {
      const isHot = this.state.isHot;
      this.setState({ isHot: !isHot });
    };
  }
  //2.渲染组件到页面
  ReactDOM.render(<Weather />, document.getElementById("test"));
</script>

# 案例二 (脚手架)

import { Component } from "react";
class Count extends Component {
  state = { count: 100 };
  render() {
    const { count } = this.state;
    return (
      <div>
        {/* jsx 事件绑定 onClick(大写的)=函数(不是函数调用) */}
        <button onClick={this.add}>+</button>
        <span>{count}</span>
        <button onClick={this.reduce}>-</button>

        {/* 事件传参,要用这种方式 */}
        <button onClick={() => this.change(500)}>随意修改</button>
      </div>
    );
  }
  add = () => {
    let { count } = this.state;
    this.setState({
      // count: ++ this.state.count // 这样会报错,不能直接修改 state
      count: count + 1, // 下边的也可以
      // count: ++count,
    });
  };
  reduce = () => {
    let { count } = this.state;
    this.setState({
      count: --count,
    });
  };
  change = (newCount) => {
    this.setState({
      count: newCount,
    });
  };
}
export default Count;

# state 总结

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

# 组件实例三大属性之一 props

props 是只读的,不可以修改
props 的类型检查,需要借助 prop-types 包实现

(https://react.docschina.org/docs/typechecking-with-proptypes.html)

# 案例一 (脚手架)

// 导入 prop 类型检查包
// prop-types 是 react 自带的
import PropTypes from "prop-types";
import React, { Component } from "react";
class MyButton extends Component {
  render() {
    const { text = "按钮" } = this.props;
    this.props.fun && this.props.fun(); //132456
    return <button>{text}</button>;
  }
}

// 对组件的 text props 进行类型校验
// 这里是 propTypes
MyButton.propTypes = {
  // 这里是 PropTypes
  text: PropTypes.string, // 只能传字符串
};

export default MyButton;

# 案例二 (对 props 进行限制)

<!-- 引入prop-types,用于对组件标签属性进行限制 -->
<script src="../js/prop-types.js"></script>
<!-- 引入了这个文件,就多了一个全局对象 PropTypes -->

<script type="text/babel">
  class Person extends React.Component {
    render() {
      const { name, age, sex } = this.props;
      //props是只读的
      //this.props.name = 'jack' //此行代码会报错,因为props是只读的
      return (
        <ul>
          <li>姓名:{name}</li>
          <li>性别:{sex}</li>
          <li>年龄:{age + 1}</li>
        </ul>
      );
    }
  }
  // 对标签属性进行类型、必要性的限制
  // 给Person类加上propTypes这个属性,就意味着加规则
  Person.propTypes = {
    name: PropTypes.string.isRequired, //限制name必传,且为字符串
    sex: PropTypes.string, //限制sex为字符串
    age: PropTypes.number, //限制age为数值
    speak: PropTypes.func, //限制speak为函数
  };
  // 指定默认标签属性值
  Person.defaultProps = {
    sex: "男", //sex默认值为男
    age: 18, //age默认值为18
  };
  // 渲染组件到页面
  ReactDOM.render(
    <Person name={100} speak={speak} />,
    document.getElementById("test1")
  );
  ReactDOM.render(
    <Person name="tom" age={18} sex="女" />,
    document.getElementById("test2")
  );

  const p = { name: "老刘", age: 18, sex: "女" };
  // ReactDOM.render(<Person name={p.name} age={p.age} sex={p.sex}/>,document.getElementById('test3'))
  ReactDOM.render(<Person {...p} />, document.getElementById("test3"));

  function speak() {
    console.log("我说话了");
  }
</script>

# 案例三 (props 简写方式 (案例二简写方式))

<script type="text/babel">
  //创建组件
  class Person extends React.Component {
    // 在实际开发中基本不写构造器
    constructor(props) {
      // 构造器是否接收props,是否传递给super,取决于:是否希望在构造器中通过this访问props
      super(props);
      console.log("constructor", this.props);
    }

    static propTypes = {
      name: PropTypes.string.isRequired, //限制name必传,且为字符串
      sex: PropTypes.string, //限制sex为字符串
      age: PropTypes.number, //限制age为数值
    };

    //指定默认标签属性值
    static defaultProps = {
      sex: "男", //sex默认值为男
      age: 18, //age默认值为18
    };

    render() {
      const { name, age, sex } = this.props;
      return (
        <ul>
          <li>姓名:{name}</li>
          <li>性别:{sex}</li>
          <li>年龄:{age + 1}</li>
        </ul>
      );
    }
  }
  ReactDOM.render(<Person name="jerry" />, document.getElementById("test1"));
</script>

# 案例四 (函数式组件使用 props)

函数式组件没法用 state 和 refs

<script src="../js/prop-types.js"></script>
<script type="text/babel">
  function Person(props) {
    const { name, age, sex } = props;
    return (
      <ul>
        <li>姓名:{name}</li>
        <li>性别:{sex}</li>
        <li>年龄:{age}</li>
      </ul>
    );
  }
  Person.propTypes = {
    name: PropTypes.string.isRequired, //限制name必传,且为字符串
    sex: PropTypes.string, //限制sex为字符串
    age: PropTypes.number, //限制age为数值
  };

  Person.defaultProps = {
    sex: "男", //sex默认值为男
    age: 18, //age默认值为18
  };
  ReactDOM.render(<Person name="jerry" />, document.getElementById("test1"));
</script>

# 案例五 (脚手架)

  • 父组件传递给子组件内容

    • App.js

      import "./App.css";
      import MyButton from "./components/MyButton";
      import MyTitle from "./components/MyTitle";
      
      function fun() {
        console.log("132456");
      }
      function App() {
        return (
          <div className="App">
            {/* 使用 props 给组件传递内容 */}
            {/* 传递的名叫fun,值是上边定义的 */}
            <MyButton text="按钮a" fun={fun} />
            {/* 这里的Mybutton调用的是对应组件中render方法的return */}
            {/* 这里调用Mybutton的时候,会输出132456 */}
      
            <MyTitle title="标题a" />
          </div>
        );
      }
      
      export default App;
    • (类组件如何接收 props) MyButton.js

      import React, { Component } from "react";
      class MyButton extends Component {
        // render函数和生命周期不需要写成箭头函数也可以获取 this
        render() {
          // 子组件接收父组件传递的 props
          // 父组件传递过来的 props 会自动放在组件的 this 下的 props 属性内
      
          const { text = "按钮" } = this.props; // 设置默认值
          // const { text: xxx } = this.props; 将 text 重命名为xxx
          this.props.fun && this.props.fun(); //132456
          return <button>{text}</button>;
        }
      }
      export default MyButton;
    • (函数式组件怎么接收 props) MtTitle.js

      const MyTitle = (props) => {
        // 函数组件里没有 this
        // 函数的参数就是 props
        const { title = "标题" } = props;
        return <h3>{title}</h3>;
      };
      export default MyTitle;

# 特殊的 prop:children

父组件将内容写在子组件的标签中间传递过来的话,子组件使用 children 接收
当父组件传递的 children 是多个的话,children 就是一个 数组
那么如何区分我到底该使用数组里面的哪一项呢
可以选择父组件传递的时候给 className
然后 className 会被当作其中一项的 props 对象的属性

# 组件实例三大属性之一 refs 和事件处理

不能在 函数组件 上使用 ref 属性
切勿过度使用 ref !!!

# 字符串形式的 ref (官方已废弃)

字符串形式的 ref 如果写多了, 效率就会变得低下 ,所以官方不推荐使用

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

# 回调函数形式的 ref

React 会自动调用 ref 函数,且会将 ref 当前所处的节点当作第一个参数传进去

  • 案例一

    <script type="text/babel">
      //创建组件
      class Demo extends React.Component {
        //展示左侧输入框的数据
        showData = () => {
          // 这里就不是从 this.refs 上取了
          // 而是从 this 上边取,因为底下赋值给了 this
          const { input1 } = this;
          alert(input1.value);
        };
        //展示右侧输入框的数据
        showData2 = () => {
          const { input2 } = this;
          alert(input2.value);
        };
        render() {
          return (
            <div>
              <input
                ref={(ele) => (this.input1 = ele)}
                type="text"
                placeholder="点击按钮提示数据"
              />
              <button onClick={this.showData}>点我提示左侧的数据</button>
              <input
                onBlur={this.showData2}
                ref={(ele) => (this.input2 = ele)}
                type="text"
                placeholder="失去焦点提示数据"
              />
            </div>
          );
        }
      }
      //渲染组件到页面
      ReactDOM.render(<Demo />, document.getElementById("test"));
    </script>
  • 案例二 (脚手架)

    import { Component } from "react";
    class RefsDemo1 extends Component {
      inputRef = null;
      render() {
        return (
          <div>
            {/*该函数默认接收的第一个参数就是真实 dom,将这个真实 dom 赋值给类的属性即可 */}
            <input type="text" ref={(ele) => (this.inputRef = ele)} />
          </div>
        );
      }
      componentDidMount() {
        this.inputRef.focus();
      }
    }
    export default RefsDemo1;

# createRef 形式的 ref (最推荐的)

  • 案例一

    <script type="text/babel">
      //创建组件
      class Demo extends React.Component {
        //  React.createRef调用后可以返回一个容器,该容器可以存储被ref所标识的节点,该容器是“专人专用”的,只能存一个
        myRef = React.createRef();
        myRef2 = React.createRef();
        //展示左侧输入框的数据
        showData = () => {
          alert(this.myRef.current.value);
        };
        //展示右侧输入框的数据
        showData2 = () => {
          alert(this.myRef2.current.value);
        };
        render() {
          return (
            <div>
              <input ref={this.myRef} type="text" />
              <button onClick={this.showData}>点我提示左侧的数据</button>
              <input onBlur={this.showData2} ref={this.myRef2} type="text" />
            </div>
          );
        }
      }
      //渲染组件到页面
      ReactDOM.render(<Demo />, document.getElementById("test"));
    </script>
  • 案例二 (脚手架)

    import { Component, createRef } from "react";
    class RefsDemo extends Component {
      // refs 如何使用
      // 1. 类里面内定义一个变量,属性的值是 creatRef()
      // 2. 将这个值绑定到任一元素的 ref 属性上
      // 那么当你访问这个属性下的 current 属性时,就访问到了对应的真实 dom
      p = createRef();
      h = createRef();
      inputRef = createRef();
      state = { count: 10 };
      // 利用 ref 实现输入框自动获得焦点
      render() {
        const { count } = this.state;
        return (
          <div>
            <h3 ref={this.h}>测试refs</h3>
            <button onClick={this.add}>+1</button>
            <button onClick={this.getP}>使用 refs 获取段落的真实 dom</button>
            <p ref={this.p}>我是一个段落{count}</p>
            <input type="text" ref={this.inputRef} />
          </div>
        );
      }
      // 一上来就获取焦点
      componentDidMount() {
        this.inputRef.current.focus();
        // 利用 ref 实现输入框自动获得焦点
      }
      getP = () => {
        console.log(this.p.current);
        console.log(this.h.current);
      };
      add = () => {
        const { count } = this.state;
        this.setState({ count: count + 1 });
      };
    }
    export default RefsDemo;

# 事件处理

  • (1). 通过 onXxx 属性指定事件处理函数 (注意大小写)

    • React 使用的是 自定义(合成)事件 ,而不是使用的原生 DOM 事件 -> 为了更好的兼容性
    • React 中的事件是通过 事件委托 方式处理的 ( 委托给组件最外层的元素 ) -> 为了高效
    • 里边传递 一定要是一个函数!!! , 跟加不加小括号没有关系
      saveFormData = (dataType) => {
        return (event) => {
          this.setState({ [dataType]: event.target.value });
        };
      };
      <input onChange={this.saveFormData("username")} name="username" />;
  • (2). 通过 event.target 得到发生事件的 DOM 元素对象 -> 不要过度使用 ref

    <script type="text/babel">
      class Demo extends React.Component {
        showData2 = (event) => {
          alert(event.target.value);
        };
        render() {
          return (
            <input
              onBlur={this.showData2}
              type="text"
              placeholder="失去焦点提示数据"
            />
          );
        }
      }
      ReactDOM.render(<Demo />, document.getElementById("test"));
    </script>

文章作者: Mrr-cxh
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 Mrr-cxh !
赏
 上一篇
React 2.0 React 2.0
React 是一个声明式,高效且灵活的用于构建用户界面的 JavaScript 库。使用 React 可以将一些简短、独立的代码片段组合成复杂的 UI 界面,这些代码片段被称作“组件”。
2021-09-12
下一篇 
Pc端OA管理系统解决方案 Pc端OA管理系统解决方案
OA管理系统是公司内部使用的一个管理系统,它能够能够高效,便捷的协助公司进行管理,有通讯录模块,请加模块,公告模块,任务模块,客户模块等等。通过编写OA管理系统,对ElementUI的掌握更进一步,且在项目中遇到的问题总结如下。
2021-08-09
  目录