欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

React中state屬性案例詳解

 更新時(shí)間:2023年11月10日 11:14:03   作者:小小橘柚  
在React中,state 是一個(gè)用于存儲(chǔ)組件內(nèi)部數(shù)據(jù)的特殊對(duì)象,每個(gè)React組件都可以包含自己的state,我們往往是通過(guò)修改state的值來(lái)驅(qū)動(dòng)React重新渲染組件,這篇文章主要介紹了React中state屬性,需要的朋友可以參考下

通過(guò)之前的文章自定義組件,我們發(fā)現(xiàn)創(chuàng)建的類式組件里面會(huì)存在state屬性。在React中,state 是一個(gè)用于存儲(chǔ)組件內(nèi)部數(shù)據(jù)的特殊對(duì)象。每個(gè)React組件都可以包含自己的state,我們往往是通過(guò)修改state的值來(lái)驅(qū)動(dòng)React重新渲染組件。

由于函數(shù)式組件this指向的是undifind所以,函數(shù)式組件不存在state

1)state案例

需求:點(diǎn)擊按鈕,切換標(biāo)題內(nèi)容

<script type="text/babel">
    // 創(chuàng)建類式組件
    class MyComponent extends React.Component {
        render() {
            console.log(this)
            return (
                <div>
                    <h1>內(nèi)容</h1>
                    <button>按鈕</button>
                </div>
            );
        }
    }
    /*渲染組件到頁(yè)面*/
    ReactDOM.render(<MyComponent/>, document.getElementById("demo"))
</script>

我們是通過(guò)修改state的值來(lái)驅(qū)動(dòng)內(nèi)容的變化,那么我們想要使內(nèi)容變化,按鈕的點(diǎn)擊事件就是修改state的值。那怎么初始化state呢,我們知道,state是實(shí)例的屬性,所以我們想要初始化state的值需要在構(gòu)造器里面實(shí)現(xiàn)。

構(gòu)造器里面需要接受參數(shù),應(yīng)該是什么參數(shù)呢,通過(guò)查詢官網(wǎng),里面?zhèn)鬟f的參數(shù)為props,即:

class MyComponent extends React.Component {
    constructor(props) {
        super(props);
    }
    render() {
        return (
            <div>
                <h1>內(nèi)容</h1>
                <button>按鈕</button>
            </div>
        );
    }
}

2)初始化state

有了構(gòu)造器我們就可以在構(gòu)造器里面初始化state的值了

class MyComponent extends React.Component {
    constructor(props, context, updater) {
        super(props, context, updater);
        // 初始化state
        this.state = {
            count: 0
        }
    }
    render() {
        return (
            <div>
                <h1>{this.state.count}</h1>
                <button>按鈕</button>
            </div>
        );
    }
}

此時(shí)就可以查看到state的值了:

3)原生JS事件綁定

原生的 JavaScript 綁定事件有多種方式,以下是其中一些常見(jiàn)的方法:

使用 addEventListener 方法 這是一種推薦的方式,可以用于為一個(gè) DOM 元素添加事件監(jiān)聽(tīng)器。它可以用于綁定多個(gè)事件處理函數(shù),而不會(huì)覆蓋之前綁定的處理函數(shù)。

var element = document.getElementById("myElement");
element.addEventListener("click", myFunction);

內(nèi)聯(lián)事件處理函數(shù): 你可以將事件處理函數(shù)直接寫在 HTML 元素的屬性中,如 onclickonmouseover 等。這不太推薦,因?yàn)閷?HTML 和 JavaScript 混合在一起可能會(huì)使代碼不夠清晰。

<button onclick="myFunction()">點(diǎn)擊我</button>

DOM 屬性方式: 你可以直接為 DOM 元素的事件處理屬性分配函數(shù),這與內(nèi)聯(lián)事件處理函數(shù)類似,但是更清晰一些。

var element = document.getElementById("myElement");
element.onclick = myFunction;

4)React事件綁定

上面提到了原生的JS事件綁定方式,除了內(nèi)斂事件處理函數(shù)其他都需要操作DOM,而我們的React是不需要操作DOM的,因此我們使用內(nèi)斂事件處理函數(shù)對(duì)元素添加事件綁定。

class MyComponent extends React.Component {
    constructor(props, context, updater) {
        super(props, context, updater);
        this.state = {
            count: 0
        }
    }
    render() {
        return (
            <div>
                <h1>{this.state.count}</h1>
                <button οnclick="increment()">按鈕</button>
            </div>
        );
    }
}
//注冊(cè)點(diǎn)擊事件
function increment() {
    console.log("按鈕被點(diǎn)擊了")
}

上面通過(guò) onClick="increment()"給按鈕注冊(cè)了點(diǎn)擊事件

通過(guò)上面的注冊(cè)事件我們發(fā)現(xiàn)控制臺(tái)報(bào)錯(cuò)了

image-20231022130311012

根據(jù)錯(cuò)誤提示,告訴我們?cè)趪L試使用 onclick 事件處理屬性時(shí)出現(xiàn)錯(cuò)誤,提示是否想使用 onClick。所以我們把onclick變成onClick。

render() {
    return (
        <div>
            <h1>{this.state.count}</h1>
            <button onClick="increment()">按鈕</button>
        </div>
    );
}

但是發(fā)現(xiàn)還是報(bào)錯(cuò)了

image-20231022130609906

報(bào)錯(cuò)的意思是期望 onClick 事件監(jiān)聽(tīng)器是一個(gè)函數(shù),但實(shí)際上它是一個(gè)字符串類型的值。我們嘗試使用JSX的表達(dá)式將函數(shù)賦值給onClick事件

<button onClick={increment()}>按鈕</button>

此時(shí)我們發(fā)現(xiàn),我們還沒(méi)有點(diǎn)擊按鈕,一刷新網(wǎng)頁(yè),控制臺(tái)立馬打印了按鈕被點(diǎn)擊了這句話,也就是說(shuō)在刷新網(wǎng)頁(yè)的時(shí)候increment()立即執(zhí)行了,點(diǎn)擊按鈕卻得不到我們想要的結(jié)果。

我們?cè)賮?lái)分析一下onClick={increment()},這里面其實(shí)是將increment()執(zhí)行結(jié)束之后的返回值賦值給onClick,而不是將函數(shù)賦值給onClick,所以increment()立即執(zhí)行,然后將返回的undefined賦值給onClick,所以點(diǎn)擊按鈕當(dāng)然沒(méi)有作用,我們能做的就是把increment函數(shù)本身賦值給onClick

<button onClick={increment}>按鈕</button>

此時(shí)點(diǎn)擊按鈕成功打印結(jié)果,控制臺(tái)也不存在報(bào)錯(cuò)。

5)類中方法this指向

解決了點(diǎn)擊事件,我們下面的目標(biāo)就修改state里面的count,我們能直接在increment函數(shù)里面修改嗎?組件的實(shí)例并不是我們創(chuàng)建的,而且函數(shù)在組件(類)的外面,incrementthis指向的是undefined,也就是說(shuō)increment函數(shù)根本訪問(wèn)不到組件的this,從而也就訪問(wèn)不到組件的state。

我們可以把increment函數(shù)寫在類組件里面,作為類的一般方法。

class MyComponent extends React.Component {
    constructor(props, context, updater) {
        super(props, context, updater);
        this.state = {
            count: 0
        }
    }
    render() {
        return (
            <div>
                <h1>{this.state.count}</h1>
                <button onClick={increment}>按鈕</button>
            </div>
        );
    }
    // 注意作為一般方法,不需要使用function修飾
    increment() {
         console.log("按鈕被點(diǎn)擊了"+this.state.count)
    }
}

此時(shí)我們發(fā)現(xiàn)控制臺(tái)又報(bào)錯(cuò)了,提示我們increment未定義,可是我們已經(jīng)定義了的

我們實(shí)現(xiàn)的increment函數(shù)作為一般方法,可以通過(guò)類的實(shí)例調(diào)用,而onClick={increment}根本訪問(wèn)不到,所以修改成下面:

<button onClick={this.increment}>按鈕</button>

此時(shí)報(bào)錯(cuò)解決了,但是我們點(diǎn)擊按鈕的時(shí)候,報(bào)錯(cuò)又接踵而至:

根據(jù)提示我們發(fā)現(xiàn)state讀取不到,可是我們的state就是掛載在this上面的屬性,怎么會(huì)讀取不到呢,我們通過(guò)在increment函數(shù)打印this查看:

increment() {
    console.log(this)
    console.log("按鈕被點(diǎn)擊了"+this.state.count)
}

我們發(fā)現(xiàn)打印的結(jié)果是undefined,這令我們很奇怪,方法定義在類里面,怎么會(huì)訪問(wèn)不到this呢,而同樣為類的方法render卻可以訪問(wèn)到this呢?

我們?cè)倩仡櫼幌聞?chuàng)建類式組件以及渲染類式組件的過(guò)程,我們定義組件重寫了render方法,返回VDOM,而React想要渲染DOM需要?jiǎng)?chuàng)建組件的實(shí)例,然后**通過(guò)實(shí)例調(diào)用render**方法。我們知道類里面的方法是掛載到原型對(duì)象上的,只有通過(guò)類的實(shí)例調(diào)用方法才能訪問(wèn)到this,而我們創(chuàng)建的組件實(shí)例并不是有我們創(chuàng)建的,我們只是把increment函數(shù)賦值給onClick,所以increment可能不是通過(guò)實(shí)例去調(diào)用的。

6)類中方法this指向案例

我們創(chuàng)建一個(gè)類,類里面有speak方法,用于打印this

class Person {
    constructor(name, age) {
        this.name = name
        this.age = age
    }
    speak(){
        console.log(this)
    }
}

創(chuàng)建實(shí)例,調(diào)用方法

 const p=new Person('jvyou',22)
 p.speak()

此時(shí)成功打印出來(lái)p的this,說(shuō)明通過(guò)類的實(shí)例調(diào)用類里面的方法,方法里面的this就是指向?qū)嵗?/p>

我們將p.speak賦值給其他變量嘗試直接調(diào)用試試:

const s = p.speak
s()

輸出的結(jié)果卻是undefined,這個(gè)屬于直接調(diào)用,原本的this應(yīng)該是window,但是由于嚴(yán)格模式下就是undefind

通過(guò)這個(gè)案例我們?cè)倩仡櫼韵挛覀兊拇a:

<button onClick={this.increment}>按鈕</button>

我們將this.increment賦值給onClick,在點(diǎn)擊按鈕的時(shí)候React會(huì)直接調(diào)用onClick,根本不是通過(guò)組件的實(shí)例調(diào)用的,所以根本訪問(wèn)不到組件的this,所以也訪問(wèn)不到組件的state

7)解決this指向undefined

我們知道可以通過(guò)bind方法給函數(shù)綁定this,我們可以在構(gòu)造函數(shù)里面訪問(wèn)到this,我們可以通過(guò)在構(gòu)造函數(shù)里面給increment方法綁定實(shí)例的this,再將綁定成功的新的函數(shù)掛載到對(duì)象的屬性上。

constructor(props, context, updater) {
    super(props, context, updater);
    this.state = {
        count: 0
    }
    this.increment = this.increment.bind(this)
}

this.increment.bind(this)綁定this之后返回一個(gè)新的函數(shù),此時(shí)函數(shù)內(nèi)部的this指向的就是創(chuàng)建的對(duì)象

再將返回的函數(shù)賦值給this.increment,作為屬性掛載到對(duì)象上。

此時(shí)再點(diǎn)擊按鈕,成功打印出組件的this,且發(fā)現(xiàn)increment也變成組件屬性了,且原型鏈上面也存在increment方法,屬性上的increment是通過(guò)原型鏈上的increment綁定this得來(lái)的,因此onClick={this.increment}是將屬性上的increment賦值給onClick。

8)修改state

通過(guò)上面的方式我們就可以在方法里面修改this.state

increment() {
    this.state.count++
    console.log("按鈕被點(diǎn)擊了" + this.state.count)
}

但是我們發(fā)現(xiàn)點(diǎn)擊了按鈕不報(bào)錯(cuò),count的值也一直為0不改變

這是因?yàn)?code>state不能直接更改,需要使用React的內(nèi)置API。

我們可以通過(guò)打印組件的this,在原型鏈上找到API:setState,所以可以直接通過(guò)this訪問(wèn)即可

increment() {
    const c = this.state.count + 1
    this.setState({count: c})
    console.log("按鈕被點(diǎn)擊了" + this.state.count)
}

此時(shí)成功解決。但是在實(shí)現(xiàn)的時(shí)候使用了const c = this.state.count + 1,嫩不能改成const c = this.state.count++呢,是不能的,因?yàn)檫@二樣會(huì)直接修改state的值。

state存在多個(gè)屬性怎么修改呢

constructor(props, context, updater) {
    super(props, context, updater);
    this.state = {
        count: 0,
        name: '橘柚'
    }
    this.increment = this.increment.bind(this)
}

上面代碼state里面存在兩個(gè)屬性

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

這里面只修改了count,但不會(huì)影響到name

9)state的簡(jiǎn)寫

簡(jiǎn)化state

我們?cè)谏厦娉跏蓟?code>state的時(shí)候是在構(gòu)造器里面實(shí)現(xiàn)的,但是我們知道,類里面可以直接定義類的屬性,而且可以直接給屬性賦值,所以我們就不需要在構(gòu)造器里面初始化state,直接修改成:

class MyComponent extends React.Component {
    //初始化state,直接作為類組件的屬性定義
    state = {
        count: 0,
        name: '橘柚'
    }
    // 構(gòu)造器
    constructor(props, context, updater) {
        super(props, context, updater);
        this.increment = this.increment.bind(this)
    }
    ...省略render和increment
}

簡(jiǎn)化事件

我們知道increment函數(shù)在MyComponent原型鏈上不通過(guò)實(shí)例調(diào)用會(huì)導(dǎo)致this指向丟失,所以我們通過(guò)bind掛載this解決,即this.increment = this.increment.bind(this),但是我們知道箭頭函數(shù)的 this 指向是與普通函數(shù)不同的。箭頭函數(shù)的 this 指向是繼承自包含它的最近的父級(jí)(詞法作用域)函數(shù)的 this 值,而不是動(dòng)態(tài)綁定的。所以只需要將increment變成箭頭函數(shù),在創(chuàng)建實(shí)例的時(shí)候incrementthis自己就會(huì)指向?qū)嵗?,無(wú)需再次綁定。

increment = () => {
    const c = this.state.count + 1
    this.setState({count: c})
    console.log("按鈕被點(diǎn)擊了" + this.state.count)
}

此時(shí)我們打印this,也能在組件的屬性上面找到increment。

一開(kāi)始我們添加構(gòu)造器是為了初始化state以及為事件綁定this,現(xiàn)在全部解決了,構(gòu)造器也就不用存在了,所以最后的代碼如下:

class MyComponent extends React.Component {
    state = {
        count: 0,
        name: '橘柚'
    }
    increment = () => {
        const c = this.state.count + 1
        this.setState({count: c})
        console.log("按鈕被點(diǎn)擊了" + this.state.count)
    }
    render() {
        return (
            <div>
                <h1>{this.state.count}{this.state.name}</h1>
                <button onClick={this.increment}>按鈕</button>
            </div>
        );
    }
}

10)setState 擴(kuò)展

對(duì)象式setState

我們可以使用 setState 來(lái)更新組件的狀態(tài),但是 setState 有兩種常見(jiàn)的寫法,上面我們一直用的是傳遞一個(gè)對(duì)象,即:

this.setState({ count: this.state.count + 1 });

這種寫法直接傳遞一個(gè)新的狀態(tài)對(duì)象給 setState。React會(huì)將新?tīng)顟B(tài)與當(dāng)前狀態(tài)合并,并在后續(xù)的更新周期中應(yīng)用這個(gè)新?tīng)顟B(tài)。

但其實(shí)setState還有第二個(gè)參數(shù):

setState( stateChange , [callback] )
stateChange :狀態(tài)改變對(duì)象

? callback:可選回調(diào)函數(shù),它在狀態(tài)更新完畢,render調(diào)用后,才被調(diào)用

這個(gè)回調(diào)有什么用呢,我們先看一個(gè)案例:

export default class Count extends Component {
    state = {
        count: 0
    }
    increment = () => {
        const {count} = this.state
        this.setState({count: count + 1})
        console.log("@count:", this.state.count)
    }
    render() {
        return (
            <div>
                <h1>當(dāng)前Count:{this.state.count}</h1>
                <button onClick={this.increment}>+1</button>
            </div>
        )
    }
}

當(dāng)我們點(diǎn)擊了“+1”的按鈕之后,頁(yè)面展示的效果確實(shí)是1,但是打印的結(jié)果卻是0,我們?cè)诖蛴ount的時(shí)候已經(jīng)執(zhí)行 this.setState({count: count + 1})進(jìn)行狀態(tài)更新了,為什么還是0呢?那是因?yàn)?code>setState 可能是異步的,所以在讀取 this.state 之前不應(yīng)該依賴于它的值。

如果需要在狀態(tài)更新后執(zhí)行一些操作,可以將這些操作放在 setState 的回調(diào)函數(shù)中:

 increment = () => {
     const {count} = this.state
     this.setState({count: count + 1}, () => {
         console.log("@count:", this.state.count)
     })
 }

函數(shù)式setState

傳遞一個(gè)更新函數(shù):

this.setState((prevState, props ) => {
  return { count: prevState.count + 1 };
} , [callback]);

這種寫法將狀態(tài)的更新邏輯封裝在一個(gè)函數(shù)中,并接受參數(shù) prevStateprops,prevState代表當(dāng)前狀態(tài)的先前值。

這兩種寫法的選擇取決于你的需求和使用情境。通常情況下,使用更新函數(shù)的方式更加安全,因?yàn)樗梢源_?;诋?dāng)前狀態(tài)來(lái)計(jì)算新?tīng)顟B(tài),避免了潛在的競(jìng)態(tài)條件和不一致性。另外,使用更新函數(shù)的方式也適用于異步更新?tīng)顟B(tài)的情況。

到此這篇關(guān)于React中state屬性的文章就介紹到這了,更多相關(guān)React state屬性內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 使用Axios在React中請(qǐng)求數(shù)據(jù)的方法詳解

    使用Axios在React中請(qǐng)求數(shù)據(jù)的方法詳解

    這篇文章主要給大家介紹了初學(xué)React,如何規(guī)范的在react中請(qǐng)求數(shù)據(jù),主要介紹了使用axios進(jìn)行簡(jiǎn)單的數(shù)據(jù)獲取,加入狀態(tài)變量,優(yōu)化交互體驗(yàn),自定義hook進(jìn)行數(shù)據(jù)獲取和使用useReducer改造請(qǐng)求,本文主要適合于剛接觸React的初學(xué)者以及不知道如何規(guī)范的在React中獲取數(shù)據(jù)的人
    2023-09-09
  • React?組件傳?children?的各種案例方案詳解

    React?組件傳?children?的各種案例方案詳解

    自定義組件的時(shí)候往往需要傳?children,由于寫法比較多樣,我就總結(jié)了一下,要自定義的組件其中包含一個(gè)?title?和一個(gè)?children,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),需要的朋友參考下吧
    2023-10-10
  • React?Context源碼實(shí)現(xiàn)原理詳解

    React?Context源碼實(shí)現(xiàn)原理詳解

    這篇文章主要為大家介紹了React?Context源碼實(shí)現(xiàn)原理示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-10-10
  • 一個(gè)基于react的圖片裁剪組件示例

    一個(gè)基于react的圖片裁剪組件示例

    本篇文章主要介紹了一個(gè)基于react的圖片裁剪組件示例,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2018-04-04
  • 基于react框架使用的一些細(xì)節(jié)要點(diǎn)的思考

    基于react框架使用的一些細(xì)節(jié)要點(diǎn)的思考

    下面小編就為大家?guī)?lái)一篇基于react框架使用的一些細(xì)節(jié)要點(diǎn)的思考。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2017-05-05
  • 如何應(yīng)用?SOLID?原則在?React?中整理代碼之開(kāi)閉原則

    如何應(yīng)用?SOLID?原則在?React?中整理代碼之開(kāi)閉原則

    React?不是面向?qū)ο?,但這些原則背后的主要思想可能是有幫助的,在本文中,我將嘗試演示如何應(yīng)用這些原則來(lái)編寫更好的代碼,對(duì)React?SOLID原則開(kāi)閉原則相關(guān)知識(shí)感興趣的朋友一起看看吧
    2022-07-07
  • React根據(jù)配置生成路由的示例代碼

    React根據(jù)配置生成路由的示例代碼

    React路由看似只能由Route組件包裹組件的結(jié)構(gòu)來(lái)構(gòu)成,但是其實(shí)也可以通過(guò)編寫路由數(shù)組配置然后通過(guò)數(shù)組循環(huán)來(lái)生成Route組件包裹組件的結(jié)構(gòu),所以本文給大家介紹了React根據(jù)配置生成路由的方法,需要的朋友可以參考下
    2024-11-11
  • 深入理解react-router 路由的實(shí)現(xiàn)原理

    深入理解react-router 路由的實(shí)現(xiàn)原理

    這篇文章主要介紹了深入理解react-router 路由的實(shí)現(xiàn)原理,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2018-09-09
  • React?函數(shù)式組件和類式組件詳情

    React?函數(shù)式組件和類式組件詳情

    這篇文章主要介紹了React函數(shù)式組件和類式組件詳情,React是組件化的的JS庫(kù),組件化也是React的核心思想,文章圍繞主題展開(kāi)詳細(xì)的內(nèi)容介紹,具有一定的參考價(jià)值,需要的小伙伴可以參考一下
    2022-08-08
  • react使用useState修改對(duì)象或者數(shù)組的值無(wú)法改變視圖的問(wèn)題

    react使用useState修改對(duì)象或者數(shù)組的值無(wú)法改變視圖的問(wèn)題

    這篇文章主要介紹了react使用useState修改對(duì)象或者數(shù)組的值無(wú)法改變視圖的問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-08-08

最新評(píng)論