图片上传:
自动化构建工具: 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
开发思路:
-
先编写海报的html代码和样式,接收外部传入的imgUrl等各种商品信息。
-
编写reactElementToImage方法,将海报组件element用iframe封装,接着html2canvas绘制。
-
绘制的canvas图片需要从base64格式转换为file格式,然后存放到formdata里面,调用接口,拿到图片地址。
开发流程:
-
海报组件向外暴露一个方法,接受sku商品信息,方法用async封装,await等待reactElementToImage完成后,返回海报地址。
-
重点为reactElementToImage方法编写,里面是通过使用html2canvas对iframe进行绘制,拿到base64格式的文件后,转换为File格式。接着将file放到 formData 里面,传给接口,拿到返回的图片url。
-
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 -
使用getRenderElement获取iframe.contentDocument.body
-
调用html2canvas:
html2canvas(renderDom, { // remderDom 为 iframe.contentDocument.body scrollX: 0, scrollY: 0, useCORS: true, backgroundColor: 'null' }) -
canvas.toDataURL('image/png')将返回的canvas设置为png
-
将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