在上篇文章我们简单实现了一个 jQuery 的基础结构,不过为了顺应潮流,这次咱把它改为模块化的写法,此举得以有效提升项目的可维护性,因此在后续也将以模块化形式进行持续开发。
模块化开发和编译需要用上 ES6 和 rollup,具体原因和使用方法请参照我之前的《冗余代码都走开——前端模块打包利器 Rollup.js 入门》一文。
本期代码均挂在我的github上,有需要的童鞋自行下载。
1. 基本配置
为了让 rollup 得以静态解析模块,从而减少可能存在的冗余代码,我们得用上 ES6 的解构赋值语法,因此得配合 babel 辅助开发。
在目录下我们新建一个 babel 配置“.babelrc”:
{ "presets": ["es2015-rollup"] }
以及 rollup 配置“rollup.comfig.js”:
var rollup = require( 'rollup' ); var babel = require('rollup-plugin-babel'); rollup.rollup({ entry: 'src/jquery.js', plugins: [ babel() ] }).then( function ( bundle ) { bundle.write({ format: 'umd', moduleName: 'jQuery', dest: 'rel/jquery.js' }); });
其中入口文件为“src/jquery.js”,并将以 umd 模式输出到 rel 文件夹下。
别忘了确保已安装了三大套:
npm i babel-preset-es2015-rollup rollup rollup-plugin-babel
后续咱们直接执行:
node rollup.config.js
即可实现打包。
2. 模块拆分
从模块功能性入手,我们暂时先简单地把上次的整个 IIFE 代码段拆分为:
src/jquery.js //出口模块 src/core.js //jQuery核心模块 src/global.js //全局变量处理模块 src/init.js //初始化模块
它们的内容分别如下:
jquery.js:
import jQuery from './core'; import global from './global'; import init from './init'; global(jQuery); init(jQuery); export default jQuery;
core.js:
var version = "0.0.1", jQuery = function (selector, context) { return new jQuery.fn.init(selector, context); }; jQuery.fn = jQuery.prototype = { jquery: version, constructor: jQuery, setBackground: function(){ this[0].style.background = 'yellow'; return this }, setColor: function(){ this[0].style.color = 'blue'; return this } }; export default jQuery;
init.js:
var init = function(jQuery){ jQuery.fn.init = function (selector, context, root) { if (!selector) { return this; } else { var elem = document.querySelector(selector); if (elem) { this[0] = elem; this.length = 1; } return this; } }; jQuery.fn.init.prototype = jQuery.fn; }; export default init;
global.js:
var global = function(jQuery){ //走模块化形式的直接绕过 if(typeof module === 'object' && typeof module.exports !== 'undefined') return; var _jQuery = window.jQuery, _$ = window.$; jQuery.noConflict = function( deep ) { //确保window.$没有再次被改写 if ( window.$ === jQuery ) { window.$ = _$; } //确保window.jQuery没有再次被改写 if ( deep && window.jQuery === jQuery ) { window.jQuery = _jQuery; } return jQuery; //返回 jQuery 接口引用 }; window.jQuery = window.$ = jQuery; }; export default global;
留意在 global.js 中我们先加了一层判断,如果使用者走的模块化形式,那是无须考虑全局变量冲突处理的,直接绕过该模块即可。
执行打包后效果如下(rel/jquery.js):
(function (global, factory) { typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : typeof define === 'function' && define.amd ? define(factory) : (global.jQuery = factory()); }(this, function () { 'use strict'; /** * Created by vajoy on 2016/8/1. */ var version = "0.0.1"; var jQuery = function jQuery(selector, context) { return new jQuery.fn.init(selector, context); }; jQuery.fn = jQuery.prototype = { jquery: version, constructor: jQuery, setBackground: function setBackground() { this[0].style.background = 'yellow'; return this; }, setColor: function setColor() { this[0].style.color = 'blue'; return this; } }; var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol ? "symbol" : typeof obj; }; /** * Created by vajoy on 2016/8/2. */ var global$1 = function global(jQuery) { //走模块化形式的直接绕过 if ((typeof exports === 'undefined' ? 'undefined' : _typeof(exports)) === 'object' && typeof module !== 'undefined') return; var _jQuery = window.jQuery, _$ = window.$; jQuery.noConflict = function (deep) { //确保window.$没有再次被改写 if (window.$ === jQuery) { window.$ = _$; } //确保window.jQuery没有再次被改写 if (deep && window.jQuery === jQuery) { window.jQuery = _jQuery; } return jQuery; //返回 jQuery 接口引用 }; window.jQuery = window.$ = jQuery; }; /** * Created by vajoy on 2016/8/1. */ var init = function init(jQuery) { jQuery.fn.init = function (selector, context, root) { if (!selector) { return this; } else { var elem = document.querySelector(selector); if (elem) { this[0] = elem; this.length = 1; } return this; } }; jQuery.fn.init.prototype = jQuery.fn; }; global$1(jQuery); init(jQuery); return jQuery; }));