草庐IT

第四节:React组件状态的State属性

曹老师 2023-09-28 原文

1. State状态理解

关于state的理解

  1. state 是组件对象中最重要的属性,值是对象(可以包含多个数据)

  2. 组件被称为"状态机",通过更新组件的state来更新对应的页面显示(重新渲染组件)

  3. state是组件实例的属性,函数组件没有实例,因为函数组件没有状态

  4. state可以理解是组件自己的数据, props数据是外部传入,state数据就是组件自己的

2. State状态的使用

2.1 state使用规则
  1. state 通常在组件的constructor中进行初始化

  2. state 只能用setState方法更新

  3. setState会导致render重新执行,渲染组件和所有的子组件

1) 初始化状态
constructor(props){
    super(props)

    // 定义state状态
    this.state = {
        flag: true,
        firstMsg: "天王盖地虎",
        lastMsg : "小鸡炖蘑菇"
    }
}

2) 读取某个状态值
render(){
    let flag = this.state.flag;
    let firstMsg = this.state.firstMsg;
    let lastMsg = this.state.lastMsg;

    // 简写方式: 结构获取state中的数据
    // let {flag,firstMsg, lastMsg} = this.state;

    return (
      <div> { flag ? firstMsg :lastMsg}</div>
    )
  }

3) 更新状态 --> 组件界面更新
this.setState({
    stateProp1: value1,
    stateProp2: value2
})

2.2 示例代码:
class MyCom extends React.Component{
    constructor(props){
        super(props);

        // 定义state状态
        this.state = {
            flag: true,
            firstMsg: "天王盖地虎",
            lastMsg : "小鸡炖蘑菇"
        }
    }

    changeFlag = () => {

        // 修改state状态数据
        this.setState({
            // 取出状态取反,然后改变状态
            flag : !this.state.flag
        })
    }

    render(){
        // let flag = this.state.flag;
        // let firstMsg = this.state.firstMsg;
        // let lastMsg = this.state.lastMsg;

        let {flag,firstMsg, lastMsg} = this.state;

        return (
            <div onClick={ this.changeFlag }> { flag ? firstMsg :lastMsg}</div>
        )
    }
}

ReactDOM.render(<MyCom/>, document.getElementById("app"))

示例说明:

  1. setState每次修改内容会自动触发React重新渲染页面
  2. 因此示例中每次点击都会修改状态,更加状态重新渲染内容,达到内容切换的目的
2.3 状态的简写定义
2.3.1 说明:
  1. ES6 class类中 constructor 函数为构造函数, 内部通过this定义的属性是类实例的属性
  2. class类中其他的方法确实实例原型上的方法
  3. 但是class类中的表达式定义的内容确实实例上的内容
2.3.2 示例
class Person{
    constructor(){
        // 实例属性
        this.name = "张三"
    }

    // 实例上的属性
    age = 18

    // 实例上的方法
    eat = function(){
        console.log("eat")
    }

    // 原型上的方法
    run(){
        console.log("eat")
    }
}

var xm = new Person
console.log(xm)

/*
打印结果:
    Person {age: 18, name: "张三", eat: ƒ}
        age: 18
        eat: ƒ ()
        name: "张三"
        __proto__:
            constructor: class Person
            run: ƒ run()
            __proto__: Object
*/

示例说明:

  1. ES6中class类里定义的表达式,无论是函数表达式,函数普通的表达式,最后都是实例的属性或方法
  2. ES6中class类中普通定义的函数是实例原型上的方法

因此我们如果想简写state的定义,就可以如下定义:

示例代码:

class MyCom extends React.Component{
    constructor(props){
        super(props);

    }

    // 初始化定义state状态
    state = {
        flag: true,
        firstMsg: "天王盖地虎",
        lastMsg : "小鸡炖蘑菇"
    }

   // 组件实例化上的方法
    changeFlag = () => {

        // 修改state状态数据
        this.setState({
            // 取出状态取反,然后改变状态
            flag : !this.state.flag
        })
    }

    render(){

        let {flag,firstMsg, lastMsg} = this.state;

        return (
            <div onClick={ this.changeFlag }> { flag ? firstMsg :lastMsg}</div>
        )
    }
}

ReactDOM.render(<MyCom/>, document.getElementById("app"))

3. 关于函数组件

3.1 说明
  1. 不知道有没有人这么思考过, 函数组件没有状态
  2. 我们是否可以使用变量来模拟状态的概念呢
  3. 好像状态也就是一个数据, 定义的变量来存储数据是否可以
3.2 示例代码:
// 定义数据
let state = {
    flag: true,
    firstMsg: "天王盖地虎",
    lastMsg : "小鸡炖蘑菇"
}

function MyCom(){
    // 获取数据
    let {flag,firstMsg, lastMsg} = state;

    // 修改数据函数
    let changeFlag = () => {
        console.log(11);
        // 11
        state.flag = !state.flag
    }

    // 返回react元素
    return (
        <div onClick={ changeFlag }> { flag ? firstMsg :lastMsg}</div>
    )
}

// 页面渲染
ReactDOM.render(<MyCom/>, document.getElementById("app"))

示例说明:

  1. 当每次点击的时候,控制台会打印11说明事件没有任何问题
  2. 每次点击过后,在控制台打印state数据,会发现flag的值发生了变化
  3. 可以页面却并没有任何变化
  4. 原因在于普通变量数据的变化并不会触发react重新渲染页面,但state会
  5. 如果真的希望页面重绘,就需要封装渲染函数,手动触发
3.3 封装渲染函数

修改示例代码如下:

function MyCom(){
    let {flag,firstMsg, lastMsg} = state;

    let changeFlag = () => {
        console.log(11);

        state.flag = !state.flag

        // 每次flag值发生改变,重新渲染页面
        render()
    }

    return (
        <div onClick={ changeFlag }> { flag ? firstMsg :lastMsg}</div>
    )
}

// 封装页面渲染函数
function render(){
    ReactDOM.render(<MyCom/>, document.getElementById("app"))
}
// 初始渲染一次
render()

示例说明:

  1. React.render渲染函数封装在render函数中
  2. 每次修改数据完毕后,手动的调用render函数,重新渲染页面
  3. 因此大多数情况下回选择使用state状态

有关第四节:React组件状态的State属性的更多相关文章

  1. ruby - 在 Ruby 程序执行时阻止 Windows 7 PC 进入休眠状态 - 2

    我需要在客户计算机上运行Ruby应用程序。通常需要几天才能完成(复制大备份文件)。问题是如果启用sleep,它会中断应用程序。否则,计算机将持续运行数周,直到我下次访问为止。有什么方法可以防止执行期间休眠并让Windows在执行后休眠吗?欢迎任何疯狂的想法;-) 最佳答案 Here建议使用SetThreadExecutionStateWinAPI函数,使应用程序能够通知系统它正在使用中,从而防止系统在应用程序运行时进入休眠状态或关闭显示。像这样的东西:require'Win32API'ES_AWAYMODE_REQUIRED=0x0

  2. ruby-on-rails - 如果为空或不验证数值,则使属性默认为 0 - 2

    我希望我的UserPrice模型的属性在它们为空或不验证数值时默认为0。这些属性是tax_rate、shipping_cost和price。classCreateUserPrices8,:scale=>2t.decimal:tax_rate,:precision=>8,:scale=>2t.decimal:shipping_cost,:precision=>8,:scale=>2endendend起初,我将所有3列的:default=>0放在表格中,但我不想要这样,因为它已经填充了字段,我想使用占位符。这是我的UserPrice模型:classUserPrice回答before_val

  3. ruby-on-rails - 在混合/模块中覆盖模型的属性访问器 - 2

    我有一个包含模块的模型。我想在模块中覆盖模型的访问器方法。例如:classBlah这显然行不通。有什么想法可以实现吗? 最佳答案 您的代码看起来是正确的。我们正在毫无困难地使用这个确切的模式。如果我没记错的话,Rails使用#method_missing作为属性setter,因此您的模块将优先,阻止ActiveRecord的setter。如果您正在使用ActiveSupport::Concern(参见thisblogpost),那么您的实例方法需要进入一个特殊的模块:classBlah

  4. ruby - 多个属性的 update_column 方法 - 2

    我有一个具有一些属性的模型:attr1、attr2和attr3。我需要在不执行回调和验证的情况下更新此属性。我找到了update_column方法,但我想同时更新三个属性。我需要这样的东西:update_columns({attr1:val1,attr2:val2,attr3:val3})代替update_column(attr1,val1)update_column(attr2,val2)update_column(attr3,val3) 最佳答案 您可以使用update_columns(attr1:val1,attr2:val2

  5. ruby-on-rails - 跳过状态机方法的所有验证 - 2

    当我的预订模型通过rake任务在状态机上转换时,我试图找出如何跳过对ActiveRecord对象的特定实例的验证。我想在reservation.close时跳过所有验证!叫做。希望调用reservation.close!(:validate=>false)之类的东西。仅供引用,我们正在使用https://github.com/pluginaweek/state_machine用于状态机。这是我的预订模型的示例。classReservation["requested","negotiating","approved"])}state_machine:initial=>'requested

  6. ruby - Nokogiri 剥离所有属性 - 2

    我有这个html标记:我想得到这个:我如何使用Nokogiri做到这一点? 最佳答案 require'nokogiri'doc=Nokogiri::HTML('')您可以通过xpath删除所有属性:doc.xpath('//@*').remove或者,如果您需要做一些更复杂的事情,有时使用以下方法遍历所有元素会更容易:doc.traversedo|node|node.keys.eachdo|attribute|node.deleteattributeendend 关于ruby-Nokog

  7. ruby-on-rails - Rails 模型——非持久类成员或属性? - 2

    对于Rails模型,是否可以/建议让一个类的成员不持久保存到数据库中?我想将用户最后选择的类型存储在session变量中。由于我无法从我的模型中设置session变量,我想将值存储在一个“虚拟”类成员中,该成员只是将值传递回Controller。你能有这样的类(class)成员吗? 最佳答案 将非持久属性添加到Rails模型就像任何其他Ruby类一样:classUser扩展解释:在Ruby中,所有实例变量都是私有(private)的,不需要在赋值前定义。attr_accessor创建一个setter和getter方法:classUs

  8. ruby - 字符串文字中的转义状态作为 `String#tr` 的参数 - 2

    对于作为String#tr参数的单引号字符串文字中反斜杠的转义状态,我觉得有些神秘。你能解释一下下面三个例子之间的对比吗?我特别不明白第二个。为了避免复杂化,我在这里使用了'd',在双引号中转义时不会改变含义("\d"="d")。'\\'.tr('\\','x')#=>"x"'\\'.tr('\\d','x')#=>"\\"'\\'.tr('\\\d','x')#=>"x" 最佳答案 在tr中转义tr的第一个参数非常类似于正则表达式中的括号字符分组。您可以在表达式的开头使用^来否定匹配(替换任何不匹配的内容)并使用例如a-f来匹配一

  9. ruby - Net::HTTP 获取源代码和状态 - 2

    我目前正在使用以下方法获取页面的源代码:Net::HTTP.get(URI.parse(page.url))我还想获取HTTP状态,而无需发出第二个请求。有没有办法用另一种方法做到这一点?我一直在查看文档,但似乎找不到我要找的东西。 最佳答案 在我看来,除非您需要一些真正的低级访问或控制,否则最好使用Ruby的内置Open::URI模块:require'open-uri'io=open('http://www.example.org/')#=>#body=io.read[0,50]#=>"["200","OK"]io.base_ur

  10. ruby-on-rails - Puma .state 文件 - 2

    我正在尝试使用Capistrano部署带有puma的Rails应用程序。在部署结束时它尝试运行bundleexecpumactl-S/home/deployer/production/shared/sockets/puma.state重启失败了/undefinedmethod`has_key?'forfalse:FalseClass.我只是为puma.state创建了一个空文件。我的问题是这个文件到底是什么,里面应该有什么? 最佳答案 Puma有一个状态文件,记录了进程的PID。如果你是第一次部署,你应该删除.state文件,然后做

随机推荐