React – 初探

  1. 先道官網下載
  2. 解壓縮後放到你的本機伺服器環境,如 http://localhost,因為有些部分需要引用內部 .js 檔案,如果不是在伺服器環境,Chrome 會出現跨網域限制提示訊息
    XMLHttpRequest cannot load file:///C:/Users/580/Desktop/react/src/helloworld.js. Cross origin requests are only supported for protocol schemes: http, data, chrome, chrome-extension, https, chrome-extension-resource.
  3. 關於 Hello World, 可參考。先在根目錄建立 helloworld.html ,並貼上
    <!DOCTYPE html>
    <html>
      <head>
        <script src="build/react.js"></script><!-- 引用 react.js -->
        <script src="build/JSXTransformer.js"></script> <!-- 因為 react.js 建議使用 jsx 的翻譯功能,來建構 Dom  -->
      </head>
      <body>
        <div id="example"></div>
        <script type="text/jsx"> <!-- 注意這裡是使用 jsx ,所以需要經過 JSXTransformer.js 來建立 DOM 結構 -->
          React.render(
            <h1>Hello, world!</h1>, // 注意喔,因為是 jsx 所以不要使用 " 或 ' 來包圍
            document.getElementById('example')
          );
        </script>
      </body>
    </html>
    

    這是內嵌的方法。

  4. 若要外嵌 React JSX 就需要這麼做。先在根目錄建立 src/helloworld.js 接著貼上

    React.render(
      <h1>Hello, world!</h1>, // 注意這裡還是使用 XML 來建立 HTML 的結構喔
      document.getElementById('example')
    );

    然後在你的 helloworld.html 添加參考

    <script type="text/jsx" src="src/helloworld.js"></script> <!-- 注意還是使用 jsx -->

     

透過上面步驟,就可以讓你簡單了解使用方式了,主要 React 建議使用 jsx 的方式來建構。下面我們看看這兩種方式的不同。原文參考

  1. var CommentBox = React.createClass({
      render: function() {
        return (
          <div className="commentBox">
            Hello, world! I am a CommentBox.
          </div>
        );
      }
    });
    React.render(
      <CommentBox />,
      document.getElementById('content')
    );

    HTML 元素的名稱,可使用小寫,如同上面的  className=”commentBox” ;然而 React 自訂的 class 名稱,開頭務必要使用大寫,如上方的 CommentBox。可自行修改大小寫,就會發現問題了。

  2. 若將上面改成使用 JSX 語法,就這麼寫
    var CommentBox = React.createClass({displayName: 'CommentBox',
      render: function() {
        return (
          // React.createElement(標籤, JSON格式的屬性, 標籤內容)
          React.createElement('div', {className: "commentBox"}, 
            "Hello, world! I am a CommentBox."
          )
        );
      }
    });
    React.render(
      React.createElement(CommentBox, null),
      document.getElementById('content')
    );

    – 上面的 var CommentBox 可以自定名稱。你可以改成如 obj ,這裡的開頭大小寫沒有限制。因為這只是變數,準備放到 React.createElement( 第一個參數這邊 ) 而已。
    – 透過 React.createClass() 可以建立一個 React 組件。
    – 最重要的方法 render ,是可以返回一個 React 的樹狀組件結構,最終會渲染到 HTML。
    – 這裡的 div 標籤,並不是真正實際的 DOM 節點,而是 React 的一個元素。也就當作是個虛擬的吧!這是安全的,因為不是實際產生 HTML,所以可以避免XSS攻擊的問題。
    – render 不可以返回基本的 HTML ,需要返回樹狀的組件結構。這就是為什麼要使用 React 的樹狀組件結構。這是非常關鍵的!
    – 透過 React.render() 產生的根組件,會注入為原始的 DOM,作為二次使用時的立足點。

    – 我將上方改寫這樣來幫助了解變化。一樣他是先建立虛擬的 React 組件後,才注入到  HTML 。

    var obj = React.createClass({
        displayName: 'CommentBox', 
        render: function (){
            return (
                React.createElement('a', {
                        className: "commentBox", //記得是 className
                        href: 'http://facebook.com',
                        title: '點擊我'
                    },
                    '我是超連結'
                )
            );
        }
    });
    
    React.render(
        React.createElement(obj, null),
        document.getElementById('content')
    );

    這是使用 JSX 的格式來寫, React 推薦使用。關於 JSX 語法文章可參考這裡

我們組合多個使用

 

建構組件 (Composing components) ,原文參考

先貼入你的 file.js

// 有個模組是 討論列表
var CommentList = React.createClass({
  render: function() {
    return (
      <div className="commentList">
        Hello, world! I am a CommentList.
      </div>
    );
  }
});

// 有個模組是 討論表單
var CommentForm = React.createClass({
  render: function() {
    return (
      <div className="commentForm">
        Hello, world! I am a CommentForm.
      </div>
    );
  }
});

// 有個模組是 討論方塊 
// <CommentList /> 會對應上方的 CommentList
// <CommentForm /> 會對應上方的 CommentForm
// 最後被 <div class="commentBox"> 包圍起來
var CommentBox = React.createClass({
  render: function() {
    return (
      <div className="commentBox">
        <h1>Comments</h1>
        <CommentList />
        <CommentForm />
      </div>
    );
  }
});


React.render(
    
    //需要的虛擬元件
    React.createElement(CommentBox, null),

    //我們會在 id="content" 內渲染出結果
    document.getElementById('content')

);

 

使用 Markdown 與 for each 資料

 

helloworld.html

<!DOCTYPE html>
<html>
  <head>
    <script src="build/react.js"></script>
    <script src="build/JSXTransformer.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/marked/0.3.2/marked.min.js"></script> <!-- 使用套件 -->
  </head>
  <body>
    <div id="content"></div>
    <script type="text/jsx" src="src/helloworld.js"></script>

  </body>
</html>

 

helloworld.js

請按照順序看喔 0) -> 1) -> 2) ….

/**
 * 2)
 * render 中返回的結構建立了 <div className="commentBox"> ,它內部的 <CommentList> 會去對應變數 CommentList
 * 而且 <CommentList> 的屬性 data 也放置了我們由外部傳遞進來的參數 data 。我們又要把資料傳遞到 CommentList 。
 * 而 <CommentForm /> 會去對應變數 CommentForm 。沒有參數的傳遞。
 */
var CommentBox = React.createClass({
  render: function() {
    return (
      <div className="commentBox">
        <h1>Comments</h1>
        <CommentList data={this.props.data} /> 
        <CommentForm />
      </div>
    );
  }
});

/**
 * 3-1)
 * 在這裡會去 each 我們 JSON 格式的資料 data 。 主要是透過 .map 的方法。
 * this.props.data.map() 的回調涵式我們自訂叫做 comment 。這個 comment 就是 data 經過 each 的每個項目。
 * 
 * 可以看到 this.props.data.map() 會返回 <Comment> 結構。 
 * 而 <Comment> 有個叫做 author 的屬性,我們傳入 comment.author 。
 * 
 */
var CommentList = React.createClass({
  render: function() {
    var commentNodes = this.props.data.map(function (comment) {
      return (
        <Comment author={comment.author}>
          {comment.text}
        </Comment>
      );
    });

    // {commentNodes} 就會替換為上方定義的變數 commentNodes ,也就是批次的節點。
    return (
      <div className="commentList">
        {commentNodes}
      </div>
    );
  }
});

/**
 * 4)
 * 這裡會返回 <div className="comment"> 結構。
 * this.props.author 會取得 <Comment author={comment.author}> 中的 author 。
 * 
 */
var Comment = React.createClass({
  render: function() {
    /**
     * 透過第三方套件 Markdown ,可以簡單格式化你的文字。
     * 例如我們在 data 中看到的 *another* 用星號包圍文字,會被轉換為強調(使用<em>斜體)的HTML。
     */
    
    /**
     * 方法一、
     * 如果只使用 {marked(this.props.children.toString())} 那在網頁就會看到
     * "<p>This is <em>another</em> comment</p>"
     * 
     * 但有個問題是,我們希望它是HTML編碼而不是要實體化的字元符號,
     * 之所以會看到實體化的字元,是因為 React 要避免造成 XSS 攻擊所做的保護。
     * 
     * 不過在這裡我們不需要使用,所以改成方法二的寫法。
     */
    // return (
    //   <div className="comment">
    //     <h2 className="commentAuthor">
    //       {this.props.author}
    //     </h2>
    //     {marked(this.props.children.toString())}
    //   </div>
    // );

    /**
     * 方法二、
     * 藉由 marked 第二個變數來啟用消毒 {sanitize: true} 功能,這可以跳脫任何來源的 HTML 。 
     * 但要小心使用。
     * 
     * 這句特殊的API dangerouslySetInnerHTML={{__html: rawMarkup}} ,
     * 是故意讓人難以插入 HTML (避免 XSS 攻擊),但我們要利用這個後門方法來正確執行 HTML 。
     */
    var rawMarkup = marked(this.props.children.toString(), {sanitize: false});
    // console.log(rawMarkup)

    return (
      <div className="comment">
        <h2 className="commentAuthor">
          {this.props.author}
        </h2>
        <span dangerouslySetInnerHTML={{__html: rawMarkup}} />
      </div>
    );
  }
});

/**
 * 3-2)
 */
var CommentForm = React.createClass({
  render: function() {
    return (
      <div className="commentForm">
        Hello, world! I am a CommentForm.
      </div>
    );
  }
});

/**
 * 0) 
 * 先定義好JSON資料,後續我們將批次取出
 * 這個通常位在伺服器端,不過我們這裡先直接寫在這裡。
 */
var data = [
  {author: "Pete Hunt", text: "This is one comment"},
  {author: "Jordan Walke", text: "This is *another* comment"},
];


/**
 * 1)
 * 第一個參數 <CommentBox data={data} /> 的意思,代表會自動對應變數 CommentBox ,並將 data 賦予到屬性 data 準備傳遞。
 * 這代表我們要將 data 傳遞到 CommentBox 。
 */
React.render(
    <CommentBox data={data} />,
    document.getElementById('content')
);

改為遠端獲取 JSON 資料

修改這段就可以了。使用 url=’你的伺服器獲取網址’

React.render(
  <CommentBox url="comments.json" />,
  document.getElementById('content')
);

 

發表迴響