国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

[ 一起學React系列 -- 2 ] UI的靈魂--State

XBaron / 812人閱讀

摘要:首先賣個關子,下面我們一起來復習下小學還是初中的一枚數學知識。一旦更改了,會觸發組件的重新渲染。為了頁面渲染性能的考慮,有助于在中進行比較并確定是否重新渲染。

概念引入
對于React來說, 沒有State就沒有頁面的渲染, 我們也將什么都看不到

咋一聽怎么那么唬人?不過的確是這樣,正如標題所言State是UI的靈魂。我們都知道React的核心思想之一是組件化,將頁面所展示的東西按一定的規則分割成很多份并進行一一封裝最后抽象成我們現在所稱為的"組件", 就好像我們搭積木一樣,一個城堡就是通過一個個小方塊堆疊在一起的。但是FaceBook覺得如果僅僅是簡單的封裝那么和普通的moudle有什么區別?和咸魚又有什么區別?于是FaceBook給這些"組件"賦予了靈魂(之一) -- State
什么叫State?顧名思義就是狀態的意思。每個組件都有自己的狀態,比如開關的閉合、顏色的切換和顯示與隱藏等等都會涉及到狀態的切換。首先賣個關子,下面我們一起來復習下小學(還是初中?)的一枚數學知識。

y=f(x)  -->(假如這是一個一元一次函數)

Are you kidding me?這是要侮辱在座的智商?不不不,請放下手里40米的大刀,筆者想拋個磚引個玉。
這是再簡單不過的了,它表示y是關于x的函數。函數在數學中是十分的嚴謹,x與y是一一對應關系換句話說就是同一個x代入運算得到的永遠是同一個y;同一個y代入運算得到的永遠是同一個x,這個特性很像Redux中的Reducer,本質上是一個純函數

初識State

那么如果我們把這個公式帶到React中會有什么樣的化學反應呢?

UI=f(State)

有木有感覺眼前一亮,Excuse me?竟然把State和UI通過一個公式關聯起來?其實本質上就是這么簡單。
同時,我們還可以繼續用函數的思想去思考它:

輸入特定的State只能輸出特定的UI

根據特定的UI就能反推出相應的State

當然實際結果也是如此,React組件所渲染出來的東西與State有直接而且唯一的關系,換句話說就是State決定組件顯示什么而且只有State才能決定組件顯示什么

比如上面提到的一個組件可能有很多切換的動作,開關、顏色、顯示與消失等等...本來這種切換的動作需要我們自己通過操作DOM來實現,但是FaceBook在設計React之初就把 直接操作DOM 這條路給堵死了(但仍給我們提供的必要的接口已備不時之需,后續文章會有相應內容),究竟為什么要這么做?因為我們都知道前端開發中特別消耗性能的是DOM操作,一旦處理不當就會影響整個頁面的展示效果,因此FaceBook一不做二不休直接搞出了一個State出來,讓開發者去輸入State隨后React自己去操作相應的DOM。

這么做有兩個好處

使得State成為頁面的唯一數據來源和頁面元素變換的唯一依據。

提高頁面的渲染性能(當然這不是React高效渲染的決定性因素)。

State大大提高了開發者對React組件的開發效率而不用擔心頁面性能問題,可謂是一舉多得。

實例展示:靜態State

下面我們來開發一個簡單的文字展示組件:

import React, {Component} from "react"       ---line 1

class Show extends Component {               ---line 2

    constructor(props) {                     ---line 3
        super(props);
        this.state = {                       ---line 4
            content: "Hello World"
        }
        //this.propName = propValue;         ---line 5
    }

    render() {                               ---line 6
        return (
            

{this.state.content}

---line 7 ) } } export default Show;
首先一起來分析下這段代碼:
line 1: 日常導包
line 2: ES6創建對象的方法。強烈推薦這么寫
line 3: 該組件的構造方法,如果組件有屬性默認值那么就需要寫構造函數
line 4: 這里表示該組件有自己的State屬性而且它還是一個字面量對象,所以與該組件有關的所有State都應該寫在這個字面量對象中。從代碼中看出該組件有一個State對象content,它包含著這個組件需要展示的一段文字。
line 5: 如果我們想給這個組件定義State以外的屬性,那么就可以項這行所寫一樣,不過需要放在this對象中,這樣才能在組件中通過this對象讀取到。
line 6: render方法是最終構建組件結構的地方,因為組件究竟長什么樣子,需要在這里寫。
line 7: 正如這個組件需要做的事情,我們在render方法中返回這個p標簽用來顯示文字信息。因為所需要的文字信息保存在State對象中,State又保存在this對象中,所以如何去獲取文字信息在這里不需要過多贅述。另外需要注意的是,render方法return的節點只能是一個,不能是多個。如果你的組件結構復雜,請在最外層用div這樣的標簽包一下然后再返回

下面看具體效果:


是不是很簡單?

實例展示:動態State

接下來再說一下狀態變化,因為狀態就是用來更改的,如果不更改那和咸魚有什么區別?

先思考下:React狀態應該如何更改?

這個問題筆者第一次遇到的時候第一反應就是:直接改啊!!!(然后被piapiapia打臉),先試下吧:

import React, {Component} from "react"

class Show extends Component {

    constructor(props) {
        super(props);
        this.state = {
            content: "Hello World"
        }
    }

    changeState = () => {
        this.state.content = "I"m React State";
    };

    render() {
        return (
            

{this.state.content}

) } } export default Show;

我們創建一個函數用來更改響應的State,然后實際運行的時候發現不管怎么點按鈕都毫無作用?Why?

因為React給我們提供了專門用于更改狀態的方法, this.setState()

我們來重新試一下:

import React, {Component} from "react"

class Show extends Component {

    constructor(props) {
        super(props);
        this.state = {
            content: "Hello World"
        }
    }

    changeState = () => {
        this.setState({
            content: "I"m React State"
        })
    };

    render() {
        return (
            

{this.state.content}

) } } export default Show;
這個方法需要我們傳入一個字符量對象,key是我們需要更改的那個State,這里是content; value是我們所期望要更改的值。( [] 是轉移符)。

可以看出頁面中那行字變成了我們所期望的文字。所以正如我們所說:

更改State要使用this.setState()方法。

一旦更改了State,會觸發組件的重新渲染。實際上是運行一次組件中的render方法

異步的setState

這個點筆者想不出合適的引入點,所以就直接拋出來了。這個問題很有趣,因為巧合的是筆者的一個萌妹子同事在學習React時候恰好遇到這個問題,代碼大概是這樣:

onchange = () => {
    this.setState({
        name: "Demo"
    });

    this.props.change(this.state.name)//調用父組件通過props傳過來的方法
};

她的本意是在本組件更改了name這個State后再通過調用父組件的方法實現父組件name的重新渲染。我們看出this.props.change(this.state.name)傳入的參數是直接從State中取的,但是實際運行的時候卻不是如想象中那樣同時更改,現象是第一次點擊時候本組件成功渲染,但是父組件并沒有同時渲染;第二次點擊時候父組件才渲染成對應的名字。
為什么呢?
因為this.setState這個方法不是同步的而是異步的,了解JavaScript中Event Loop機制的朋友都知道,如果一段js代碼中有異步的代碼那么會將其放在一個隊列中,等待這段代碼其余代碼運行完后再從那個隊列中取出異步代碼運行。this.setState機制也和它差不多,當我們set一個State后React并不會立即去更改對應的State,而是在合適的時機下進行更改甚至為了提高性能會將多個setState過程合并成一個。為了證明這個異步機制,我們通過打印的方式做個試驗:

import React, {Component} from "react"

class Show extends Component {

    constructor(props) {
        super(props);
        this.state = {
            content: "Hello World"
        }
    }

    changeState = () => {
        console.log(`1 -- ${this.state.content}`);
        this.setState({
            content: "I"m React State"
        });
        console.log(`2 -- ${this.state.content}`);
        console.log("end");
    };

    render() {
        return (
            

{this.state.content}

) } } export default Show;

控制臺打印結果如下:

可以看出,頁面正常渲染了說明對應的State已經更改了,但是控制臺顯示的信息卻沒有更改后的現象,所以可以確定真正的setState并不是調用this.setState()方法的瞬間,而是在之后的某個時間。所以有個問題需要注意:不要用當前的State去計算下一個State,因為你不能保證當前的State是最新的

但如果有個需求,需要在更改State后立即執行某個動作怎么辦?

正常來說我們無法預知真正的setState是在何時,所以React理所當然得給我們提供了辦法,那么就是this.setState的第二個參數,第二個參數是一個方法,當對應的State修改成功后會立即執行,我們修改下代碼:

...
changeState = () => {
    console.log(`1 -- ${this.state.content}`);
    this.setState({
        content: "I"m React State"
    }, () => {
        console.log(`3 -- ${this.state.content}`);
    });
    console.log(`2 -- ${this.state.content}`);
    console.log("end");
};
...

看結果咯:

與預期一致,沒毛病!!!

State的不可變

看到這個小標題,估計很多人會很懵逼,前面還說不更改的State和咸魚有什么區別怎么到這里就要不可變了?其實是混淆了。
官方的建議是將State的所有對象當做是不可變對象,一旦每個對象更改了那么需要重新創建這個對象。舉例子說,前面的代碼中有:

this.state = {
    content: "Hello World"
}

當我們更改了content的值,用"I"m React State"替換了原有的"Hello World"。其實在這里,content對用的value不僅僅是內容上的變化也是地址上的變化,這種在基本變量上體現不出來,比如我們有個State要保存一個列表內容那么就得是個數組(字面量對象亦如此):

this.state = {
    navis: ["React","Vue","Angular"]
}

這個時候如果我們直接將navis的值拿出來push一個元素進去然后setState:

addNavi = () => {
    this.setState({
        navis: this.state.navis.push("React-Native")
    })
};

結果是頁面并沒有重新渲染,Why? 因為React在對比navis新的和老的兩個值時候發現它們的地址都沒變化就認為它們內容也沒變化就不會重新渲染。這是個坑!!!。所以此時State對象的不可變原則就有作用了,解決方案有兩個:

1、 復制原來的值,push完后進行setState。
addNavi = () => {
    let navisCopy = this.state.navis.slice();
    this.setState({
        navis: navisCopy.push("React-Native")
    })
};

這樣就能正常運行了,因為navis對應的值不僅僅在內容上變了,地址也變化了,React檢測到變化后就進行了重新渲染。

2、第三方插件

Immutable.js

immutability-helper

immutability-helper-x

至于為什么需要這么做?

State數據更明確,方便管理和開發調試。

為了頁面渲染性能的考慮,有助于在shouldComponentUpdate中進行比較并確定是否重新渲染。

Bingo...本期的博文就結束了,這期筆者也精心準備了很久,希望大家都能喜歡!!

文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。

轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/97365.html

相關文章

  • [ 一起React系列 -- 3 ] UI擴展數據源Props以及Props約束

    摘要:所以還是印證那句話是組件渲染的唯一依據。所以對組件的進行約束是創建一個健康組件的必要條件。這里我們約束屬性類型為。使用方式運行結果沒有錯誤假如我們再加入一個子組件控制臺如預期報錯自定義約束萬物皆有其局限性。 日常扯淡前的廢話 上一篇我們介紹了React中State對象,說到它是組件渲染的唯一依據;當然我們也可以認為State是組件中的數據源之一,它保存著組件渲染的所有數據并且可以直接作...

    kumfo 評論0 收藏0
  • [ 一起React系列 -- 6 ] 秘術之時間旅行-1

    摘要:所謂的時間旅行從廣義上來說無非就是三個動作回到過去進入未來回到現在,這個無論是從現實還是前端技術來說都是可靠的。單從技術棧來說,時間旅行不是一門技術而是一個思想套路。 標題看起來挺新穎的,筆者都覺得很高大上是不是哈哈... 拋轉 時間旅行在生活中是一個非常吸引人的概念,雖然現在無法實現但說不定未來的某天就實現了!然后就穿梭會過去殺掉小時候的自己然后就開始懵逼自己是誰類似的狗血劇情......

    付倫 評論0 收藏0
  • [ 一起React系列 -- 4 ] 透傳Context

    摘要:官方對的介紹是意思就是提供了一種通過組件樹傳遞數據的方法,而無需在每個級別手動傳遞。這也是基于重要物證哈哈實例使用學習技術最終是要有產出的。依然被視作一個組件,不過不同的是它的子組件必須是一個方法并且該方法接收當前對象并最終返回一個節點。 拋轉引玉 通過上一篇的科普我們知道如果父節點需要向子節點傳遞數據,那么就得通過Props來實現;那么擺在我們眼前的就有一個問題了:現有N個節點并且它...

    firim 評論0 收藏0
  • [ 一起React系列 -- 7 ] 秘術之時間旅行-2

    摘要:但這樣做的缺點很多,不利于狀態在組件之間共享。所以本篇使用作為狀態管理器來實現時間旅行。并且從中可以看出過程不僅僅向對象中添加一個狀態對象,還對進行了加一操作,這是為了保證狀態與保持同步。 距離上一次更新已經有半個月了,這半個月來主要在忙兩件事:一個是最近老板給了個自動化測試任務,另一個是和學校的弟弟一起搞一個微信小游戲...emmmm!其實主要是懶!!! 本篇是作為上篇的續集,不知道...

    nidaye 評論0 收藏0
  • React習之初入React世界

    摘要:語法將語法直接加入到代碼中,再通過翻譯器裝換到純后由瀏覽器執行。事實上,并不需要花精力學習。可以說,基本語法基本被囊括了,但也有少許不同。明確的數據流動。這條原則讓組件之間的關系變得簡單且可預測。使用獲取和顯示回調。 JSX語法 JSX將HTML語法直接加入到JavaScript代碼中,再通過翻譯器裝換到純JavaScript后由瀏覽器執行。在實際開發中,JSX在產品打包階段都已經編...

    cjie 評論0 收藏0

發表評論

0條評論

最新活動
閱讀需要支付1元查看
<