javascript模块化(二)--RequireJS初探

媒介:在慕课网上随着视频《侧边工具栏开辟》做了一遍,用到了jquery操纵DOM,个中,用requirejs治理模块依靠,然后自定义了两个模块它们都依靠jquery,而且个中一个自定义模块依靠另一个,所以要暴露出接口。看完视频开端认识了一下requirejs,以及模块化开辟的观点,在此做一下总结。谢谢慕课网上的先生。

运用模块化开辟的优点:

  1. 有用的防备定名争执

  2. 声明差别的js文件之间的依靠

  3. 能够让我们写出模块化的代码,便于复用

1.需求与目的

这个视频《侧边工具栏开辟》的需求很简单,就是做一个侧边工具条,

  1. 牢固定位在页面的某个位置,

  2. 在没有把页面向下转动时,显现三个按钮,

  3. 当页面向下转动肯定间隔以后,第四个按钮涌现。

  4. 点击这个按钮,页面会回到顶部。

  5. 鼠标hover到每一个按钮上都有一些响应的动画(CSS3完成这里不写)

《javascript模块化(二)--RequireJS初探》《javascript模块化(二)--RequireJS初探》

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>

一些申明:

  1. 为了让页面显现转动条,须要在这个上述代码下面加很多行<p></p>标签以便撑开页面显现转动条。

  2. CSS部份视频中先生讲了三种要领,而且用到了SASS,感兴趣的同砚能够去看一下,这里不再赘述。

3.requirejs入门

(1)项目目次组织

个中jquery-3.1.0.js和require.js是在各自官网下载的资本文件。main.js是自定义的进口文件。
《javascript模块化(二)--RequireJS初探》

(2)加载初始化requirejs

在未引入模块化编写代码之前引入js文件是在<body>标签之前写多个<script>标签,依据js文件加载的递次,增加js文件。如今依据requirejs的异步加载的特征,能够设定一个主进口文件,只用一个<script>完成其他js文件的加载。

  1. 首先是引入requirejs:在HTML文件的<body>标签的之前增加script标签,

  2. 然后引入requirejs文件,然后用data-main这个属性来引入进口文件。(当用requirejs援用文件时,能够省略js文件的js后缀名,所以此处引入的就是项目目次中的main.js
    以下:

    <script src="js/require.js" data-main="js/main"></script>

(3)requirejs的经常使用要领

  1. requirejs.config为模块指定别号,轻易模块的引入),在进口文件中定义
    如这个demo要引入屡次jquery-3.1.0.js,然则这个名字很长所以能够在进口文件main.js中为它定义一个别号,以下:

    //为jquery模块定义别号
    requirejs.config({
        paths:{
            jquery:'jquery-3.1.0.js'
        }
    });
  1. requirejs()要领(将写好的模块举行引入
    requirejs()吸收两个参数,第一个参数是一个数组,写入要引入的模块的名字。第二个参数是一个回调函数,须要通报一个参数,来替代前面所引入的模块。如:引入jquery模块

    requirejs(['jquery'],function($){
        //写一段代码考证jquery是不是被准确引入
        //将body背景色彩变成赤色
        $('body').css('background-color','red');
    });
  1. define()(利用它定义编写模块,然后在响应的处所举行引入。)
    define()吸收三个参数,第一个参数是为本模块定名的值,能够不写,第二个参数示意须要引入的模块,第三个参数是各依靠项胜利加载后所运转的函数,传入的参数与各个依靠项构成对应的关联。

    define(
        moduleName,  //可选,如果此参数不写,则默许运用本模块地点文件的文件名
        dependencies,    //一个数组,此数组包含着此文件所需的各个依靠项目,这个数组中各项对应的是所依靠文件相对于requirejs库所构成的相对路径文件名。
        function(parameters){  
            //各依靠项胜利加载后所运转的函数
            //传入的参数与dependencies数组中的各个依靠项构成对应关联
        }
    );

(4)demo的基本功用完成

如今先对demo中的基本功用举行完成:

现在的目次组织以下:
《javascript模块化(二)--RequireJS初探》

  1. 首先在HTML中初始化requirejs:在</body>标签之前:
    <script src="js/require.js" data-main="js/main"></script>

  2. 在进口文件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)将功用笼统成模块

上述代码虽然完成了功用,然则存在以下题目:

  1. move和go函数都是抵达顶部的功用,完成的功用很类似,作用如果想在别的处所运用这个功用,就要再举行代码的复制,不轻易功用的复用。所以应当将功用笼统成模块。

  2. 完胜利能的功用单一:两个函数都是抵达顶部,如许即使笼统成模块也会遭到很大的限定,所以能够进一步将题目笼统成挪动转动条到指定位置。

第一步:建立一个新模块,用scrollto.js示意,现在这个demo的目次组织如图:
《javascript模块化(二)--RequireJS初探》

第二步:将功用笼统成模块,写入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
        };
        
    });
    

代码详解:

  1. 通报的参数为一个对象,用opts示意

  2. 用户没有通报参数时,运用默许的参数,默许参数直接写在ScrollTo组织函数上,相当于构成一个静态属性,然后经由过程jquery的extend()要领举行原型的扩大

  3. 完成用户通报参数用之,不通报参数用默许值。jquery的extend()要领

  4. 在原型上增加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));
    
    });

上述代码中有一点须要注重:

  1. 在第6行中,如果增加点击按钮回到指定位置事宜时,这么写:
    $('#backTop').on('click', scroll.move);

  2. 此时浏览器控制台会报错:Uncaught TypeError: Cannot read property 'ScrollTo' of undefined

  3. 剖析缘由是由于,在main.js中挪用scrollto.js模块中在ScrollTo.prototype.move原型要领move时,main.js中this指的是ScrollTo的实例,即scrollto,而在语句$('#backTop').on('click', scroll.move);中,这个this指代的是id为backTop的这个按钮。

  4. 处理办法:用jquery供应的要领,直接将this指向scroll对象。
    $('#backTop').on('click', $.proxy(scroll.move, scroll))

第四步:一个bug
这时候基本功用虽然完成了,点击底部谁人按钮,传入设定的返回位置和返回的速率,页面能够再次返回顶部指定位置,然则现在还存在一个bug:在点击底部按钮回到顶部指定位置时,如果一连屡次点击这个按钮,则页面回到顶部后就没法再次向下转动页面。

bug剖析:

  1. 如果实行的函数如上面第三步中代码,速率设置成较慢的速率2000,那末在返回顶部指定位置时能够屡次点击这个按钮,

  2. 如许每次点击按钮事宜都要挪用move要领实行内里的动画,点击多少次,这个动画就要实行多少次。

  3. 因此在页面返回顶部后,再次转动页面向下会马上实行返回顶部动画,所以在实行完点击次数的动画之前,用户都没法向下转动。(而且异常耗机能)

处理办法,在转动条正在活动或许已抵达目的地,就不应当实行动画。增加推断。
所以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模块。

所以现在的项目目次以下图:
《javascript模块化(二)--RequireJS初探》

第一步:如今来写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中的模块化是如许一种头脑:

  1. 首先把功用函数放在一个模块中(move和go)

  2. 把全部完胜利能也笼统成一个模块,依靠上一个功用函数模块

  3. 末了只须要在进口文件中实例化一下这个最外层的模块,即可完成一系列功用的挪用。

  4. 每一个模块都用面向对象的头脑,定义模块而且暴露接口

  5. 默许值的用法能够让挪用者拿起就用,能够不必斟酌传参数。

    原文作者:yangdepp
    原文地址: https://segmentfault.com/a/1190000006011186
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞