成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

精益 React 學(xué)習(xí)指南 (Lean React)- 1.3 React 組件

不知名網(wǎng)友 / 2959人閱讀

摘要:無(wú)狀態(tài)組件除了可以通過(guò)來(lái)創(chuàng)建組件以外,組件也可以通過(guò)一個(gè)普通的函數(shù)定義,函數(shù)的返回值為組件渲染的結(jié)果。這就是為什么要有屬性,屬性能夠幫助定位與數(shù)組元素的關(guān)系,在重渲染的時(shí)候能夠?qū)崿F(xiàn)渲染優(yōu)化。

書籍完整目錄

1.3 React 組件

1.3.1 React 組件介紹

在 React 中組件是第一元素,是 React 的基礎(chǔ),一個(gè) React 應(yīng)用就是基于 React 組件的組合而成。
前面的 JSX 練習(xí)過(guò)后,大家應(yīng)該對(duì) React 組件不陌生了,在這一節(jié)我們將溫習(xí)以及深入學(xué)習(xí) React 組件。

1.3.2 創(chuàng)建一個(gè) React 組件

創(chuàng)建一個(gè) React 組件的方法為,調(diào)用 React.createClass 方法,傳入的參數(shù)為一個(gè)對(duì)象,對(duì)象必須定義一個(gè) render 方法,render 方法返回值為組件的渲染結(jié)構(gòu),也可以理解為一個(gè)組件實(shí)例(React.createElement 工廠方法的返回值),返回值有且只能為一個(gè)組件實(shí)例,或者返回 null/false,當(dāng)返回值為 null/false 的時(shí)候,React 內(nèi)部通過(guò)

eg:

    var MyComponent = React.createClass({
        render: function() {
            return 

....

; } });
組件命名空間

可以看出 React.createClass 生成的組件類為一個(gè) Javascript 對(duì)象。 當(dāng)我們想設(shè)置命名空間組件時(shí),可以在組件下面添加子組件:

eg:

    MyComponent.SubComponent = React.createClass({...});
    MyComponent.SubComponent.Sub = React.createClass({....});

在組件較多的情況下,可以借助命名空間優(yōu)化組件維護(hù)結(jié)構(gòu)以及解決組件名稱沖突問(wèn)題。

無(wú)狀態(tài)組件

除了可以通過(guò) React.createClass 來(lái)創(chuàng)建組件以外,組件也可以通過(guò)一個(gè)普通的函數(shù)定義,函數(shù)的返回值為組件渲染的結(jié)果。

eg:

    function StatelessComponent(props) {
        return  
Hello {props.name}
}

無(wú)狀態(tài)組件能夠優(yōu)化性能,因?yàn)槠鋬?nèi)部不會(huì)維護(hù)狀態(tài),React 內(nèi)部不會(huì)有一個(gè)對(duì)應(yīng)的組件實(shí)例,并且也沒(méi)有生命周期 hook。

1.3.3 將組件渲染到 DOM 中

當(dāng)創(chuàng)建好了組件過(guò)后,為了將組件渲染到 DOM 中顯示出來(lái),需要兩個(gè)步驟

在 HTML 中定義一個(gè)元素,設(shè)置 id 屬性

JSX 中調(diào)用 ReactDOM.render 方法, 第一個(gè)參數(shù)為 組件,第二個(gè)為剛才定義的 DOM 元素

eg:


對(duì)于組件的渲染,可能涉及到的一些問(wèn)題:

Q1: 只能 render 到一個(gè)元素嗎?

Q2: 在程序運(yùn)行時(shí)能夠動(dòng)態(tài)的調(diào)用 render 嗎?

Q3: 修改了數(shù)據(jù)過(guò)后,還需要重新調(diào)用 render 方法嗎?

這里要先提一下 React 的設(shè)計(jì)初衷,React 在開(kāi)發(fā)時(shí)候的目標(biāo)就是簡(jiǎn)單精巧,可以和其他框架結(jié)合起來(lái)使用。簡(jiǎn)單而言我們可以當(dāng) React 是一個(gè)渲染數(shù)據(jù)對(duì)象到 DOM 中的 Javascript 函數(shù)工具類,工具類當(dāng)然可以多次使用。

那么對(duì)于上面的問(wèn)題:

A1: 不是,React 可以渲染到多個(gè)元素,任意位置的元素。

A2: 可以,比如以一個(gè)彈出層組件為例,我們希望創(chuàng)建一個(gè) append 到 body 最后的組件來(lái)實(shí)現(xiàn)全屏遮罩, 那么我們可以動(dòng)態(tài)的創(chuàng)建一個(gè) div append 到 body 最后,然后將彈出層 render 到那個(gè) div 內(nèi)。

A3: 假設(shè)每次數(shù)據(jù)改變都重新調(diào)用 render 方法,那么每次 render 帶來(lái)的結(jié)果是重新創(chuàng)建一個(gè)頂級(jí)組件實(shí)例,以及子組件實(shí)例。 如果只調(diào)用 render 一次,將數(shù)據(jù)的變更放在組件內(nèi)部,那么就不會(huì)重復(fù)創(chuàng)建頂級(jí)組件。

1.3.4 組件狀態(tài) State

React 中每個(gè)組件可以存儲(chǔ)自己的當(dāng)前狀態(tài), 以一個(gè) switch 開(kāi)關(guān)組件為例,開(kāi)關(guān)的狀態(tài)可以存儲(chǔ)在組件內(nèi)部。

React 的渲染結(jié)果是由組件屬性和狀態(tài)共同決定的,狀態(tài)和屬性的區(qū)別是,狀態(tài)維護(hù)在組件內(nèi)部,屬性是由外部控制,我們先介紹組件狀態(tài)相關(guān)細(xì)節(jié):

控制狀態(tài)的 API 為:

this.state:組件的當(dāng)前狀態(tài)

getInitialState:獲取組件的初始狀態(tài),在組件加載的時(shí)候會(huì)被調(diào)用一次,返回值賦予 this.state 作為初始值

this.setState:

組件狀態(tài)改變時(shí),可以通過(guò) this.setState 修改狀態(tài)

setState 方法支持按需修改,如 state 有兩個(gè)字段,僅當(dāng) setState 傳入的對(duì)象包含字段 key 才會(huì)修改屬性

每次調(diào)用 setState 會(huì)導(dǎo)致重渲染調(diào)用 render 方法

直接修改 state 不會(huì)重渲染組件

eg:

    var Switch = React.createClass({
        // 定義組件的初始狀態(tài),初始為關(guān)
        getInitialState: function() {
            return {
                open: false
            }
        },
        // 通過(guò) this.state 獲取當(dāng)前狀態(tài)
        render: function() {
            console.log("render switch component");
            var open = this.state.open;
            return 
        },
        // 通過(guò) setState 修改組件狀態(tài)
        // setState 過(guò)后會(huì) React 會(huì)調(diào)用 render 方法重渲染
        toggleSwitch: function() {
            var open = this.state.open;
            this.setState({
                open: !open
            });
        }
    })
1.3.5 組件屬性 Props

前面已經(jīng)提到過(guò) React 組件可以傳遞屬性給組件,傳遞方法和 HTML 中無(wú)異, 可以通過(guò) this.props 獲取組件屬性

屬性相關(guān)的 API 為:

this.props: 獲取屬性值

getDefaultProps: 獲取默認(rèn)屬性對(duì)象,會(huì)被調(diào)用一次,當(dāng)組件類創(chuàng)建的時(shí)候就會(huì)被調(diào)用,返回值會(huì)被緩存起來(lái),當(dāng)組件被實(shí)例化過(guò)后如果傳入的屬性沒(méi)有值,會(huì)返回默認(rèn)屬性值

this.props.children:子節(jié)點(diǎn)屬性

propTypes: 屬性類型檢查

以一個(gè)代辦事項(xiàng)的列表項(xiàng)組件為例:

    // props.name 表示代辦事項(xiàng)的名稱
    var TodoItem = React.createClass({
        render: function() {
            var props = this.props;
            return 
{props.name}
} }); ReactDOM.render( , document.getElementById("example"));
children 屬性

組件屬性中會(huì)有一個(gè)特殊屬性 children ,表示子組件, 還是以上面一個(gè)組件為例子,我們可以換一種方式定義 name:

    var TodoItem = React.createClass({
        render: function() {
            var props = this.props;
            return 
{props.children}
} }); ReactDOM.render( 代辦事項(xiàng)1, document.getElementById("example"));

需要注意的是,children 只能為一個(gè)元素,不能為多個(gè)組件

屬性類型檢查

為了保證組件傳遞屬性的正確性, 我們可以通過(guò)定義 propsType 對(duì)象來(lái)實(shí)現(xiàn)對(duì)組件屬性的嚴(yán)格校驗(yàn):

    var MyComponent = React.createClass({
        propTypes: {
            optionalArray: React.PropTypes.array,
            optionalBool: React.PropTypes.bool,
            optionalFunc: React.PropTypes.func,
            optionalNumber: React.PropTypes.number,
            optionalObject: React.PropTypes.object,
            optionalString: React.PropTypes.string,
            // 任何可以被渲染的包括,數(shù)字,字符串,組件,或者數(shù)組
            optionalNode: React.PropTypes.node,
            // React 元素
            optionalElement: React.PropTypes.element,
            // 枚舉
            optionalEnum: React.PropTypes.oneOf(["News", "Photos"]),
            // 任意一種類型
            optionalUnion: React.PropTypes.oneOfType([
              React.PropTypes.string,
              React.PropTypes.number,
              React.PropTypes.instanceOf(Message)
            ]),
            // 具體類型的數(shù)組
            optionalArrayOf: React.PropTypes.arrayOf(React.PropTypes.number),
            // 具體類型的對(duì)象
            optionalObjectOf: React.PropTypes.objectOf(React.PropTypes.number),
            // 符合定義的對(duì)象
            optionalObjectWithShape: React.PropTypes.shape({
              color: React.PropTypes.string,
              fontSize: React.PropTypes.number
            }),
            requiredFunc: React.PropTypes.func.isRequired,
            requiredAny: React.PropTypes.any.isRequired,
            // 自定義校驗(yàn)
            customProp: function(props, propName, componentName) {}
        }
    });
屬性傳遞的單向性

我們已經(jīng)提到過(guò) React 的單向數(shù)據(jù)流模式,數(shù)據(jù)的流動(dòng)管道就是 props,流動(dòng)的方向就是組件的層級(jí)自定向下的方向。所以一個(gè)組件是不能修改自身的屬性的,組件的屬性一定是通過(guò)父組件傳遞而來(lái)(或者默認(rèn)屬性)。

無(wú)狀態(tài)組件屬性

對(duì)于無(wú)狀態(tài)組件,可以添加 .propTypes.defaultProps 屬性到函數(shù)上。

1.3.6 組件的嵌套組合

在 1.2 節(jié)的 JSX 實(shí)例子中,當(dāng)我們循環(huán)輸出 todo 列表的時(shí)候,React 會(huì)提示對(duì)于循環(huán)輸出的組件,需要有一個(gè)唯一的 key 屬性。這個(gè)問(wèn)題的原因在于 React 的調(diào)和機(jī)制(Reconciliation)上。

什么叫調(diào)和?

在每次數(shù)據(jù)更新過(guò)后,React 會(huì)重新調(diào)用 render 渲染出新的組件結(jié)構(gòu),新的結(jié)構(gòu)應(yīng)用到 DOM 中的過(guò)程就叫做調(diào)和過(guò)程。

為什么需要調(diào)和?

想一想,假設(shè)我們有一個(gè)輸入組件,這個(gè)時(shí)候我們正聚焦在輸入框中,當(dāng)修改值過(guò)后觸發(fā)事件導(dǎo)致了數(shù)據(jù)改變,數(shù)據(jù)改變導(dǎo)致了重渲染, 這個(gè)時(shí)候輸入框被替換成了新的 DOM。 這個(gè)過(guò)程對(duì)用戶來(lái)說(shuō)應(yīng)該是無(wú)感知的,所以那原來(lái)的聚焦?fàn)顟B(tài)應(yīng)該被保存, 那怎么做到的呢? DOM 都被替換了,輸入狀態(tài),選擇狀態(tài)為什么還能保存。 我們先不急著知道 How,目前只需要知道這就是調(diào)和過(guò)程,后面我們會(huì)在 React 實(shí)現(xiàn)原理章節(jié)進(jìn)行詳細(xì)介紹。

除了保存狀態(tài)以外,調(diào)和過(guò)程還做了很多 DOM 優(yōu)化。 比如輸出一個(gè)數(shù)組的時(shí)候,數(shù)據(jù)新增加或者減少了一下,或者數(shù)組項(xiàng)值改變了,實(shí)際上我們沒(méi)有必要?jiǎng)h除原來(lái)的 DOM 結(jié)構(gòu),只需要修改 DOM 的值或者刪除 DOM 就能實(shí)現(xiàn)重渲染。

這就是為什么要有 key 屬性,key 屬性能夠幫助定位 DOM 與數(shù)組元素的關(guān)系,在重渲染的時(shí)候能夠?qū)崿F(xiàn)渲染優(yōu)化。

1.3.7 實(shí)例練習(xí):通過(guò)組件化的方式優(yōu)化之前的待辦事項(xiàng)列表 問(wèn)題

優(yōu)化 JSX 語(yǔ)法練習(xí)的 TODOMVC 頁(yè)面, 通過(guò)組件化的方式拆分頁(yè)面!

組件如下:

App 組件:整個(gè)頁(yè)面的最完成組件

Header 組件:頭部輸入組件

TodoList 組件:列表組件

TodoItem 組件: 列表項(xiàng)

Footer 組件:底部操作組件

Tips

循環(huán)輸出組件的方式

方式一:先計(jì)算出組件

 function render() {
    var todos = this.props.todos;
    var $todos = todos.map(function(todo) {
        return 
    });
    return 
{$todos}
}

方式二:{} 內(nèi)直接計(jì)算

 function render() {
    var todos = this.props.todos;
    return 
{todos.map(function(todo) { return })}
}
參考答案

https://github.com/leanklass/leanreact/tree/component

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/79489.html

相關(guān)文章

  • 精益 React 學(xué)習(xí)指南Lean React)- 1.3 React 組件

    摘要:無(wú)狀態(tài)組件除了可以通過(guò)來(lái)創(chuàng)建組件以外,組件也可以通過(guò)一個(gè)普通的函數(shù)定義,函數(shù)的返回值為組件渲染的結(jié)果。這就是為什么要有屬性,屬性能夠幫助定位與數(shù)組元素的關(guān)系,在重渲染的時(shí)候能夠?qū)崿F(xiàn)渲染優(yōu)化。 書籍完整目錄 1.3 React 組件 showImg(https://segmentfault.com/img/bVvLOW); 1.3.1 React 組件介紹 在 React 中組件是第一元...

    cyrils 評(píng)論0 收藏0
  • 精益 React 學(xué)習(xí)指南Lean React)- 4.1 react 代碼規(guī)范

    書籍完整目錄 4.1 react 代碼規(guī)范 showImg(https://segmentfault.com/img/bVyE9m); 關(guān)于 基礎(chǔ)規(guī)范 組件結(jié)構(gòu) 命名規(guī)范 jsx 書寫規(guī)范 eslint-plugin-react 關(guān)于 在代碼的設(shè)計(jì)上,每個(gè)團(tuán)隊(duì)可能都有一定的代碼規(guī)范和模式,好的代碼規(guī)范能夠提高代碼的可讀性便于協(xié)作溝通,好的模式能夠上層設(shè)計(jì)上避免不必要的 bug 出現(xiàn)。本節(jié)會(huì)參考...

    zhangqh 評(píng)論0 收藏0
  • 精益 React 學(xué)習(xí)指南Lean React)- 1.2 JSX 語(yǔ)法

    摘要:需要提醒讀者的是,的很多例子都是通過(guò)來(lái)寫的,但這并不是語(yǔ)法,后面我們會(huì)有單獨(dú)的一小節(jié)講解的基本語(yǔ)法,不過(guò)目前為止我們先將跟多精力放在上。 書籍完整目錄 1.2 JSX 語(yǔ)法 showImg(https://segmentfault.com/img/bVvKLR); 官方文檔 https://facebook.github.io/react/docs/jsx-in-depth.html ...

    moven_j 評(píng)論0 收藏0
  • 精益 React 學(xué)習(xí)指南Lean React)- 1.1 React 介紹

    摘要:?jiǎn)蜗驍?shù)據(jù)流應(yīng)用的核心設(shè)計(jì)模式,數(shù)據(jù)流向自頂向下我也是性子急的人,按照技術(shù)界的慣例,在學(xué)習(xí)一個(gè)技術(shù)前,首先得說(shuō)一句。然而的單向數(shù)據(jù)流的設(shè)計(jì)讓前端定位變得簡(jiǎn)單,頁(yè)面的和數(shù)據(jù)的對(duì)應(yīng)是唯一的我們可以通過(guò)定位數(shù)據(jù)變化就可以定位頁(yè)面展現(xiàn)問(wèn)題。 書籍完整目錄 1.1 React 介紹 showImg(https://segmentfault.com/img/bVvJgS); 1.1.1 React ...

    lsxiao 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<