React Loops 尝鲜

一个简单的Loops

咱们先来实现一个简单的需求,使用 React 打印 数组 中的数据并显示

相信聪明的你早已想到了解决方案,如下是个人实现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> 结构git

咱们再来看看使用 loops 的版本github

使用 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 属性,省去咱们手动操做或是遗漏带来的麻烦。npm

为何会有Loops

加强代码语义化

loops 译为'循环',顾名思义是为了优化 React 中的循环操做。 它以其独特的 <For /> 标签的形式,使团队开发的代码风格更加统一化,并具备良好的可读性。而loops 的出现,自己是受到了 Angular(ng-repeat)Vue(v-for) 指令语法的启发,熟悉 AngularVue 的朋友们应该会有既视感。三大框架的发展本质就是相互学(抄)习(袭)和启发的过程。数组

让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

相关文章
相关标签/搜索