凡人修React|新手练气筑基必备! 抖音商城[商品信息卡组件]开发

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第1天,点击查看活动详情

前言

React

  • 声明式:React 使创建交互式 UI 变得轻而易举。为你应用的每一个状态设计简洁的视图,当数据改变时 React 能有效地更新并正确地渲染组件。
  • 组件化:创建拥有各自状态的组件,再由这些组件构成更加复杂的 UI。组件逻辑使用 JavaScript 编写而非模版,因此你可以轻松地在应用中传递数据,并使得状态与 DOM 分离。

本次通过开发抖音商城商品信息列表组件,走进React的怀抱。
不多说,先看效果gh-pageshunag-mouren.github.io/dy_mall/
再看项目架构

63.png

1. 组件设计与功能需求

1.1 组件设计

首先将商品信息卡列表组件细化,分为头部tabs切换部分信息卡列表部分,其中信息卡列表部分包含有商品信息卡项直播信息卡项视频信息卡项,且各项信息卡项包含两种状态,分别为数据加载前的状态数据加载后的状态。即:

  • 头部tabs切换部分
  • 商品信息卡项
  • 直播信息卡项
  • 视频信息卡项

如下图所示。 bing.png 基于以上我们有如下组件蓝本的代码: 1.png

1.2 功能需求

就实际应用场景而言,有如下功能应当实现:

  • Tabs切换跟随点击显示高亮并激活
  • 信息卡列表部分跟随tabs切换显示相应内容
  • 第一进入某个信息卡数据加载时应当显示数据加载前的状态,后面再进入该项不再显示数据加载前的状态
  • 图片懒加载的实现
  • 当滚动到底部后可以加载新的数据

2. 组件实现

2.1 Tabs切换部分实现

Tabs切换部分将使用antd-mobile中的Tabs组件来实现,其选项卡面板为Tabs.tab。其中本次涉及属性有:

Tabs属性

  • activeKey:为当前激活面板的key值
  • onChange:切换面板时的回调,传入的参数为将被选中Tab的key值

Tabs.Tab属性

  • key:和Tabs的activeKey对应
  • title:选项卡的标题名字

由以上可知,当我们选中的面板被激活,则Tabs中的activeKey属性值就会变成对应选中面板Tab的key值,凭此会为为Tab面板添加“adm-tabs-tab-active”的类名(如下图所示),进而被选中时高亮。

2.png 那我们只需要把activeKey值修改为我们将选中的面板的key值就可以激活它,这时我们就可以借助onChange属性,在回调函数中修改activeKey的值。但是activeKey作为属性不好在回调函数中操作,那不妨利用一个中间变量,修改中间变量的值,再把中间变量的值传给activeKey。考虑到后续在切换面板时要显示相应的内容,那么我们这里使用State Hook,利用useState()方法返回的state值作为中间变量以及更新state值的函数来修改该值,以达到更新activeKey值得目的,进而实现Tabs切换。实现代码如下。

6.png 考虑到我们当前定义的从useState()方法解构出来的[activityKey,setActivityKey]不仅仅只会在GoodCardList组件中被使用,我们应当将其放在父组件当中。于是我们通过父组件给子组件传参,让GoodCardList组件得到这些属性。代码将修改如下。

4.png

5.png 至此Tabs头部切换完成,效果如下。

chrome-capture-2022-5-28.gif

2.2 信息卡列表部分实现

由上文可知信息卡列表部分其实是由商品信息卡项直播信息卡项视频信息卡项组成,就实际情况而言可视该三项内容为通用组件。这三项异曲同工,不妨就以商品信息卡为例。这时我们需要进行数据请求,数据方面我们通过在线接口工具fastmock组织,fastmock可以让你在没有后端程序的情况下能真实地在线模拟 ajax 请求,实现前后端分离。然后我们通过axios进行请求数据,axios是一个基于promise 的 HTTP 库。同时使用async函数与await操作符同步化获取数据过程。 在src目录下新建一个api文件夹,在其之下新建request.js文件,该文件用于做请求方面的工作,我们数据请求的代码就封装在其中。

8.png

数据请求一般都在页面级别组件,请求到的数据通过参数传递给子组件。这时我们就要请出Effect Hook,它可以告诉React组件需要在渲染后执行某些操作。React 会保存你传递的函数(我们将它称之为 “effect”),并且在执行DOM更新之后调用它。默认情况下,它在第一次渲染之后和每次更新之后都会执行。但我们可以通过给它的第二参数(是个数组)来控制它,如果这个数组里的内容在两次重渲染之间没有发生变化,就可以通知 React 跳过对这个effect 的调用;如果发生了改变就会再次对这个effect进行调用。那么我们在切换不同面板时需要请求不同的内容,我们就可以把请求数据的过程放在Effect中,并通过前文的定义的State中的activityKey来实现面板切换时是否需要请求数据。

9.png

GoodsCardList组件内接收数据后,根据数据生成(map)信息卡列表里各项内容,同时别忘了在map列表里的数据内容时,要给每一项添加一个独一无二的key值
因为每当一个列表重新渲染时,React 会根据每一项列表元素的 key 来检索上一次渲染时与每个 key 所匹配的列表项。如果 React 发现当前的列表有一个之前不存在的 key,那么就会创建出一个新的组件。如果 React 发现和之前对比少了一个 key,那么就会销毁之前对应的组件。如果一个组件的 key 发生了变化,这个组件会被销毁,然后使用新的 state 重新创建一。(这里我在fastmock组织的数据中给每条数据都自动生成了一个独一无key)

12.png

商品信息卡项组件的实现

13.png

至此商品信息卡列表组件开发过半,来看看目前效果。

11.gif

2.3 增加loading状态

发现每次切换面板的时候,页面需要过一段时间才会显示内容,用户体验不好。这时由于数据还在请求中,数据请求完成后才渲染出该列表内容,那么我们这时需要添加一个loading状态,在数据请求数显示loading状态的页面内容。

增加一个新的State Hook ,[loading,setLoading]=useState(false)来控制是否需要loading,[requestKey,setRequestKey]=useState([])来记录某个面板是否被访问过,访问过后再访问不会再出现loading状态。

14.png

并给商品信息卡项直播信息卡项视频信息卡项加入loading状态时显示的框架内容。其种loading状态显示的框架屏内容使用了antd-mobile的Skeleton,它可以在需要等待加载内容的位置提供一个占位图形组合。具体如下

15.png

看看现在的效果

88.gif

2.4 实现图片懒加载

考虑实际应用场景,我们不妨在加上懒加载,当图片未出现在可视区域是用占位图代替,进入可视区域显示图片 使用IntersectionObserver创建观察器实例,通过检查图片是否出现在可视区域,来实现懒加载。 16.png

效果如下。

99.gif

2.5 滚动底部自动加载数据

实现滚动到底部自动加载更多数据 这是使用到antd-mobil的InfiniteScroll,它有如下属性

  • hasMore:是否还有更多内容
  • loadMore:加载更多的回调函数
  • threshold:触发加载事件的滚动触底距离阈值,单位为像素

用户想看到新的数据时,可以上滑页面自动加载数据。当 hasMore 属性为 true 时,用户页面滚动到底部 threshold (默认为 250px)时无限滚动组件会调用定义的 loadMore 函数。代码如下:

55.png 并配和上文的requestKey来实现当首次进入某个面板未请求数据前不提供该滚动组件,否则在第一次进入某个面板时该滚动组件会先执行。来看下当前效果吧。

100.gif 可以看到当滚动到底部时会去请求数据,并将根据新数据创建新的信息卡项,当然是通过信息卡项中的key来决定是否要新建,像之前就创建好的信息卡项在这次就不会新建了。

总结

至此该商品信息列表组件开发就完成了,另外还有三个通用组件,商品信息卡项组件直播信息卡项组件视频信息卡项组件。这四个组件在以后都会经常被用到的。接下来对本次组件开发过程进行总结

  • State Hook:它让我们在 React 函数组件上添加内部 state,通过useState()方法我们可以定义当前 state 以及更新 state 的函数。

  • Effect Hook:它可以告诉 React 组件需要在渲染后执行某些操作。React 会保存你传递的函数(我们将它称之为 “effect”),并且在执行 DOM 更新之后调用它。默认情况下,它在第一次渲染之后和每次更新之后都会执行。但同时,我们可以给它的第二个参数传入一个数组,当数组里的内容发生改变时effectc才会再执行。

  • key值:在map生成新的组件时,记得添加独一无二的key,因为每当一个列表重新渲染时,React 会根据每一项列表元素的 key 来检索上一次渲染时与每个 key 所匹配的列表项。如果 React 发现当前的列表有一个之前不存在的 key,那么就会创建出一个新的组件。如果 React 发现和之前对比少了一个 key,那么就会销毁之前对应的组件。如果一个组件的 key 发生了变化,这个组件会被销毁,然后使用新的 state 重新创建一份。

  • styled-components:css in js 。styled-components 为您的样式生成唯一的类名。您永远不必担心重复、重叠或拼写错误。很难知道类名是否在您的代码库中的某处使用。styled-components 让它变得显而易见,因为每一个样式都与特定的组件相关联。如果组件未使用(工具可以检测到)并被删除,则其所有样式都会随之删除。根据组件的 props 或全局主题调整组件的样式简单直观,无需手动管理数十个类。本次就通过props将背景图片自定义参数化传入。

  • antd-mobile:移动端的常用组件库,比如本次用的Tabs,Skeleton,Space。用就对了。

  • font-awesome:Font Awesome 字体为我们提供可缩放矢量图标,它可以被定制大小、颜色、阴影以及任何可以用CSS的样式。用就对了

Next

商品信息卡列表组件开发完毕,下一步将会开始搭建商城主页面,并将Router安排上。
本次项目地址github.com/hunag-moure…
gh-pageshunag-mouren.github.io/dy_mall/

猜你喜欢

转载自juejin.im/post/7114655551820136485