react 官方文檔翻譯系列

react 官方文檔翻譯

此文檔只是針對本身在學習react的過程當中進行的翻譯。可能不是太專業,可是基於本身的理解,用於日後的查閱來講應該是足夠了。javascript

JSX 的介紹

思考如下變量的聲明:
const element = <h1>Hello, world!<h1>
以上有意思的語法,既不是字符串,也不是HTML。
咱們稱之爲JSX,它是基於JavaScript的擴展語法。咱們推薦在React中使用JSX語法來描述UI應該是什麼樣子的。JSX也許會讓你想到模板
語言,可是它可以很好的與JavaScript結合,具備JavaScript一樣強大的功能。

JSX用於生成React的元素(elements),咱們將在下一章節探討如何把它們渲染到DOM上。接下來, 你將會了解到開始使用JSX須要掌握的
一些必要知識。

1. 在JSX中嵌入表達式

在JSX中能夠嵌入任何JavaScript 表達式,經過使用一對花括號「{}」進行包裹。
例如2 + 2, user.firstName, 和 formatName(user)都是有效的表達式:
import React from 'react';
      import ReactDom from 'react-dom';
      function formatName(user) {
          return user.firstName + ' ' + user.lastName;
      }

      const user = {
          firstName: 'Harper',
          lastName: 'Perez'
      };

      const element = (
          <h1>
              Hello, {formatName(user)}!
          </h1>
      );

      ReactDom.render(
          element,
          document.getElementById('root')
      );
輸出結果爲:  Hello, Harper Perez!
爲了方便閱讀,咱們把JSX分割成多行來書寫,固然並非必須的,可是若是要這麼作的話,咱們仍是建議用圓括號括起來,從而避免分號自動
插入的陷阱。

2. JSX也是一種表達式

編譯以後,JSX表達式就會變成普通的JavaScript對象。
這意味着你能夠在if以及for語句塊裏使用JSX,賦值給一個變量,當作參數傳遞以及做爲函數的返回值:
function getGreeting(user) {
        if (user) {
          return <h1>Hello, {formatName(user)}!</h1>;
        }
        return <h1>Hello, Stranger.</h1>;
      }

3. 使用JSX來指定屬性值

你可使用引號來爲屬性指定字符串常量值:
const element = <div tabIndex="0"></div>;
你也能夠在屬性值中使用花括號來嵌套JavaScript表達式:
const element = <img src={user.avatarUrl}></img>;
當使用花括號來嵌套JavaScript表達式的時候,不要在花括號外面使用引號來嵌套。不然JSX將會把該值當作一個字符串字面量來處理,而不是
表達式。在同一個屬性值當中,你可使用花括號和引號中的任意一個,可是不能兩個都同時使用。

4. 使用JSX來指定子元素

若是一個標籤是空的,你可使用‘/>’進行標籤的閉合。看以下的XML:
const element = <img src={user.avatarUrl} />;
JSX標籤可能會包含子元素:
const element = (
        <div>
          <h1>Hello!</h1>
          <h2>Good to see you here.</h2>
        </div>
      );
警告:比起HTML,JSX更接近於JavaScript,因此JSX採用駝峯式的屬性命名約定來代替HTML中的屬性名。
  例如在JSX中,class變爲className, tabindx變爲tabIndex。

5. JSX阻止了注入攻擊

在JSX中嵌入用戶的輸入是安全的:
const title = response.potentiallyMaliciousInput;
      // This is safe:
      const element = <h1>{title}</h1>;
默認狀況下, 在渲染以前,React Dom會把嵌套在JSX裏的任何值進行轉義,也就是意味着,你沒法注入任何非明確在應用中指定的東西。
在渲染以前,全部的值都會被轉換成字符串,這幫助解決了跨站點攻擊。

6. JSX 是對象

Babel 把 JSX 語法編譯以後,其實就是調用了 React.createElement().
 如下的兩個實例是等效的:
const element = (
       <h1 className="greeting">
          Hello, world!
       </h1>
     );
     const element = React.createElement(
       'h1',
       {className: 'greeting'},
       'Hello, world!'
     );
    
     React.createElement() 在執行的時候進行了一些校驗以幫助咱們寫出更加健壯的代碼,本質上它建立了以下的一個對象:
        // 注意: 當前這個結構是簡化了的
        const element = {
          type: 'h1',
          props: {
            className: 'greeting',
            children: 'Hello, world'
          }
        };
這樣的對象咱們稱之爲React元素。你能夠把它想象爲咱們在屏幕上所看到元素的一個描述。React讀取這些對象,使用它們來構造DOM,而且保持實時更新。

咱們將在下一章節討論如何把React的元素渲染到DOM上。

提示: 咱們推薦使用支持Babel的編輯器,從而es6和JSX語法均可以正確的高亮顯示。

渲染元素

元素是React應用中最小的構建模塊。
一個元素描述了你想要在屏幕上看到的東西:
const element = <h1>Hello, world<h1/>;
不像瀏覽器DOM元素那樣,React元素是簡單的對象,而且易於建立。(瀏覽器的元素建立代價比較昂貴)React DOM
兼顧更新DOM去匹配React元素。

注意: 另一個被你們熟知的概念「組件」可能會使元素理解起來比較困惑。咱們將在下一章節講解組件。元素是組件
的組成部分, 咱們建議在閱讀下一章節前仔細閱讀該部分的內容。

1. 把元素渲染到DOM

假設在你的HTML文件中有一個<div>元素:
    <div id="root"></div>
咱們稱之爲根元素節點,由於在該元素當中的全部內容將會由React DOM 所管理。
使用React構建的應用一般來講只有單一的一個根節點。若是你想在現有的應用中集成React的話,那你能夠定義多個
孤立的根節點。

渲染React元素到根DOM節點上,把兩者都傳遞給ReactDom.render():
const element = <h1>Hello, world</h1>;
        ReactDOM.render(
            element,
            document.getElementById('root')
        );
在頁面中將會顯示: Hello, world

2. 更新已經渲染的元素

React元素是不可變的。只要建立一個元素以後,就不能改變它的子元素和屬性。一個元素就像是電影中的某一幀:它
表明了在某一個肯定的時間點上的UI展示。

根據咱們目前的知識,更新UI的惟一途徑是建立一個新的元素,傳遞給ReactDOM.render()進行渲染。

思考如下時鐘的示例:
function tick() {
            var element = (
                <div>
                  <h1>Hello, world!</h1>
                  <h2>It is {new Date().toLocaleTimeString()}.</h2>
                </div>
            );
            ReactDom.render(
                element,
                document.getElementById('root')
            );
        }
        
        setInterval(tick, 1000);
每隔一秒鐘setInteval的回調就會去調用一次ReactDom.render()。
    
注意: 在實踐中,大多數的React應用只調用一次ReactDom.render()。下一個章節中,咱們將會學習如何在
有狀態的組件(stateful components)中去封裝這樣的代碼。

3. React只會更新須要更新的元素

React DOM會比較前一個元素以及它的子元素,而且只會去更新須要更新的DOM,從而達到預期的效果。
你能夠運行上一個例子,經過瀏覽器工具來進行驗證。(如下爲實例的截圖)

圖片描述

儘管咱們在每一秒鐘的時候建立了一個描述整個UI樹的元素,可是隻有文本節點當中的內容被React DOM更新了。

組件和Props

組件可讓你把UI分紅獨立的,可服用的一些代碼塊。每個代碼塊均可以單獨的考慮。

在概念上,組件相似於JavaScript的函數(function)。他們接收任意的輸入(稱之爲「props」),返回一個React 元素,
描述了屏幕上應該顯示的信息。

1. 函數(functional)和類(class)申明的組件

定義組件的最簡單的方式是寫一個JavaScript函數:
function Welcome(props) {
        return <h1>Hello, {props.name}</h1>;
      }
這個函數是一個有效的React組件,由於它接收一個單一的props對象做爲參數,而且返回了一個React元素。咱們稱之爲
函數化的組件,由於從字面上來看它就是一個JavaScript函數。

你一樣可使用es6的class來定義一個組件:
class Welcome extends React.Component {
          render() {
            return <h1>Hello, {this.props.name}</h1>;
          }
      }
從React的角度來看,以上兩個組件是等價的。
 
 Classes 有一些其餘的特性,咱們將在下一章節探討。鑑於函數化的組件簡潔,咱們將使用它來進行組件的定義。

2. 渲染組件

在上面的示例中,咱們僅僅使用到了表示DOM標籤的React元素:
const element = <div />;
另外,元素也能夠是用戶自定義的組件:
const element = <Welcome name="Sara" />;
當React遇到用戶自定義的組件的時候,它把JSX屬性當作一個對象傳遞給組件,咱們把改對象稱之爲「props」。
例如,下面的代碼將會把「Hello, Sara」渲染到上:
function Welcome(props) {
          return <h1>Hello, {props.name}</h1>;
      }
      const element = <Welcome name="Sara" />;
      ReactDOM.render(
        element,
        document.getElementById('root')
      );
讓咱們回顧下這個示例都發生了什麼:
  1. 咱們調用ReactDom.render()來渲染<Welcome name="Sara" />
  2. React調用Welcome組件,把{name: 'Sara'}做爲props
  3. Welcome組件返回一個<h1>Hello, Sara</h1>元素做爲結果。
  4. React DOM會及時的更新DOM去匹配 <h1>Hello, Sara</h1>
  
警告: 
組件名稱要以大寫字母開頭。
例如:<div />表示DOM標籤,可是<Welcome />表明一個組件。

3. 組件的組合

組件能夠被另一個組件所引用。這使得咱們能夠在不一樣層級的詳細信息中使用同一個組件。一個button,form,
dialog,screen:在React中,這些一般都表現爲一個組件。

例如,咱們能夠建立一個屢次渲染 Welcome 的組件App:
function Welcome(props) {
        return <h1>Hello, {props.name}</h1>;
      }
      function App() {
          return (
            <div>
              <Welcome name="Sara" />
              <Welcome name="Cahal" />
              <Welcome name="Edite" />
            </div>
          );
      }
      ReactDOM.render(
          <App />,
          document.getElementById('root')
      );
典型的,新的React應用會在頂部有一個單一的App組件。然而,若是是在已有的項目中集成React,你能夠經過自下而上的方式,從一個小的組件例如Botton開始,按照你本身的方式逐漸的由下而上
到達視圖的頂部。

警告: 
組件必須返回一個單一根元素的元素。這就是爲何咱們添加一個<div>來包含全部的<Welcome />
元素了。

4. 組件的提取

不要擔憂把組件切分爲更小的組件。
例如,思考以下的 Comment 組件:
function Comment(props) {
          return (
            <div className="Comment">
              <div className="UserInfo">
                <img className="Avatar"
                  src={props.author.avatarUrl}
                  alt={props.author.name}
                />
                <div className="UserInfo-name">
                  {props.author.name}
                </div>
              </div>
              <div className="Comment-text">
                {props.text}
              </div>
              <div className="Comment-date">
                {formatDate(props.date)}
              </div>
            </div>
          );
      }
它接收author(一個對象),text(字符串),以及date(日期)做爲props,描述了一個社交媒體
網站上的評論。

由於嵌套的關係,這個評論組件很差去作改動,也難於重用其中的我的信息部分。讓咱們從中提取
一些組件。
首先,咱們將提取Avatar:
function Avatar(props) {
          return (
              <img className="Avatar"
              src={props.user.avatarUrl}
              alt={props.user.name}
             />
          );
      }
Avatar組件並不須要知道在Comment組件當中被渲染了。這也是爲何咱們把prop的name定義爲
更加通用的user,而不是author。

咱們更加推薦從組件自身的視圖角度來命名props,而不是經過他被使用的場景來定義。

如今咱們能夠稍微的簡化下Comment:
function Comment(props) {
          return (
            <div className="Comment">
              <div className="UserInfo">
                <Avatar user={props.author} />
                <div className="UserInfo-name">
                  {props.author.name}
                </div>
              </div>
              <div className="Comment-text">
                {props.text}
              </div>
              <div className="Comment-date">
                {formatDate(props.date)}
              </div>
            </div>
          );
        }
下一步咱們將要提取UserInfo組件,該組件緊挨着用戶的姓名,渲染一個Avatar組件:
function UserInfo(props) {
          return (
            <div className="UserInfo">
              <Avatar user={props.user} />
              <div className="UserInfo-name">
                {props.user.name}
              </div>
            </div>
          );
        }
這讓咱們進一步的簡化Comment組件:
function Comment(props) {
          return (
            <div className="Comment">
              <UserInfo user={props.author} />
              <div className="Comment-text">
                {props.text}
              </div>
              <div className="Comment-date">
                {formatDate(props.date)}
              </div>
            </div>
          );
        }
提取組件彷佛是一件枯燥乏味的工做,可是在大型的應用中提供了可重用組件的模板。首要的一個原則
就是若是UI中的一部分被使用了屢次(Button, Panel, Avatar),或者足夠的複雜(pp, 
FeedStory,Comment),它將會是可重用組件的最佳候選。

5. Props是隻讀的

無論你是經過function或者是class的方式申明的組件,它從不會修改它自身的props。思考以下的
Sum函數:
function sum(a,b) {
            renturn a + b;
        }
相似這樣的函數咱們稱之爲純粹(pure)的函數,由於這樣的函數不會試圖去改變他們的輸入參數,
而且相同的輸入老是返回相同的結果。

相反,以下的函數並非純粹的,由於它改變了它的入參。
function withdraw(account, amount) {
          account.total -= amount;
        }
React很是的靈活,可是它有一條很是嚴格的規則:
    全部的React組件必須像純粹的函數同樣,不去影響到他們的props。
固然,應用程序的UI是隨時在變化的。在下一個章節,咱們將介紹一個新的概念:state。State容許
React組件根據用戶的動做、網絡的響應以及其餘的事件來改變他們的輸出,可是並不違背這一原則。


待續...
相關文章
相關標籤/搜索