先来说说我对“组件”的定义。
前端开发过程中,可能会用到一些第三方插件,比如 jBox 或者 asDatepicker:这些插件会附带一个 css 文件用来定义样式。于是我们在使用这些插件的时候,页面看上去是这样的:
<link rel="stylesheet" href="jBox.css">
<script src="jBox.js"></script>
这里有一个小问题:既然需要加载 jBox.js 的时候总是需要加载 jBox.css 的,那为什么不将 jBox.css 写进 jBox.js 呢?这样可以减少一次 HTTP 请求。
但是总所周知,在 js 里的长文本是很难维护的,所以最好的解决方案是:开发时分成多个文件,但在生产环境时合并成一个文件;相关的文件最好放在一处,比如说放在同一个文件夹下——这就是我所认为的“组件”的定义。
require.js 配合 text插件与 r.js 文件组合工具就可以实现上面的需求了,只是 r.js 的配置有点繁琐:它是奔着将所有的依赖文件都合并在一起的目标去的,而我这里的需求是只想合并组件而已,为此我不得不为每一个组件进行单独配置,这肯定是不利于维护的。
于是,我自己动手写了一个小工具:requirejs-components-combine,它的作用单一而简单,但可以很好的满足我的需求。
举个例子。我有一个组件叫 modal-box,这个组件的作用是取代浏览器的 alert() 与 confirm() 方法,它的文件结构如下:
modal-box/
|----- template.html(模板)
|----- modal.css(样式)
------ index.js (逻辑)
下面简单列出这三个文件的内容: template.html
<!-- 前略 -->
<body>
<div class="modal-box">Hello World</div>
</body></html>
modal.css
.modal-box { color:red; display:none }
index.js
define(['jquery', 'text!template.html!strip', 'text!modal.css'], function ($, HTML, CSS) {
var $modal = $( HTML ).appendTo( 'body' );
$('<style>' + CSS + '</style>').appendTo( 'head' );
return {
show: function () { $modal.show(); } ,
hide: function () { $midal.hide(); }
};
} );
最后,我们在代码里应该是这样使用它的: test.js
require( ['modal-box/index'] , function (modal) {
modal.show();
});
这样,开发时避免了将模板与样式直接写进 index.js 里,而在上线前,就可以使用我的小工具进行合并了,合并之后的文件结构是这样的:
modal-box/
|----- template.html(模板)
|----- modal.css(样式)
------ index.js (逻辑)
modal-box.js(合并后的文件)
modal-box.js 的内容是:
define('_template.html',function(){return'<div class="modal-box">Hello World</div>'});
define('_modal.css',function(){return'.modal-box { color:red; display:none }'});
define( [ 'jquery' , '_template.html' , '_modal.css' ] , function ( $ , HTML , CSS ) {
var $modal = $( HTML ).appendTo( 'body' );
$('<style>' + CSS + '</style>').appendTo( 'head' );
return {
show:function () { $modal.show(); } ,
hide:function () { $midal.hide(); }
};
} );
最后,我们还需要将 test.js 里面的引用从 modal-box/index 改成 modal-box;我们可以在开发时就写一个“代理模块”,避免每次组合完成后都需要更改模块引用:
开发时就先写一个 modal-box.js
define(['modal-box/index'],function (m) { return m; });
组件合并工具会覆盖这个“代理模块”,那么在开发时,test.js就可以放心的引用 modal-box ,不需要更改模块引用了。
就是这样了!