持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第1天,点击查看活动详情
前言
React
声明式
:React 使创建交互式 UI 变得轻而易举。为你应用的每一个状态设计简洁的视图,当数据改变时 React 能有效地更新并正确地渲染组件。组件化
:创建拥有各自状态的组件,再由这些组件构成更加复杂的 UI。组件逻辑使用 JavaScript 编写而非模版,因此你可以轻松地在应用中传递数据,并使得状态与 DOM 分离。
本次通过开发抖音商城商品信息列表组件
,走进React的怀抱。
不多说,先看效果gh-pageshunag-mouren.github.io/dy_mall/
再看项目架构
1. 组件设计与功能需求
1.1 组件设计
首先将商品信息卡列表组件
细化,分为头部tabs切换部分
和信息卡列表部分
,其中信息卡列表部分包含有商品信息卡项
、直播信息卡项
、视频信息卡项
,且各项信息卡项包含两种状态,分别为数据加载前的状态
和数据加载后的状态
。即:
头部tabs切换部分
商品信息卡项
直播信息卡项
视频信息卡项
如下图所示。 基于以上我们有如下组件蓝本的代码:
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”的类名(如下图所示),进而被选中时高亮。
那我们只需要把activeKey值修改为我们将选中的面板的key值就可以激活它,这时我们就可以借助onChange属性,在回调函数中修改activeKey的值。但是activeKey作为属性不好在回调函数中操作,那不妨利用一个中间变量,修改中间变量的值,再把中间变量的值传给activeKey。考虑到后续在切换面板时要显示相应的内容,那么我们这里使用State Hook,利用useState()方法返回的state值作为中间变量以及更新state值的函数来修改该值,以达到更新activeKey值得目的,进而实现Tabs切换。实现代码如下。
考虑到我们当前定义的从useState()方法解构出来的
[activityKey,setActivityKey]
不仅仅只会在GoodCardList组件中被使用,我们应当将其放在父组件当中。于是我们通过父组件给子组件传参
,让GoodCardList组件得到这些属性。代码将修改如下。
至此Tabs头部切换完成,效果如下。
2.2 信息卡列表部分实现
由上文可知信息卡列表部分其实是由商品信息卡项
、直播信息卡项
、视频信息卡项
组成,就实际情况而言可视该三项内容为通用组件
。这三项异曲同工,不妨就以商品信息卡为例。这时我们需要进行数据请求,数据方面我们通过在线接口工具fastmock组织,fastmock可以让你在没有后端程序的情况下能真实地在线模拟 ajax 请求,实现前后端分离。然后我们通过axios
进行请求数据,axios是一个基于promise 的 HTTP 库。同时使用async函数与await操作符同步化获取数据过程。 在src目录下新建一个api文件夹,在其之下新建request.js文件,该文件用于做请求方面的工作,我们数据请求的代码就封装在其中。
数据请求一般都在页面级别组件,请求到的数据通过参数传递给子组件。这时我们就要请出Effect Hook,它可以告诉React组件需要在渲染后执行某些操作。React 会保存你传递的函数(我们将它称之为 “effect”),并且在执行DOM更新之后调用它。默认情况下,它在第一次渲染之后和每次更新之后都会执行。但我们可以通过给它的第二参数(是个数组)来控制它,如果这个数组里的内容在两次重渲染之间没有发生变化,就可以通知 React 跳过对这个effect 的调用;如果发生了改变就会再次对这个effect进行调用。那么我们在切换不同面板时需要请求不同的内容,我们就可以把请求数据的过程放在Effect中,并通过前文的定义的State中的activityKey来实现面板切换时是否需要请求数据。
GoodsCardList组件内接收数据后,根据数据生成(map)信息卡列表里各项内容,同时别忘了在map列表里的数据内容时,要给每一项添加一个独一无二的key值
。
因为每当一个列表重新渲染时,React 会根据每一项列表元素的 key 来检索上一次渲染时与每个 key 所匹配的列表项
。如果 React 发现当前的列表有一个之前不存在的 key,那么就会创建出一个新的组件。如果 React 发现和之前对比少了一个 key,那么就会销毁之前对应的组件。如果一个组件的 key 发生了变化,这个组件会被销毁,然后使用新的 state 重新创建一。(这里我在fastmock组织的数据中给每条数据都自动生成了一个独一无key)
商品信息卡项组件的实现
至此商品信息卡列表组件开发过半,来看看目前效果。
2.3 增加loading状态
发现每次切换面板的时候,页面需要过一段时间才会显示内容,用户体验不好。这时由于数据还在请求中,数据请求完成后才渲染出该列表内容,那么我们这时需要添加一个loading状态,在数据请求数显示loading状态的页面内容。
增加一个新的State Hook ,[loading,setLoading]=useState(false)
来控制是否需要loading,[requestKey,setRequestKey]=useState([])
来记录某个面板是否被访问过,访问过后再访问不会再出现loading状态。
并给商品信息卡项
、直播信息卡项
、视频信息卡项
加入loading状态时显示的框架内容。其种loading状态显示的框架屏内容使用了antd-mobile的Skeleton,它可以在需要等待加载内容的位置提供一个占位图形组合。具体如下
看看现在的效果
2.4 实现图片懒加载
考虑实际应用场景,我们不妨在加上懒加载,当图片未出现在可视区域是用占位图代替,进入可视区域显示图片 使用IntersectionObserver创建观察器实例,通过检查图片是否出现在可视区域,来实现懒加载。
效果如下。
2.5 滚动底部自动加载数据
实现滚动到底部自动加载更多数据 这是使用到antd-mobil的InfiniteScroll,它有如下属性
- hasMore:是否还有更多内容
- loadMore:加载更多的回调函数
- threshold:触发加载事件的滚动触底距离阈值,单位为像素
用户想看到新的数据时,可以上滑页面自动加载数据。当 hasMore
属性为 true
时,用户页面滚动到底部 threshold
(默认为 250px)时无限滚动组件会调用定义的 loadMore
函数。代码如下:
并配和上文的requestKey来实现当首次进入某个面板未请求数据前不提供该滚动组件,否则在第一次进入某个面板时该滚动组件会先执行。来看下当前效果吧。
可以看到当滚动到底部时会去请求数据,并将根据新数据创建新的信息卡项,当然是通过信息卡项中的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-pages:hunag-mouren.github.io/dy_mall/