Reactjs 踏坑指南2: JSX&&組件

JSX 知識(shí)準(zhǔn)備

JSX 并不是一門(mén)全新的語(yǔ)言及刻,僅僅是一個(gè)語(yǔ)法糖,允許開(kāi)發(fā)者在javascript中編寫(xiě)XML語(yǔ)言穷当。這樣使用JavaScript來(lái)構(gòu)建組件以及組件之間關(guān)系的應(yīng)用,在代碼層面顯得更加清晰淹禾,而不再是使用JavaScript操作DOM來(lái)創(chuàng)建組件以及組件之間的嵌套關(guān)系馁菜。

作為是React的核心部分,JSX使用XML標(biāo)記的方式直接聲明頁(yè)面铃岔。在JavaScript代碼里直接寫(xiě)XML的語(yǔ)法汪疮,每一個(gè)XML標(biāo)簽都會(huì)被JSX轉(zhuǎn)換工具轉(zhuǎn)換成純JavaScript代碼盾似。HTML直接寫(xiě)到JavaScript中不加任何分號(hào)砚哗,這就是JSX的語(yǔ)法奧義

JSX環(huán)境準(zhǔn)備

JSX必須借助ReactJS環(huán)境才能運(yùn)行厘托。在編寫(xiě)JSX代碼之前就珠,需要先加載ReactJS文件狈蚤,比react.js.光有ReactJs還不行剩晴,還需要加載JSX解析器萤晴。下面大家一起準(zhǔn)備好一個(gè)最基礎(chǔ)的ReactJS環(huán)境

  • 創(chuàng)建一個(gè)test.html文件

  • <head>標(biāo)簽中引入如下文件

      <script src="http://cdn.bootcss.com/react/15.2.0/react.js"></script>
      <script src="http://cdn.bootcss.com/react/15.2.0/react-dom.min.js"></script>
      <script src="https://cdnjs.cloudflare.com/ajax/libs/babel-core/5.8.34/browser.min.js"></script>
    

這樣環(huán)境就搭建好了互艾,然后按照慣例载碌,雙手奉上一個(gè)Hello World 程序猜嘱。

  <body>
    <div id="example"></div>
    <script type="text/babel">
      var HelloComponent = React.createClass({
        render: function(){
          return <span>Hello World !</span>
        }
      });
      
      ReactDOM.render(
        <HelloComponent />,
        document.getElementById('example')
      );
    </script>
  </body>

運(yùn)行結(jié)果

如上面代碼,我們?cè)贘avaScript中書(shū)寫(xiě)HTML標(biāo)簽時(shí)嫁艇,不再像以前那樣作為字符串用引號(hào)引起來(lái)朗伶,而是想在XML文件中書(shū)寫(xiě)一樣,直接寫(xiě)即可步咪。

除了<span>Hello World !</span>這種直接使用的HTML標(biāo)簽外论皆,還有一個(gè)<HelloComponent />標(biāo)簽。這個(gè)是ReactJS創(chuàng)建的組件類(lèi)標(biāo)簽,通過(guò)這種方式点晴,把創(chuàng)建的HelloComponent組件引用進(jìn)來(lái)感凤。ReactJS約定,自定義的組件標(biāo)簽首字母一定要大些觉鼻,用來(lái)區(qū)分是組件標(biāo)簽還是HTML標(biāo)簽俊扭。

注意幾點(diǎn)

  • script 標(biāo)簽的 type 屬性為 text/babel,這是React 獨(dú)有的 JSX 語(yǔ)法坠陈,跟 JavaScript 不兼容萨惑。凡是在頁(yè)面中直接使用 JSX 的地方,都要加上 type="text/babel"仇矾。
  • 一共用了三個(gè)庫(kù): react.js 庸蔼、react-dom.js 和 browser.min.js ,它們必須首先加載贮匕。其中姐仅,react.js 是 React 的核心庫(kù),react-dom.js 是提供與 DOM 相關(guān)的功能刻盐, browser.min.js的作用是將 JSX 語(yǔ)法轉(zhuǎn)為 JavaScript 語(yǔ)法掏膏。
  • 將 JSX 語(yǔ)法轉(zhuǎn)為 JavaScript 語(yǔ)法,這一步很消耗時(shí)間《匦浚現(xiàn)在前端項(xiàng)目馒疹,都會(huì)使用前端工程化,不會(huì)直接在html頁(yè)面中直接寫(xiě)js代碼乙墙,寫(xiě)好的js代碼都會(huì)使用工具進(jìn)行編譯壓縮等颖变。這樣的話,我們的jsx也會(huì)通過(guò)編譯直接轉(zhuǎn)化成js語(yǔ)法听想,讓瀏覽器直接使用腥刹。

JSX執(zhí)行JavaScript表達(dá)式

JSX使用{}來(lái)執(zhí)行JavaScript表達(dá)式。

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

JSX定義屬性&&樣式使用

HTML中可以通過(guò)標(biāo)簽上的屬性來(lái)改變當(dāng)前元素的樣式汉买,當(dāng)然衔峰,這在JSX中也是可以的,只不過(guò)JSX在使用行內(nèi)樣式的時(shí)候是有缺陷的蛙粘。朽色。使用{{}}而不是引號(hào)的方式,如下

React.render(
    <div style={{color:'red',marginTop:'20px'}}>
        xxxxx
    </div>,
    document.body
);

注:直接在標(biāo)簽上使用style屬性時(shí)组题,要寫(xiě)成style={{}}是兩個(gè)大括號(hào)葫男,外層大括號(hào)是告知jsx這里是js語(yǔ)法,和真實(shí)DOM不同的是崔列,屬性值不能是字符串而必須為對(duì)象梢褐,需要注意的是屬性名同樣需要駝峰命名法旺遮。即margin-top要寫(xiě)成marginTop,屬性之間以逗號(hào)間隔盈咳。還有class 屬性需要寫(xiě)成 className 耿眉,for 屬性需要寫(xiě)成 htmlFor ,這是因?yàn)?class 和 for 是 JavaScript 的保留字鱼响。

JSX中的延展屬性

在JSX中我們可以使用ES6中的最新語(yǔ)法...來(lái)遍歷對(duì)象

  var HelloMessage = React.createClass({
    render: function() {
      return <h1>Hello {this.props.name}  get {this.props.votes} votes</h1>;
    }
  });

  var Lucy = {
    name: "feng",
    votes: "23"
  }

  ReactDOM.render(
  <HelloMessage {...Lucy} />,
    document.getElementById('example')
  );

JSX中的事件綁定

JSX支持事件的綁定鸣剪,語(yǔ)法類(lèi)似于HTML中事件的綁定,不同的是這里事件的名稱(chēng)必須按照駝峰式丈积,下面給個(gè)例子大家參考一下筐骇。

var HelloComponent = React.createClass({
    testClick: function (str) {
      alert('hello ' +  str)
    },
    render: function() {
      return (
          <p
          onClick={this.testClick.bind(this, 'feng')} style={{olor:'#ff6600',width:'200px', height:'100p'}}
          >
          Click me
          </p>
          )
        
    }
  })

  
  ReactDOM.render(
  <HelloComponent  />,
    document.getElementById('example')
  );

知曉了JSX的基本使用之后,開(kāi)始介紹ReactJS的組件的概念和使用方法

組件初步

ReactJS的基礎(chǔ)就是實(shí)例化江滨,即按功能封裝成一個(gè)又一個(gè)的組件铛纬,各個(gè)組件維護(hù)自己的狀態(tài)和UI,當(dāng)狀態(tài)改變時(shí)唬滑,會(huì)自動(dòng)重新渲染整個(gè)組件告唆,多個(gè)組件一起協(xié)作構(gòu)成了整個(gè)ReactJS應(yīng)用。

以一個(gè)簡(jiǎn)單的Hello World開(kāi)始

<head>
    <meta charset="UTF-8" />
    <title>Hello React!</title>
    <script src="http://cdn.bootcss.com/react/15.2.0/react.js"></script>
    <script src="http://cdn.bootcss.com/react/15.2.0/react-dom.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/babel-core/5.8.34/browser.min.js"></script>
<head>
<body>
    <div id="example"></div>
    <script type="text/babel">
          var HelloMessage = React.createClass({
            render: function() {
                  return <div>Hello,{this.props.name}</div>
            }
          })
          ReactDOM.render(<HelloMessage name="World" />, document.getElementById('example'))
    </script>
</body>

運(yùn)行結(jié)果:

運(yùn)行結(jié)果

審查元素發(fā)現(xiàn)DOM結(jié)構(gòu)如下:

上面的代碼中晶密,我們調(diào)用React提供的工廠方法來(lái)創(chuàng)建組件擒悬,其中:

  • React是全局對(duì)象,ReactJS的所有頂級(jí)API都掛在這個(gè)對(duì)象下稻艰。
  • React.createClass是ReactJS用來(lái)創(chuàng)建組件類(lèi)的方法懂牧,這個(gè)對(duì)象必須包含一個(gè)render方法和若干可選的生命周期(詳情請(qǐng)見(jiàn)下文)方法,其中
  • render是一個(gè)組件級(jí)的API,是React.createClass內(nèi)部最常用的API,該方法主要用來(lái)返回組件結(jié)構(gòu)
  • React.render(這里我用的是ReactDOM.render)是最常用的方法连锯,用于將模板轉(zhuǎn)換成HTML語(yǔ)言归苍,并將轉(zhuǎn)換后的DOM結(jié)構(gòu)插入到制定的DOM節(jié)點(diǎn)上
  • 簡(jiǎn)而言之就是:先通過(guò)React.createClass來(lái)創(chuàng)建一個(gè)組件類(lèi)用狱,調(diào)用組件的render方法輸出組件的DOM結(jié)構(gòu)运怖,最后調(diào)用React.render將組建插入到id為example的節(jié)點(diǎn)上

這里我們需要保證render函數(shù)是純函數(shù):即同樣的輸入始終返回相同的輸出,并且執(zhí)行過(guò)程中沒(méi)有副作用(和DOM交互或者發(fā)Ajax請(qǐng)求)夏伊。但一個(gè)組件要和DOM交互或者發(fā)Ajax請(qǐng)求需求是很正常的摇展,那么就要用到其他生命周期方法了。

組件的狀態(tài)與屬性

組件本質(zhì)上是狀態(tài)機(jī)溺忧,輸入確定咏连,輸出一定確定。組件把狀態(tài)與結(jié)果一一對(duì)應(yīng)起來(lái)鲁森,組件中有state與prop(狀態(tài)與屬性)祟滴。

  • 屬性(props)是由父組件傳遞給子組件的;
  • 狀態(tài)(state)是子組件內(nèi)部維護(hù)的數(shù)據(jù)歌溉,當(dāng)狀態(tài)發(fā)生變化的同時(shí)垄懂,組件也會(huì)進(jìn)行更新骑晶。當(dāng)狀態(tài)發(fā)生轉(zhuǎn)換時(shí)會(huì)觸發(fā)不同的鉤子函數(shù)(詳見(jiàn)下文中生命周期),從而讓開(kāi)發(fā)者有機(jī)會(huì)做出相應(yīng)草慧。

props屬性的用法

props是一個(gè)對(duì)象桶蛔,是組建用來(lái)接收外面?zhèn)鱽?lái)的參數(shù),組件內(nèi)部是不允許修改自己的props屬性的漫谷,只能夠通過(guò)父組件來(lái)修改仔雷。具體的使用方法如下

  • 接收鍵值對(duì)數(shù)據(jù)

    <HelloWorld name= ? />

    1. 字符串:"XiaoFeng"

    2. 求值表達(dá)式 {123}、{"XiaoFeng"}

    3. 數(shù)組{[1,2,3]}

    4. 變量{variable}

    5. 函數(shù)求值表達(dá)式{function}(不推薦舔示,如果需要函數(shù)可以單獨(dú)把函數(shù)提取出來(lái)然后單獨(dú)調(diào)用函數(shù))

       var HelloWorld =React.createClass({
        render:function () {
             console.log(this.props)
            return <p>Hello,{this.props.name ? this.props.name : " World"}</p>;
        },
       });
       var HelloUniverse = React.createClass({
          getInitialState:function () {
              return {
                  name:''
              };
          },
          handleChange: function (event) {
              this.setState({name: event.target.value});
          },
          render: function () {
              return (<div>
              <HelloWorld name={this.state.name}></HelloWorld>
              <br/>
              <input type="text" onChange={this.handleChange} />
              </div>
              );
          }
       });
       ReactDOM.render(<HelloUniverse />,example);
      
  • setProps

    已過(guò)時(shí)碟婆,即將廢棄

  • propTypes

    組件的屬性可以接受任意值,字符串斩郎、對(duì)象脑融、函數(shù)等等都可以。有時(shí)缩宜,我們需要一種機(jī)制肘迎,驗(yàn)證別人使用組件時(shí),提供的參數(shù)是否符合要求锻煌。

      var MyTitle = React.createClass({
        propTypes: {
          title: React.PropTypes.string.isRequired,
        },
        render: function() {
           return <h1> {this.props.title} </h1>;
         }
      });
    

    上面的Mytitle組件有一個(gè)title屬性妓布。PropTypes 告訴 React,這個(gè) title 屬性是必須的宋梧,而且它的值必須是字符串∠徽樱現(xiàn)在,我們?cè)O(shè)置 title 屬性的值是一個(gè)數(shù)值捂龄。

      var data = 123;
      ReactDOM.render(
        <MyTitle title={data} />,
        document.body
      );
    

    這樣一來(lái)释涛,title屬性就通不過(guò)驗(yàn)證了【氩祝控制臺(tái)會(huì)顯示一行錯(cuò)誤信息

  • getDefaultProps

    getDefaultProps 方法可以用來(lái)設(shè)置組件屬性的默認(rèn)值

      var MyTitle = React.createClass({
        getDefaultProps : function () {
          return {
            title : 'Hello World'
          };
        },
      
        render: function() {
           return <h1> {this.props.title} </h1>;
         }
      });
      ReactDOM.render(<MyTitle />,document.body);
    
  • this.props.children

    this.props 對(duì)象的屬性與組件的屬性一一對(duì)應(yīng)唇撬,但是有一個(gè)例外,就是 this.props.children 屬性展融。它表示組件的所有子節(jié)點(diǎn)

      var NotesList = React.createClass({
        render: function() {
          return (
            <ol>
            {
              React.Children.map(this.props.children, function (child) {
                return <li>{child}</li>;
              })
            }
            </ol>
          );
        }
      });
      ReactDOM.render(
        <NotesList>
          <span>hello</span>
          <span>world</span>
        </NotesList>,example
      );
    

    上面代碼的 NoteList 組件有兩個(gè) span 子節(jié)點(diǎn)窖认,它們都可以通過(guò) this.props.children 讀取。這里需要注意告希, this.props.children 的值有三種可能:

    1. 如果當(dāng)前組件沒(méi)有子節(jié)點(diǎn)扑浸,它就是 undefined;
    2. 如果有一個(gè)子節(jié)點(diǎn)燕偶,數(shù)據(jù)類(lèi)型是 object喝噪;
    3. 如果有多個(gè)子節(jié)點(diǎn),數(shù)據(jù)類(lèi)型就是 array

    React 提供一個(gè)工具方法 React.Children 來(lái)處理 this.props.children 指么。我們可以用 React.Children.map 來(lái)遍歷子節(jié)點(diǎn)酝惧,而不用擔(dān)心 this.props.children 的數(shù)據(jù)類(lèi)型是 undefined 還是 object驰吓。

state屬性的用法

React把組件當(dāng)成狀態(tài)機(jī),一旦用戶(hù)交互導(dǎo)致?tīng)顟B(tài)發(fā)生變化系奉,就會(huì)觸發(fā)重新渲染UI檬贰。this.state會(huì)隨著用戶(hù)的交互而發(fā)生變化。

  • 工作原理

    常用的通知 React 數(shù)據(jù)變化的方法是調(diào)用 setState(data, callback)缺亮。這個(gè)方法會(huì)合并(merge) data 到 this.state翁涤,并重新渲染組件。渲染完成后萌踱,調(diào)用可選的 callback 回調(diào)葵礼。大部分情況下不需要提供 callback,因?yàn)?React 會(huì)負(fù)責(zé)把界面更新到最新?tīng)顟B(tài)并鸵。

  • getInitialState

    object getInitialState()

    getInitialState 方法用于定義初始狀態(tài)鸳粉,也就是一個(gè)對(duì)象,這個(gè)對(duì)象可以通過(guò) this.state 屬性讀取园担。在組件掛載之前調(diào)用一次届谈。返回值將會(huì)作為 this.state 的初始值。

  • setState

    setState(object nextState[, function callback])

    this.setState 方法用于修改狀態(tài)值弯汰,每次修改以后艰山,自動(dòng)調(diào)用 this.render 方法,再次渲染組件咏闪。

    注意:

    1. 絕對(duì)不要直接改變 this.state曙搬,因?yàn)樵谥笳{(diào)用 setState() 可能會(huì)替換掉你做的更改。把 this.state 當(dāng)做不可變的鸽嫂。
    2. setState()不會(huì)立刻改變 this.state纵装,而是創(chuàng)建一個(gè)即將處理的state轉(zhuǎn)變。在調(diào)用該方法之后獲取 this.state 的值可能會(huì)得到現(xiàn)有的值据某,而不是最新設(shè)置的值橡娄。
    3. 不保證 setState()調(diào)用的同步性,為了提升性能哗脖,可能會(huì)批量執(zhí)行state轉(zhuǎn)變和DOM 渲染瀑踢。
    4. setState ( ) 將總是觸發(fā)一次重繪扳还,除非在 shouldComponentUpdate()中實(shí)現(xiàn)了條件渲染邏輯才避。如果使用可變的對(duì)象,但是又不能在shouldComponentUpdate()中實(shí)現(xiàn)這種邏輯氨距,僅在新 state 和之前的 state 存在差異的時(shí)候調(diào)用 setState()可以避免不必要的重新渲染桑逝。

    常用的模式是創(chuàng)建多個(gè)只負(fù)責(zé)渲染數(shù)據(jù)的無(wú)狀態(tài)(stateless)組件,在它們的上層創(chuàng)建一個(gè)有狀態(tài)(stateful)組件并把它的狀態(tài)通過(guò) props 傳給子級(jí)俏让。這個(gè)有狀態(tài)的組件封裝了所有用戶(hù)的交互邏輯楞遏,而這些無(wú)狀態(tài)組件則負(fù)責(zé)聲明式地渲染數(shù)據(jù)茬暇。

組件的生命周期

生命周期各階段

在整個(gè)ReactJS的聲明周期中,主要會(huì)經(jīng)歷這四個(gè)階段:創(chuàng)建階段寡喝、實(shí)例化階段糙俗、更新階段、銷(xiāo)毀階段预鬓。下面通過(guò)一段代碼巧骚,來(lái)深入了解組件各個(gè)環(huán)節(jié)的運(yùn)作流程

  var OneComponent = React.createClass({
    //1.創(chuàng)建階段
    getDefaultProps: function() {
      //在創(chuàng)建類(lèi)的時(shí)候被調(diào)用
      console.log('getDefaultProps');
      return {}
    },

    //2.實(shí)例化階段
    getInitialState: function() {
      //獲取this.state的默認(rèn)值
      console.log('getInitialState');
      return {};
    },
    componentWillMount: function() {
      //在render之前調(diào)用此方法
      //業(yè)務(wù)邏輯的處理都應(yīng)該放在這里,比如對(duì)state的操作等
      console.log('componentWillMount')
    },
    render: function() {
      //渲染并返回一個(gè)虛擬DOM
      console.log('render');
      return (
          <div> hello <b> {this.props.name} </b></div>
        )
    },
    componentDidMount: function() {
      //該方法發(fā)生在render方法之后
      //在該方法中格二,ReactJS會(huì)使用render方法返回的虛擬DOM對(duì)象來(lái)創(chuàng)建真實(shí)DOM結(jié)構(gòu)
      console.log('componentDidMount');
    },

    //3.個(gè)更新階段
    componentWillReceieveProps: function() {
      //該方法發(fā)生在this.props被修改或富組件調(diào)用setProps()方法之后
      console.log('componentWillRecieveProps');
    },
    shouldComponentUpdate: function() {
      //是否需要更新
      console.log('shouldComponentUpdate');
      return true;
    },
    componentWillUpadate: function() {
      //將要更新
      console.log('componentWillUpadate');
    },
    componentDidUpdate: function() {
      //更新完畢
      console.log('componentDidUpdate');
    },
    //4.銷(xiāo)毀階段
    componentWillUnmout: function() {
      //銷(xiāo)毀時(shí)被調(diào)用
      console.log('componentWillUnmout');
    }
  })

  
  ReactDOM.render(
  <OneComponent  name="World "/>,
    document.getElementById('example')
  );

創(chuàng)建階段:

該階段主要發(fā)生在創(chuàng)建組件類(lèi)的時(shí)候劈彪,即在調(diào)用React.createClass的時(shí)候。這個(gè)階段只會(huì)觸發(fā)一個(gè)getDefaultProps方法顶猜,該方法會(huì)返回一個(gè)對(duì)象沧奴,并緩存下來(lái)。然后與富組件制定的props對(duì)象合并长窄,最后賦值給this.props作為該組件的默認(rèn)屬性滔吠。

實(shí)例化階段

該階段主要發(fā)生在實(shí)例化組件類(lèi)的時(shí)候,也就是組件類(lèi)被調(diào)用的時(shí)候挠日。

  ReactDOM.render(
  <OneComponent  name="World "/>,
    document.getElementById('example')
  );

該組件被調(diào)用的時(shí)候屠凶,這個(gè)階段會(huì)觸發(fā)一系列的流程,具體的執(zhí)行順序如下所示肆资。

  • getInitialState矗愧。初始化組件的state的值,其返回值會(huì)賦值給組件的this.state屬性郑原。

  • componentWillMount 在渲染(掛載)之前調(diào)用一次唉韭。

    此時(shí)this.refs對(duì)象為空。如果在此時(shí)調(diào)用this.setState()則會(huì)更新this.state對(duì)象犯犁,而render只會(huì)調(diào)用一次属愤。

  • render 根據(jù)state的值,生成頁(yè)面需要的虛擬DOM結(jié)構(gòu)酸役,并返回該結(jié)構(gòu)

  • componentDidMount 在渲染之后調(diào)用一次住诸。根據(jù)虛擬DOM結(jié)構(gòu)而生成的真實(shí)DOM進(jìn)行相應(yīng)的處理,組件內(nèi)部可以通過(guò)this.getDOMNode()來(lái)獲取當(dāng)前組件的節(jié)點(diǎn)涣澡,然后就可以像在web開(kāi)發(fā)中那樣操作里面的DOM元素了贱呐。

      componentDidMount () {
        const textbox = React.findDOMNode(this.refs.text)
        if (this.props.autoFocus) textbox.focus()
      }
    

更新階段

主要發(fā)生在用戶(hù)操作或者組件有更新的時(shí)候,此時(shí)會(huì)根據(jù)用戶(hù)的操作行為進(jìn)行相應(yīng)的頁(yè)面結(jié)構(gòu)的調(diào)整入桂。該階段也會(huì)觸發(fā)一系列的流程奄薇,具體的執(zhí)行順序如下所示。

  • componentWillReceiveProps 在將要接收props時(shí)調(diào)用抗愁。在該函數(shù)中馁蒂,通澈峭恚可以調(diào)用this.setState方法來(lái)完成對(duì)state的修改。

    props是父組件傳遞給資組建的沫屡。父組件發(fā)生render的時(shí)候子組件就會(huì)調(diào)用componentWillReceiveProps(不管props有沒(méi)有更新饵隙,也不管父子組件之間有沒(méi)有數(shù)據(jù)交換)。

      componentWillReceiveProps (nextProps) {
        if (this.props.disabled !== nextProps.disabled) {
      // disabled這個(gè)屬性改變了
        }
      }
    
  • shouldComponentUpdate:該方法用來(lái)攔截新的props或state沮脖,然后根據(jù)事先設(shè)定好的判斷邏輯癞季,返回值決定組件是否需要update。

    組件掛載之后倘潜,每次調(diào)用setState后都會(huì)調(diào)用shouldComponentUpdate判斷是否需要重新渲染組件绷柒。默認(rèn)返回true,需要重新render涮因。在比較復(fù)雜的應(yīng)用里废睦,有一些數(shù)據(jù)的改變并不影響界面展示,可以在這里做判斷养泡,優(yōu)化渲染效率嗜湃。

      shouldComponentUpdate (nextProps, nextState) {
          // 比較props或者states,返回true則更新照常澜掩,返回false則取消更新购披,且不會(huì)調(diào)用下面的兩個(gè)生命周期函數(shù)
      }
    
  • componentWillUpdate :組件更新之前調(diào)用一次。當(dāng)上一部中shouldComponentUpdate方法返回true時(shí)候肩榕,就可以在該方法中做一些更新之前的操作刚陡。

  • render 根據(jù)一系列的diff算法,聲稱(chēng)需要更心動(dòng)額虛擬DOM數(shù)據(jù)株汉。實(shí)際表明筐乳,在render中,最好只做數(shù)據(jù)和模板的結(jié)合乔妈,而不進(jìn)行state等邏輯的修改蝙云,這樣組件結(jié)構(gòu)更清晰。

  • componentDidUpdate 組件的更新已經(jīng)同步到DOM中后出發(fā)路召。

    除了首次render之后調(diào)用componentDidMount勃刨,其它render結(jié)束之后都是調(diào)用componentDidUpdate。

銷(xiāo)毀階段

  • componentWillUnmount 會(huì)在組件即將從掛載點(diǎn)移去時(shí)調(diào)用股淡,用來(lái)取出去除即將被銷(xiāo)毀的DOM節(jié)點(diǎn)的引用身隐,或者是清除計(jì)時(shí)器,取消監(jiān)聽(tīng)的時(shí)間等等揣非。

注意:

絕對(duì)不要在componentWillUpdate和componentDidUpdate中調(diào)用this.setState方法抡医,否則將導(dǎo)致無(wú)限循環(huán)調(diào)用躲因。

componentWillMount早敬、componentDidMount和componentWillUpdate忌傻、componentDidUpdate可以對(duì)應(yīng)起來(lái)。區(qū)別在于搞监,前者只有在掛載的時(shí)候會(huì)被調(diào)用水孩;而后者在以后的每次更新渲染之后都會(huì)被調(diào)用。

組件生命周期流程圖

圖片來(lái)自網(wǎng)絡(luò)文章

組件之間的通信

先創(chuàng)建一個(gè)父類(lèi)組件Parent琐驴,它內(nèi)部調(diào)用一個(gè)叫做Child的子組件俘种,并將接收到的外部參數(shù)name傳遞給子組件Child。

var Parent = React.createClass({
    handleClick: function() {
      this.refs.myTextInput.focus();
    },
    render: function() {
      return (
          <div onClick={this.handleClick}>
            <input type="text" ref="myTextInput" />
            Parent is:
              <Child name={this.props.name}></Child>
          </div>
        )
    }
});

在創(chuàng)建一個(gè)子類(lèi)組件Child

  var Child = React.createClass({
    render: function() {
      return <span>{this.props.name}</span>
    }
  });

自后通過(guò)React.render方法將組件渲染到頁(yè)面上

  ReactDOM.render(
    <Parent name="React" />,document.getElementById('example')
  );

運(yùn)行結(jié)果

整個(gè)應(yīng)用的功能是父組件接收傳入的用戶(hù)名稱(chēng)绝淡,并將用于名稱(chēng)傳給子組件宙刘,最后再由子組件渲染顯示到頁(yè)面上。這些組件直接按是怎么通訊的呢牢酵?下面通過(guò)兩方面介紹一下

  • 子組件調(diào)用父組件的方法悬包。從上面的例子可以看出,子組件要拿到父組件的屬性撑瞧,需要通過(guò)this.props方法曼尊。所以料滥,如果子組件想要調(diào)用父組件的方法屿岂,只需要父組件把要被調(diào)用的方法以屬性的方式放在子組件上阻肩,子組件內(nèi)部便可通過(guò)"this.props.被調(diào)用的方法"這樣的方式拿到name屬性的。然后渡贾,每次父組件修改了傳入的name屬性囤屹,子組件便會(huì)得到通知复局,然后自動(dòng)獲取新的name屬性
  • 父組件調(diào)用子組件的方法角钩。子組件調(diào)用父組件是通過(guò)prop屬性脊髓,而反過(guò)來(lái)依疼,父組件調(diào)用子組件通過(guò)的就是 ref 屬性。子組件被設(shè)置了ref屬性之后,父組件便可以通過(guò)this.ref.xxx來(lái)獲取到子組件了盒蟆,其中xx為子組件的ref值寒屯。

組件實(shí)踐

1. 靜態(tài)組件

var MyComponent=React.createClass({
  render: function() {
   return <h1 className="my-h1" style={{color:'red'}}>Hello world!</h1>;
 }
});
ReactDOM.render(
 <MyComponent />,
 document.getElementById('example')
);

運(yùn)行結(jié)果

運(yùn)行結(jié)果

2. 動(dòng)態(tài)組件

var Counter = React.createClass({
    incrementCount: function(){
        this.setState({
            count: this.state.count + 1
        });
    },
    getInitialState: function(){
        return {
            count: 0
        }
    },
    render: function(){
        return (
            <div className="my-component">
                <h1>Count: {this.state.count}</h1>
                <button type="button" onClick={this.incrementCount}>{this.props.name}</button>
            </div>
        );
    }
});

ReactDOM.render(
    <Counter name="遞增按鈕" />,
    document.getElementById('mount-point')
);

運(yùn)行結(jié)果:

遞增按鈕

參考內(nèi)容

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末瞧栗,一起剝皮案震驚了整個(gè)濱河市海铆,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌能耻,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,126評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件栗恩,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡洪燥,警方通過(guò)查閱死者的電腦和手機(jī)磕秤,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,254評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)捧韵,“玉大人市咆,你說(shuō)我怎么就攤上這事≡倮矗” “怎么了蒙兰?”我有些...
    開(kāi)封第一講書(shū)人閱讀 152,445評(píng)論 0 341
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)芒篷。 經(jīng)常有香客問(wèn)我搜变,道長(zhǎng),這世上最難降的妖魔是什么针炉? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 55,185評(píng)論 1 278
  • 正文 為了忘掉前任挠他,我火速辦了婚禮,結(jié)果婚禮上糊识,老公的妹妹穿的比我還像新娘绩社。我一直安慰自己,他們只是感情好赂苗,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,178評(píng)論 5 371
  • 文/花漫 我一把揭開(kāi)白布愉耙。 她就那樣靜靜地躺著,像睡著了一般拌滋。 火紅的嫁衣襯著肌膚如雪朴沿。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 48,970評(píng)論 1 284
  • 那天败砂,我揣著相機(jī)與錄音赌渣,去河邊找鬼。 笑死昌犹,一個(gè)胖子當(dāng)著我的面吹牛坚芜,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播斜姥,決...
    沈念sama閱讀 38,276評(píng)論 3 399
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼鸿竖,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼沧竟!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起缚忧,我...
    開(kāi)封第一講書(shū)人閱讀 36,927評(píng)論 0 259
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤悟泵,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后闪水,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體糕非,經(jīng)...
    沈念sama閱讀 43,400評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,883評(píng)論 2 323
  • 正文 我和宋清朗相戀三年球榆,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了朽肥。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 37,997評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡芜果,死狀恐怖鞠呈,靈堂內(nèi)的尸體忽然破棺而出融师,到底是詐尸還是另有隱情右钾,我是刑警寧澤,帶...
    沈念sama閱讀 33,646評(píng)論 4 322
  • 正文 年R本政府宣布旱爆,位于F島的核電站舀射,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏怀伦。R本人自食惡果不足惜脆烟,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,213評(píng)論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望房待。 院中可真熱鬧邢羔,春花似錦、人聲如沸桑孩。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,204評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)流椒。三九已至敏簿,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間宣虾,已是汗流浹背惯裕。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,423評(píng)論 1 260
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留绣硝,地道東北人蜻势。 一個(gè)月前我還...
    沈念sama閱讀 45,423評(píng)論 2 352
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像鹉胖,于是被迫代替她去往敵國(guó)和親握玛。 傳聞我的和親對(duì)象是個(gè)殘疾皇子猜煮,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,722評(píng)論 2 345

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

  • 按照慣例,先給ReactJS背書(shū) React是一個(gè)Facebook開(kāi)發(fā)的UI庫(kù)败许,于2013年5月開(kāi)源王带,并迅速的從最...
    艾倫先生閱讀 3,222評(píng)論 1 12
  • 3. JSX JSX是對(duì)JavaScript語(yǔ)言的一個(gè)擴(kuò)展語(yǔ)法, 用于生產(chǎn)React“元素”市殷,建議在描述UI的時(shí)候...
    pixels閱讀 2,806評(píng)論 0 24
  • 使用 create-react-app 快速構(gòu)建 React 開(kāi)發(fā)環(huán)境 項(xiàng)目的目錄結(jié)構(gòu)如下: React JSX ...
    majun00閱讀 502評(píng)論 0 0
  • 以下內(nèi)容是我在學(xué)習(xí)和研究React時(shí)愕撰,對(duì)React的特性、重點(diǎn)和注意事項(xiàng)的提取醋寝、精練和總結(jié)搞挣,可以做為React特性...
    科研者閱讀 8,219評(píng)論 2 21
  • 自己最近的項(xiàng)目是基于react的,于是讀了一遍react的文檔音羞,做了一些記錄(除了REFERENCE部分還沒(méi)開(kāi)始讀...
    潘逸飛閱讀 3,339評(píng)論 1 10