學習react之React 入門(阮一峯教程筆記)

一 react.js react-dom.js Brower.js

  1. react.js 核心庫
  2. react-dom.js提供dom方法
  3. Brower.js JSX語法--->JS語法
    服務器
    $ babel src --out-dir build //src內的js文件全部轉換 放入build文件夾

二 ReactDOM.render()

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

三 JSX語法

  1. 支持js和html混寫
var names = ['Alice', 'Emily', 'Kate'];

ReactDOM.render(
  <div>
  {
    names.map(function (name) {
      return <div>Hello, {name}!</div>
    })
  }
  </div>,
  document.getElementById('example')
);

2.< 與 {
JSX 與 數組

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

# 四 組件
```javascipt
var HelloMessage = React.createClass({
  render: function() {
    return <h1>Hello {this.props.name}</h1>;
  }
});

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

解釋:

  1. 通過 React.createClass()方法構造組件類 HelloMessage,HelloMessage 是個類所以規範和類一樣。組件類的第一個字母必須大寫,否則會報錯。
  2. 模版插入 <HelloMessage name="John" /> 的時候,就是在生成一個HelloMessage類的實例。
  3. 所有組件類必須擁有一個自己的render方法 用於輸出組件。
  4. 組件類只能包含一個頂層標籤
  5. 同原生HTML一樣,組件可以加入自定義屬性,如例子中的 name="John",然後通過組件類的this.props屬性獲取。
  6. 由於原生js的保留字,class屬性要寫成className for屬性要寫成htmlFor

五 this.props.children屬性

this.props的屬性和組件的屬性基本是一一對應的,但是有一個例外就是this.props.children屬性。它是在遍歷組件的子節點

var NodeList = React.createClass({
  render: function() {
    return <ul>
          React.Children.map(this.props.children,(child)=>{
             return  <li>{child}</li>   //記住要return啊兄dei
})
    </ul>;
  }
});

ReactDOM.render(
  <NodeList>
      <span>john</span>
      <span>sam</span>
  </NodeList>
  document.getElementById('example')
);

解釋:

  1. this.props.children的值有三種可能 :一個孩子節點:對象;多個孩子節點:數組;沒有孩子節點:undefined
  2. React.Children是一個React提供的工具函數,用來處理this.props.children 而不用太關心子節點的類型(這個map方法的用法需要理解記一下)
  3. React.Children還有一些別的方法 ,官方手冊

六 PropType

  1. 組件的屬性可以接受字符串,數字,函數等任意類型,然而有時候我們想要規定組件能接受的類型,需要驗證別人使用組件時的參數是否符合要求。
var MyTitle = React.createClass({
  propTypes: {
    title: React.PropTypes.string.isRequired //要求類型時string
  },

  render: function() {
     return <h1> {this.props.title} </h1>;
   }
});

var data = 123;

ReactDOM.render(
  <MyTitle title={data} />  //由於data是個數字不是要求的string類型 所以控制檯會報錯
  document.body

 

留下PropType的官方文檔

  1. 可以通過getDefaultProps設置默認屬性
var MyTitle = React.createClass({
  getDefaultProps : function () {
    return {
      title : 'Hello World'
    };
  },

  render: function() {
     return <h1> {this.props.title} </h1>;
   }
});

ReactDOM.render(
  <MyTitle />,
  document.body
);

 

七 獲取真實的DOM節點

  1. diff算法:
    組件並不是真實的DOM節點,而是存在與內存中的一種數據結構,叫做虛擬DOM,只有當它真正插入文檔中的時候纔會真的變成DOM。
    React的設計時所有的DOM變動都現在虛擬的DOM上發生,然後再將實際變動的部分反映在真實的DOM上。這就是DOM diff 算法,它可以大大提升網頁的性能表現。

  2. 如果想要拿到真實DOM,就要使用ref屬性

 

var MyComponent = React.createClass({
  handleClick: function() {
    this.refs.myTextInput.focus();
  },
  render: function() {
    return (
      <div>
        <input type="text" ref="myTextInput" />
        <input type="button" value="Focus the text input" onClick={this.handleClick} />
      </div>
    );
  }
});

ReactDOM.render(
  <MyComponent />,
  document.getElementById('example')
);
  1. 由於虛擬DOM是不能拿到用戶的輸入,所以如果要拿到輸入,文本框必須要有一個ref屬性(上例中:ref="myTextInput"),然後this.refs.[refName]就會返回真實的節點(上例子中:this.refs.myTextInput)
  2. 注意:由於this.refs.[refName]獲取的是真實的DOM,所以一定要等到虛擬DOM插入文檔之後才能使用這個屬性,否則會報錯,上例中通過爲組件制定Click事件的回調函數,使得只有在真正的DOM被click(意味着虛擬DOM已經轉換成了真實的DOM)之後,纔讀取this.refs.[refName]獲得真實的DOM

this.state

將組件看成一個狀態機,有一個初始狀態,然後隨着用戶的交互狀態發生改變而重新渲染UI。

var LikeButton = React.createClass({
  getInitialState: function() {
    return {liked: false};
  },
  handleClick: function(event) {
    this.setState({liked: !this.state.liked});
  },
  render: function() {
    var text = this.state.liked ? 'like' : 'haven\'t liked';
    return (
      <p onClick={this.handleClick}>
        You {text} this. Click to toggle.
      </p>
    );
  }
});

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

 

  1. LikeButton組件類的getInitialState方法(這個方法是自帶的)設置一個狀態的初始值,就是一個對象(本例中{like:false}),這個對象可以通過this.state讀取。render渲染出組件。用戶點擊導致狀態變化,this.setState 方法就修改狀態值,每次修改以後,自動調用 this.render 方法,再次渲染組件。
    由於 this.props 和 this.state 都用於描述組件的特性,可能會產生混淆。一個簡單的區分方法是,this.props 表示那些一旦定義,就不再改變的特性,而 this.state 是會隨着用戶互動而產生變化的特性。

十 組件的生命週期

  1. 組件生命週期有三種:
    - Mounting: 已插入真實的DOM
    - Updating: 正在被重新渲染
    - Unmounting: 已移除真實DOM

  2. 每個狀態都配有Will 和 Did相應的處理函數

    • componentWillMount()
    • componentDidMount()
    • componentWillUpdate(object nextProps, object nextState)
    • componentDidUpdate(object prevProps, object prevState)
    • componentWillUnmount()
  3. 兩個特殊狀態的處理函數

    • componentWillReceiveProps(object nextProps):已加載組件收到新的參數時調用
    • shouldComponentUpdate(object nextProps, object nextState):組件判斷是否重新渲染時調用

參考文檔

  1. 例子
var Hello = React.createClass({
  getInitialState: function () {
    return {
      opacity: 1.0
    };
  },

  componentDidMount: function () {
    this.timer = setInterval(function () {
      var opacity = this.state.opacity;
      opacity -= .05;
      if (opacity < 0.1) {
        opacity = 1.0;
      }
      this.setState({
        opacity: opacity
      });
    }.bind(this), 100);
  },

  render: function () {
    return (
      <div style={{opacity: this.state.opacity}}>
        Hello {this.props.name}
      </div>
    );
  }
});

ReactDOM.render(
  <Hello name="world"/>,
  document.body
);

上面代碼在hello組件加載以後,通過 componentDidMount 方法設置一個定時器,每隔100毫秒,就重新設置組件的透明度,從而引發重新渲染
注意,內聯樣式

<div style={{opacity: this.state.opacity}}> //正確 外層大括號表示這是JS語法
<div style={opacity: this.state.opacity}> //錯誤

Ajax & Promise

採用Promise抓取github上面最高點讚的項目的例子是個很好的promise加React應用的例子。

var RepoList = React.createClass({
  getInitialState: function() {
    return { loading: true, error: null, data: null};
  },

  componentDidMount() {
    this.props.promise.then(
      value => this.setState({loading: false, data: value}),
      error => this.setState({loading: false, error: error}));
  },

  render: function() {
    if (this.state.loading) {
      return <span>Loading...</span>;
    }
    else if (this.state.error !== null) {
      return <span>Error: {this.state.error.message}</span>;
    }
    else {
      var repos = this.state.data.items;
      var repoList = repos.map(function (repo) {
        return (
          <li>
            <a href={repo.html_url}>{repo.name}</a> ({repo.stargazers_count} stars) <br/> {repo.description}
          </li>
        );
      });
      return (
        <main>
          <h1>Most Popular JavaScript Projects in Github</h1>
          <ol>{repoList}</ol>
        </main>
      );
    }
  }
});

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章