state

F_Sharp
• 阅读 957

基本用法

React中,有一个重要的概念,就是组件的状态state,它用来表示整个组件的数据模型,是组件渲染时的数据依据。这里,我们首先通过一个简单的示例:计数器,来讲解state的用法。首先创建这个组件:

import React, { Component } from "react"
import ReactDOM from "react-dom"

class Counter extends Component {
  render() {
    return (
      <div>
        <h1>一共点击了0次</h1>
        <input type="button" value="+" />
        <input type="button" value="-" />
      </div>
    )
  }
}

ReactDOM.render(<Counter />, document.querySelector("#root"))

我们使用h1元素用来标志用户点击次数,然后提供两个按钮给用户进行点击。当用户点击+按钮时,次数递增,同理,点击-按钮,次数递减。

接下来,我们再来看一下如何添加组件的状态,在react中,状态是通过state属性来描述的,我们首先在组件中定义这个属性,然后再添加一个count用来描述用户点击的次数,初始值为0:

class Counter extends Component {

  state = {
    count: 0
  }
  
  ...
}

然后再把这个状态值绑定到h1元素中,这里我们可以使用表达式来访问这些状态。

<h1>一共点击了{this.state.count}次</h1>

当完成这一步之后,整个组件就变成一个有状态组件了,接下来,就是用户的操作,我们首先给这两个按钮添加点击事件,方法很简单,我们只需要在按钮的元素上添加onClick属性就可以绑定点击事件,这里表达式中的函数,就是当用户点击按钮时触发的事件句柄。

<input type="button" onClick={() => console.log("in")} value="+" />
<input type="button" onClick={() => console.log("de")} value="-" />

点击之后可以看到控制台已经输出,说明这个函数被调用了。

除了这种直接声明函数的方式以外,我们还可以在组件类内部来定义这个函数。

import React, { Component } from "react"
import ReactDOM from "react-dom"

class Counter extends Component {

  state = {
    count: 0
  }

  increment = () => {
    console.log("in")
  }

  decrement = () => {
    console.log("de")
  }

  render() {
    return (
      <div>
        <h1>一共点击了{this.state.count}次</h1>
        <input type="button" onClick={this.increment} value="+" />
        <input type="button" onClick={this.decrement} value="-" />
      </div>
    )
  }
}

ReactDOM.render(<Counter />, document.querySelector("#root"))

点击之后,我们看到依然成功触发。

接下来,我们需要在用户点击按钮的时候,更新count的状态值。React提供了一个方法用来更新组件的state,我们只需要在这些方法中,通过调用this.setState,来更新状态就可以了:

increment = () => {
    this.setState({
        count: this.state.count + 1
    })
}

decrement = () => {
    this.setState({
        count: this.state.count - 1
    })
}

setState方法接收一个对象作为参数,然后它会将这个对象合并到当前的state中,从而达到更新的目的。这时,当我们再点击按钮时,可以看到页面就会自动更新了。以上操作就是state的基本用法。

MVC

接下来我们再来了解一下React中的状态管理机制。在前端的开发中,我们经常提到MVC的概念,同时,很多前端框架也说自己是基于MVC,那什么是MVC呢?单从概念上理解,MVC实际上指的是一种软件开发的设计思路,它将我们的代码,从组织的形式上,分成了3个部分,分别是ViewModelController,也就是视图,数据模型和控制器。

state

  • View:视图,实际上指的就是用户操作界面。
  • Model:数据模型,指的就是应用的内部数据,它可以是用户看到的数据,也可能是某些视图的显示状态,这些数据我们统统称之为应用的状态。
  • Controller:控制器,指的就是整个应用的逻辑处理,比如用户的行为,数据的处理等等,我们常常把这一部分定义成方法,当成控制器来统一管理。

接下来,我们再来看看这三部分之间的关系,视图层View是用来展示应用数据的,因此,我们将Model中的数据交给View,同时,在视图层中,还绑定了不同类型的事件等待用户触发,当用户触发某一类型的事件的时候,比如点击了某个按钮,这时,Controller控制器中的方法被执行,在这些方法中,会涉及到不同业务的处理,处理完成之后,会去更新应用中的数据状态,当数据状态发生更新时,会通知其视图层进行更新。这时,用户就可以看到最新的数据了。从这种数据流的方式上我们可以发现,整个视图的显示,实际上就是依赖于应用中的Model,当Model一旦发生更新,View也会随着它的更新而更新。

下面我们在来看一下,MVC的这种设计思路,在React框架中是如何体现的,回到刚刚计数器那个示例。

state

我们可以看到,在Counter组件中:

  • state相当于MVC中的Model,也就是整个应用的数据状态;
  • incrementdecrement这两个方法就是Controller控制器,调用时更新state
  • render方法的返回值,就是应用的用户界面View

state

  1. 在页面初始化时,render方法被调用,同时返回整个页面的结构,ReactDOM会根据这个结构来构建用户界面。渲染完成之后,页面进入到运行阶段,等待用户进行操作。
  2. 当用户触发某种事件时,组件内部的方法被调用,也就是controller被执行,这时,应用执行相应的业务处理,完成之后,调用setState方法来更新当前的状态值。
  3. state完成更新之后,调用render方法,获取到当前最新的页面结构。
  4. 更新view,用户就可以看到最新的页面了。

从以上的流程上我们可以知道,View的展示,依赖于state,当state更新时,View也会主动更新。在传统的方式中,当页面构建完成之后,如果需要更新页面中的某个数据时,我们首先需要拿到绑定了这个数据的节点,然后将新的数据更新到这个节点中,才能完成视图的更新。但是在react中,我们不再需要考虑怎样去拿到节点,更新数据,而是直接修改state状态即可,关于视图的更新,则交给react自行完成,这样的方式,让我们从繁琐的节点操作中脱离出来,直接面向数据进行操作。

点赞
收藏
评论区
推荐文章
亚瑟 亚瑟
4年前
自定义 Hook – React
自定义Hook_Hook_是React16.8的新增特性。它可以让你在不编写class的情况下使用state以及其他的React特性。通过自定义Hook,可以将组件逻辑提取到可重用的函数中。在我们学习时,我们已经见过这个聊天程序中的组件,该组件用于显示好友的在线状态:importReact,{useSta
浩浩 浩浩
4年前
【Flutter实战】布局类组件简介
4.1布局类组件简介布局类组件都会包含一个或多个子组件,不同的布局类组件对子组件排版(layout)方式不同。我们在前面说过Element树才是最终的绘制树,Element树是通过Widget树来创建的(通过Widget.createElement()),Widget其实就是Element的配置数据。在Flutter中,根据Widget是否
浩浩 浩浩
4年前
【Flutter实战】输入框和表单
3.7输入框及表单Material组件库中提供了输入框组件TextField和表单组件Form。下面我们分别介绍一下。3.7.1TextFieldTextField用于文本输入,它提供了很多属性,我们先简单介绍一下主要属性的作用,然后通过几个示例来演示一下关键属性的用法。dartconstTextField({...
Easter79 Easter79
4年前
TypeScript Generics(泛型)
软件工程的一个主要部分就是构建组件,构建的组件不仅需要具有明确的定义和统一的接口,同时也需要组件可复用。支持现有的数据类型和将来添加的数据类型的组件为大型软件系统的开发过程提供很好的灵活性。在C和Java中,可以使用"泛型"来创建可复用的组件,并且组件可支持多种数据类型。这样便可以让用户根据自己的数据类型来使用组件。泛型的简单案例首先,
可莉 可莉
4年前
14Flutter StatefulWidget有状态组件、页面上绑定数据、改变页面数据、实现计数器功能、动态列表
/FlutterStatefulWidget有状态组件、页面上绑定数据、改变页面数据在Flutter中自定义组件其实就是一个类,这个类需要继承StatelessWidget/StatefulWidgetStatelessWidget是无状态组件,状态不可变得widgetStatef
Stella981 Stella981
4年前
React.js 时间组件 + 组件生命周期(更新模拟)
React是用于构建用户界面的JavaScript库,React组件使用一个名为render()的方法,接收数据作为输入,输出页面中对应展示的内容。React除了可以使用外部传入的数据以外(通过this.props访问传入数据),组件还可以拥有其内部的状态数据(通过this.state访问状态数据)。当组件的状态
Stella981 Stella981
4年前
CocosCreator 代码组件(创建与使用、cc.Class类型、生命周期函数)(第三篇)
前言:在前面一篇中讲解了场景的搭建,现在开始介绍一个重要的部分代码组件,通过在不同节点上挂载不同逻辑功能的代码组件来实现游戏的开发。VSCode下载链接:https://code.visualstudio.com/(https://www.oschina.net/action/GoToLink?urlhttps%3A%
程序员小五 程序员小五
1年前
融云IM干货丨uni-app中的uni-list 插件具体怎么用?
unilist是uniapp中用于构建列表的组件,以下是具体的使用方法:1.基本用法导入组件:首先,你需要在你的页面或组件中导入unilist和unilistitem组件。例如:javascriptimportuniListfrom'@/component
陈杨 陈杨
8个月前
鸿蒙5横向柱状图series属性解析
大家好,欢迎回来鸿蒙5莓创图表组件的专场,我们这一期来讲解McHorBarChart(横向柱状图)组件中series属性的详细用法。series属性是控制柱状图数据系列的核心配置项,掌握好这些属性可以让你轻松创建各种样式的柱状图效果。1.name属性作用:
陈杨 陈杨
8个月前
鸿蒙5莓创横向柱状图legend属性详解
大家好,欢迎回来鸿蒙5莓创图表组件的专场,我们这一期来讲解组合图组件中legend属性的详细用法。legend(图例)是图表中非常重要的组成部分,它帮助用户理解图表中不同颜色或形状所代表的数据系列。下面我们将全面解析legend的各个属性及其用法。1.sh
陈杨 陈杨
8个月前
鸿蒙5莓创横向柱状图tooltip属性详解
大家好,欢迎回来鸿蒙5莓创图表组件的专场,我们这一期来讲解横向柱状图(McHorBarChart)中tooltip属性的详细用法。tooltip是图表中非常重要的交互组件,它能够在用户悬停或点击时显示详细的数据信息。下面我们将全面解析tooltip的各个属