React 入門總結(JSX與元件)

logzh發表於2016-03-21

第一印象

開發程式碼

demo.html

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8" />
    <title>Hello React!</title>
    <script src="build/react.js"></script>
    <script src="build/react-dom.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/babel-core/5.8.23/browser.min.js"></script>
  </head>
  <body>
    <div id="example"></div>
    <script type="text/babel">
      ReactDOM.render(
        <h1>Hello, world!</h1>,
        document.getElementById(`example`)
      );
    </script>
  </body>
</html>

開發程式碼將 JSX 轉換後,上線的程式碼:

helloworld.js

ReactDOM.render(
  React.createElement(`h1`, null, `Hello, world!`),
  document.getElementById(`example`)
);

demo.html

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8" />
    <title>Hello React!</title>
    <script src="build/react.js"></script>
    <script src="build/react-dom.js"></script>
    <!-- No need for Babel! -->
  </head>
  <body>
    <div id="example"></div>
    <script src="build/helloworld.js"></script>
  </body>
</html>

React是什麼

React 是一個 UI 庫,具體說 React 是做 UI 元件的 JavaScript 庫,也就是用 JS 寫前端UI。不同於 Angular 是一個完整的框架,React 僅僅只是 VIEW 層。
官方定義:A Javascript Library For Building User Interfaces 。

hello 元件

var Hello = React.createClass({
    render: function() {
        return <div>Hello {this.props.name}</div>;
    }
});
 
ReactDom.render(<Hello name="World" />, document.getElementById(`container`));

Timer 元件

var Timer = React.createClass({
  getInitialState: function() {
    return {secondsElapsed: 0};
  },
  tick: function() {
    this.setState({secondsElapsed: this.state.secondsElapsed + 1});
  },
  componentDidMount: function() {
    this.interval = setInterval(this.tick, 1000);
  },
  componentWillUnmount: function() {
    clearInterval(this.interval);
  },
  render: function() {
    return (
      <div>Seconds Elapsed: {this.state.secondsElapsed}</div>
    );
  }
});

ReactDom.render(<Timer />, document.getElementById(`container`));

Timer 元件結合 webpack 的使用

Hello.jsx定義元件

var React = require(`react`);

var Timer = React.createClass({
  getInitialState: function() {
    return {secondsElapsed: 0};
  },
  tick: function() {
    this.setState({secondsElapsed: this.state.secondsElapsed + 1});
  },
  componentDidMount: function() {
    this.interval = setInterval(this.tick, 1000);
  },
  componentWillUnmount: function() {
    clearInterval(this.interval);
  },
  render: function() {
    return (
      <div>Seconds Elapsed: {this.state.secondsElapsed}</div>
    );
  }
});

module.exports = Timer;

index.js使用元件

var React = require(`react`);
var ReactDom = require(`react-dom`);
var Timer = require(`Timer`);

ReactDom.render(<Timer />, document.getElementById(`container`));

優勢

  • api 少,類庫易學

  • 元件內聚,易於組合

  • 原生元件和自定義元件融合渲染

  • 狀態/屬性驅動全域性更新,不用關注細節更新

    • props

    • state

  • commonjs 生態圈/工具鏈完善(webpack)

    • webpack

四個概念

  • JSX (可選的)

  • 元件

  • Virtual Dom

  • Data Flow 單向資料繫結

這是 react 四個主要的知識點。本文只簡單介紹總結 JSX 和元件。

JSX

JSX 語法是類似 Html 的xml格式。注意和 Html 語法不太一樣,比如必須是駝峰命名,以及屬性名不能和 JS 關鍵字衝突,例如:className,readOnly。

一、JSX 是可選的

使用 JSX

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

ReactDOM.render(<HelloMessage name="John" />, mountNode);

不使用 JSX

"use strict";

var HelloMessage = React.createClass({
  displayName: "HelloMessage",

  render: function render() {
    return React.createElement(
      "div",
      null,
      "Hello ",
      this.props.name
    );
  }
});

ReactDOM.render(React.createElement(HelloMessage, { name: "John" }), mountNode);

二、JSX 嵌入變數

可以通過 {變數名} 來將變數的值作為屬性值

var HelloMessage = React.createClass({
  render: function() {
    return <div>name: {this.props.name}, age: {this.props.age}</div>;
  }
});

var user = {"name":"jack", age:29};
ReactDOM.render(<User user={user} />, mountNode);

三、JSX 熟悉擴散 JSX Spread Attributes

可以用通過 {…obj} 來批量設定一個物件的鍵值對到元件的屬性,注意順序,因為熟悉可以被覆蓋

var HelloMessage = React.createClass({
  render: function() {
    return <div>name: {this.props.name}, age: {this.props.age}</div>;
  }
});

var user = {"name":"jack", age:29};
ReactDOM.render(<User {...user} name="override name"/>, mountNode);

四、屬性值可以使用 Javascript 表示式

return (
  <nav>
    <Home />
    {loggedIn ? <LogoutButton /> : <LoginButton />}
  </nav>
);

五、需要自閉元件(標籤)Self-Closing Tag

元件(標籤)需要閉合。

var HelloMessage = React.createClass({
  render: function() {
    return (
      <div>
           <MyComponent /> //valid
           <MyComponent >  //invalid
           <img src="#" /> //valid
           <img src="#" > //invalid
      </div>
    );
  }
});

六、一個元件只能返回一個跟節點 Maximum Number of JSX Root Nodes

元件的render函式只能返回一個根節點,如果包含多個子元件,需要使用div或者span或者其他元件包裹。

//valid

var HelloMessage = React.createClass({
  render: function() {
    return (
      <div>
           <MyComponent /> 
           <img src="#" />
      </div>
    );
  }
});

//invalid

var HelloMessage = React.createClass({
  render: function() {
    return (
      <MyComponent /> 
      <img src="#" />
    );
  }
});

七、JSX中的 false

常見的三種場景

  1. Renders as id=”false”:

    ReactDOM.render(<div id={false} />, mountNode);
  2. String “false” as input value:

    ReactDOM.render(<input value={false} />, mountNode);
  3. No child:

    ReactDOM.render(<div>{false}</div>, mountNode);

這裡不會渲染成字串 false 作為div的子元件。這種做法類似我們常見的一種用法:

<div>{x > 1 && `You have more than one item`}</div>

元件

元件有兩個核心的概念:

  • props 屬性,由外面的 JSX 熟悉傳入,永遠是隻讀的,之後建議不要修改。主要用於資料的展示、父子元件的資料傳遞。

  • state 狀態,元件可以理解為一個狀態機,fn(state)=>UI。一旦狀態發生改變,元件會自動 render 方法重新渲染UI。

開發元件時,應該讓狀態儘可能的少,但能完全表達整個UI,這樣元件邏輯就容易維護。

無狀態元件(stateless function): 使用純粹的函式可以定義無狀態的元件。這種元件只是簡單的從外面接受 props 渲染 DOM。

var React = require(`react`);
require(`../css/gotop.css`);

//Stateless functional components

var Top = function () {
    return (
        <div className="back-top">
            <a className="code">
                <div className="code-box"><i></i><img src="http://cdn.tig.qq.com/images/wwq_wx_qrcode.jpg" alt="玩物圈微信二維碼"/></div>
            </a>
            <a href="#top" className="top"></a>
        </div>
    );
};

module.exports = Top;

通常的做法是:一個頂級父元件為中包括狀態和邏輯,通過props傳遞資料給各個子元件,而子元件是沒有狀態的,子元件只關注資料的渲染。
參考

Most of your components should simply take some data from props and render it. However, sometimes you need to respond to user input, a server request or the passage of time. For this you use state.

Try to keep as many of your components as possible stateless. By doing this you`ll isolate the state to its most logical place and minimize redundancy, making it easier to reason about your application.

A common pattern is to create several stateless components that just render data, and have a stateful component above them in the hierarchy that passes its state to its children via props. The stateful component encapsulates all of the interaction logic, while the stateless components take care of rendering data in a declarative way.

這種做法在 redux(單向資料流 Flux 模式的一種實現)中顯得很明顯。

參考文件:

相關文章