React組件與JSX語法

virtual DOM

真實(shí)頁面對(duì)應(yīng)一個(gè)DOM樹彻舰。在傳統(tǒng)頁面的開發(fā)模式中伐割,每一次需要更新頁面的時(shí)候,都需要手動(dòng)操作DOM來進(jìn)行更新淹遵。

傳統(tǒng)DOM更新

DOM的操作是十分昂貴的口猜,我們?cè)谇岸碎_發(fā)中,性能消耗最大的就是DOM操作透揣,而且這部分的代碼會(huì)讓整體項(xiàng)目的代碼變得難以維護(hù)济炎。React把真實(shí)的DOM樹轉(zhuǎn)換為JavaScript對(duì)象樹,也就是virtual DOM辐真。

React DOM更新

每一次數(shù)據(jù)更新后须尚,重新計(jì)算Virtual DOM,并和上一次生成的Virtual DOM進(jìn)行比對(duì)侍咱,對(duì)發(fā)生變化的部分進(jìn)行批量更新耐床。Rect也提供直接的shouldComponentUpdate聲明周期回調(diào),來減少數(shù)據(jù)變化后的不必要的Virtual DOM對(duì)比的過程楔脯,用來保證性能撩轰。

JSX語法

JSXReact有什么關(guān)系?簡(jiǎn)單的來說,React為了方便view層組件化堪嫂,承載了構(gòu)建HTML結(jié)構(gòu)化頁面的職責(zé)偎箫,React通過創(chuàng)建于與跟新虛擬元素(virtual DOM)來管理整個(gè)Virtual DOM
React創(chuàng)建虛擬元素可以劃分為兩類皆串,DOM元素(DOM element)與組件元素(component element),分別對(duì)應(yīng)原生的DOM元素和自定義元素淹办,而JSX與創(chuàng)建元素有很大的關(guān)系。
JSX的官方定義是類XML語法的ECMAScript擴(kuò)展恶复。它完美的利用了JavaScript自帶的語法和特性怜森,并且使用大家熟悉的HTML語法來創(chuàng)建虛擬元素“担可以說副硅,JSX基本語法被XML囊括了,但是也有少許不同的地方翅萤。

XML基礎(chǔ)語法

使用類XML語法的好處是標(biāo)簽可以任意嵌套想许,我們可以像HTML一樣清晰看到DOM樹結(jié)構(gòu)和其屬性,比如我們構(gòu)建一個(gè)List組件断序。

const List = () =>{
  <div>
    <Title>This is Title</Title>
    <ul>
      <li>list item</li>
    </ul>
  </div>
}

List的過程就像寫HTML一樣,只不過它被包裹在JavaScript的方法中糜烹,但是在這個(gè)過程中需要注意以下幾點(diǎn):

  • 標(biāo)簽一定要閉合
  • 定義標(biāo)簽的時(shí)候违诗,只允許被一個(gè)標(biāo)簽包裹。所以上面的寫法是錯(cuò)誤的疮蹦。
const List = () =>{
  <div>
    <Title>This is Title</Title>
    <ul>
      <li>list item</li>
    </ul>
  </div>
 <div>
    <Title>This is Title</Title>
    <ul>
      <li>list item</li>
    </ul>
  </div>
}
元素類型

我們都知道JSX語法中的元素分為DOM元素(DOM element)與組件元素(component element),JSX對(duì)應(yīng)的規(guī)則是HTML標(biāo)簽是否為小寫字母诸迟,其中小寫字母對(duì)應(yīng)DOM元素,而逐漸元素自然對(duì)應(yīng)的是首字母大寫愕乎。

注釋

事實(shí)上JSX還是JavaScript阵苇,依然可以用簡(jiǎn)單的方法使用注釋,唯一需要注意的是感论,在一個(gè)組件的子元素位置使用注釋需要{}進(jìn)行包裹绅项,實(shí)例代碼如下:

const App = (
  <Nav>
    {/*節(jié)點(diǎn)注釋*/}
    <Person
      /*多行
        注釋*/
      name =  {window.isLoggedIn?window.name : ''}
    />
  </Nav>
)
元素屬性

JSX中,不論是DOM元素還是組件元素比肄,它們都是有屬性的快耿,不同的是,DOM元素的屬性是標(biāo)準(zhǔn)規(guī)范屬性芳绩,但是有兩個(gè)例外--classfor掀亥,這是因?yàn)樵?code>JavaScript中這兩個(gè)單詞是關(guān)鍵詞,因此我們這么轉(zhuǎn)換妥色。

  • class屬性修改為className
  • for屬性改為htmlFor

而組件元素的屬性是完全自定義的搪花,也可以理解成組件需要的參數(shù),舉個(gè)栗子:

const Header = ({title,children})=>{
  <h3 title = {title}>{children}</h3>
};
<Header title='hello world'>hello world</Header>

我們可以對(duì)屬性進(jìn)行展開展開,這個(gè)應(yīng)用場(chǎng)景主要是撮竿,當(dāng)我們知道組件的全部屬性的時(shí)候吮便,使用JSX可以這么寫:

//方法一
const component = <Component name = {name} value = {value}/>;

//方法二
const component = <Component / >;
component.props.name = name;
component .props.value = value;

// 方法三:使用ES6特性來提高效率
const data = {name:'foo', value:'bar'};
const component = <Component name = {data.name} value = {data.value}/>;
//方法三可以使用ES6來進(jìn)行簡(jiǎn)寫
const data = {name:'foo', value:'bar'};
const component = < Component  {...data} />;
javaScript屬性表達(dá)式

屬性值要使用表達(dá)式的話,只要使用{}進(jìn)行替換即可倚聚。

//輸入(JSX)
const person = <Person name ={window.isLoggedIn ? window.name:''} />
//輸出(JavaScript)
const person = React.createElement (
  person,
  {name:window.isLoggedIn ? window.name:' '}
);

其中子組件也可以作為表達(dá)式使用:

//輸入(JSX)
const content = <Container>{window.idLoggedIn ? <Nav  /> :<login />}</Container>
//輸出(JavaScript)
const content = React.createElement (
  Container,
  null,
  {name:window.isLoggedIn ? React.createElement(Nav) : React.createElement(Login)}
);

小結(jié):

  • JSX是一個(gè)看起來很像XMLJavaScript語法擴(kuò)展线衫,這種語法允許你在寫JavaScript中寫可嵌套的閉合標(biāo)簽。
  • JSXHTML語法很像惑折,可以嵌套授账,可以自定義屬性。
  • JSX允許在閉合標(biāo)簽中使用JavaScript表達(dá)式惨驶,但是要被{}所包裹
  • JSX中的內(nèi)聯(lián)樣式也是通過style屬性來定義的白热,但屬性值不能是字符串而必須為對(duì)象,而且要注意對(duì)象中的屬性名需要使用駝峰命名法粗卜。
  • JSX中屋确,標(biāo)簽子節(jié)點(diǎn)內(nèi)的注釋應(yīng)該寫在{}內(nèi)。
  • JSX中的數(shù)組會(huì)自動(dòng)的展開所有的成員续扔,但是需要注意的是攻臀,如果數(shù)組或是迭代器中的每一項(xiàng)都是HTML標(biāo)簽或是組件的話,那么他們必須要擁有唯一的key屬性

React組件

其實(shí)對(duì)組件的封裝很類似與面向?qū)ο蟮乃枷肷疵粒换セ旧弦圆僮?code>DOM為主刨啸,邏輯上是結(jié)構(gòu)上哪里需要變,我們就操作哪里识脆。此外设联,對(duì)于JavaScript的結(jié)構(gòu),我們得到了幾項(xiàng)規(guī)范標(biāo)準(zhǔn)組件的信息灼捂。

  • 基本的封裝性:盡管說JavaScript沒有真正的面向?qū)ο蟮姆椒ɡ肜俏覀冞€是可以通過實(shí)例化的方法來制造對(duì)象。
  • 簡(jiǎn)單的生命周期:最明顯的兩個(gè)方法是:constructordestroy悉稠,代表了組件的掛載卸載的過程宫蛆,但是除此之外,其他過程(如更新時(shí)的聲明周期)并沒有體現(xiàn)偎球。
  • 明確的數(shù)據(jù)流動(dòng):這里的數(shù)據(jù)指的是地道用組件的參數(shù)洒扎。一旦確定參數(shù)的值,就會(huì)解析傳進(jìn)來的參數(shù)衰絮,根據(jù)參數(shù)的不同做出不同的響應(yīng)袍冷,從而得到渲染的結(jié)果。

Web Components規(guī)范:這個(gè)規(guī)范想要同意web端關(guān)于組件的定義猫牡,它可以通過定義Custom Elements(自定義元素)的方式來統(tǒng)一組件胡诗。每一個(gè)自定義元素可以定義自己對(duì)外提供的屬性、方法、還有事件煌恢,內(nèi)部可以像寫一個(gè)頁面一樣骇陈,專注于實(shí)現(xiàn)功能來完成對(duì)組件的封裝。

Web Components組成

Web Components定義了一切我們想要的組件化的概念瑰抵,其中HTML Template定義了之前的模板概念你雌,Customer Element定義了組件的展現(xiàn)形式,shadow DOM定義了組件的作用域范圍二汛,可以包括樣式婿崭,HTML Imports提出了新的引入方式。

React組件的構(gòu)建

React組件即為組件元素:組件元素描述成純粹的Json對(duì)象肴颊,意味著可以使用方法或是類來構(gòu)建氓栈。React組件即為組件元素,組件基本上由3個(gè)部分組成-- 屬性(props)婿着、狀態(tài)(state)以及生命周期方法授瘦,這里我們從一張圖來簡(jiǎn)單的概括React

React組件的組成

React組件可以接受參數(shù)竟宋,也可以有自身的狀態(tài)提完,一旦接受到的參數(shù)或是自身的狀態(tài)有所改變,React組件就會(huì)執(zhí)行相對(duì)應(yīng)的生命周期的方法丘侠,最后渲染氯葬,整個(gè)過程完全符合傳統(tǒng)組件所定義的組件職責(zé)。
React和web component的關(guān)系
Reactweb component傳達(dá)的理念是一致的婉陷,但是二者的實(shí)現(xiàn)方式是不同的,

  • React自定義元素的庫(kù)是自己構(gòu)建的官研,與web component規(guī)范是不一致的
  • React渲染過程包含了模板的概念秽澳,也就是之前說的JSX
  • React組件的實(shí)現(xiàn)均在方法和類中,因此做到了相互的隔離戏羽,但是不包含樣式担神。
  • React引用方式遵循ES6標(biāo)準(zhǔn)

官方在React組件構(gòu)建上提供了3種不同的方法:React.createClass,ES6 classes 和無狀態(tài)函數(shù)。
React.createClass方法是構(gòu)建組件最傳統(tǒng)始花,也是兼容性最好的方法妄讯,實(shí)例代碼如下:

const Button = React.createClass({
  getDefaultProps(){
    return {
      color:'red',
      text:'cancle',
    };
  },
  render(){
    const {color, text} = this.props;
    return (
      <button className ={`btn btn - ${color}`}>
        <em>{text}</em>
      </button>
    );
  }
});

當(dāng)組件需要調(diào)用Button組件的時(shí)候,只需要寫<Button />,就可以被解析成React.createElement(Button)方法來創(chuàng)建Button實(shí)例酷宵,這意味著在一個(gè)應(yīng)用中調(diào)用幾次Button亥贸,就會(huì)創(chuàng)建幾次Button的實(shí)例。

ES6 classes

ES6 classes的寫法是通過ES6標(biāo)準(zhǔn)的類語法的方式來構(gòu)建方法:

import React, {Component } from 'react';

class Button extends Component{
  constructor (props){
    super(props);
  }
  static defaultProps ={ // 用來設(shè)置默認(rèn)屬性
    color:'blue',
    text:'Confirm',
  };
  render(){
    const {color,text} = this.props;

    return (
      <button className = {`btn btn-${color}`}>
        <em>{text}</em>
      </button>
    );
  }
}

這里的直觀感受是從調(diào)用內(nèi)部方法變成了類來實(shí)現(xiàn)浇垦,與createClass的結(jié)果相同的是炕置,調(diào)用類實(shí)現(xiàn)的組件會(huì)創(chuàng)建實(shí)例對(duì)象。在React組件開發(fā)中,常用的方式是將組件拆分到合理的粒度朴摊,用組合的方式合成業(yè)務(wù)組件默垄。

無狀態(tài)函數(shù)

使用無狀態(tài)函數(shù)構(gòu)建的組件稱為無狀態(tài)組件,這樣的寫法比較受官方推崇甚纲。我們看一下示例代碼:

function Button({color = 'blue',text = 'confirm'}){
  return (
    <button className = {`btn btn-${color}`}>
      <em>{text}</em>
    </button>
  );
}

無狀態(tài)組件只傳入propscontext兩個(gè)參數(shù)口锭;也就是說,它不存在state介杆,也沒有生命周期方法鹃操,組件本身即上面兩種React組件構(gòu)建方法中的render方法。不過这溅,像propTypesdefaultProps還是可以通過向方法設(shè)置靜態(tài)屬性來實(shí)現(xiàn)组民。
我們使用React實(shí)現(xiàn)Tabs組件:

import React,{Component悲靴,PropType} from 'react';

class Tabs extends Component {
  constructor(props){
    super(props);
  }
  //...
  render(){
    return <div className = 'ui-tabs'></div>
  }
};
export defaults Tabs;
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末臭胜,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子癞尚,更是在濱河造成了極大的恐慌耸三,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,402評(píng)論 6 499
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件浇揩,死亡現(xiàn)場(chǎng)離奇詭異仪壮,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)胳徽,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,377評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門积锅,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人养盗,你說我怎么就攤上這事缚陷。” “怎么了往核?”我有些...
    開封第一講書人閱讀 162,483評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵箫爷,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我聂儒,道長(zhǎng)虎锚,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,165評(píng)論 1 292
  • 正文 為了忘掉前任衩婚,我火速辦了婚禮窜护,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘非春。我一直安慰自己柄慰,他們只是感情好鳍悠,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,176評(píng)論 6 388
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著坐搔,像睡著了一般藏研。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上概行,一...
    開封第一講書人閱讀 51,146評(píng)論 1 297
  • 那天蠢挡,我揣著相機(jī)與錄音,去河邊找鬼凳忙。 笑死业踏,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的涧卵。 我是一名探鬼主播勤家,決...
    沈念sama閱讀 40,032評(píng)論 3 417
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼柳恐!你這毒婦竟也來了伐脖?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,896評(píng)論 0 274
  • 序言:老撾萬榮一對(duì)情侶失蹤乐设,失蹤者是張志新(化名)和其女友劉穎讼庇,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體近尚,經(jīng)...
    沈念sama閱讀 45,311評(píng)論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡蠕啄,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,536評(píng)論 2 332
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了戈锻。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片歼跟。...
    茶點(diǎn)故事閱讀 39,696評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖格遭,靈堂內(nèi)的尸體忽然破棺而出嘹承,到底是詐尸還是另有隱情,我是刑警寧澤如庭,帶...
    沈念sama閱讀 35,413評(píng)論 5 343
  • 正文 年R本政府宣布,位于F島的核電站撼港,受9級(jí)特大地震影響坪它,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜帝牡,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,008評(píng)論 3 325
  • 文/蒙蒙 一往毡、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧靶溜,春花似錦开瞭、人聲如沸懒震。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,659評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽个扰。三九已至,卻和暖如春葱色,著一層夾襖步出監(jiān)牢的瞬間递宅,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,815評(píng)論 1 269
  • 我被黑心中介騙來泰國(guó)打工苍狰, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留办龄,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 47,698評(píng)論 2 368
  • 正文 我出身青樓淋昭,卻偏偏與公主長(zhǎng)得像俐填,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子翔忽,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,592評(píng)論 2 353

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

  • 原教程內(nèi)容詳見精益 React 學(xué)習(xí)指南英融,這只是我在學(xué)習(xí)過程中的一些閱讀筆記,個(gè)人覺得該教程講解深入淺出呀打,比目前大...
    leonaxiong閱讀 2,833評(píng)論 1 18
  • 40矢赁、React 什么是React?React 是一個(gè)用于構(gòu)建用戶界面的框架(采用的是MVC模式):集中處理VIE...
    萌妹撒閱讀 1,014評(píng)論 0 1
  • 1.1React 簡(jiǎn)介 React 把用戶界面抽象成一個(gè)個(gè)組件贬丛,開發(fā)者通過組合這些組件撩银,最終得到功能豐富、可交互的...
    sylvia_yue閱讀 465評(píng)論 2 1
  • 你知道嗎,現(xiàn)在看到很多虐待兒童恭应,虐待女性抄邀,虐待動(dòng)物等等這些新聞,我會(huì)逃避性的馬上忽略過去昼榛。 以前會(huì)看境肾,看完了生氣流...
    miss番小薯閱讀 481評(píng)論 0 0
  • 秋攤開了難言的色彩 仿佛這一切 剛發(fā)生 又好像曾經(jīng) 一直都存在著 這古色古香的小徑 為你的憧憬 解決了最佳方案 銀...
    江城妖怪閱讀 284評(píng)論 0 0