话说上周末看到 一个吐槽腾讯“内部开源”的微博 ,后来我想了想,自己那么骚包的在项目还没做完之前,就在CSSConf 上说我们将来要开源一个名叫 Zorro 的库。结果好几个月过去了还是没有准备好,也就不敢再笑话别人了……
我觉得把东西开源出来之前,有几件事要准备好,不然除了自己刷存在感之外,真的没意义。比如:
印象中我见到的优秀的开源项目,基本都在被大家广泛认识之前,都已经把这些事情打理好了——这也是我一直推崇的。好吧很惭愧,这几点我还都没有做到……
不过在这之前,我愿意在此分享一些自己开发中的心得,跟大家一起探讨相关的话题。
---- 以上是一些比较啰嗦的铺陈 ----
在开发大型应用的时候,难免要用到一些组件化的分解方式。比如:把一个相册浏览界面分解成:“相册列表”和“大图预览”两个区域,“相册列表”又由一个个“相册缩略图”组成,每个“相册缩略图”包含了一个“小图片”以及“预览按钮”、“删除按钮”、“排序按钮”等操作按钮……
而如何管理和划分组件逐渐变成了前端工程里的一门学问。
最简单的分解方式是树形分解,自上而下。比如刚才的那个相册浏览界面的例子。
同时,我们会发现,树形的最末端往往存在着有共性的组件,比如按钮、文本框之类的组件,它们无处不在。这时,就有了所谓的“基础组件”和“业务组件”之分。“基础组件”是共享的,树形结构中的任何一个结点(“业务组件”)都可以直接使用这些“基础组件”。
如果程序的结构再复杂,那么就在“业务”和“基础”之间分更多的层,每一层有自己明确的职能范围,同时,较高层的组件可以自由调用较低层的组件。
配置信息大多是在组件在兼顾通用性抽象和特殊性业务时出现的。好的配置设计可以避免大量重复的组件设计和实现。
较简单的配置信息通常都是组件本身的一些属性 (properties) 或特性 (attributes),在 webcomponents ( polymer ) 的场景下,就是:
<polymer-element name="x-person" attributes="name, age, gender, avatar, ..."> ... </polymer-element>
进一步的,有时候我们需要把上层组件的配置信息带到更下层的组件:
<polymer-element name="x-person-avatar" attributes="avatar"> ... </polymer-element> <polymer-element name="x-person" attributes="name, age, gender, avatar, ..."> <template> ... <x-person-avatar avatar="{{avatar}}"></x-person-avatar> ... </template> ... </polymer-element>
如果一个程序的组件层次太深,则可能出现下面两个问题:
于是顺着这个思路,我们发现,有一种不太起眼的办法在很早的时候就被忽略掉了——这就是全局配置信息。
通常情况下, 和整体应用所处环境相关,同时和上层组件无关的配置适合做全局配置 。
举一个实践中的例子:在开发图片上传组件的时候,我们发现,图片上传组件往往需要一个上传图片的服务器地址,这个地址在固定的用户、固定的应用之中,通常是一致的,只是在不同的应用中,图片可能需要长传到不同的服务器地址。
这种情况下,通过组件的配置字段一层一层向下传递找到图片上传组件显然是很繁琐的。于是我们想了个简单的办法:
<body>
里面) 写入一些 <input type="hidden">
的标签,注明服务器相关配置 于是整个程序变成了:
<polymer-element ...> <script> Polymer({ ready: function () { var inputList = document.querySelectorAll('input[type="hidden"]'); ... } }); </script> </polymer-element> ... <body> <input type="hidden" name="uploadUrl" value="/pathToUpload.do"> ... </body>
这样不管图片上传组件用在哪里,其它组件都不会因此而产生负担,同时这些配置的管理也变得很清晰——这甚至和前端工程师平时和后端工程师协作的流程是完全吻合的:前端负责写好 components,后端负责把 <input type="hidden">
配置好。
我们顺着上面的思路继续想:如果程序中很多组件都有类似的配置需求,那么:
<input type="hidden">
不能被滥用 于是,就有了 Zorro 现在的一个组件: <z-config>
。它的大致功能如下:
<body>
最外层的 <input type="hidden">
配置信息——这显然是和后端工程师约定过的 自从有了这个组件,很多配置相关的问题在 webcomponents 中都显得很轻松了。毫不夸张的说前端工程师和后端工程师的关系也因此不像之前那么紧张了。
后来,我们在配置管理的基础上,加入了更多的实用信息。比如:
location.href
中的字段信息 localStorage
一样提供一块全局共享的键值对空间,方便组件之间共享状态信息 <z-config>
在被创建时,根据不同的场景设置一些初始化数据等 以上这些,构成了今天的 <z-config>
组件
实现机制并不复杂,这里就暂不贴代码出来了,但终归是会开源的,我保证。
说回配置管理本身,它实际上是一种信息在程序和组件之间的流通方式。我们基于对 webcomponents 自身特点和形态的理解,加上业务实践中的一些体会,设计了这样的一个标签。希望给大家一些启发,同时也欢迎大家的讨论和观点。