首页 > 编程语言 >React 面向组件编程 之 类式组件、组件实例的三大核心属性

React 面向组件编程 之 类式组件、组件实例的三大核心属性

时间:2022-09-22 10:23:47浏览次数:56  
标签:render App Component React test 组件 类式

类式组件

import React, { Component } from "react";

export default class App extends Component {
    render() {
        return <h2>我是类式组件</h2>
    }
}

创建类式组件,必须继承React.Component,render必须写,render必须要有返回值。


组件实例的三大核心属性 1:state

state是组件对象最重要的属性,值必须是对象。

组件被称为状态机,通过更新组件的state来更新对应页面的显式,重新渲染组件。

强烈注意:

  • 组件中的render方法中的this,为组件的实例对象
  • 组件中自定义的方法,this为undefined,如何解决?
    • 第一种方法:通过函数bind强制绑定this
    • 第二种方法:使用赋值语句+箭头函数(主流推荐)
  • state不可以直接更新,必须通过React提供的API来进行更新,setState。
import React, { Component } from "react";

export default class App extends Component {

    // 自定义方法
    test() {
        console.log(this); // undefined
    }

    render() {
        return (
            <button onClick={this.test}>test</button>
        )
    }
}

为什么自定义方法test()的this会为undefined?

答:首先,test方法是放在App的原型对象上的,供实例对象使用。

了解this指向的同学应该知道,在对象上的方法,其this的指向是,谁调用这个方法,就指向谁。

但由于,test是作为onClick的回调,所以并不是通过实例对象去调用的,而是直接调用,因此this的指向本应该是window。

然而类中的方法默认开启了局部的严格模式,所以test中的this为undefined。


解决方法:

第一种,通过函数bind强制绑定this

import React, { Component } from "react";

export default class App extends Component {
    // 如果写了构造器,一定要接受props,和super(props)去传props,不然会出现undefined的bug
    constructor(props) {
        super(props);
        this.test = this.test.bind(this);
    }

    // 自定义方法
    test() {
        console.log(this); // App {props: {…}, context: {…}, refs: {…}, updater: {…}, test: ƒ, …}
    }

    render() {
        return (
            <button onClick={this.test}>test</button>
        )
    }
}

第二种,使用赋值语句+箭头函数(主流推荐)

import React, { Component } from "react";

export default class App extends Component {
    test = () => {
        console.log(this); // App {props: {…}, context: {…}, refs: {…}, updater: {…}, test: ƒ, …}
    }

    render() {
        return (
            <button onClick={this.test}>test</button>
        )
    }
}

为什么将普通函数写成箭头函数就可以使得this指向实例对象呢?

答:箭头函数的this指向,是定义时所在的作用域指向的对象,而不是使用时所在的作用域指向的对象,因此指向实例对象App


类式组件中state的使用:

import React, { Component } from "react";

export default class App extends Component {
    // state初始化状态
    state = {count: 1}

    add = () => {
        let { count } = this.state;
        // 更新state的API
        this.setState({ count: count + 1 });
    }

    render() {
        return (
            <>
                <h2>{ this.state.count }</h2>
                <button onClick={ this.add }>+1</button>
            </>
        )
    }
}

组件实例的三大核心属性 2:props

props是只读的,无法修改。

import React, { Component } from "react";

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

// 将App组件标签渲染到index页面的div上
ReactDOM.createRoot(document.getElementById('root')).render(<App name="cxk" sex="女" age="22" />);

批量传递props

let obj = {
    name: 'cxk',
    sex: '女',
    age: '22'
};

ReactDOM.createRoot(document.getElementById('root')).render(<App {...obj} />);

为什么这里的...obj不会报错?

答:众所周知,...展开运算符是无法展开对象的。

但在原生JS中{...obj}的写法,不会报错,因为它是复制对象的一种写法。

然而在React中,{...obj},最外层的{},只是单纯的表示里面要写js表达式了,因此这里真的只是...obj。

但既然对象无法展开,会报错,那为什么这里...obj不会报错呢?

因为React中babel会将...p翻译,如果在原生JS中...obj必然会报错。


组件实例的三大核心属性 3:refs

refs是React中用来取得某个JSX组件或者某个DOM中的一些状态值的时候,用来获取节点的方法。

在React官方的解释中,它的适用范围如下:

  • 管理焦点,文本选择或媒体播放。
  • 触发强制动画。
  • 集成第三方 DOM 库。

React文档中再三强调,请不要过度使用refs,所以当我们可以用dom原生对象解决时,尽量不要使用refs。


1、字符串形式的ref

这里的ref可以理解为id。

字符串形式的ref已经不被官方推荐使用了,之后很有可能会被删除。

因为string类型的ref存在效率问题,写多了程序会很慢。但是在之前版本的编码中还是有很多人使用,因为它太方便了。

import React, { Component } from "react";

export default class App extends Component {
    showData = () => {
        // 这是获取到一个真实DOM
        console.log(this.refs.input1);
    }
    showData2 = () => {
        alert(this.refs.input2.value)
    }
    render() {
        return (
            <div>
                <input ref="input1" type="text" placeholder="点击按钮提示数据" />&nbsp;
                <button ref="button1" onClick={this.showData}>点我提示左侧的数据</button>&nbsp;
                <input ref="input2" type="text" placeholder="失去焦点提示数据" onBlur={this.showData2} />
            </div>
        )
    }
}

2、 回调函数形式的ref

import React, { Component } from "react";

export default class App extends Component {
    showData = () => {
        // 这是获取到一个真实DOM
        console.log(this.input1.value);
    }
    showData2 = () => {
        alert(this.input2.value)
    }
    render() {
        return (
            <div>
                <input ref={c => { this.input1 = c }} type="text" placeholder="点击按钮提示数据" />&nbsp;
                <button ref={c => { this.button1 = c }} onClick={this.showData}>点我提示左侧的数据</button>&nbsp;
                <input ref={c => {this.input2 = c }} type="text" placeholder="失去焦点提示数据" onBlur={this.showData2} />
            </div>
        )
    }
}

回调ref中回调执行次数的问题

如果ref回调函数是以内联函数的方式定义的,那么在更新状态state的过程中,它会被执行两次。

第一次传入参数null,然后第二次会传入参数DOM元素,这是因为在每次渲染时会创建一个新的函数实例,所以react为了清空旧的ref并且设置新的。

通过将ref的回调函数定义成class的绑定函数的方式可以避免上述问题,但大多时候这个问题是无关紧要的。

开发中,都是写成内联的。


3、createRef的使用

React官方最推荐的创建ref的方法:

import React, { Component } from "react";

export default class App extends Component {
    myRef = React.createRef();
    myRef2 = React.createRef();

    showData = () => {
        // 这是获取到一个真实DOM
        console.log(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 ref={ this.myRef2 } type="text" placeholder="失去焦点提示数据" onBlur={this.showData2} />
            </div>
        )
    }
}

4、React中的事件处理

请勿过度使用ref。触发事件的元素,和获取数据的元素,是同一个DOM元素的时候,可以不用写ref:

import React, { Component } from "react";

export default class App extends Component {
    showData = (event) => {
        alert(event.target.value);
    }

    render() {
        return (
            <div>
                <input ype="text" placeholder="失去焦点提示数据" onBlur={this.showData} />
            </div>
        )
    }
}

标签:render,App,Component,React,test,组件,类式
From: https://www.cnblogs.com/luckest/p/16718240.html

相关文章

  • vue3 基础-动态组件 & 异步组件
    之前学习的都是父子组件传值的话题,一句话总结就是,常规数据通过属性传,dom结构通过插槽slot来传.而本篇则关注如何通过数据去控制组件的显示问题,如咱经常用到的......
  • 基本组件之 UISprite 面板控制
    1基本组件之UISprite面板控制1.1.UISprite显示图片①创建UISprite组件,步骤:NGUI-->Create-->Sprite;②选择图集,选择要显示的图片;\③Widget中点击“Snap”按钮,让......
  • vue学习笔记(二):vue目录结构,及vue组件和用法
    一、目录结构: 二、vue组件:  项目目录中的app.vue是一个顶级组件,可以删除里面的代码,然后来重新写:  注意:<template>标签下面只能有一个根元素,也就是说下面的写......
  • Axure RP大数据可视化大屏原型组件源文件
    AxureRP大数据可视化大屏原型模板大数据BI分析上大屏,在很多大企业和政府单位客户都需要,高新区市场监控等,那使用AxureRP做交互原型是必不可少的,有了大屏原型模板可做出不......
  • React 路由5
    大家好,又见面了,我是你们的朋友全栈君。ReactReact路由对SPA的理解1.单页Web应用(singlepagewebapplication,SPA)。2.整个应用只有一个完整的页面。3.点击页面......
  • react-antd组件之Steps组件自定义icon svg图片颜色跟随完成进度改变
    demo.svg<?xmlversion="1.0"encoding="UTF-8"?><svgwidth="58px"height="44px"viewBox="005844"version="1.1"xmlns="http://www.w3.org/2000/svg"xmlns:xli......
  • 封装分页组件
    效果图   主要框架:vue2+element一:pagination组件代码<template><!--原理:分页中有三个地方需要使用插槽(首页,末页,确定),一个分页模块中只能使用一个插槽,所以......
  • sass在react中的基本使用
    1.安装sass较新的版本不需要配置sass-loader等一系列插件,安装即用。npminstall--save-devsass2.编写App.tsx中的基本DOM更改app.css为app.scss,并删除其中全部内......
  • react hooks组件父组件调用子组件方法
    函数组件父组件调用子组件方法需要使用useImperativeHandle和forwardRef两个方法1.子组件    2.父组件 注意:一定要使用ref来接从子组件传过来的实例值,用......
  • 本周四晚19:00知识赋能第八期第2课丨ArkUI自定义组件
     9月21日19:00~20:00,第八期知识赋能第2节直播就要开始啦!本次直播将为同学们带来涂鸦小游戏的趣味体验,让大家全面了解ArkUI框架的应用,帮助你们在自己已有专业的基础上拓宽知......