一個簡單的Loops
我們先來實現一個簡單的需求,使用
React
列印 陣列 中的資料並顯示
相信聰明的你早已想到了解決方案,以下是我的實現
import React from 'react'
const List = () => {
const arr = [1, 2, 3, 4]
return (
<ul>
{
arr.map((item, index) => <li key={index}>{item}</li>) // 需要帶上 key 屬性
}
</ul>
)
}
export default List
複製程式碼
使用 ES6 的 map
方法遍歷並返回 <li></li>
結構
我們再來看看使用 loops
的版本
使用
loops
前我們首先要安裝react-loops
npm install react-loops
或者yarn add react-loops
import React from 'react'
import { For } from 'react-loops' // 引入 react-loops
const List = () => {
const arr = [1, 2, 3, 4]
return (
<div>
<For of={arr} as={item => <li>{item}</li>} /> // 可省略 key 屬性
</div>
)
}
export default List
複製程式碼
你會發現使用 loops
後,只是替換了之前的 map
方法,以一個 <For />
標籤的形式來遍歷資料,of
屬性中寫入需要遍歷項,as
則類似於 map
方法中的回撥函式。但其實內部做了很多優化和封裝。
值得注意的是,在使用第一種方法時,為了 diff 演算法優化,我們必須帶上 key
屬性,否則瀏覽器會報警告錯誤。
而使用 loops
後,其內部會為每項自動注入 key
屬性,省去我們手動操作或是遺漏帶來的麻煩。
為什麼會有Loops
增強程式碼語義化
loops
譯為'迴圈',顧名思義是為了優化 React
中的迴圈操作。 它以其獨特的 <For />
標籤的形式,使團隊開發的程式碼風格更加統一化,並具有良好的可讀性。而loops
的出現,本身是受到了 Angular(ng-repeat)
和 Vue(v-for)
指令語法的啟發,熟悉 Angular
或 Vue
的朋友們應該會有既視感。三大框架的發展本質就是相互學(抄)習(襲)和啟發的過程。
讓For標籤一統迴圈界江湖
我們知道在 JS
中有許多可遍歷結構,除陣列之外,還有偽陣列、物件、Map、Set...可迭代結構,這個時候我們需要針對不同儲存結構來進行遍歷方法的選擇。比如我們現在修改一下之前的需求
使用
React
列印 物件 中的資料並顯示
此處思考一分鐘,聰明的你可以想想如何實現。
我們知道物件身上是沒有 map
方法的,這時我們需要先將物件的 key
轉為一個陣列的集合,再使用 map
方法來進行操作。
import React from 'react'
const List = () => {
const obj = {
name: 'z',
age: 20
}
return (
<ul>
{
// Object.keys(obj) => ['name', 'age']
Object.keys(obj).map(item => <li key={item}>{obj[item]}</li>) // 需要帶上 key 屬性
}
</ul>
)
}
export default List
複製程式碼
又或者我們可以使用 for in
迴圈來遍歷這個物件得出遍歷結果並列印。可以發現遍歷的方法有很多種,而 loops
就是為了統一迴圈風格而生,可遍歷項均可以使用一個 <For />
標籤來實現,值得注意的是,在遍歷 物件 時,我們需要用 <For />
標籤上的 in
屬性,這個後面詳細說明。
import React from 'react'
import { For } from 'react-loops'
const List = () => {
const obj = {
name: 'z',
age: 20,
}
return (
<div>
// 遍歷物件時,需要使用 in 屬性
<For in={obj} as={item => <li>{item}</li>} /> // 可省略 key 屬性
</div>
)
}
export default List
複製程式碼
怎樣使用Loops
在使用 loops
時,分為兩種情況
- 遍歷陣列、偽陣列、Iterables(可迭代物件 Map、Set等)
- 遍歷物件
For-of Loops
在使用 of
屬性時,我們可以接收陣列、偽陣列、Iterables(可迭代物件 Map、Set等)
const arr = [1, 2, 3, 4] // 可以接收陣列
const arrLike = { 0: 'z', 1: 'h', length: 2 } // 可接收偽陣列
const setLoop = new Set([1, 2, 3, 4]) // 可接收 Set
const mapLoop = new Map([['name', 'z'], ['age', 20]) // 可接收 Map
return (
<div>
<For of={arr} as={item => <li>{item}</li>} />
</div>
)
複製程式碼
而 as
屬性則類似於 map
方法的回撥函式,當然你也可以不用 as
屬性,這時需要將回撥函式巢狀在 <For></For>
中
return (
<For of={arr}>
{item => <li>{item}</li>}
</For>
)
複製程式碼
當然 as
這個回撥函式在 map
方法之上又做了一層封裝,其第二個引數非常特別,它給我們提供了一些與遍歷有關的屬性。
return (
<div>
// metadata 為回撥函式的第二個引數
<For of={arr} as={(item, metadata) => {
console.log(metadata) // 列印輸出 metadata
return <li>{item}</li>
}} />
</div>
)
複製程式碼
我們先列印輸出下第二個引數
- index --- 遍歷項標記值,從0開始,類似於
map((item, index) => {})
中的index
- isFirst --- 是否為第一項
- isLast --- 是否為最後一項
- key --- 遍歷項的鍵,陣列為其下標,物件為物件的
key
- length --- 遍歷項數目
有了這些屬性,我們可以通過解構的方式來取出需要使用的資料。例如我們要手動新增 key
時,便可以從第二個引數中取出
return (
<div>
// {key} 解構出 key 的值
<For of={arr} as={(item, {key}) => <li key={key}>{item}</li>} />
</div>
)
複製程式碼
For-in Loops
在我們需要遍歷一個物件時,需要使用 For-in
的結構 <For in={obj} />
還是引用上述例子
const List = () => {
const obj = {
name: 'z',
age: 20,
}
return (
<div>
// 遍歷物件時,需要使用 in 屬性
<For in={obj} as={item => <li>{item}</li>} />
</div>
)
}
複製程式碼
原因其實很簡單,我們可以類比於 for in
迴圈
const obj = {
name: 'z',
age: 20,
}
for(let key in obj) {
...
}
複製程式碼
如果我們嘗試用 For-of
來遍歷物件(偽陣列除外),會發現瀏覽器報錯
For-of
只對陣列、偽陣列、Iterables(可迭代物件 Map、Set等)有效。我們再嘗試看看原始碼是如何判斷
function For(props) {
...
// 如果使用的是 of 屬性
var list = props.of;
if (!list) {
return null;
}
// 判斷是否為陣列
if (!Array.isArray(list)) {
// 不是陣列就判斷是否為集合 ( 偽陣列 和 Iterable(Map、Set) )
if (!iterall.isCollection(list)) {
// 不是陣列,也不是集合,則丟擲異常
throw new TypeError(
"<For> `of` expects an Array, Array-like, or Iterable collection"
);
}
// 是陣列,將用新陣列存放
var array = [];
iterall.forEach(list, function(item) {
array.push(item);
});
list = array;
}
...
}
// 判斷是否為集合
function isCollection(obj) {
// 如果是物件,但物件只能是 偽陣列 和 Iterable(Map、Set)
return Object(obj) === obj && (isArrayLike(obj) || isIterable(obj));
}
複製程式碼
結尾
通過這幾個小例子的學習,可以發現 loops
確實是非常簡單而且好用的 react
遍歷工具。是輪子就有它存在的意義,如果你厭倦了手寫JS遍歷,不妨也來嚐嚐 loops
,或許你就會喜歡上這個小而巧的庫。
react-loops
地址:react-loops
demo
地址:github