咱們先來實現一個簡單的需求,使用
React
打印 數組 中的數據並顯示react
相信聰明的你早已想到了解決方案,如下是個人實現git
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>
結構github
咱們再來看看使用 loops
的版本算法
使用
loops
前咱們首先要安裝react-loops
npm install react-loops
或者yarn add react-loops
npm
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
譯爲'循環',顧名思義是爲了優化 React
中的循環操做。 它以其獨特的 <For />
標籤的形式,使團隊開發的代碼風格更加統一化,並具備良好的可讀性。而loops
的出現,自己是受到了 Angular(ng-repeat)
和 Vue(v-for)
指令語法的啓發,熟悉 Angular
或 Vue
的朋友們應該會有既視感。三大框架的發展本質就是相互學(抄)習(襲)和啓發的過程。框架
咱們知道在 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
時,分爲兩種狀況
在使用 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
的結構 <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