高效开发H5页面: 常用业务组件封装指南

791 阅读6分钟

图片上传:

自动化构建工具: gulp - 配置文件gulpfile

  • less 转 css 输出

  • 输出图片,图片过小不做压缩

          // less 转 css 输出
          gulp.task('Panda', () => {
              return gulp.src('./src/*.less')
                  .pipe(less())
                  .pipe(gulp.dest('./dist'))
          })
          // 输出图片,图片过小不做压缩
          gulp.task('Monkey',()=>{
              return gulp.src(['./src/image/*.svg','./src/image/*.png'])
                  .pipe(gulp.dest('./dist/image'))
          })
    

技术: react、UI组件库

开发思路:

    1. 主文件代码逻辑:负责组件的UI和交互开发,包括图片点击预览查看,删除图片等操作;
    2. 图片上传接口和图片压缩 两个功能,代码逻辑较多,单独放置在两个功能模块,主文件引用;
    3. 另外还有新建less文件,img文件夹放置svg、png图片
    4. 采用typeScript开发
    5. 组件参数包括comPressSize:Number类型,表示大于给定值进行图片压缩; baseUrl: String类型,图片上传的接口

开发流程:

  • 图片上传组件子模块单独开发,封装了input,type="file",onChange传入了图片上传的事件处理函数,event.target.files可以拿到我们选中的图片,multiple为true时可多选,H5中多选这个属性安卓不兼容,所以需要做下判断。

  • 选中的图片会调用上传接口,上传成功后存放到一个列表中,让后将这个图片列表用map展示出来,这里面做了判断,大于或等于3张图片就不展示图片上传组件的入口。

  • 然后已经上传的图片,展示列表中,也可以对这些图片删除、预览操作,预览是用了previewImg的一个UI组件,删除就之前通过filter过滤掉。

  • 图片上传的格式我们是设置为new Blob,然后把它存放到formdata里面,然后就作为data的数据上传,上传的url也是可以自定义的。

  • 图片上传时我们有个操作,是对大于8M的图片做压缩处理,因为我们服务端不支持大于8M的图片上传。这里面压缩是用的canvas,canvs最终生成的是base64的格式,如果还需要将base64转换为File格式。如果小于8M就正常上传。

  • 这里面还做了一些判断,像上传时loading会设置为true,防止又点击了图片上传组件,只有上传成功才重新设置为false。

  • 图片大小:我们input选中图片后,获得的是一个对象,里面有个size,image.size / 1024 就是图片的KB了。然后就可以作比较。

上传的图片列表格式:const form = new FormData()

单张图片格式:

          const file = new Blob([imgFileType], {  // IOS11以下, 使用File API, 无法正确传递数据;使用Blob则无问题
              type: image.type
          })
                                

传入form:

    form.append('file${i}', file, name)
    

base64转File:

        export function dataURLtoFile(dataUrl, fileName){
                var arr = dataUrl.split(','), mime = arr[0].match(/:(.*?);/)[1],
                    bstr = atob(arr[1]), n = bstr.length, u8arr = new Uint8Array(n)
                        while(n--){
                            u8arr[n] = bstr.charCodeAt(n)
                        }
                    return new File([u8arr], fileName, {type:mime})
           }

实际开发遇到的问题:

  • IOS11 以下, 使用File API, 无法正确传递数据;使用Blob则无问题
  • 图片上传进度展示
  • 多选图片上传失败,图片展示列表清空
  • multiple导致的兼容性问题

海报生成:

技术:ReactDOMServer、 html2canvas、 typeScript

开发思路:

  1. 先编写海报的html代码和样式,接收外部传入的imgUrl等各种商品信息。

  2. 编写reactElementToImage方法,将海报组件element用iframe封装,接着html2canvas绘制。

  3. 绘制的canvas图片需要从base64格式转换为file格式,然后存放到formdata里面,调用接口,拿到图片地址。

开发流程:

  1. 海报组件向外暴露一个方法,接受sku商品信息,方法用async封装,await等待reactElementToImage完成后,返回海报地址。

  2. 重点为reactElementToImage方法编写,里面是通过使用html2canvas对iframe进行绘制,拿到base64格式的文件后,转换为File格式。接着将file放到 formData 里面,传给接口,拿到返回的图片url。

  3. iframe:是将海报设计的ReactElement嵌入到iframe中:

         createElement('iframe')
         // iframe.style设置
         const renderString = ReactDOMServer.renderToStaticMarkup(renderComponent)
         const xmlTree = new DOMParser().parseFromString(renderString, 'text/html')
         iframe.contentDocument.body.appendChild(xmlTree.body.firstElementChild)
         return iframe
         
    
  4. 使用getRenderElement获取iframe.contentDocument.body

  5. 调用html2canvas:

         html2canvas(renderDom, { // remderDom 为 iframe.contentDocument.body
             scrollX: 0,
             scrollY: 0,
             useCORS: true,
             backgroundColor: 'null'
         })
    
  6. canvas.toDataURL('image/png')将返回的canvas设置为png

  7. 将base64转换File格式,调用接口,拿到返回图片url

自动化埋点:

开发背景:

    1.项目埋点多且杂,增加开发成本
    2.各页面埋点初始化没统一、使用形式不一致
    3.部分埋点过于冗余,灵活性较低
    4.手动代码埋点虽然使用起来灵活,但是开发成本较高,一旦上线就很难修改

埋点类型及优先级:

  • 点击埋点(click)
  • 浏览埋点(pageView/pageLeave)
  • 曝光埋点(expose)

优化及关注点:

    1.埋点支持自动化+手动双模式
    2.统一、规范、精简各项目埋点使用
    3.埋点数据上报具有高灵活性,可动态变动
    4.数据结构—>规范、埋点接口—>易用、上报策略—>可靠
    

具体实现: docs.qq.com/doc/DWmRwSE…

点击埋点

实现目标:

埋点可直接添加到dom元素上实现自动化监听上报,也可手动处理相关动态参数后上报。

实现细节:

自动化监听data-track属性上报。将 "click" 埋在 dom 节点上,js 监听 dom 节点的点击事件,用户点击到该 dom 时,js 解析该 dom 上的数据,匹配JSON配置页面埋点事件进行上报。

浏览埋点(浏览/离开)

实现目标:

自动化上报prePage页面的pageLeave上报,以及当前页面的pageView事件。

实现细节:

通过hash改变了url,会触发hashchange事件,只要监听hashchange事件,就能捕获到通过hash改变url的行为。

曝光埋点

实现目标:

Expose模块包裹需监听曝光模块进行上报。

实现细节:

使用Expose模块包裹需要曝光的元素

页面绑定埋点对象

  • 多页面的项目,只需一个配置文件,配置文件内以页面为单位配置多个页面对象。(!!!页面名称跟路由对应)
  • 路由监听页面hash变化,除了触发pageView|pageLeave上报,也将会绑定页面对象(公参等)

埋点数据初始化及动态变化

  • 相同的埋点字段,取值优先级: 项目 < 页面 < 事件(配置文件固定)< 事件(手动传值|动态)
  • 项目、页面公参支持在配置文件中配置,埋点事件可传公参进行覆盖并上报,但不会改变原项目、页面配置的公参。
  • 支持API:改变页面公参API、改变项目公参API