React的四個(gè)概念簡(jiǎn)單介紹

React的四個(gè)概念簡(jiǎn)單介紹

React主要有四個(gè)主要概念構(gòu)成,下面分別來(lái)介紹一下:

Virtual DOM

  1. 虛擬DOM是React的基石。
  • 之所以引入虛擬DOM,一方面是性能的考慮。Web應(yīng)用和網(wǎng)站不同,一個(gè)Web應(yīng)用 中通常會(huì)在單頁(yè)內(nèi)有大量的DOM操作,而這些DOM操作很慢。
  • 在React中,應(yīng)用程序在虛擬DOM上操作,這讓React有了優(yōu)化的機(jī)會(huì)。簡(jiǎn)單說, React在每次需要渲染時(shí),會(huì)先比較當(dāng)前DOM內(nèi)容和待渲染內(nèi)容的差異, 然后再?zèng)Q定如何最優(yōu)地更新DOM。這個(gè)過程被稱為reconciliation。
  • 除了性能的考慮,React引入虛擬DOM更重要的意義是提供了一種一致的開發(fā)方 式來(lái)開發(fā)服務(wù)端應(yīng)用、Web應(yīng)用和手機(jī)端應(yīng)用:
圖片2.png

因?yàn)橛辛颂摂MDOM這一層,所以通過配備不同的渲染器,就可以將虛擬DOM的內(nèi)容 渲染到不同的平臺(tái)。而應(yīng)用開發(fā)者,使用JavaScript就可以通吃各個(gè)平臺(tái)了。相當(dāng)棒的思路!

  1. Virtual DOM速度快的說明

在Web開發(fā)中,我們總需要將變化的數(shù)據(jù)實(shí)時(shí)反應(yīng)到UI上,這時(shí)就需要對(duì)DOM進(jìn)行操作。而復(fù)雜或頻繁的DOM操作通常是性能瓶頸產(chǎn)生的原因(如何 進(jìn)行高性能的復(fù)雜DOM操作通常是衡量一個(gè)前端開發(fā)人員技能的重要指標(biāo))。React為此引入了虛擬DOM(Virtual DOM)的機(jī)制:在瀏覽器端用Javascript實(shí)現(xiàn)了一套DOM API。基于React進(jìn)行開發(fā)時(shí)所有的DOM構(gòu)造都是通過虛擬DOM進(jìn)行,每當(dāng)數(shù)據(jù)變化時(shí),React都會(huì)重新構(gòu)建整個(gè)DOM樹,然后React將當(dāng)前 整個(gè)DOM樹和上一次的DOM樹進(jìn)行對(duì)比,得到DOM結(jié)構(gòu)的區(qū)別,然后僅僅將需要變化的部分進(jìn)行實(shí)際的瀏覽器DOM更新。而且React能夠批處理虛擬 DOM的刷新,在一個(gè)事件循環(huán)(Event Loop)內(nèi)的兩次數(shù)據(jù)變化會(huì)被合并,例如你連續(xù)的先將節(jié)點(diǎn)內(nèi)容從A變成B,然后又從B變成A,React會(huì)認(rèn)為UI不發(fā)生任何變化,而如果通過手動(dòng)控 制,這種邏輯通常是極其復(fù)雜的。盡管每一次都需要構(gòu)造完整的虛擬DOM樹,但是因?yàn)?strong>虛擬DOM是內(nèi)存數(shù)據(jù),性能是極高的,而對(duì)實(shí)際DOM進(jìn)行操作的僅僅是 Diff部分,因而能達(dá)到提高性能的目的。這樣,在保證性能的同時(shí),開發(fā)者將不再需要關(guān)注某個(gè)數(shù)據(jù)的變化如何更新到一個(gè)或多個(gè)具體的DOM元素,而只需要 關(guān)心在任意一個(gè)數(shù)據(jù)狀態(tài)下,整個(gè)界面是如何Render的。詳情查看

React組件

  • 組件化概念
  1. 虛擬DOM(virtual-dom)不僅帶來(lái)了簡(jiǎn)單的UI開發(fā)邏輯,同時(shí)也帶來(lái)了組件化開發(fā)的思想,所謂組件,即封裝起來(lái)的具有獨(dú)立功能的UI部 件。React推薦以組件的方式去重新思考UI構(gòu)成,將UI上每一個(gè)功能相對(duì)獨(dú)立的模塊定義成組件,然后將小的組件通過組合或者嵌套的方式構(gòu)成大的組件, 最終完成整體UI的構(gòu)建。例如,F(xiàn)acebook的instagram.com整站都采用了React來(lái)開發(fā),整個(gè)頁(yè)面就是一個(gè)大的組件,其中包含了嵌套 的大量其它組件,大家有興趣可以看下它背后的代碼。
  2. 如果說MVC的思想讓你做到視圖-數(shù)據(jù)-控制器的分離,那么組件化的思考方式則是帶來(lái)了UI功能模塊之間的分離。我們通過一個(gè)典型的Blog評(píng)論界面來(lái)看MVC和組件化開發(fā)思路的區(qū)別
  3. 對(duì)于MVC開發(fā)模式來(lái)說,開發(fā)者將三者定義成不同的類,實(shí)現(xiàn)了表現(xiàn),數(shù)據(jù),控制的分離。開發(fā)者更多的是從技術(shù)的角度來(lái)對(duì)UI進(jìn)行拆分,實(shí)現(xiàn)松耦合。

對(duì)于React而言,則完全是一個(gè)新的思路,開發(fā)者從功能的角度出發(fā),將UI分成不同的組件,每個(gè)組件都獨(dú)立封裝。
在React中,你按照界面模塊自然劃分的方式來(lái)組織和編寫你的代碼,對(duì)于評(píng)論界面而言,整個(gè)UI是一個(gè)通過小組件構(gòu)成的大組件,每個(gè)組件只關(guān)心自己部分的邏輯,彼此獨(dú)立。

  • 組件化開發(fā)特性
    React認(rèn)為一個(gè)組件應(yīng)該具有如下特征:
  1. 可組合(Composeable):一個(gè)組件易于和其它組件一起使用,或者嵌套在另一個(gè)組件內(nèi)部。如果一個(gè)組件內(nèi)部創(chuàng)建了另一個(gè)組件,那么說父組件擁有(own)它創(chuàng)建的子組件,通過這個(gè)特性,一個(gè)復(fù)雜的UI可以拆分成多個(gè)簡(jiǎn)單的UI組件;
  2. 可重用(Reusable):每個(gè)組件都是具有獨(dú)立功能的,它可以被使用在多個(gè)UI場(chǎng)景;
  3. 可維護(hù)(Maintainable):每個(gè)小的組件僅僅包含自身的邏輯,更容易被理解和維護(hù);
  4. 可測(cè)試(Testable):因?yàn)槊總€(gè)組件都是獨(dú)立的,那么對(duì)于各個(gè)組件分別測(cè)試顯然要比對(duì)于整個(gè)UI進(jìn)行測(cè)試容易的多。
  • 組件定義
    在React中定義一個(gè)組件也是相當(dāng)?shù)娜菀?,組件就是一個(gè) 實(shí)現(xiàn)預(yù)定義接口的JavaScript類:
  1. 組件渲染

ReactDOM.render 是 React 的最基本方法,用于將模板轉(zhuǎn)為 HTML 語(yǔ)言,并插入指定的 DOM 節(jié)點(diǎn)。

ReactDOM.render(
  <h1>Hello, world!</h1>,
  document.getElementById('example')
  );

而這個(gè)方法, 必須而且只能返回一個(gè)有效的React元素。這意味著,如果你的組件是由多個(gè)元素構(gòu)成的,那么你必須在外邊包一個(gè)頂層 元素,然后返回這個(gè)頂層元素。比如我們創(chuàng)建一個(gè)布局組件:

render:function(){
    return React.createElement(
        "div",null,
        React.createElement("div",null,"header"),
        React.createElement("div",null,"content"),
        React.createElement("div",null,"footer")
    );
}
  1. ES5方式定義組件
"use strict";
var HelloMessage = React.createClass({
  displayName: "HelloMessage",
render: function render() {
    return React.createElement(
      "div",
      null,
      "Hello ",
      this.props.name
    );
  }
  });
ReactDOM.render(React.createElement(HelloMessage, { name: "John" }), mountNode);
  1. Jsx中定義組件
var HelloMessage = React.createClass({
  render: function() {
    return <div>Hello {this.props.name}</div>;
  }
});
ReactDOM.render(<HelloMessage name="John" />, mountNode);
  1. ES6中定義組件
import './Hello.css';
import './Hello.scss';
import React, {Component} from 'react';
// 內(nèi)聯(lián)樣式
let style={
    backgroundColor:'blue'
}
export default class Hello extends Component {
    constructor(props) {
        super(props);
        this.state = { count: 'es6'};
    }
    render() {
        return (
            <div>
                <h1 style={style}>Hello world{this.state.count}</h1>
                <br/>
                <image/>
            </div>
        )
            }
}

5 注意事項(xiàng)

(1)你的React組件名稱的首字母應(yīng)當(dāng)大寫,關(guān)于大小寫的差異你會(huì)在后面發(fā)現(xiàn)。
(2)你應(yīng)該會(huì)注意到div元素的樣式類是用 className而不是class聲明的,這是因?yàn)閏lass 是JavaScript的保留字,渲染后,真實(shí)的DOM還會(huì)是:

<div class="ez-led">Hello, React!</div>

Jsx語(yǔ)法

  • 什么是jsx

在用React寫組件的時(shí)候,通常會(huì)用到JSX語(yǔ)法,粗看上去,像是在Javascript代碼里直接寫起了XML標(biāo)簽,實(shí)質(zhì)上這只是一個(gè)語(yǔ)法糖,每一個(gè) XML標(biāo)簽都會(huì)被JSX轉(zhuǎn)換工具轉(zhuǎn)換成純Javascript代碼,當(dāng)然你想直接使用純Javascript代碼寫也是可以的,只是利用JSX,組件的結(jié) 構(gòu)和組件之間的關(guān)系看上去更加清晰

  • Jsx語(yǔ)法使用
    HTML 語(yǔ)言直接寫在 JavaScript 語(yǔ)言之中,不加任何引號(hào),這就是 JSX 的語(yǔ)法,它允許 HTML 與 JavaScript 的混寫。
var names = ['Alice', 'Emily', 'Kate'];
ReactDOM.render(
  <div>
  {
    names.map(function (name) {
      return <div>Hello, {name}!</div>
    })
  }
  </div>,
  document.getElementById('example')
);

上面代碼體現(xiàn)了 JSX 的基本語(yǔ)法規(guī)則:遇到 HTML 標(biāo)簽(以 < 開頭),就用 HTML 規(guī)則解析;遇到代碼塊(以 { 開頭),就用 JavaScript 規(guī)則解析。


JSX 允許直接在模板插入 JavaScript 變量。如果這個(gè)變量是一個(gè)數(shù)組,則會(huì)展開這個(gè)數(shù)組的所有成員

var arr = [
  <h1>Hello world!</h1>,
  <h2>React is awesome</h2>,
];
ReactDOM.render(
  <div>{arr}</div>,
  document.getElementById('example')
);

上面代碼的arr變量是一個(gè)數(shù)組,結(jié)果 JSX 會(huì)把它的所有成員,添加到模板,運(yùn)行結(jié)果如下。

Data Flow(單向數(shù)據(jù)流)

  • 傳統(tǒng)的mvc

到了 Flux 當(dāng)中, 除了名字改變了, 重要的是大量的 Model 歸到了 Store, View 也統(tǒng)一了,從而得到了所謂單向的數(shù)據(jù)流, 就是 Model 和 View 之間關(guān)系非常清晰了。這樣需要人為管理的狀態(tài)就一下少了很多, 結(jié)果體現(xiàn)在開發(fā)應(yīng)用的效率當(dāng)中:

  • Flux
  1. 詳細(xì)學(xué)習(xí)地址:https://hulufei.gitbooks.io/react-tutorial/content/flux.html
  2. React 標(biāo)榜自己是 MVC 里面 V 的部分,那么 Flux 就相當(dāng)于添加 M 和 C 的部分,F(xiàn)lux 是 Facebook 使用的一套前端應(yīng)用的架構(gòu)模式。
  3. 一個(gè) Flux 應(yīng)用主要包含四個(gè)部分:
    1. dispatcher 處理動(dòng)作分發(fā),維護(hù) Store 之間的依賴關(guān)系
    2. stores 數(shù)據(jù)和邏輯部分
    3. views React 組件,這一層可以看作 controller-views,作為視圖同時(shí)響應(yīng)用戶交互
    4. actions 提供給 dispatcher 傳遞數(shù)據(jù)給 store
  4. 單向數(shù)據(jù)流
    先來(lái)了解一下 Flux 的核心“單向數(shù)據(jù)流“怎么運(yùn)作的:
    Action -> Dispatcher -> Store -> View
    更多時(shí)候 View 會(huì)通過用戶交互觸發(fā) Action,所以一個(gè)簡(jiǎn)單完整的數(shù)據(jù)流類似這樣:

整個(gè)流程如下:

  1. 首先要有 action,通過定義一些 action creator 方法根據(jù)需要?jiǎng)?chuàng)建 Action 提供給 dispatcher
  2. View 層通過用戶交互(比如 onClick)會(huì)觸發(fā) Action
  3. Dispatcher 會(huì)分發(fā)觸發(fā)的 Action 給所有注冊(cè)的 Store 的回調(diào)函數(shù)
  4. Store 回調(diào)函數(shù)根據(jù)接收的 Action 更新自身數(shù)據(jù)之后會(huì)觸發(fā)一個(gè) change 事件通知 View 數(shù)據(jù)更改了
  5. View 會(huì)監(jiān)聽這個(gè) change 事件,拿到對(duì)應(yīng)的新數(shù)據(jù)并調(diào)用 setState 更新組件 UI
    所有的狀態(tài)都由 Store 來(lái)維護(hù),通過 Action 傳遞數(shù)據(jù),構(gòu)成了如上所述的單向數(shù)據(jù)流循環(huán),所以應(yīng)用中的各部分分工就相當(dāng)明確,高度解耦了。
    這種單向數(shù)據(jù)流使得整個(gè)系統(tǒng)都是透明可預(yù)測(cè)的。

Redux

Redux官方中文文檔:http://camsong.github.io/redux-in-chinese/index.html

Reflux:https://segmentfault.com/a/1190000002793786?utm_source=tuicool

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容