1.js模块化演变过程
1.通过立即执行函数达到隐藏私有变量、暴露公共方法
2.通过require.js sea.js这一类js模块加载框架
3.通过ES6 import实现js模块化
2.代码演示
1.通过立即执行函数达到隐藏私有变量、暴露公共方法
1. 方案1:
(function(exports){
function add(){
}
var flag = true;
var x = 10;
//导出(导出的就相当于全局对象的属性、方法,支持任意一个js模块引用其导出方法、属性)
//其实就是通过window,将方法属性添加到其上面
exports.add = add;
exports.flag = flag;
})(window)
2.方案2
var module = (function(){
function add(){ }
var flag = true;
var x = 10; //导出
return {
add:add,
flag:flag
}
})()
// 这两种方案其实都可,但是第一种方案是将对外暴露的方法挂载到window上,说白了还是全局变量。
第二种方案最多只会暴露一个全局变量,建议第2种。
2.sea.js 使用
// sea.js的使用(sea.js会将一个js文件当做一个模块来看,类似的node里的require、exports,sea.js的
api和node语法很类似,通过require引入,exports导出)
// 语法:
// *****定义一个模块******
// *id:模块id,通常就是当前写的js文件的路径(官方建议id不写)
// *[]:依赖文件:就是使用这个js之前需要提前引入那些文件(官方建议不写)
// *callback:第三个参数为回调函数,有三个参数,其中module是整个模块的信息,包括前面所说
的模块id,模块依赖,可通过console.log(module)查看模块信息
// 正常写法
define(id,[],function(require,exports,module){
})
// 推荐写法
define(function(require,exports,module){
// 引入a模块
var a= require('a');
// 引入b模块
var b = require('b');
// 使用a,b模块导出的方法
a.run();b.sleep();
// 定义自己的方法、变量
var num = 10;
function eat(){
}
// 导出自己的方法、变量
// 方法1(问什么不能用exports指向对象呢,下面会说明)
exports.num = num;
exports.eat = eat;
// 方法2
module.exports = {
num : num,
eat : eat
}
// 方法3
return {
num : num,
eat : eat
}
})
// *****页面内使用sea.js******
直接<script src="js/sea.js"></script>即可
// 引入口文件
<script>
// 一般一个html的入口文件只有一个
seajs.use('init.js') 或 seajs.use('init.js',function(){})
// 如果一个html入口文件有多个
seajs.use(['init.js','x.js']) 或 seajs.use(['init.js','x.js'],function(){})
</script>
// ******sea.js的配置*******
// 注:只会配置常见项,其他的查看api文档
seajs.config({
// base是基础目录,所有的文件都是基于base来查找的,base默认目录是sea.js存在的目录
// 但是建议不设置(除非你的sea.js放置目录很好,否则麻烦的一匹)
// base:''
// 设置别名
alias:{
'jquery':''
}
})
// 说明一下匹配规则,以及建议常见的使用方案
* 在seajs配置中,如果别名的设置 以 相对路径设置的,则其的匹配规则是: "以当前页面use使用的目录为
基准目录,别名目录就以它为基准就行寻找,会导致路径复杂度提高"
* 如果别名设置是以 'app/jquery'这种目录的,则寻找目录的基准目录为base目录
常见使用方案:
1.sea.js源文件放在一个好的位置,什么是好的位置,答案:js文件下的子文件(sea所在目录为js目录)
2.use () :使用相对路径,不用别名(记住,不为use文件设置别名),规则是:当前html引入该use文件的路径
3.require():当使用相对路径时,是相对于当前js文件的,如果是require('app')的,则会寻找config的别名配置
总之一句话,sea的位置放的好,其他就都不是问题了。
常见问题:
1.为什么不能exports = {}这种格式导出?
exports指向了module.exports;真正导出是通过module.exports导出的,exports仅仅是 module.exports的映射,当exports指向了新的对象,与module.exports的联系便断了。(和node一样) 2. sea中使用jq,报错?
jq用一层包裹;
define(function(){
jq源码
return $.noConflict();
})
3. ES6语法
// b.js
import {a} from './a.js'
// a.js
const a = 10;
export {a}