【全棧React】第5天: 資料驅動

全棧講師_金雲龍發表於2017-08-02

本文轉載自:眾成翻譯
譯者:iOSDevLog
連結:http://www.zcfy.cc/article/3821
原文:https://www.fullstackreact.com/30-days-of-react/day-5/

我們的應用程式中的硬編碼資料不是好主意。 今天,我們將把我們的元件設定為由資料驅動,訪問外部資料。

通過這一點,我們已經編寫了我們的第一個元件並將其設定為子/父關係。但是,我們還沒有將任何資料繫結到我們的React元件。雖然在React中寫一個網站是一個更愉快的體驗(在我們看來),我們還沒有利用React的力量來顯示任何動態資料。

今天我們來改一下。

資料驅動

回想一下,昨天我們構建了包含頭和活動列表的時間軸元件的開始:

我們將演示分解成元件,最終用靜態JSX模板構建了三個獨立的元件。每當我們改變網站的資料時,不得不更新我們元件的模板是不方便的。

而是讓我們給出要使用的元件資料進行顯示。我們從 <Header /> 元件開始吧。現在,<Header />元件只顯示元素的標題 Timeline。這是一個很好的元素,它將是很好的能夠重用它在我們的頁面的其他部分,但標題是 Timeline 沒有意義的每一次使用。

讓我們告訴React,我們希望能夠將標題設定為別的東西。

介紹屬性

React允許我們以與HTML相同的語法向元件傳送資料,使用元件上的特性或 屬性。這類似於將 src 屬性傳遞給影像標籤。我們可以考慮 <img /> 標籤的屬性,因為prop我們正在設定呼叫的元件img。

我們可以訪問元件內的這些屬性 this.props。讓我們看看在動作中使用 props

回想一下,我們將 <Header /> 元件定義為:

class Header extends React.Component {
  render() {
    return (
      <div className="header">
        <div className="menuIcon">
          <div className="dashTop"></div>
          <div className="dashBottom"></div>
          <div className="circle"></div>
        </div>

        <span className="title">
          {this.props.title}
        </span>

        <input
          type="text"
          className="searchInput"
          placeholder="Search ..." />

        <div className="fa fa-search searchIcon"></div>
      </div>
    )
  }
}

當我們使用該 <Header /> 元件時,我們將它放在我們的 <App /> 元件中:

<Header />

我們可以 title 作為一個屬性傳遞我們作為一個屬性,<Header /> 通過更新元件的使用設定呼叫 title 某個字串的屬性,如下所示:

<Header title="Timeline" />

在我們的元件內部,我們可以 title 從課程中的 this.props 屬性訪問 Header。而不是像 Timeline 模板一樣靜態設定標題,我們可以將其替換為傳入的屬性。

import React from `react`

class Header extends React.Component {
  render() {
    return (
      <div className="header">
        <div className="menuIcon">
          <div className="dashTop"></div>
          <div className="dashBottom"></div>
          <div className="circle"></div>
        </div>

        <span className="title">
          {this.props.title}
        </span>

        <input
          type="text"
          className="searchInput"
          placeholder="Search ..." />

        <div className="fa fa-search searchIcon"></div>
      </div>
    )
  }
}

export default Header

現在我們的 <Header /> 元件將顯示我們傳入的字串,title 當我們呼叫該元件時。例如,<Header /> 像這樣呼叫我們的元件四次:

<Header title="Timeline" />
<Header title="Profile" />
<Header title="Settings" />
<Header title="Chat" />

結果四個 <Header /> 元件載入完成後如下:

很漂亮,是嗎?現在我們可以複用 <Header /> 元件, 使用一個動態 title 屬性。

我們可以傳遞不僅僅是元件中的字串。我們可以傳遞數字,字串,各種物件,甚至功能!我們將進一步討論如何定義這些不同的屬性,以便稍後構建元件api。

我們來看內容元件,並用資料變數而不是而不是靜態設定內容和日期。就像我們可以使用HTML元件一樣,我們可以將多個 props 元件傳遞給元件。

回想一下,昨天我們定義了我們的 Content 容器,如下所示:

class Content extends React.Component {
  render() {
    return (
      <div className="content">
        <div className="line"></div>

      {/* Timeline item */}
        <div className="item">
          <div className="avatar">
            <img src="http://p0.qhimg.com/t01e9226cd16ce24fb4.jpg" />
            Doug
          </div>

          <span className="time">
            An hour ago
          </span>
          <p>Ate lunch</p>
          <div className="commentCount">
            2
          </div>
        </div>

        {/* ... */}

      </div>
    )
  }
}

和我們 title 一樣,我們來看看 props 我們的 Content 元件需求:

  • 使用者的頭像圖片
  • 活動的時間戳
  • 活動項的文字
  • 評論數量

假設我們有一個代表活動專案的JavaScript物件。我們將有一些欄位,如字串欄位(文字)和日期物件。我們可能會有一些巢狀的物件 usercomments。例如:

{
  timestamp: new Date().getTime(),
  text: "Ate lunch",
  user: {
    id: 1,
    name: `Nate`,
    avatar: "http://www.croop.cl/UI/twitter/images/doug.jpg"
  },
  comments: [
    { from: `Ari`, text: `Me too!` }
  ]
}

就像我們將一個字串標題傳遞給 <Header /> 元件一樣,我們可以把這個 activity 物件傳遞給 Content 元件。我們轉換我們的元件來顯示它的模板內的這個活動的細節。

為了將動態變數的值傳遞給一個模板,我們必須使用模板語法在我們的模板中呈現。例如:

import React from `react`

class Content extends React.Component {
  render() {
    const {activity} = this.props; // ES6 destructuring

    return (
      <div className="content">
        <div className="line"></div>

        {/* Timeline item */}
        <div className="item">
          <div className="avatar">
            <img
              alt={activity.text}
              src={activity.user.avatar} />
            {activity.user.name}
          </div>

          <span className="time">
            {activity.timestamp}
          </span>
          <p>{activity.text}</p>
          <div className="commentCount">
            {activity.comments.length}
          </div>
        </div>
      </div>
    )
  }
}

export default Content

我們在我們的類定義中使用了一點ES6,在第一行定義就是這個render() 的解構函式。以下兩行在功能上相當:

// these lines do the same thing
const activity = this.props.activity;
const {activity} = this.props; 

解構使我們能夠以更短,更緊湊的方式節省打字和定義變數。

然後,我們可以通過傳遞一個物件作為支援而不是硬編碼的字串來_使用_這個新內容。例如:

<Content activity={moment1} />

太棒了,現在我們有一個由一個物件驅動的活動項。但是,您可能已經注意到,我們將不得不使用不同的註釋實現這個多次。相反,我們可以將一組物件傳遞到元件中。

假設我們有一個包含多個活動專案的物件:

const activities = [
  {
    timestamp: new Date().getTime(),
    text: "Ate lunch",
    user: {
      id: 1, name: `Nate`,
      avatar: "http://www.croop.cl/UI/twitter/images/doug.jpg"
    },
    comments: [{ from: `Ari`, text: `Me too!` }]
  },
  {
    timestamp: new Date().getTime(),
    text: "Woke up early for a beautiful run",
    user: {
      id: 2, name: `Ari`,
      avatar: "http://www.croop.cl/UI/twitter/images/doug.jpg"
    },
    comments: [{ from: `Nate`, text: `I am so jealous` }]
  },
]

我們可以 <Content /> 通過傳遞多個活動來重新闡述我們的使用,而不僅僅是一個:

<Content activities={activities} />

但是,如果我們重新整理檢視什麼都不會出現!我們需要先更新我們的 Content 元件以接受多個活動。正如我們以前瞭解到的,JSX真的只是由瀏覽器執行的JavaScript。我們可以在JSX內容中執行JavaScript函式,因為它將像瀏覽器的JavaScript一樣執行。

我們將我們的活動專案 JSX 移動 map 到我們將針對每個專案執行的專案中。

import React from `react`

class Content extends React.Component {
  render() {
    const {activities} = this.props; // ES6 destructuring

    return (
      <div className="content">
        <div className="line"></div>

        {/* Timeline item */}
        {activities.map((activity) => {
          return (
            <div className="item">
              <div className="avatar">
                <img
                  alt={activity.text}
                  src={activity.user.avatar} />
                {activity.user.name}
              </div>

              <span className="time">
                {activity.timestamp}
              </span>
              <p>{activity.text}</p>
              <div className="commentCount">
                {activity.comments.length}
              </div>
            </div>
          );
        })}

      </div>
    )
  }
}

export default Content

現在我們可以將任何數量的活動傳遞給我們的陣列,Content 元件將處理它,但是如果我們現在離開元件,那麼我們將有一個相對複雜的元件處理,包含和顯示活動列表。像這樣離開真的不是React的方式。

活動項

這裡寫一個元件包含顯示單個活動項然後再建立一個複雜的 Content 元件是有意義的,我們可以移動責任。這也將使測試更容易,新增功能等

讓我們更新我們的 Content 元件以顯示元件列表 ActivityItem(我們將在下面建立)。

import React from `react`

import ActivityItem from `./ActivityItem`;

class Content extends React.Component {
  render() {
    const {activities} = this.props; // ES6 destructuring

    return (
      <div className="content">
        <div className="line"></div>

        {/* Timeline item */}
        {activities.map((activity) => (
          <ActivityItem
            activity={activity} />
        ))}

      </div>
    )
  }
}

export default Content

這不僅僅是簡單易懂,而且使得這兩個元件的測試更容易。

使用我們新鮮的 Content 元件,讓我們建立 ActivityItem 元件。由於我們已經為此建立了檢視 ActivityItem,所以我們需要做的就是將它從我們 Content 元件的模板複製為自己的模組。

import React from `react`

class ActivityItem extends React.Component {
  render() {
    const {activity} = this.props; // ES6 destructuring

    return (
      <div className="item">
        <div className="avatar">
          <img 
            alt={activity.text} 
            src={activity.user.avatar} />
          {activity.user.name}
        </div>

        <span className="time">
          {activity.timestamp}
        </span>
        <p>{activity.text}</p>
        <div className="commentCount">
          {activity.comments.length}
        </div>
      </div>
    )
  }
}

export default ActivityItem

本週,我們使用React props 概念更新了由資料驅動的元件。在下一節中,我們將介紹有狀態的元件。

相關文章