React 入门:组件实例三大属性之state

state 介绍

state 即状态,通俗的讲,也是数据,对于组件而言我总结出以下几点:

  • 状态 state 是组件私有的,完全受控于当前组件。除了拥有并设置了它的组件,其他组件都无法访问。
  • state 用来管理组件内部的数据,数据的改变就是状态。
  • 尽管 state 是 React 本身设置的,且都拥有特殊的含义,但我们可以随意更改设置 state,通常我们会将 state 初始化为一个对象,使用起来更灵活方便。

可能与组件实例的另外一大属性 props 相比较来讲更容易理解,state 用来管理组件内部的数据,props 用来管理组件外部传进来的数据。

准备代码

先准备一个基础类式组件:

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <title>state</title>
</head>

<body>
    <!-- 准备好一个容器 -->
    <div id="app"></div>

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

    <script type="text/babel"> /* 此处一定要写babel */

        // 1. 创建类式组件
        class Weather extends React.Component {
            constructor(props) {
                super(props);
            }

            render() {
                return <h2 onClick={this.changeWeather}>今天天气很凉爽,微风。</h2>
            }
        }

        // 渲染组件到页面
        ReactDOM.render(<Weather/>, document.getElementById('app'));
    </script>
</body>

</html>

下文的代码片段都可以添加到该组件,来运行以验证结果。

state 初始化

在类式组件的构造器中初始化状态 state,代码片段如下:

constructor (props) {
    super(props);

    // 初始化状态 state
    this.state = {isHot: true, wind: '微风'};

    // TODO 其他代码……
}

注意:构造器中是唯一可以通过 this.state = {...} 的形式赋值的地方。

读取 state

  • 在 render 方法中,可通过 this 直接读取,代码片段如下:
render() {
    const {isHot, wind} = this.state;
    return <h1>今天天气很{isHot ? '炎热' : '凉爽'}{wind}</h1>;
}
  • 在用户自定义的类的方法中,无法通过 this 直接读取,代码片段如下:
// 定义类的方法
changeWeather() {
    console.log(this); // 控制台输入:undefined
}

// 调用自定义方法
render() {
    const {isHot, wind} = this.state;
    return <h1 onClick={this.changeWeather}>今天天气很{isHot ? '炎热' : '凉爽'}{wind}</h1>;
}

将代码文件通过 Live Server 在浏览器中打开, 点击 h1 标题文本,浏览器控制台输出如下:
在这里插入图片描述

此时自定义方法中的 this 是 undefined,原因如下:

  • 由于 changeWeather 是作为 onClick 的回调,所以不是通过实例调用的,是直接调用;
  • 类中的方法默认开启了局部的严格模式,所以 changeWeather 中的 this 为 undefined。

如何解决上面的问题呢?其实很简单,只要想办法让自定义方法中的 this 指向组件实例对象即可。

改变类式组件中自定义方法的 this 指向

在组件的构造器中通过 bind 方法来改变类中自定义的方法的 this 指向,并将其指向组件实例。代码片段如下:

constructor (props) {
    super(props);

    // 初始化状态 state
    this.state = {isHot: true, wind: '微风'};

    // 改变 changeWeather 中 this 指向
    this.changeWeather = this.changeWeather.bind(this);
}

将代码文件通过 Live Server 在浏览器中打开, 点击 h1 标题文本,浏览器控制台输出如下:
在这里插入图片描述

更改设置 state

  • 不能直接修改 state。
// 下面这样的写法是错误的
this.state.isHot = false;

通过上面的方式虽然不会报错,但是不会重新渲染组件。

  • state 必须通过 setState 进行合并更新。
    当调用 setState() 的时候,React 会把你提供的对象合并到当前的 state,而不是替换。
changeWeather() {
    // 获取原来的 isHot 值
    const isHot = this.state.isHot;

    // 状态必须通过 setState 进行更新,且更新是一种合并,不是替换。
    this.setState({isHot: !isHot});
}

此时代码文件通过 Live Server 在浏览器中打开, 点击 h1 标题文本,就会交替显示“炎热”和“凉爽”。

完整代码(state 标准写法)

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <title>state</title>
</head>

<body>
    <!-- 准备好一个容器 -->
    <div id="app"></div>

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

    <script type="text/babel"> /* 此处一定要写babel */

        // 1. 创建类式组件
        class Weather extends React.Component {
            constructor(props) {
                super(props);

                // 初始化状态 state
                this.state = {isHot: true, wind: '微风'};

                // 改变 changeWeather 中 this 指向
                this.changeWeather = this.changeWeather.bind(this);
            }

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

            changeWeather() {
                // 获取原来的 isHot 值
                const isHot = this.state.isHot;

                // 状态必须通过 setState 进行更新,且更新是一种合并,不是替换。
                this.setState({isHot: !isHot});
            }
        }

        // 渲染组件到页面
        ReactDOM.render(<Weather/>, document.getElementById('app'));
    </script>
</body>

</html>

state 的简写方式

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <title>state</title>
</head>

<body>
    <!-- 准备好一个容器 -->
    <div id="app"></div>

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

    <script type="text/babel"> /* 此处一定要写babel */

        // 1. 创建类式组件
        class Weather extends React.Component {

            // 初始化 state
            state = {isHot: true, wind: '微风'};

            // 自定义方法
            changeWeather = () => {
                const isHot = this.state.isHot;
                this.setState({isHot: !isHot});
            }

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

        // 渲染组件到页面
        ReactDOM.render(<Weather/>, document.getElementById('app'));
    </script>
</body>

</html>

简写方式解析,实际上都是用了 js 语言的本身的一些特性:

  • 简写后的初始化 state,就是类中通过赋值语句定义属性的语法,这种方式定义的属性,会被放到类的实例对象上;
  • 简写后的自定义方法是结合了赋值语句箭头函数的特性,复制语句和初始化 state 思路一样,箭头函数特点之一就是它内部没有自己的 this ,而是指向箭头函数外部的对象 ,而赋值语句定义的属性又被放到了类的实例对象上,从而也解决了自定义方法 this 指向的问题。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

西涯三锋

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值