如果想在所有的地方都能访问同一个变量,那么应该怎么办呢?
在实践中这种场景很多,比如全局的状态管理。
但前面我们介绍过,在实际开发中,不要轻易使用全局变量,那又该怎么办呢?模块化的思维能够帮助我们解决这个问题。
模块化开发是目前最流行,也是必须要掌握的一种开发思路。而模块化其实是建立在单例模式基础之上的,因此模块化开发和闭包息息相关。
目前流行的模块化开发思路,无论是require,还是ES6的modules,虽然实现方式不同,但是核心思路一样。因此为了方便大家理解模块化的思维,这里就以建立在函数自执行基础上的单例模式为例,一起来感受一下模块化开发的魅力。
第一,请记住:每一个单例就是一个模块。
其实,你也知道,每一个文件也是一个模块。而这里把每一个单例模式假想成一个单独的文件即可。定义一个模块,而变量名就是模块名。
var module_test = (function() {
})();
第二,每一个模块要想与其他模块交互,则必须有获取其它模块的能力,例如requirejs中的require与ES6modules中的import。
//require
var $ = require('jquery');
//es6 modules
import $ from 'jquery';
第三,每一个模块都应该有对外的接口,以保证与其他模块交互的能力。这里直接使用return返回一个字面量对象的方式来对外提供接口。(你可以回顾一下现在那些模块的导出是多么便捷)
var module_test = (function() {
...
return {
testfn1: function() {},
testfn2: function() {}
}
})();
现在我们结合一个简单的案例来走一遍模块化开发的流程。这个例子想要实现的功能是每个一秒,body的背景色就随着一个数字的递增在固定的三种颜色之间切换。
(1)首先创建一个专门用来管理全局状态的模块。这个模块中有一个私有变量保存了所有的状态值,并对外提供了访问与设置这个私有变量的方法,代码如下:
var module_status = (function() {
var status = {
number: 0,
color: null
}
var get = function(prop) {
return status[prop];
}
var set = function(prop,value) {
status[prop] = value;
}
return {
get,
set
}
})();
(2)在来创建一个模块,这个模块专门负责body背景颜色的改变。
var module_color = (function() {
//假装用这种方式执行第二步引入模块
//类似 import state from 'module_status';
var state = module_status;
var colors = ['yellow','#ccc','red'];
function render() {
var color = colors[state.get('number') % 3];
document.body.style.backgroundColor = color;
}
return {
render
}
})();
在这个模块,引入了状态管理的模块,并且将颜色的管理与改变方式都定义在该模块中,因此在使用时我们只需调用render方法就可以了。
接下来我们还需要创建另外一个模块来负责显示当前的number的值,用于参考对比。
var module_context = (function() {
var state = module_status;
function renderNumber() {
document.body.innerHTML = 'now number is' + state.get('number');
}
return {
renderNumber
}
})()
这些功能模块都创建完毕后,最后我们只需创建一个主模块即可。这个主模块的目的就是借助功能模块,来实现我们想要的效果。
var module_main = (function() {
var state = module_status;
var color = module_color;
var context = module_context;
setInterval(function() {
var newNumber = state.get('number') + 1;
state.set('number',newNumber);
color.render();
context.renderNumber();
},1000)
})();
好了,整一个模块化就完成了。你可以将整段代码插入到一个HTML文件script标签下即可看到展示效果。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>change yourself</title>
</head>
<body>
<div id="app"></div>
</body>
</html>
<script>
var module_status = (function() {
var status = {
number: 0,
color: null
}
var get = function(prop) {
return status[prop];
}
var set = function(prop,value) {
status[prop] = value;
}
return {
get,
set
}
})();
var module_color = (function() {
//假装用这种方式执行第二步引入模块
//类似 import state from 'module_status';
var state = module_status;
var colors = ['yellow','#ccc','red'];
function render() {
var color = colors[state.get('number') % 3];
document.body.style.backgroundColor = color;
}
return {
render
}
})();
var module_context = (function() {
var state = module_status;
function renderNumber() {
document.body.innerHTML = 'now number is' + state.get('number');
}
return {
renderNumber
}
})();
var module_main = (function() {
var state = module_status;
var color = module_color;
var context = module_context;
setInterval(function() {
var newNumber = state.get('number') + 1;
state.set('number',newNumber);
color.render();
context.renderNumber();
},1000)
})();
</script>
运行以上完整代码,就可以看到如果效果啦
当然它是每个一秒变一次的....
这些都是我以往的学习笔记。如果您看到此笔记,希望您能指出我的错误。有这么一个群,里面的小伙伴互相监督,坚持每天输出自己的学习心得,不输出就出局。希望您能加入,我们一起终身学习。欢迎添加我的个人微信号:Pan1005919589