媒介:在慕课网上随着视频《侧边工具栏开辟》做了一遍,用到了jquery操纵DOM,个中,用requirejs治理模块依靠,然后自定义了两个模块它们都依靠jquery,而且个中一个自定义模块依靠另一个,所以要暴露出接口。看完视频开端认识了一下requirejs,以及模块化开辟的观点,在此做一下总结。谢谢慕课网上的先生。
运用模块化开辟的优点:
有用的防备定名争执
声明差别的js文件之间的依靠
能够让我们写出模块化的代码,便于复用
1.需求与目的
这个视频《侧边工具栏开辟》的需求很简单,就是做一个侧边工具条,
牢固定位在页面的某个位置,
在没有把页面向下转动时,显现三个按钮,
当页面向下转动肯定间隔以后,第四个按钮涌现。
点击这个按钮,页面会回到顶部。
鼠标hover到每一个按钮上都有一些响应的动画(CSS3完成这里不写)
2.HTML组织
<div class="toolbar">
<!--第一个微信按钮-->
<a href="javascript:;" class="toolbar-item toolbar-item-weixin">
<span class="toolbar-layer"></span>
</a>
<!--第二个看法反应按钮-->
<a href="javascript:;" class="toolbar-item toolbar-feedback"></a>
<!--第三个app下载按钮-->
<a href="javascript:;" class="toolbar-item toolbar-item-app">
<span class="toolbar-layer"></span>
</a>
<!--第四个回到顶部按钮-->
<a id="backTop" href="javascript:;" class="toolbar-item toolbar-item-top"></a>
</div>
一些申明:
为了让页面显现转动条,须要在这个上述代码下面加很多行
<p></p>
标签以便撑开页面显现转动条。CSS部份视频中先生讲了三种要领,而且用到了SASS,感兴趣的同砚能够去看一下,这里不再赘述。
3.requirejs入门
(1)项目目次组织
个中jquery-3.1.0.js和require.js是在各自官网下载的资本文件。main.js是自定义的进口文件。
(2)加载初始化requirejs
在未引入模块化编写代码之前引入js文件是在<body>
标签之前写多个<script>
标签,依据js文件加载的递次,增加js文件。如今依据requirejs
的异步加载的特征,能够设定一个主进口文件,只用一个<script>
完成其他js文件的加载。
首先是引入requirejs:在
HTML
文件的<body>
标签的之前增加script标签,然后引入
requirejs
文件,然后用data-main
这个属性来引入进口文件。(当用requirejs援用文件时,能够省略js文件的js后缀名,所以此处引入的就是项目目次中的main.js
)
以下:
<script src="js/require.js" data-main="js/main"></script>
(3)requirejs的经常使用要领
requirejs.config
(为模块指定别号,轻易模块的引入
),在进口文件中定义
如这个demo要引入屡次jquery-3.1.0.js
,然则这个名字很长所以能够在进口文件main.js
中为它定义一个别号,以下:
//为jquery模块定义别号
requirejs.config({
paths:{
jquery:'jquery-3.1.0.js'
}
});
requirejs()
要领(将写好的模块举行引入
)
requirejs()吸收两个参数,第一个参数是一个数组,写入要引入的模块的名字。第二个参数是一个回调函数,须要通报一个参数,来替代前面所引入的模块。如:引入jquery模块
requirejs(['jquery'],function($){
//写一段代码考证jquery是不是被准确引入
//将body背景色彩变成赤色
$('body').css('background-color','red');
});
define()
(利用它定义编写模块,然后在响应的处所举行引入。
)define()
吸收三个参数,第一个参数是为本模块定名的值,能够不写,第二个参数示意须要引入的模块,第三个参数是各依靠项胜利加载后所运转的函数,传入的参数与各个依靠项构成对应的关联。
define(
moduleName, //可选,如果此参数不写,则默许运用本模块地点文件的文件名
dependencies, //一个数组,此数组包含着此文件所需的各个依靠项目,这个数组中各项对应的是所依靠文件相对于requirejs库所构成的相对路径文件名。
function(parameters){
//各依靠项胜利加载后所运转的函数
//传入的参数与dependencies数组中的各个依靠项构成对应关联
}
);
(4)demo的基本功用完成
如今先对demo中的基本功用举行完成:
现在的目次组织以下:
首先在HTML中初始化
requirejs
:在</body>
标签之前:<script src="js/require.js" data-main="js/main"></script>
在进口文件main.js中完成基本功用
//1.首先为jquery模块定义别号
requirejs.config({
paths: {
jquery: 'jquery-3.1.0'
}
});
//2.然后用requirejs()要领引入jquery模块完成demo中需求
requirejs(['jquery'],function($){
//为id值为backTop的第四个按钮增加点击回到顶部事宜,当点击时实行move函数回到顶部
$('#backTop').on('click',move);
//监听一下windows对象的转动事宜,
//每次转动都实行函数checkPosition肯定一下位置,是不是抵达设定的临界点,以显现和隐蔽第四个按钮
$(window).on('scroll',function(){
checkPosition($(window).height());
});
//处理bug:在革新页面时也涌现第四个按钮,即页面加载时就搜检一下转动位置
checkPosition($(window).height());
//------------------------------分割线------------------------------------------
//move函数的详细完成,加动画结果
function move(){
$('html, body').animate({
scrollTop:0
},800);
}
//go函数能够马上挪动到顶部
function go(){
$('html, body').scrollTop(0);
}
//checkPosition函数的详细完成
function checkPosition(pos){
if($(window).scrollTop() > pos){
$('#backTop').fadeIn();
}else{
$('#backTop').fadeOut();
}
}
});
分割线以上是实行的代码,分割线以下是写的被挪用的函数。
(5)将功用笼统成模块
上述代码虽然完成了功用,然则存在以下题目:
move和go函数都是抵达顶部的功用,完成的功用很类似,作用如果想在别的处所运用这个功用,就要再举行代码的复制,不轻易功用的复用。所以应当将功用笼统成模块。
完胜利能的功用单一:两个函数都是抵达顶部,如许即使笼统成模块也会遭到很大的限定,所以能够进一步将题目笼统成挪动转动条到指定位置。
第一步:建立一个新模块,用scrollto.js
示意,现在这个demo的目次组织如图:
第二步:将功用笼统成模块,写入scrollto.js
中
//1.先定义这个模块,由于要用到jquery,所以还要引入jquery
define(['jquery'],function($){
//定义组织函数
function ScrollTo(opts){
this.opts = $.extend({},ScrollTo.DEFAULTS,opts); //完成传参掩盖
this.$el = $('html, body');
}
//原型增加要领
ScrollTo.prototype.move = function (){
var opts = this.opts;
this.$el.animate({
scrollTop:opts.dest
},opts.speed);
};
ScrollTo.prototype.go = function(){
this.$el.scrollTop(opts.dest);
};
//定义默许的参数
ScrollTo.DEFAULTS = {
dest:0,
speed:800
};
//定义接口
return {
ScrollTo:ScrollTo
};
});
代码详解:
通报的参数为一个对象,用opts示意
用户没有通报参数时,运用默许的参数,默许参数直接写在ScrollTo组织函数上,相当于构成一个静态属性,然后经由过程jquery的extend()要领举行原型的扩大
完成用户通报参数用之,不通报参数用默许值。jquery的
extend()
要领在原型上增加move和go要领
第三步:在进口文件main.js中引入这个scrollto.js
的模块
requirejs(['jquery','scrollto'], function($,scrollto){
//为了运用scrollto模块,须要实例化一下
var scroll = new scrollto.ScrollTo({
dest:0,
speed:2000
});
//点击回到顶部按钮回到指定位置功用
$('#backTop').on('click', $.proxy(scroll.move, scroll));
});
上述代码中有一点须要注重:
在第6行中,如果增加点击按钮回到指定位置事宜时,这么写:
$('#backTop').on('click', scroll.move)
;此时浏览器控制台会报错:
Uncaught TypeError: Cannot read property 'ScrollTo' of undefined
剖析缘由是由于,在main.js中挪用
scrollto.js
模块中在ScrollTo.prototype.move
原型要领move时,main.js中this指的是ScrollTo的实例,即scrollto,而在语句$('#backTop').on('click', scroll.move)
;中,这个this指代的是id为backTop的这个按钮。处理办法:用jquery供应的要领,直接将this指向scroll对象。
$('#backTop').on('click', $.proxy(scroll.move, scroll))
第四步:一个bug
这时候基本功用虽然完成了,点击底部谁人按钮,传入设定的返回位置和返回的速率,页面能够再次返回顶部指定位置,然则现在还存在一个bug:在点击底部按钮回到顶部指定位置时,如果一连屡次点击这个按钮,则页面回到顶部后就没法再次向下转动页面。
bug剖析:
如果实行的函数如上面第三步中代码,速率设置成较慢的速率2000,那末在返回顶部指定位置时能够屡次点击这个按钮,
如许每次点击按钮事宜都要挪用move要领实行内里的动画,点击多少次,这个动画就要实行多少次。
因此在页面返回顶部后,再次转动页面向下会马上实行返回顶部动画,所以在实行完点击次数的动画之前,用户都没法向下转动。(而且异常耗机能)
处理办法,在转动条正在活动或许已抵达目的地,就不应当实行动画。增加推断。
所以scrollto.js
的代码能够改成以下:
define(['jquery'],function($){
//定义组织函数
function ScrollTo(opts){
this.opts = $.extend({},ScrollTo.DEFAULTS,opts); //完成传参掩盖
this.$el = $('html, body');
}
//原型增加要领
ScrollTo.prototype.move = function (){
var opts = this.opts;
if ($(window).scrollTop() != opts.dest){ //推断是不是抵达指定位置
if(!this.$el.is(':animated')){ //推断是不是在活动
this.$el.animate({
scrollTop:opts.dest
},opts.speed);
}
}
};
ScrollTo.prototype.go = function(){
var dest = this.opts.dest;
if($(window).scrollTop() != dest){
this.$el.scrollTop(dest);
}
};
//定义默许的参数
ScrollTo.DEFAULTS = {
dest:0,
speed:800
};
//定义接口
return {
ScrollTo:ScrollTo
};
});
(6)将返回顶部团体笼统成模块
我们把返回的功用函数move和go都笼统在了scrollto.js
模块中,如今还能够直接把全部返回顶部的功用(包含转动肯定间隔后隐蔽的按钮涌现,和点击按钮以后回到顶部指定位置)
然后在进口文件中只须要引入这个模块(取名叫backtop.js
),这个back.js
须要依靠上面定义的scrollto.js
模块。
所以现在的项目目次以下图:
第一步:如今来写backtop.js
模块
define(['jquery', 'scrollto'], function($, scrollto){
//实行函数部份
function BackTop(el, opts){
this.opts = $.extend({}, BackTop.DEFAULTS, opts);
this.$el = $(el); //el是节点
this.scroll = new scrollto.ScrollTo({
dest: 0,
speed: this.opts.speed
});
this._checkPosition(); //加载时就搜检位置,处理bug
if(this.opts.mode == 'move'){ //是move才实行move函数,其他实行go
this.$el.on('click', $.proxy(this._move, this));
}else{
this.$el.on('click', $.proxy(this._go, this));
}
$(window).on('scroll', $.proxy(this._checkPOsition, this));
}
//定义默许属性部份
BackTop.DEFAULTS = {
mode: 'move',
pos: $(window).height(),
speed: 800
};
//定义功用函数部份
BackTop.prototype._move = function(){
this.scroll.move();
};
BackTop.prototype._go = function(){
this.scroll.go();
};
BackTop.prototype._checkPosition = function(){
if($(window).scrollTop() > this.opts.pos){
this.$el.fadeIn();
}else{
this.$el.fadeOut();
}
};
//暴露模块接口,返回全部对象
return{
BackTop: BackTop
};
});
第二步:scrollto.js坚持稳定
第三步:写main.js进口文件
//定义别号
requirejs.config({
paths: {
jquery: 'jquery-3.1.0'
}
});
//挪用backtop.js模块
requirejs(['jquery', 'backtop'], function($, backtop){
//实例化BackTop
new backtop.BackTop($('#backtop'),{
mode: 'move',
pos:100,
speed: 2000
});
});
4.总结
这个demo中的模块化是如许一种头脑:
首先把功用函数放在一个模块中(move和go)
把全部完胜利能也笼统成一个模块,依靠上一个功用函数模块
末了只须要在进口文件中实例化一下这个最外层的模块,即可完成一系列功用的挪用。
每一个模块都用面向对象的头脑,定义模块而且暴露接口
默许值的用法能够让挪用者拿起就用,能够不必斟酌传参数。