React框架學(xué)習(xí)

React的起源和發(fā)展

起初facebook在建設(shè)instagram(圖片分享)的時(shí)候嘞,因?yàn)闋砍兜揭粋€(gè)東東叫數(shù)據(jù)流,那為了處理數(shù)據(jù)流并且還要考慮好性能方面的問題嘞卷雕,F(xiàn)acebook開始對市場上的各種前端MVC框架去進(jìn)行一個(gè)研究幸逆,然而并沒有看上眼的却嗡,于是Facebook覺得纵隔,還是自己開發(fā)一個(gè)才是最棒的翻诉,那么他們決定拋開很多所謂的“最佳實(shí)踐”,重新思考前端界面的構(gòu)建方式巨朦,他們就自己開發(fā)了一套,果然大牛創(chuàng)造力還是很強(qiáng)大的剑令。

React的出發(fā)點(diǎn)

基于HTML的前端界面開發(fā)正變得越來越復(fù)雜糊啡,其本質(zhì)問題基本都可以歸結(jié)于如何將來自于服務(wù)器端或者用戶輸入的動(dòng)態(tài)數(shù)據(jù)高效的反映到復(fù)雜的用戶界面上。而來自Facebook的React框架正是完全面向此問題的一個(gè)解決方案吁津,按官網(wǎng)描述棚蓄,其出發(fā)點(diǎn)為:用于開發(fā)數(shù)據(jù)不斷變化的大型應(yīng)用程序(Building large applications with data that changes over time)。相比傳統(tǒng)型的前端開發(fā)碍脏,React開辟了一個(gè)相當(dāng)另類的途徑梭依,實(shí)現(xiàn)了前端界面的高性能高效率開發(fā)。

React與傳統(tǒng)MVC的關(guān)系

輕量級的視圖層框架典尾! React不是一個(gè)完整的MVC框架役拴,最多可以認(rèn)為是MVC中的V(View),甚至React并不非常認(rèn)可MVC開發(fā)模式钾埂;

React高性能的體現(xiàn):虛擬DOM

React高性能的原理:
在Web開發(fā)中我們總需要將變化的數(shù)據(jù)實(shí)時(shí)反應(yīng)到UI上河闰,這時(shí)就需要對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)行對比氨菇,得到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)為A變成B奶是,然后又從B變成A UI不發(fā)生任何變化楣责,而如果通過手動(dòng)控制竣灌,這種邏輯通常是極其復(fù)雜的。

盡管每一次都需要構(gòu)造完整的虛擬DOM樹秆麸,但是因?yàn)樘摂MDOM是內(nèi)存數(shù)據(jù)初嘹,性能是極高的,部而對實(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的缸匪。數(shù)據(jù)驅(qū)動(dòng)翁狐,聲明式

React的特點(diǎn)和優(yōu)勢

  1. 虛擬DOM 我們以前操作dom的方式是通過document.getElementById()的方式,這樣的過程實(shí)際上是先去讀取html的dom結(jié)構(gòu)凌蔬,將結(jié)構(gòu)轉(zhuǎn)換成變量露懒,再進(jìn)行操作 而reactjs定義了一套變量形式的dom模型,一切操作和換算直接在變量中砂心,這樣減少了操作真實(shí)dom懈词,性能真實(shí)相當(dāng)?shù)母哂止伲椭髁鱉VC框架有本質(zhì)的區(qū)別赃蛛,并不和dom打交道
  2. 組件系統(tǒng) react最核心的思想是將頁面中任何一個(gè)區(qū)域或者元素都可以看做一個(gè)組件 component 那么什么是組件呢操禀? 組件指的就是同時(shí)包含了html讶请、css撼班、js永淌、image元素的聚合體使用react開發(fā)的核心就是將頁面拆分成若干個(gè)組件粪般,并且react一個(gè)組件中同時(shí)耦合了css察纯、js秧秉、image褐桌,這種模式整個(gè)顛覆了過去的傳統(tǒng)的方式
  3. 單向數(shù)據(jù)流 其實(shí)reactjs的核心內(nèi)容就是數(shù)據(jù)綁定,所謂數(shù)據(jù)綁定指的是只要將一些服務(wù)端的數(shù)據(jù)和前端頁面綁定好象迎,開發(fā)者只關(guān)注實(shí)現(xiàn)業(yè)務(wù)就行了
  4. JSX 語法 在vue中荧嵌,我們使用render函數(shù)來構(gòu)建組件的dom結(jié)構(gòu)性能較高,因?yàn)槭∪チ瞬檎液途幾g模板的過程砾淌,但是在render中利用createElement創(chuàng)建結(jié)構(gòu)的時(shí)候代碼可讀性較低啦撮,較為復(fù)雜,此時(shí)可以利用jsx語法來在render中創(chuàng)建dom汪厨,解決這個(gè)問題赃春,但是前提是需要使用工具來編譯jsx

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

react開發(fā)需要引入多個(gè)依賴文件:react.js、react-dom.js劫乱,分別又有開發(fā)版本和生成版本
在這里一開始织中,我們先學(xué)習(xí)es5的組件寫法锥涕,React.createClass,需要引入的是15+
react.js中有React對象狭吼,幫助我們創(chuàng)建組件等功能
react-dom.js中有ReactDOM對象层坠,渲染組件的虛擬dom為真實(shí)dom的爆發(fā)功能
在編寫react代碼的時(shí)候會(huì)大量的使用到j(luò)sx代碼,但是需要編譯:

  1. 瀏覽器端編譯刁笙,通過引入browser破花、babel等對引入的script內(nèi)的代碼做編譯
  2. 利用webpack等開發(fā)環(huán)境進(jìn)行編譯,將編譯好的文件引入到應(yīng)用中

    //創(chuàng)建組件
    var Hello = React.createClass({
        render:function () {
            //render函數(shù)和Vue組件里的render完全一樣疲吸,在vue組件中可以不用編寫render函數(shù)座每,
            //這個(gè)時(shí)候可以使用template模板來編寫組件的虛擬dom結(jié)構(gòu),
            //然后vue組件會(huì)自動(dòng)講模板compile成虛擬dom結(jié)構(gòu)放入到render中執(zhí)行摘悴,但是react需要編寫render函數(shù)

            return (
                //jsx語法
                <div>asdasd</div>
            )
            
        }
    })
    //利用ReactDOM對象的render方法將組件渲染到某個(gè)節(jié)點(diǎn)里
    ReactDOM.render(<Hello/>,document.getElementById("app"))

組件是通過React.createClass創(chuàng)建的(ES5)峭梳,在es6中直接通過class關(guān)鍵字來創(chuàng)建
組件其實(shí)就是一個(gè)構(gòu)造器,每次使用組件都相當(dāng)于在實(shí)例化組件
react的組件必須使用render函數(shù)來創(chuàng)建組件的虛擬dom結(jié)構(gòu)
組件需要使用ReactDOM.render方法將其掛載在某一個(gè)節(jié)點(diǎn)上
組件的首字母必須大寫

JSX語法糖

JSX是一種語法,全稱:javascript xml
JSX語法不是必須使用的烦租,但是因?yàn)槭褂昧薐SX語法之后會(huì)降低我們的開發(fā)難度延赌,故而這樣的語法又被成為語法糖
在不使用JSX的時(shí)候除盏,需要使用React.createElement來創(chuàng)建組件的dom結(jié)構(gòu)叉橱,但是這樣的寫法雖然不需要編譯,但是維護(hù)和開發(fā)的難度很高者蠕,且可讀性很差

var world = React.createElement('h1',{className:'abc',id:'haha'},[
    React.createElement('span',null,'Hello'),
    React.createElement('mark',null,'React')
])
            
//利用ReactDOM對象的render方法將組件渲染到某個(gè)節(jié)點(diǎn)里
ReactDOM.render(world,document.getElementById("app1"))

及時(shí)使用了JSX語法了之后窃祝,也是需要將其編譯成原生的createElement的
JSX就是在js中使用的xml,但是踱侣,這里的xml不是真正的xml粪小,只能借鑒了一些xml的語法,例如:
最外層必須有根節(jié)點(diǎn)抡句、標(biāo)簽必須閉合
jsx借鑒xml的語法而不是html的語法原因:xml要比html嚴(yán)謹(jǐn)探膊,編譯更方便

組件dom添加樣式

在react里表達(dá)式的符號是 "{ }",作用和vue的表達(dá)式作用是一樣的
想給虛擬dom添加行內(nèi)樣式,需要使用表達(dá)式傳入樣式對象的方式來實(shí)現(xiàn):

<p style = { {color:'red',fontSize:2+'em'} }>Hello world</p>

行內(nèi)樣式需要寫入一個(gè)樣式對象待榔,而這個(gè)樣式對象的位置可以放在很多地方逞壁,例如React.createClass的配置項(xiàng)中、render函數(shù)里锐锣、組件原型上腌闯、外鏈js文件中
React推薦我們使用行內(nèi)樣式,因?yàn)閞eact覺得每一個(gè)組件都是一個(gè)獨(dú)立的整體
其實(shí)我們大多數(shù)情況下還是大量的在為元素添加類名雕憔、id以使用某些樣式姿骏,但是需要注意的是,class需要寫成className(因?yàn)楫吘故窃趯戭恓s代碼斤彼,會(huì)收到j(luò)s規(guī)則的現(xiàn)在分瘦,而class是關(guān)鍵字)

<p className="bg-p" id="myp" style = { this.style }>Hello world</p>

React Event

在react中蘸泻,我們想要給組件的dom添加事件的話,也是 需要在行內(nèi)添加的方式擅腰,事件名字需要寫成小駝峰的方式蟋恬,值利用表達(dá)式傳入一個(gè)函數(shù)即可
注意,在沒有渲染的時(shí)候趁冈,頁面中沒有真實(shí)dom歼争,所以是獲取不到dom的
給虛擬dom結(jié)構(gòu)中的節(jié)點(diǎn)添加樣式。在行內(nèi)添加,寫成駝峰形式渗勘,值是一個(gè)函數(shù)名沐绒,需要用{}包裹

handleClick:function () {
    alert(1)
},
render:function () {
    return (
        <div>
            <button onClick = {this.handleClick} className="click-btn">click</button>
            <button onDoubleClick = {this.handleClick} className="click-btn">click</button>
        </div>
    )
}

組件嵌套

將一個(gè)組件渲染到某一個(gè)節(jié)點(diǎn)里的時(shí)候,會(huì)將這個(gè)節(jié)點(diǎn)里原有內(nèi)容覆蓋
組件嵌套的方式就是將子組件寫入到父組件的模板中去旺坠,且react沒有Vue中的內(nèi)容分發(fā)機(jī)制(slot)乔遮,所以我們在一個(gè)組件的模板中只能看到父子關(guān)系

var Hello = React.createClass({
    render(){
        return (
            <h1>
                Hello
                <World></World>
            </h1>
        )
    }
})
var World = React.createClass({
    render(){
        return (
            <mark>
                World-<Person/>
            </mark>
        )
    }
})
//無狀態(tài)組件
var Person =function(){
    return (<mark>lilei</mark>)
}
ReactDOM.render(<Hello/>,app)

注意,react中jsx里的注釋要寫成{/* */}的方式

React中的數(shù)據(jù)承載-Props/State

數(shù)據(jù)驅(qū)動(dòng)取刃、聲明式渲染:

任意的視圖變化都應(yīng)該由數(shù)據(jù)來控制

//$(".a").html(0)
var num = 0
function renderNum () { $(".a").html(num) }

React也是基于數(shù)據(jù)驅(qū)動(dòng)(聲明式)的框架蹋肮,組件中必然需要承載一些數(shù)據(jù),在react中起到這個(gè)作用的是屬性和狀態(tài)(props & state)

  1. 屬性(props) 在組件外部傳入璧疗,或者內(nèi)部設(shè)置坯辩,組件內(nèi)部通過this.props獲得
  2. 狀態(tài)(state) 在組件內(nèi)部設(shè)置或者更改,組件內(nèi)部通過this.state獲得
屬性(props)

屬性一般是外部傳入的崩侠,組件內(nèi)部也可以通過一些方式來初始化的設(shè)置漆魔,屬性不能被組件自己更改
屬性是描述性質(zhì)、特點(diǎn)的却音,組件自己不能隨意更改
使組件擁有屬性的方式:

  1. 在裝載(mount)組件的時(shí)候給組件傳入
    傳入數(shù)據(jù)的時(shí)候改抡,除了字符串類型,其他的都應(yīng)該包上表達(dá)式系瓢,但是為了規(guī)整阿纤,所有的數(shù)據(jù)傳遞,最好都包上{}
var Gouzi = React.createClass({
    render(){
        console.log(this)
        return (
            <div>
                <p>我的名字:{this.props.name}</p>
                <p>我的性別:{this.props.sex}</p>
                <p>我的年齡:{this.props.age}</p>  
                <p>我的父親是:{this.props.father}</p>                                              
            </div>
        )
    }
})
let info = {
    sex:'male',
    father:'狗爸'
}
ReactDOM.render(<Gouzi {...info} name={"大狗子"} age={26}/>,app)
  1. 父組件給子組件傳入
    父組件在嵌套子組件的時(shí)候?yàn)樽咏M件傳入夷陋,傳入的方式和上面的方式一樣
//父組件的render函數(shù)
render(){
    return (
        <div>
            <p>父組件:</p>
            <hr/>
            <Son name={'大狗子'}/>
            <Son name={'二狗子'}/>
        </div>
    )
}
  1. 子組件自己設(shè)置
    子組件可以通過getDefaultProps來設(shè)置默認(rèn)的屬性
    getDefaultProps的值是函數(shù)欠拾,這個(gè)函數(shù)會(huì)返回一個(gè)對象,我們在這里對象里為組件設(shè)置默認(rèn)屬性
    這種方式設(shè)置的屬性優(yōu)先級低肌稻,會(huì)被外部傳入的屬性值所覆蓋
getDefaultProps:function () {
    console.log('getDefaultProps')
    return {
        name:'狗爸',
        sonname:'二狗子'
    }
},
//render
<p>我是{this.props.sonname}的父親-{this.props.name}</p>

根據(jù)屬性或狀態(tài)清蚀,我們可以在render中的表達(dá)式里做一些邏輯判斷,可以使用||爹谭、三元表達(dá)式枷邪、子執(zhí)行函數(shù)等等

getName(){
    return this.props.name || '野狗子'
},
render:function () {
    let {name} = this.props
    return (
    <div>
        <p>我是子組件-{this.props.name || '野狗子'}</p>
        <p>我是子組件-{this.props.name?this.props.name:'野狗子'}</p>
        <p>我是子組件-{this.getName()}</p>
        <p>我是子組件-{(function (obj) {
            return obj.props.name || '野狗子'
        })(this)}</p>
    </div>
    )
}
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子东揣,更是在濱河造成了極大的恐慌践惑,老刑警劉巖,帶你破解...
    沈念sama閱讀 221,888評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件嘶卧,死亡現(xiàn)場離奇詭異尔觉,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)芥吟,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,677評論 3 399
  • 文/潘曉璐 我一進(jìn)店門侦铜,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人钟鸵,你說我怎么就攤上這事钉稍。” “怎么了棺耍?”我有些...
    開封第一講書人閱讀 168,386評論 0 360
  • 文/不壞的土叔 我叫張陵贡未,是天一觀的道長。 經(jīng)常有香客問我蒙袍,道長俊卤,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,726評論 1 297
  • 正文 為了忘掉前任害幅,我火速辦了婚禮消恍,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘矫限。我一直安慰自己哺哼,他們只是感情好佩抹,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,729評論 6 397
  • 文/花漫 我一把揭開白布叼风。 她就那樣靜靜地躺著,像睡著了一般棍苹。 火紅的嫁衣襯著肌膚如雪无宿。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,337評論 1 310
  • 那天枢里,我揣著相機(jī)與錄音孽鸡,去河邊找鬼。 笑死栏豺,一個(gè)胖子當(dāng)著我的面吹牛彬碱,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播奥洼,決...
    沈念sama閱讀 40,902評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼巷疼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了灵奖?” 一聲冷哼從身側(cè)響起嚼沿,我...
    開封第一講書人閱讀 39,807評論 0 276
  • 序言:老撾萬榮一對情侶失蹤估盘,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后骡尽,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體遣妥,經(jīng)...
    沈念sama閱讀 46,349評論 1 318
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,439評論 3 340
  • 正文 我和宋清朗相戀三年攀细,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了箫踩。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,567評論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡谭贪,死狀恐怖班套,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情故河,我是刑警寧澤吱韭,帶...
    沈念sama閱讀 36,242評論 5 350
  • 正文 年R本政府宣布,位于F島的核電站鱼的,受9級特大地震影響理盆,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜凑阶,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,933評論 3 334
  • 文/蒙蒙 一猿规、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧宙橱,春花似錦姨俩、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,420評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至宝冕,卻和暖如春张遭,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背地梨。 一陣腳步聲響...
    開封第一講書人閱讀 33,531評論 1 272
  • 我被黑心中介騙來泰國打工菊卷, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人宝剖。 一個(gè)月前我還...
    沈念sama閱讀 48,995評論 3 377
  • 正文 我出身青樓洁闰,卻偏偏與公主長得像,于是被迫代替她去往敵國和親万细。 傳聞我的和親對象是個(gè)殘疾皇子扑眉,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,585評論 2 359

推薦閱讀更多精彩內(nèi)容

  • React.js 小書學(xué)習(xí) 之 【使用 JSX 描述 UI 信息】 從 JSX 到頁面 過程圖解:JSX 到頁面過...
    zdlucky閱讀 1,282評論 0 20
  • 原教程內(nèi)容詳見精益 React 學(xué)習(xí)指南襟雷,這只是我在學(xué)習(xí)過程中的一些閱讀筆記刃滓,個(gè)人覺得該教程講解深入淺出,比目前大...
    leonaxiong閱讀 2,843評論 1 18
  • 40耸弄、React 什么是React咧虎?React 是一個(gè)用于構(gòu)建用戶界面的框架(采用的是MVC模式):集中處理VIE...
    萌妹撒閱讀 1,022評論 0 1
  • $ 前言 ? 最近在考慮框架轉(zhuǎn)型,鑒于作為一名JSer计呈,要時(shí)時(shí)刻刻保持對新技術(shù)和流行技術(shù)的敏感性砰诵,而 React、...
    果汁涼茶丶閱讀 22,004評論 5 32
  • 《千字文》可以說是蒙學(xué)經(jīng)典的一座里程碑捌显。大家一定會(huì)說我這話說的太嚴(yán)重了茁彭,不就是小孩子讀的兒歌嗎?其實(shí)也不然扶歪,外行看...
    結(jié)雨堂李宏宇閱讀 3,503評論 1 9