React三大属性之props与refs简介

本文详细介绍了React中Props和Refs的使用方法,包括Props的基本概念、Props类型验证、默认Props设置,以及Refs的不同使用方式等内容。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

之前介绍的state属性主要作用是标记组件的状态,且可以在初始化组件时就设置,而props属性主要是用来接收外部传入的数据。考虑如下诉求:实现人的信息的展示,人的信息由组件外的数据传入。此时需要使用props属性,React能自动收集组件标签中的各个属性数据,放入props属性中,然后在render方法中可以使用props属性中的数据:

class MyDemo extends React.Component{
    render() {
        const {name, age, sex} = this.props;
        return (
            <h1>
                <ul>
                    <li>姓名:{name}</li>
                    <li>年龄:{age}</li>
                    <li>性别:{sex}</li>
                </ul>
            </h1>)
    }
}
ReactDOM.render(<MyDemo name="Jack" age="18" sex="男"/>, document.getElementById("test"));

如果觉得MyDemo标签中写上各个属性很麻烦,可以自定义一个对象p,然后使用扩展运算符传入:

class MyDemo extends React.Component{
    render() {
        const {name, age, sex} = this.props;
        return (
            <h1>
                <ul>
                    <li>姓名:{name}</li>
                    <li>年龄:{age}</li>
                    <li>性别:{sex}</li>
                </ul>
            </h1>)
    }
}
let p = {name: "Jack", age: "18", sex: "男"};
ReactDOM.render(<MyDemo {...p}/>, document.getElementById("test"));

注意,在javascript中,扩展运算符...本不可以使用于对象,只能用在实现了iterator接口的对象上,但在React中能这样使用,且必须加上大括号,且只能在组件标签中这样写。但是javascript中也有大括号里使用扩展运算法作用于对象的情况,表示复制一个对象,而且是深复制,即所有属性都会重新克隆一份。React的这种大括号中使用扩展运算法作用于对象与javascript的大括号中使用扩展运算法作用于对象没有任何关系,前者只是React的jsx的一种特殊写法而已。

如果需要对传入的属性做一些约束,需要引入prop-types.js

<script src="../static/js/prop-types.js"></script>

然后在类组件外面加上类型约束和默认值约束:

MyDemo.propTypes = {
    name:PropTypes.string.isRequired,
    age:PropTypes.number,
    sex:PropTypes.string
}
MyDemo.defaultProps = {
    sex: "男",
}

这样,如果传入的名字或者性别非字符串,或者年龄非数字,则控制台会出现警告,但友好的是,依然会显示出来。如果没传性别,则为男。这些约束相当于在类上面(而非实例对象)加了propTypes和defaultProps两个属性,React会自动识别作为约束。这些约束的单词或者大小写非常容易写错,需要注意。上述约束可以简写在类里,用static关键字表示为类属性:

class MyDemo extends React.Component{
    render() {
        const {name, age, sex} = this.props;
        return (
            <h1>
                <ul>
                    <li>姓名:{name}</li>
                    <li>年龄:{age}</li>
                    <li>性别:{sex}</li>
                </ul>
            </h1>)
    }
    static propTypes = {
        name:PropTypes.string.isRequired,
        age:PropTypes.number,
        sex:PropTypes.string
    }
    static defaultProps = {
        sex: "男",
    }
}

补充一下函数类型的约束:

static propTypes = {
    name:PropTypes.string.isRequired,
    age:PropTypes.number,
    sex:PropTypes.string,
    fun:PropTypes.func.isRequired
}

props属性也可以在构造器中传入,但一般不这样用,详情可参见尚硅谷React技术全家桶全套完整版。props作为React组件三大属性之一,是唯一一个能被函数式组件使用的属性,state和refs都不能被函数式组件使用,上述例子使用函数式组件代码如下:

function MyDemo (props) {
    const {name, age, sex} = props;
    return (
        <h1>
            <ul>
                <li>姓名:{name}</li>
                <li>年龄:{age}</li>
                <li>性别:{sex}</li>
            </ul>
        </h1>);
}
MyDemo.propTypes = {
    name:PropTypes.string.isRequired,
    age:PropTypes.number,
    sex:PropTypes.string,
}
MyDemo.defaultProps = {
    sex: "男",
}

接下来是refs属性,refs属性主要用来取节点,代替document.getElementById类似的方法。考虑如下诉求:点击按钮,在控制台打印输入框1的内容,输入框2失去焦点,打印输入框2的内容。

class MyDemo extends React.Component{
    render() {
        return (
                <div>
                    <input ref="input1" type="text" placeholder="点击按钮打印数据"/> &nbsp;
                    <button onClick={this.showData1}>按钮</button> &nbsp;
                    <input ref="input2" onBlur={this.showData2} type="text" placeholder="失去焦点打印数据"/>
                </div>
            )
    }
    showData1 = () => {
        console.log(this.refs.input1.value);
    }

    showData2 = () => {
        console.log(this.refs.input2.value);
    }
}
ReactDOM.render(<MyDemo/>, document.getElementById("test1"));

上述实现方式使用了字符串形式的refs,只要在标签中添加ref属性,然后就可以在this.refs中获取到相应节点,节点名ref属性值。但React官网并不推荐字符串形式的refs,以下使用函数式refs:

class MyDemo extends React.Component{
    render() {
        return (
                <div>
                    <input ref={c => this.input1 = c} type="text" placeholder="点击按钮打印数据"/> &nbsp;
                    <button onClick={this.showData1}>按钮</button> &nbsp;
                    <input ref={c => this.input2 = c} onBlur={this.showData2} type="text" placeholder="失去焦点打印数据"/>
                </div>
            )
    }
    showData1 = () => {
        console.log(this.input1.value);
    }

    showData2 = () => {
        console.log(this.input2.value);
    }
}

函数的入参就是当前节点,函数体就是将给当前对象挂上一个属性,名为input1,值为当前节点,因此使用时直接写this.input1.value。注意这里的回调函数是一个箭头函数,或者说匿名函数,在React初始渲染时,该函数会调用一次,如果组件更新导致React重新渲染,则该匿名函数会再调用两次,依次传入的当前节点c为null,第二次才是真正的节点,可以通过控制台打印观察。如果想避免这种小问题,可以新定义一个箭头函数:

class MyDemo extends React.Component{
    render() {
        return (
                <div>
                    <input ref={this.saveInput1} type="text" placeholder="点击按钮打印数据"/> &nbsp;
                    <button onClick={this.showData1}>按钮</button> &nbsp;
                    <input ref={c => this.input2 = c} onBlur={this.showData2} type="text" placeholder="失去焦点打印数据"/>
                </div>
            )
    }
    showData1 = () => {
        console.log(this.input1.value);
    }

    showData2 = () => {
        console.log(this.input2.value);
    }

    saveInput1 = (currentNode) => {
        this.input1 = currentNode;
    }
}

React官方也认为上述问题无足轻重,因此真实开发中直接用内联的箭头函数也ok。说个题外话,jsx中的注释写法也需要注意,不能直接ctrl+/,否则可能会报红(只是可能)。建议使用/* 代码 */先包起来,再用大括号{}包起来,这样注释万无一失。接下来是refs的最后一种形式:React.createRef(),这种形式不如函数的形式用得多,但也是React官网推荐的,主要思想是建议一个容器,ref属性的值都会自动存在容器中,但一个容器只能有一个ref,后来者会替换掉先来者,代码如下:

class MyDemo extends React.Component{
    myRef1 = React.createRef();
    myRef2 = React.createRef();
    render() {
        return (
                <div>
                    <input ref={this.myRef1} type="text" placeholder="点击按钮打印数据"/> &nbsp;
                    <button onClick={this.showData1}>按钮</button> &nbsp;
                    <input ref={this.myRef2} onBlur={this.showData2} type="text" placeholder="失去焦点打印数据"/>
                </div>
            )
    }
    showData1 = () => {
        console.log(this.myRef1.current.value);
    }

    showData2 = () => {
        console.log(this.myRef2.current.value);
    }
}

需要注意的是,获取节点的方式时不要忘记current,这是React中的固定key的名字。

回答: React中的属性props、state和refs。\[1\] props是组件的属性,可以通过this.props来访问。它可以用来传递数据给组件,并且可以对属性值进行类型限制和必要性限制。可以使用PropTypes来进行属性类型的限制,也可以设置默认属性值。\[1\] state是组件的状态,可以通过this.state来访问。它用于存储组件内部的数据,并且可以通过setState方法来更新状态。状态的改变会触发组件的重新渲染。\[2\] refs是用来标识组件内部标签的引用。它可以通过字符串形式或者React.createRef()来定义。通过refs可以获取到标签的真实DOM节点或者组件实例。\[3\] 这属性React中非常重要,可以帮助我们管理组件的数据和交互。 #### 引用[.reference_title] - *1* [react属性](https://blog.csdn.net/weixin_30617797/article/details/102410491)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* *3* [React —— React中组件的属性(state,props,ref)](https://blog.csdn.net/Bonsoir777/article/details/127568414)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值