Skip to content

前言

要想摩托跑得快,螺丝必须得拧紧。说的就是我这种野鸡,只顾着往前跑,切记穿鞋了。跑到最后,裁判说你没穿鞋,成绩不算,功亏一篑

今天咱就把三颗重要螺丝再拧一拧

在React开发反而过程中,出现最多的无非就是state、porps、ref三大属性

因为卷的原因,我这次用 react+vite+TypeScript 创建一个项目出来把三大属性过一遍,一方面加深TS的运用,另一方面加深React的认识,也算是总结吧。

组件实例三大属性 — state

定义:这个就相当于一个存储数据的对象。

如果用过vue的伙伴都知道,vue里面存储当前实例的数据是data,而这个data官方建议是个函数而不是对象,有兴趣可以去了解一下,个人总结的原因就是每个.vue都是一个单独的实例,如果使用对象,这个会变成全局性的,会影响到其他实例的data数据,而函数有作用域并不会影响到。

写法一:

ts
import React, { Component } from "react";

interface stateType {
  isHot: boolean;
  wind: string;
}

export default class App extends Component<{}, stateType> {
  constructor(props: any) {
    super(props);
    //初始化状态
    this.state = { isHot: false, wind: "微风" };
    this.changeWeather = this.changeWeather.bind(this);
  }
  changeWeather() {
    console.log("changeWeather",this);
    //获取原来的isHot值
    const isHot = this.state.isHot;
    this.setState({ isHot: !isHot });
  }
  render() {
    console.log("render");
    const { isHot, wind } = this.state;
    return (
      <h1 onClick={this.changeWeather}>
        今天天气很{isHot ? "炎热" : "凉爽"},{wind}
      </h1>
    );
  }
}
import React, { Component } from "react";

interface stateType {
  isHot: boolean;
  wind: string;
}

export default class App extends Component<{}, stateType> {
  constructor(props: any) {
    super(props);
    //初始化状态
    this.state = { isHot: false, wind: "微风" };
    this.changeWeather = this.changeWeather.bind(this);
  }
  changeWeather() {
    console.log("changeWeather",this);
    //获取原来的isHot值
    const isHot = this.state.isHot;
    this.setState({ isHot: !isHot });
  }
  render() {
    console.log("render");
    const { isHot, wind } = this.state;
    return (
      <h1 onClick={this.changeWeather}>
        今天天气很{isHot ? "炎热" : "凉爽"},{wind}
      </h1>
    );
  }
}

这里有几个知识点,我们来梳理一下,

1、为什么Component<{}, stateType>这样的写法?

如果熟悉ts的同学就知道这是个类型断言,stateType是个自定义的接口,那为什么有两个参数在里面呢?很简单,让我们来看一下React源码定义的这个Component

image.png

可以看到我们的 Component被定义成Component<P,S>,其中的PS都是个泛型,再看看state被定义为Readonly<S> ,意思是:state的所有属性设置为只读的类型。props被定义为Readonly<P> | P,意思是:props的所有属性设置为只读的类型 或者是 P类型

既然都是泛型,那么类型肯定要有自己来定义了,所以才会出现这样的写法Component<{}, stateType>

2、为什么使用bind改变changeWeather的this指向呢,也就是我们代码中的this.changeWeather = this.changeWeather.bind(this)

写过ES6的class类的伙伴们都知道,一般在class类里面定义的方法,在没有被属性的修饰符修饰前,changeWeather放在App的原型对象上,提供给实例使用。

ES6 class的修饰符(具体详情查看阮一峰老师的ES6讲解):

  • 静态属性和静态方法在前面添加static
  • 私有属性在前面添加#
  • 私有方法用下划线表示,但是在外部还可以被访问到不保险

TS class的修饰符(具体可以查看英文TS官网对修饰符的解释):

  • public修饰符---公共的,类中成员默认的修饰符,代表的是公共的,任何位置都可以访问类中的成员
  • private修饰符---私有的,类中的成员如果使用private来修饰,那么外部是无法访问这个成员数据的,当然,子类中也是无法访问该成员数据的
  • protected修饰符---受保护的,类中的成员如果使用protected来修饰,那么外部是无法访问这个成员数据的,当然,子类中是可以访问该成员数据的
  • #修饰符---表示私有字段,有时我们称之为私有名称; 每个私有字段名称都唯一地限定于其包含的类; 不能在私有字段上使用 TypeScript 可访问性修饰符(如 public 或 private); 私有字段不能在包含的类之外访问,甚至不能被检测到
  • readonly修饰符---只读不能写
  • static修饰符---通过static修饰的成员叫静态成员,静态成员无需实例化,直接通过类名调用

由于changeWeather是作为onClick的回调,所以不是通过实例调用的,是直接调用,类中的方法默认开启了局部的严格模式,所以changeWeather中的this为undefined,我们可以看这个例子:

js
    function aa(){
        console.log(this)
    }
    aa()

    function bb(){
        "use strict";
        console.log(this)
    }

    bb()
    function aa(){
        console.log(this)
    }
    aa()

    function bb(){
        "use strict";
        console.log(this)
    }

    bb()

打印的结果:

image.png

如果熟悉this指向的同学一看就知道其中的原因所在,我也给大家总结一下,这里先不做详细的介绍:

  • 在严格模式下,在全局作用域中,this指向window对象。
  • 在严格模式下,全局作用域中函数中的this等于undefined。不是严格模式时,这里的this指向window。在react中render()里的this是指向组件的实例对象。注意区分是render()里的this还是函数中的this。(这两个this指向不同,所以没法在全局作用域的函数中直接调用this取值)
  • 在严格模式下,对象的函数中的this指向调用函数的对象实例
  • 在严格模式下,构造函数中的this指向构造函数创建的对象实例。
  • 在严格模式下,在事件处理函数中,this指向触发事件的目标对象。

所以最后你知道了为什么要改变changeWeather中的this指向了吗?

总结了上面的知识,我们来简写一下写法吧

写法二:

ts
import React, { Component } from "react";
interface stateType {
  isHot: boolean;
  wind: string;
}

export default class example1 extends Component<{}, stateType> {
  state = {
    isHot: false,
    wind: "微风",
  };
  changeWeather = () => {
    const isHot = this.state.isHot;
    this.setState({ isHot: !isHot });
  };

  render() {
    const { isHot, wind } = this.state;
    return (
      <h1 onClick={this.changeWeather}>
        今天天气很{isHot ? "炎热" : "凉爽"},{wind}
      </h1>
    );
  }
}
import React, { Component } from "react";
interface stateType {
  isHot: boolean;
  wind: string;
}

export default class example1 extends Component<{}, stateType> {
  state = {
    isHot: false,
    wind: "微风",
  };
  changeWeather = () => {
    const isHot = this.state.isHot;
    this.setState({ isHot: !isHot });
  };

  render() {
    const { isHot, wind } = this.state;
    return (
      <h1 onClick={this.changeWeather}>
        今天天气很{isHot ? "炎热" : "凉爽"},{wind}
      </h1>
    );
  }
}

这个写法是不是不要比写法一精简很多了。

1、为什么有了箭头函数后就不用改变changeWeatherthis指向呢,我们来认识一下箭头函数与普通函数的区别:

一、箭头函数不会创建自己的this(重要!!深入理解!!),也就是说他没有自己的this,有兴趣的可以去看一下MDN对箭头函数的this的解释

二、箭头函数继承而来的this指向永远不变(重要!!深入理解!!)

三、.call()/.apply()/.bind()无法改变箭头函数中this的指向

四、箭头函数不能作为构造函数使用,也就是说他不能new。我们先了解一下构造函数的new都做了些什么?简单来说,分为四步:

① JS内部首先会先生成一个对象;

② 再把函数中的this指向该对象;

③ 然后执行构造函数中的语句;

④ 最终返回该对象实例。

但是!!因为箭头函数没有自己的this,它的this其实是继承了外层执行环境中的this,且this指向永远不会随在哪里调用、被谁调用而改变,所以箭头函数不能作为构造函数使用,或者说构造函数不能定义成箭头函数,否则用new调用时会报错!

js
let Fun = (name, age) => {
    this.name = name;
    this.age = age;
};

// 报错
let p = new Fun('cao', 24);
let Fun = (name, age) => {
    this.name = name;
    this.age = age;
};

// 报错
let p = new Fun('cao', 24);

五、箭头函数没有自己的arguments。在箭头函数中访问arguments实际上获得的是外层局部(函数)执行环境中的值。

js
// 例子一
let fun = (val) => {
    console.log(val);   // 111
    // 下面一行会报错
    // Uncaught ReferenceError: arguments is not defined
    // 因为外层全局环境没有arguments对象
    console.log(arguments); 
};
fun(111);

// 例子二
function outer(val1, val2) {
    let argOut = arguments;
    console.log(argOut);    // ①
    let fun = () => {
        let argIn = arguments;
        console.log(argIn);     // ②
        console.log(argOut === argIn);  // ③
    };
    fun();
}
outer(111, 222);
// 例子一
let fun = (val) => {
    console.log(val);   // 111
    // 下面一行会报错
    // Uncaught ReferenceError: arguments is not defined
    // 因为外层全局环境没有arguments对象
    console.log(arguments); 
};
fun(111);

// 例子二
function outer(val1, val2) {
    let argOut = arguments;
    console.log(argOut);    // ①
    let fun = () => {
        let argIn = arguments;
        console.log(argIn);     // ②
        console.log(argOut === argIn);  // ③
    };
    fun();
}
outer(111, 222);

上面例子二,①②③处的输出结果如下:

image.png 很明显,普通函数outer内部的箭头函数fun中的arguments对象,其实是沿作用域链向上访问的外层outer函数的arguments对象。

可以在箭头函数中使用rest参数代替arguments对象,来访问箭头函数的参数列表!!

六、箭头函数没有原型prototype

七、箭头函数不能用作Generator函数,不能使用yeild关键字

单单一个state就能让我学习到class类的修饰符、this指向,箭头函数、泛型、类型断言、泛型工具、联合类型,真是不总结都知道害怕,我已卷到这么多了。

组件实例三大属性 — props

定义:在父组件给子组件传递参数时的桥梁作用,相当于vue的props传值一样的效果,但是却没有vue用起来那么麻烦,纯属个人感受。

写法:

ts
import React, { Component } from "react";
interface propsType {
  name: string;
  age: number;
  sex: "男" | "女";
}

class Index1 extends Component<propsType> {
  render(): React.ReactNode {
    const { name, age, sex } = this.props;
    return (
      <ul>
        <li>姓名:{name}</li>
        <li>性别:{sex}</li>
        <li>年龄:{age}</li>
      </ul>
    );
  }
}

export default class example2 extends Component {
  render() {
    let p:propsType = {
      name:"李青霞",
      age:20,
      sex:"女"
    }
    return (
      <>
        <h1>Props基本使用</h1>
        <Index1 name="周星星" age={18} sex="男"></Index1>
        <Index1 name="朱茵" age={19} sex="女"></Index1>
        <Index1 {...p}></Index1>
      </>
    );
  }
}
import React, { Component } from "react";
interface propsType {
  name: string;
  age: number;
  sex: "男" | "女";
}

class Index1 extends Component<propsType> {
  render(): React.ReactNode {
    const { name, age, sex } = this.props;
    return (
      <ul>
        <li>姓名:{name}</li>
        <li>性别:{sex}</li>
        <li>年龄:{age}</li>
      </ul>
    );
  }
}

export default class example2 extends Component {
  render() {
    let p:propsType = {
      name:"李青霞",
      age:20,
      sex:"女"
    }
    return (
      <>
        <h1>Props基本使用</h1>
        <Index1 name="周星星" age={18} sex="男"></Index1>
        <Index1 name="朱茵" age={19} sex="女"></Index1>
        <Index1 {...p}></Index1>
      </>
    );
  }
}

从上面就可以看出,React的props传值就很有意思,直接写在标签内,还可以解构的形式,是不是写起来比vue方便很多。

我们在vue中使用prop传值时,会有一个类型的定义,是否必传,还可以写校验规则的,具体可以看一下vue对Prop验证的解释

我们的React中也可以,但是只不过要借助另外一个库叫prop-types,具体的配置项可以看一下React对PropsType的解释。

ts
import React, { Component } from "react";
import PropTypes from "prop-types";
interface propsType {
  name: string;
  age: number;
  sex: "男" | "女";
  speak?:Function
}
function speak() {
  console.log("我说话了");
}

class Index1 extends Component<propsType> {
  static propTypes: { name: PropTypes.Validator<string>; sex: PropTypes.Requireable<string>; age: PropTypes.Requireable<number>; speak: PropTypes.Requireable<(...args: any[]) => any> };
  static defaultProps: {
    sex: string; //sex默认值为男
    age: number; //age默认值为18
    name: string;
  };
  render(): React.ReactNode {
    const { name, age, sex,speak } = this.props;
    if(speak){
      speak!()
      console.log("是谁在说话",name)
    }
    
    return (
      <ul>
        <li>姓名:{name}</li>
        <li>性别:{sex}</li>
        <li>年龄:{age}</li>
      </ul>
    );
  }
}
Index1.propTypes = {
  name: PropTypes.string.isRequired,
  sex: PropTypes.string,
  age: PropTypes.number,
  speak: PropTypes.func,
};

Index1.defaultProps = {
  sex: "男", //sex默认值为男
  age: 18, //age默认值为18
  name: "李四",
};

export default class example2 extends Component {
  render() {
    let p: propsType = {
      name: "李青霞",
      age: 20,
      sex: "女",
    };
    return (
      <>
        <h1>Props基本使用</h1>
        <Index1 name="周星星" age={18} sex="男" speak={speak}></Index1>
        <Index1 name="朱茵" age={19} sex="女"></Index1>
        <Index1 {...p}></Index1>
        <Index1></Index1>
      </>
    );
  }
}
import React, { Component } from "react";
import PropTypes from "prop-types";
interface propsType {
  name: string;
  age: number;
  sex: "男" | "女";
  speak?:Function
}
function speak() {
  console.log("我说话了");
}

class Index1 extends Component<propsType> {
  static propTypes: { name: PropTypes.Validator<string>; sex: PropTypes.Requireable<string>; age: PropTypes.Requireable<number>; speak: PropTypes.Requireable<(...args: any[]) => any> };
  static defaultProps: {
    sex: string; //sex默认值为男
    age: number; //age默认值为18
    name: string;
  };
  render(): React.ReactNode {
    const { name, age, sex,speak } = this.props;
    if(speak){
      speak!()
      console.log("是谁在说话",name)
    }
    
    return (
      <ul>
        <li>姓名:{name}</li>
        <li>性别:{sex}</li>
        <li>年龄:{age}</li>
      </ul>
    );
  }
}
Index1.propTypes = {
  name: PropTypes.string.isRequired,
  sex: PropTypes.string,
  age: PropTypes.number,
  speak: PropTypes.func,
};

Index1.defaultProps = {
  sex: "男", //sex默认值为男
  age: 18, //age默认值为18
  name: "李四",
};

export default class example2 extends Component {
  render() {
    let p: propsType = {
      name: "李青霞",
      age: 20,
      sex: "女",
    };
    return (
      <>
        <h1>Props基本使用</h1>
        <Index1 name="周星星" age={18} sex="男" speak={speak}></Index1>
        <Index1 name="朱茵" age={19} sex="女"></Index1>
        <Index1 {...p}></Index1>
        <Index1></Index1>
      </>
    );
  }
}

其实在TS这种强类型的语言下,先提前定义好接口类型,也是可以的。

然后我们可以把它简写:

ts
import React, { Component } from "react";
import PropTypes from "prop-types";
interface propsType {
  name: string;
  age: number;
  sex: "男" | "女";
}
function speak() {
  console.log("我说话了");
}

class Index1 extends Component<propsType> {
  static propTypes: { name: PropTypes.Validator<string>; sex: PropTypes.Requireable<string>; age: PropTypes.Requireable<number>; speak: PropTypes.Requireable<(...args: any[]) => any> } = {
    name: PropTypes.string.isRequired,
    sex: PropTypes.string,
    age: PropTypes.number,
    speak: PropTypes.func,
  };
  static defaultProps: {
    sex: string; //sex默认值为男
    age: number; //age默认值为18
  } = {
    sex: "男", //sex默认值为男
    age: 18, //age默认值为18
  };
  render(): React.ReactNode {
    const { name, age, sex } = this.props;
    return (
      <ul>
        <li>姓名:{name}</li>
        <li>性别:{sex}</li>
        <li>年龄:{age}</li>
      </ul>
    );
  }
}

export default class example2 extends Component {
  render() {
    let p: propsType = {
      name: "李青霞",
      age: 20,
      sex: "女",
    };
    return (
      <>
        <h1>Props基本使用</h1>
        <Index1 name="周星星" age={18} sex="男"></Index1>
        <Index1 name="朱茵" age={19} sex="女"></Index1>
        <Index1 {...p}></Index1>
        <Index1 name="李四"></Index1>
      </>
    );
  }
}
import React, { Component } from "react";
import PropTypes from "prop-types";
interface propsType {
  name: string;
  age: number;
  sex: "男" | "女";
}
function speak() {
  console.log("我说话了");
}

class Index1 extends Component<propsType> {
  static propTypes: { name: PropTypes.Validator<string>; sex: PropTypes.Requireable<string>; age: PropTypes.Requireable<number>; speak: PropTypes.Requireable<(...args: any[]) => any> } = {
    name: PropTypes.string.isRequired,
    sex: PropTypes.string,
    age: PropTypes.number,
    speak: PropTypes.func,
  };
  static defaultProps: {
    sex: string; //sex默认值为男
    age: number; //age默认值为18
  } = {
    sex: "男", //sex默认值为男
    age: 18, //age默认值为18
  };
  render(): React.ReactNode {
    const { name, age, sex } = this.props;
    return (
      <ul>
        <li>姓名:{name}</li>
        <li>性别:{sex}</li>
        <li>年龄:{age}</li>
      </ul>
    );
  }
}

export default class example2 extends Component {
  render() {
    let p: propsType = {
      name: "李青霞",
      age: 20,
      sex: "女",
    };
    return (
      <>
        <h1>Props基本使用</h1>
        <Index1 name="周星星" age={18} sex="男"></Index1>
        <Index1 name="朱茵" age={19} sex="女"></Index1>
        <Index1 {...p}></Index1>
        <Index1 name="李四"></Index1>
      </>
    );
  }
}

函数式组件的写法也差不多的:

js
import PropTypes from "prop-types";
import React from "react";
interface propsType {
  name: string;
  age: number;
  sex: "男" | "女";
}
function Index1(props: propsType) {
  const { name, age, sex } = props;
  return (
    <ul>
      <li>姓名:{name}</li>
      <li>性别:{sex}</li>
      <li>年龄:{age}</li>
    </ul>
  );
}

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

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

export default function example5() {
  return (
    <>
      <h1>函数组件使用props</h1>
      <Index1 name="李四"></Index1>
    </>
  );
}
import PropTypes from "prop-types";
import React from "react";
interface propsType {
  name: string;
  age: number;
  sex: "男" | "女";
}
function Index1(props: propsType) {
  const { name, age, sex } = props;
  return (
    <ul>
      <li>姓名:{name}</li>
      <li>性别:{sex}</li>
      <li>年龄:{age}</li>
    </ul>
  );
}

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

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

export default function example5() {
  return (
    <>
      <h1>函数组件使用props</h1>
      <Index1 name="李四"></Index1>
    </>
  );
}

组件实例三大属性 — ref

定义:一般是用来获取DOM或者是DOM值,例如input标签,可以通过绑定拿到input中输入的值

字符串形式的ref

js
import React, { Component } from "react";

export default class example6 extends Component {
  showData = ()=>{
    //会报错
    console.log(this.refs)
  }
  render() {
    return (
      <>
        <h1>字符串形式的ref</h1>
        <input ref="inputRef" type="text"  placeholder="请输入"/>
        <button onClick={this.showData}>获取ref</button>
      </>
    );
  }
}
import React, { Component } from "react";

export default class example6 extends Component {
  showData = ()=>{
    //会报错
    console.log(this.refs)
  }
  render() {
    return (
      <>
        <h1>字符串形式的ref</h1>
        <input ref="inputRef" type="text"  placeholder="请输入"/>
        <button onClick={this.showData}>获取ref</button>
      </>
    );
  }
}

这样的写法控制台会报错,官方不建议用这过时的写法,具体可以看React对字符串Ref的解释

回调函数形式的ref

ts
import React, { Component } from "react";

export default class example6 extends Component {
  showData = () => {
    const { inputRef } = this;
    console.log(inputRef?.value);
  };
  inputRef: HTMLInputElement | null | undefined;
  render() {
    return (
      <>
        <h1>回调函数形式的ref</h1>
        <input ref={(c) => (this.inputRef = c;console.log('@',c);)} type="text" placeholder="请输入" />
        <button onClick={this.showData}>获取ref数据</button>
      </>
    );
  }
}
import React, { Component } from "react";

export default class example6 extends Component {
  showData = () => {
    const { inputRef } = this;
    console.log(inputRef?.value);
  };
  inputRef: HTMLInputElement | null | undefined;
  render() {
    return (
      <>
        <h1>回调函数形式的ref</h1>
        <input ref={(c) => (this.inputRef = c;console.log('@',c);)} type="text" placeholder="请输入" />
        <button onClick={this.showData}>获取ref数据</button>
      </>
    );
  }
}

这样写就不会报错了,但是会有一个问题,当我render更新时,回调函数会一直调用。

这样写就可以解决这个问题:

ts
import React, { Component } from "react";

export default class example6 extends Component {
  state = { isHot: false };

  showInfo = () => {
    const { inputRef } = this;
    alert(inputRef!.value);
  };

  changeWeather = () => {
    //获取原来的状态
    const { isHot } = this.state;
    //更新状态
    this.setState({ isHot: !isHot });
  };

  saveInput = (c: HTMLInputElement | null | undefined) => {
    this.inputRef = c;
    console.log("@", c);
  };
  inputRef: HTMLInputElement | null | undefined;
  render() {
    const { isHot } = this.state;
    return (
      <>
        <h2>今天天气很{isHot ? "炎热" : "凉爽"}</h2>
        <input ref={this.saveInput} type="text" />
        <br />
        <br />
        <button onClick={this.showInfo}>点我提示输入的数据</button>
        <button onClick={this.changeWeather}>点我切换天气</button>
      </>
    );
  }
}
import React, { Component } from "react";

export default class example6 extends Component {
  state = { isHot: false };

  showInfo = () => {
    const { inputRef } = this;
    alert(inputRef!.value);
  };

  changeWeather = () => {
    //获取原来的状态
    const { isHot } = this.state;
    //更新状态
    this.setState({ isHot: !isHot });
  };

  saveInput = (c: HTMLInputElement | null | undefined) => {
    this.inputRef = c;
    console.log("@", c);
  };
  inputRef: HTMLInputElement | null | undefined;
  render() {
    const { isHot } = this.state;
    return (
      <>
        <h2>今天天气很{isHot ? "炎热" : "凉爽"}</h2>
        <input ref={this.saveInput} type="text" />
        <br />
        <br />
        <button onClick={this.showInfo}>点我提示输入的数据</button>
        <button onClick={this.changeWeather}>点我切换天气</button>
      </>
    );
  }
}

createRef 创建ref

这个方法相对于上面的都好用很多,个人觉得

ts
import React, { Component } from "react";

export default class example9 extends Component {
  myRef = React.createRef<HTMLInputElement>();
  myRef2 = React.createRef<HTMLInputElement>();
  //展示左侧输入框的数据
  showData = () => {
    alert(this.myRef.current!.value);
  };
  //展示右侧输入框的数据
  showData2 = () => {
    alert(this.myRef2.current!.value);
  };
  render() {
    return (
      <div>
        <input ref={this.myRef} type="text" placeholder="点击按钮提示数据" />
        &nbsp;
        <button onClick={this.showData}>点我提示左侧的数据</button>&nbsp;
        <input onBlur={this.showData2} ref={this.myRef2} type="text" placeholder="失去焦点提示数据" />
        &nbsp;
      </div>
    );
  }
}
import React, { Component } from "react";

export default class example9 extends Component {
  myRef = React.createRef<HTMLInputElement>();
  myRef2 = React.createRef<HTMLInputElement>();
  //展示左侧输入框的数据
  showData = () => {
    alert(this.myRef.current!.value);
  };
  //展示右侧输入框的数据
  showData2 = () => {
    alert(this.myRef2.current!.value);
  };
  render() {
    return (
      <div>
        <input ref={this.myRef} type="text" placeholder="点击按钮提示数据" />
        &nbsp;
        <button onClick={this.showData}>点我提示左侧的数据</button>&nbsp;
        <input onBlur={this.showData2} ref={this.myRef2} type="text" placeholder="失去焦点提示数据" />
        &nbsp;
      </div>
    );
  }
}

总结

React中的state、props、ref三颗螺丝我已经再次拧了一下,顺便也拧了拧class类的修饰符、this指向,箭头函数、泛型、类型断言、泛型工具、联合类型这几颗小螺丝。准备发车了,伙伴们准备好了嘛

今天特意设置了一个提醒,提醒今天是周四要发学习分享了

96e04c66575460dd90624f14f121952.jpg