今天要写的H5朋友圈也是基于笔者开发的cms搭建的,我将仿照微信朋友圈,带大家一起开发一个能发布动态(包括图片上传)的朋友圈应用。有关服务端部分笔者在本文中不会细讲,如果感兴趣的朋友可以参考我的文章:
基于Koa + React + TS从零开发全栈文档编辑器(进阶实战)。
朋友圈列表
查看朋友圈图片
发布动态
在开始文章之前,笔者想先粗略总结一下开发H5移动端应用需要考虑的点。对于任何移动端应用来说,我们都要考虑如下问题:
以上介绍的只是移动端优化的凤毛麟角,有关前端页面性能优化的方案还有很多,笔者在之前的文章中也详细介绍过,下面我们进入正文。
笔者将采用umi作为项目的前端集成解决方案,其提供了非常多了功能,使用起来也非常方便,并且对于antd和antd-mobile自动做了按需导入,所以熟悉react的朋友可以尝试一下,本文的方案对于vue选手来说也是适用的,因为任何场景下,方法和思维模式都是跨语言跨框架的。
目前umi已经升级到3.0,本文所使用的是2.0,不过差异不是很大,大家可以放心使用3.0. 具体使用步骤如下
// umi2.0
// 新建项目目录
mkdir friendcircle
// 创建umi项目
cd friendcircle
yarn create umi
// 安装依赖
yarn
yarn add antd-moblie
这样一个umi项目就创建好了。
在项目创建好之后,我们先分析我们需要用到那些技术点:
笔者在设计时研究了很多懒加载实现方式,目前采用react-lazy-load来实现,好处是支持加载事件通知,比如我们需要做埋点或者广告上报等功能时非常方便。当然大家也可以自己通过observer API去实现,具体实现方案笔者在几个非常有意思的javascript知识点总结文章中有所介绍。具体使用方式:
<LazyLoad key={item.uid} overflow height={280} onContentVisible={onContentVisible}>
// 需要懒加载的组件
<ComponentA />
</LazyLoad>
react-lazy-load使用方式非常简单,大家不懂的可以在官网学习了解。
目前在朋友圈列表页有个核心的需求就是我们需要在用户传入不同数量的图片时,要有不同的布局,就像微信朋友圈一样,主要作用就是为了让用户尽可能多的看到图片,提高用户体验,如下图所示例子:
我们用js实现起来很方便,但是对性能及其不友好,而且对于用户发布的每一条动态的图片都需要用js重新计算一遍,作为一个有追求的程序员是不可能让这种情况发生的,所以我们用css3来实现,其实有关这种实现方式笔者在之前的css3高级技巧的文章中有详细介绍,我们这里用到了子节点选择器,具体实现如下:
.imgItem {
margin-right: 6px;
margin-bottom: 10px;
&:nth-last-child(1):first-child {
margin-right: 0;
width: 100%;
}
&:nth-last-child(2):first-child,
&:nth-last-child(3):first-child,
&:nth-last-child(4):first-child,
&:first-child:nth-last-child(n+2) ~ div {
width:calc(50% - 6px);
height: 200px;
overflow: hidden;
}
&:first-child:nth-last-child(n+5),
&:first-child:nth-last-child(n+5) ~ div {
width: calc(33.33333% - 6px);
height: 150px;
overflow: hidden;
}
}
以上代码中我们对于一张图片,2-4张图片,5张以上的图片分别设置了不同的尺寸,这样就可以实现我们的需求了,还有一个要注意的是,当用户上传不同尺寸的图片时,有可能出现高低不一致的情况,这个时候为了显示一致,我们可以使用img样式中的object-fit属性,有点类似于background-size,我们可以把img便签看作一个容器,里面的内容如何填充这个容器,完全用object-fit来设置,具体属性如下:
所以为了让图片保持一致,我们这么设置img标签的样式:
img {
width: 100%;
height: 100%;
object-fit: cover;
}
FP是笔者开源的一个表单配置平台,主要用来定制和分析各种表单模型,界面如下:
通过该平台可以定制各种表单模版并分析表单数据。这里朋友圈功能我们只需要配置一个简单的朋友圈发布功能即可,如下:
由于笔者电脑数据丢失导致代码部分损失,感兴趣可以了解一下。
对于朋友圈另一个重要的功能就是能查看每一条动态的图片,类似于微信朋友圈的图片查看器,这里笔者采用第三方开源库rc-viewer来实现,具体代码如下:
<RcViewer options={{title: 0, navbar: 0, toolbar: 0}} ref={imgViewRef}>
<div className={styles.imgBox}>
{
item.imgUrls.map((item, i) => {
return <div className={styles.imgItem} key={i}>
<img src={item} alt=""/>
</div>
})
}
</div>
</RcViewer>
由上代码可知我们只需要在RcViewer组件里写我们需要的查看的图片结构就行了,其提供了很多配置选项可是使用,这里笔者在option中配置了title,navbar,toolbar均为0,意思是不显示这些功能,因为移动端只需要有基本的查看,缩放,切换图片功能即可,尽可能轻量化。效果如下:
当我们点击动态中的某一张图片时,我们可以看到它的大图,并通过手势进行切换。
实现文件上传,除了采用antd的upload组件,我们也可以结合http请求库和formdata来实现,为了支持多图上传并保证时机,我们采用async await函数,具体代码如下:
const onSubmit = async () => {
// ... something code
const formData = new FormData()
for(let i=0; i< files.length; i++) {
formData.delete('file')
formData.append('file', files[i].file)
try{
const res = await req({
method: 'post',
url: '/files/upload/tx',
data: formData,
headers: {
'Content-Type': 'multipart/form-data'
}
});
// ... something co
}catch(err) {
Toast.fail('上传失败', 2);
}
}
其中req是笔者基于axios封装的http请求库,支持简单的请求/响应拦截,感兴趣的朋友可以参考笔者源码。
如果想学习更多H5游戏, webpack,node,gulp,css3,javascript,nodeJS,canvas数据可视化等前端知识和实战,欢迎在公号《趣谈前端》加入我们的技术群一起学习讨论,共同探索前端的边界。