當父元件想要傳參數給子元件,子元件想要從父元件那邊得到資料時,我們就會用到props這個東西了~
用法十分簡單,首先,我們新增一個檔案src/components/list.js,如下:
src/components/list.js
import React from "react"
export default props => (
<ul>
<li>{props.itemData}</li>
</ul>
)
這個元件回傳了一個 "接收了一個props作為參數" 的一個箭頭函式。而props這個物件的itemData這個屬性,便是我們要從父層元件傳過來的資料。那我們又要怎麼傳過來呢??
在page/index.js裡,我們可以這樣去使用它:src/pages/index.js
import React from "react"
import Layout from "../components/layout"
import List from "../components/list"
export default () => (
<Layout>
<p>
我是內容
</p>
<List itemData="Apple"></List>
</Layout>
)
就是這樣的簡單,只要把資料作為屬性去做設定,就能以物件的一個屬性的形式,讓子元件使用了。
而如果設定多個屬性,便可以在props,這個物件裡面,去接收到多個資料。
順便一提,props雖然是這個傳遞資料的物件的名稱,但參數名稱不一定要是props,也可以haha跟hehe跟banana
此時的畫面,應該會長這樣。
然而常常,我們會希望給子元件一個陣列形式的資料,讓我們的子元件去產生多個元素,例如下面這樣子:src/pages/index.js
import React from "react"
import Layout from "../components/layout"
import List from "../components/list"
const foods = ['Apple', 'Banana', 'Cake'];
export default () => (
<Layout>
<p>
我是內容
</p>
<List itemData={foods}></List>
</Layout>
)
但我們在此時看到的畫面卻會是這個樣子:
從這個結果,我們可以知道,當JSX在顯示陣列資料時,會直接把陣列中的資料依序放上去,不經任何處理
所以這時候,會使用到JS陣列中的map方法,來針對陣列中的每個資料,變成我們想要讓它在畫面中的樣子。
於是我們修改過後,長這樣:src/components/list.js
import React from "react"
export default props=> {
const itemData = props.itemData.map((data)=>(<li>{data}</li>));
return (
<ul>
<li>{itemData}</li>
</ul>
)
}
以上例來講,就是用map直接將陣列中的每個內容都變成一個li元素,最後顯示時,因為是一個一個直接放上去,所以就會變成我們要的樣子。
當我們在做完上述的步驟後,我們會發現console吐出了警告訊息,原因是因為當我們在把陣列渲染到畫面上時,react會希望我們幫它加入一個"key"屬性,像這樣:src/components/list.js
import React from "react"
export default props=> {
const itemData = props.itemData.map((data)=>(<li key={data}>{data}</li>));
return (
<ul>
{itemData}
</ul>
)
}
在上面這個例子中,我們將它的key設為跟data相同,當然未必要這樣設定,react希望我們可以讓這個key作為這個資料的一個識別符,因此一個資料應該只有一個key,且不能相同,所以在這個例子裡我用了data(當然這是在確保陣列內沒有重複項時才能這樣使用)。
然而若使用陣列的index來做為key的話,程式上就不會報錯,但就無法達到我們要的功能。(因為萬一我們將陣列的第0項delete掉,其他元素的index都會發生變動)
這個key屬性的功能就是,當資料發生變動時,react會根據其所對應的key,來跟原本陣列中的資料做連結,意思是說假如我們不加key,或是資料沒有跟唯一那一組key綁在一起,那當資料發生變動時,react就無法知道那些元素不需要重新渲染,就會全部重新渲染。
反之,如果有加key,那當那個key對應的資料被刪除時,其他的元素就不會被重新渲染,因為他們的資料還在。
簡單來講,就是能達到減少render時間消耗的一個功能。
為了讓key能不重複,我們修改一下原本的陣列內容:src/pages/index.js
import React from "react"
import Layout from "../components/layout"
import List from "../components/list"
const foods = [{ id: 1, name:'Apple'}, { id: 2, name:'Banana'}, { id: 3, name:'Cake'}];
export default () => (
<Layout>
<p>
我是內容
</p>
<List itemData={foods}></List>
</Layout>
)
src/components/list.js
import React from "react"
export default props=> {
const itemData = props.itemData.map((data)=>(<li key={data.id}>{data.name}</li>));
return (
<ul>
{itemData}
</ul>
)
}
今天就這樣囉,明天或後天希望能完成React的部分,當然因為篇幅有限,大家想更了解的人,可以去看React的官方文檔或是其他文章,我是無法講得比那些詳細的XDD
這邊做的只能是一些比較常用的功能,讓之後實作上能比較順暢一點的進行而已。
明後天計畫,將我們的list變成一個具有新增跟刪除功能的元件。(需要功能: 事件監聽、函式、在元件間傳遞事件,簡單來講,就是透過觸發事件並傳遞事件,進而去執行元件的函示來變動資料)