分享组件是全站通用组件,用于自定义分享信息、统计推荐关系,是营销团队打包输出 MGM 能力的重要工具。
分享组件支持集团内外部应用宿主(微信、金管家、银行、证券等app)中,分享链接/海报到不同渠道(微信、微博、行员app、快乐平安等)。
效果预览
改版前后的截图:
需求背景
改版前分享组件面临的挑战主要有两个:
- UI层面——弹窗面板空间有限,最多仅能展示六个分享图标;
- 扩展性——原先组件打包为单一文件,含有所有宿主的逻辑和依赖文件,随着渠道和业务逻辑增加,文件尺寸越来越大,达到性能瓶颈。
这和之前微海报改版需求背景有共通之处。
方案
针对第一个挑战,我们将页面居中弹窗,改为底部弹层,单行四个,超出则可滚动。
针对第二个挑战,将单文件拆分为二,做了异步加载。并划分为同步模块、异步模块、渠道模块,实现按需加载。
盗用罗帅的结构图:
改版前后的文件构成图:
左边是单一文件,所有依赖和逻辑代码在一个文件中,随着业务逻辑日益复杂和接入的渠道增加,文件尺寸和维护难题渐渐显露。
右边是拆分后的,其中 loader 模块负责环境判断和UI、事件绑定等初始化操作。
可异步执行的逻辑如请求流水号,放到 AsyncMode 类。
渠道专有逻辑,继承 AsyncMode 类,和 jssdk 一起,各个渠道分别打包到 asyncMode**.js 文件中。
文件名中的**,为渠道名称首字母缩写,loader 根据宿主环境判断加载对应的渠道 AsyncMode 文件。比如页面投放到微信,loader 会加载 asyncModeWX.js 文件,投放到金管家app,则加载 asyncModeJGJ.js 文件。这样就实现了不同渠道的逻辑代码隔离,避免互相牵扯,缩减加载的冗余代码。
工程化方面,组件使用 typescript 编写,构建采用 rollup (TS 的类型系统和 ES6 特性支持,特别是 Class 用在新版组件里,真香!)
组件工具库 kits
改版过程中还产生个副产物 kits 工具库,其实就是 zepto 的精简版——由于原来的组件依赖 zepto ,这对于越来越多外部页面接入的通用组件而言显然不合时宜,所以需要剥离依赖。有想过改用原生写法,但这样一来基本就成了纯体力活,且后续维护不便。就想着不如把组件所使用到的 zepto 方法抽离出来,后续还可进一步优化,顺便可以归纳一下组件中常用的库工具方法是哪些。结果如下:
Core
- $()
$.camelCase- $.contains
- $.each
- $.extend
$.fn$.grep$.inArray- $.isArray
- $.isFunction
- $.isNumeric
$.isPlainObject$.isWindow- $.map
$.noop$.parseJSON$.trim- $.type
add- addClass
after- append
- appendTo
- attr
beforechildrenclone- closest
concat- contents
- css
data- each
- empty
- eq
filterfindfirstforEachgethas- hasClass
height- hide
- html
indexindexOf- insertAfter
- insertBefore
islast- map
nextnotoffsetoffsetParentparent- parents
- pluck
position- prepend
- prependTo
prevproppushreadyreduce- remove
- removeAttr
- removeClass
removePropreplaceWithscrollLeftscrollTop- show
siblingssize- slice
- text
toggle- toggleClass
unwrap- val
widthwrapwrapAllwrapInner
Detect
Detect module
Event
$.Event$.proxybinddelegatedieevent.isDefaultPreventedevent.isImmediatePropagationStoppedevent.isPropagationStoppedliveoff- on
onetriggertriggerHandlerunbindundelegate
Ajax
- $.ajax
- $.ajaxJSONP
- $.ajaxSettings
$.get$.getJSON- $.param
$.postload
Form
精简后的代码连注释不到800行,如果不要 ajax 相关方法,挪出所在匿名函数即可,可再减少 300 行代码,算是抄了个轮子吧… 不过还蛮适合组件使用的。
想起七年前在17173参与的第一个组件——登录弹窗组件,直接 <iframe src="javascript:
后面 document.write
style 和 script 标签,实现资源动态、异步加载,极大缩减启动脚本文件尺寸,并实现组件环境和宿主页环境的隔离,还支持到 ie6 版本。方案沿用至今想来是没什么大的问题。竟有些怀念当时满满的草莽气息。