為什么要有React.js?

之前一直用 React.js 來(lái)寫(xiě)一個(gè)電影選購(gòu)商城,對(duì)于剛上手的我來(lái)說(shuō)感覺(jué)處處和 Vue.js 差不多呀,反正就是無(wú)腦使用數(shù)據(jù)綁定,然后 render 就收工了,一直沒(méi)有去了解 React 誕生的原因。如果你也一直用著 React.js 但是不了解它的歷史,那么希望這篇文章可以幫到你。

簡(jiǎn)單的加減器

我們先來(lái)做一個(gè)簡(jiǎn)音的加減器,要求

  1. 顯示一個(gè)數(shù)字
  2. 點(diǎn)擊按鈕+,數(shù)字加1
  3. 點(diǎn)擊按鈕-,數(shù)字減1
    使用原生的 DOM API,我們可能會(huì)寫(xiě)出這樣的代碼:
<div>
    <span id="result">0</span>
    <button id="add">+</button>
    <button id="minus">-</button>
</div>
let result = document.querySelector('#result')
let add = document.querySelector('#add')
let minus = document.querySelector('#minus')

add.addEventListener('click', function () {
    // Turn to number
    let number = parseInt(result.innerText)
    number += 1
    result.innerText = number
})

minus.addEventListener('click', function () {
    // Turn to number
    let number = parseInt(result.innerText)
    number -= 1
    result.innerText = number
})

這里的代碼無(wú)非就是

  1. 先獲取要用的元素
  2. 每次點(diǎn)擊先獲取值,然后進(jìn)行處理(加減法)
  3. 最后再賦上新值
    這就是我們經(jīng)常說(shuō)的“意大利面條”代碼,跟語(yǔ)文老師說(shuō)的“你的文章寫(xiě)得跟流水賬一樣”。怎么才能避免這樣的寫(xiě)法呢?答案:將代碼抽象。

思路

我們現(xiàn)在的思路就是下圖這樣的。



React 程序員這時(shí)候想要是能把上面的獲取步驟去掉就好了:

  • 我不從 DOM 元素里取,而是在 JS 里直接生成一個(gè) DOM 元素
  • 每次值改變的時(shí)候,重新將這個(gè)元素渲染(清除,修改,追加)

虛擬 DOM

生成 DOM 元素當(dāng)然不是就用 document.createElement 那么簡(jiǎn)單了,我們希望創(chuàng)建 DOM 的時(shí)候把其下面的子元素和屬性都帶上一并創(chuàng)建,一個(gè)好的創(chuàng)建函數(shù)可以是這樣的:

createElement(RootElement root, Attributes {}, Children [])

有了這個(gè)創(chuàng)建元素的函數(shù)后我們就可以不用在 HTML 里寫(xiě)元素了,直接用這個(gè)函數(shù)創(chuàng)建就好。

<div id="root"></div>

這樣寫(xiě)JS就更容易理解了。

let number = 0
let add = () => {
    number += 1
    render()
}

let minus = () => {
    number -= 1
    render()
}

let render = () => {
    let span = React.createElement('span', { className: 'red' }, number)
    let addBtn  = React.createElement('button', {onClick: add}, '+')
    let minusBtn = React.createElement('button', {onClick: minus}, '-')
    let div = React.createElement('div', { className: 'parent' }, span, addBtn, minusBtn)
    ReactDOM.render(div, document.querySelector('#root'))
}

render()

現(xiàn)在我們的思路是:點(diǎn)擊 => 修改數(shù)據(jù) => 渲染,去掉了取值的操作。

JSX 的發(fā)明

這時(shí)候 React 程序員還是覺(jué)得不好,這一大坨的React.createElement很zz,所以他們做了下面的3件事:

  1. 先將React.createElementh來(lái)代替,即let h = React.createElement。嗯,這樣代碼縮短了一點(diǎn)點(diǎn)
  2. 將一次使用過(guò)的變量直接傳入創(chuàng)建divReact.createElement里,所以變成這樣
let div =
    h( 'div', { className: 'parent' },
        h('span', { className: 'red' }, number),
        h('button', {onClick: add}, '+'),
        h('button', {onClick: minus}, '-'))
  1. 這時(shí)候有沒(méi)有突然發(fā)現(xiàn)這樣的代碼和我們的 HTML 有點(diǎn)像啊?div 是父元素,其它的都是子元素,只要縮進(jìn)縮得好,一切好像都能用 HTML 代碼來(lái)表示
let trans = `
    <div class="parent">
        <span class="red">number</span>
        <button onclick="add">+</button>
        <button onclick="minus">-</button>
    </div>`

所以 JSX 就被發(fā)明出來(lái)了,為了能夠區(qū)分變量和字符串,變量要用{}來(lái)包住變量,而且為了和 HTML 區(qū)分 onclick 變成 onClick、class 變成 className

let jsx = `
    <div className="parent">
        <span className="red">{number}</span>
        <button onClick={add}>+</button>
        <button onClick={minus}>-</button>
    </div>`

看看用 Babel 翻譯后的結(jié)果


Babel 轉(zhuǎn)譯后的結(jié)果.png

最終React版本

直接使用 JSX 語(yǔ)法就是我們 React 一直使用的樣子了。

let number = 0
let add = () => {
    number += 1
    render()
}

let minus = () => {
    number -= 1
    render()
}

let render = () => {
    ReactDOM.render(
        <div className="parent">
            <span className="red">{number}</span>
            <button onClick={add}>+</button>
            <button onClick={minus}>-</button>
        </div>,
        document.querySelector('#root'))
}

render()

很多人開(kāi)始學(xué) React 的時(shí)候一直覺(jué)得虛擬 DOM 是什么高大上的東西,其實(shí)簡(jiǎn)單來(lái)說(shuō)就是假的 DOM。為什么呢?因?yàn)椴贿^(guò)是通過(guò)對(duì)象來(lái)創(chuàng)建 DOM 元素罷了,如

let attr = {
    className: "parent",
    text: 'hello'
}
React.createElement(root, attr, childElement)

所以虛擬 DOM 其實(shí)就是表示真實(shí) DOM 元素的對(duì)象而已。
(完)

?著作權(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)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

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

  • 原文地址:Learning React.js is easier than you think原文作者:Samer...
    sunshine小小倩閱讀 4,328評(píng)論 3 41
  • HTML模版 之后出現(xiàn)的React代碼嵌套入模版中。 1. Hello world 這段代碼將一個(gè)一級(jí)標(biāo)題插入到指...
    ryanho84閱讀 6,422評(píng)論 0 9
  • 40、React 什么是React?React 是一個(gè)用于構(gòu)建用戶界面的框架(采用的是MVC模式):集中處理VIE...
    萌妹撒閱讀 1,179評(píng)論 0 1
  • 3. JSX JSX是對(duì)JavaScript語(yǔ)言的一個(gè)擴(kuò)展語(yǔ)法, 用于生產(chǎn)React“元素”,建議在描述UI的時(shí)候...
    pixels閱讀 2,971評(píng)論 0 24
  • 簡(jiǎn)單的事情重復(fù)做,反復(fù)的細(xì)化每一個(gè)角度,結(jié)合客戶的想法去深化,專注自己的技能和知識(shí),這樣才能讓客戶看到一個(gè)好作品,...
    踏雪無(wú)痕sdf閱讀 280評(píng)論 0 0

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