斑码教育web前端课堂笔记-第66天-模块式开发

模块化开发

一、组合模式

组合模式又叫部分整体模式。把一组相似的对象当做单一的对象处理。组合模式依据树形结构,用来表示部分和整体。

创建一个包含自己对象组的基(父)类,该类提供了修改相同对象组的方式。其他类继承自该基类,基类不实例化任何的对象。

斑码教育web前端课堂笔记-第66天-模块式开发

/* 
    组合模式的定义: 定义一个基类,该基类要具有组合的所有属性和方法,他不产生实例对象,被其他类继承    
*/
// 定义基类
function Base() {
    // 属性
    this.dom = null;
    this.children = [];
}

// 设置基类的方法
// 添加子元素
Base.prototype.add = function(child) {
    this.children.push(child);
    return this;
}

// 渲染元素
Base.prototype.render = function() {
    // 上树
    // 备份this
    var me = this;
    this.children.forEach(function(child) {
        me.dom.appendChild(child.dom);
    })
}

// 创建最大的容器----树根
function Container() {
    // 寄生式组合继承
    Base.call(this);
    // 创建一个ol
    this.dom = document.createElement('ol');
}

// 继承方法
Container.prototype = Object.create(Base.prototype);


// 创建li容器
function Item() {
    Base.call(this);
    // 创建一个li
    this.dom = document.createElement('li');
}

// 继承方法
Item.prototype = Object.create(Base.prototype);


// 创建文本节点----最小的节点,不需要包含子元素
function Leaf(text) {
    // createTextNode 创建文本节点, text文字内容
    this.dom = document.createTextNode(text);
}

// 创建树叶---文本节点
var leaf1 = new Leaf('31省新增本土确诊42例:河北40例');
var leaf2 = new Leaf('特朗普夫人发文谴责国会*');
var leaf3 = new Leaf('河北固安全县居民居家隔离7天');
var leaf4 = new Leaf('蒙古发生6.8级地震');
var leaf5 = new Leaf('北京新增1例本土确诊 系5岁男童');

// 创建树枝---li
var li1 = new Item();
var li2 = new Item();
var li3 = new Item();
var li4 = new Item();
var li5 = new Item();

// 创建树根---ol
var ol = new Container();

// 将树叶添加到树枝上
li1.add(leaf1).render();
li2.add(leaf2).render();
li3.add(leaf3).render();
li4.add(leaf4).render();
li5.add(leaf5).render();

// 添加子元素
ol.add(li1).add(li2).add(li3).add(li4).add(li5).render();

// 父元素上树
document.body.appendChild(ol.dom);

二、观察者模式

特别重要

观察者模式又叫: 消息管道、订阅-发布、消息机制、自定义事件

当对象存在一对多的关系,则使用观察者模式。当一个对象被修改的时候,需要通知依赖他的对象,这种模式称之为观察者模式。

在js中的应用有两个方面: 一对多的修改, 跨模块传输消息。

DOM0级观察者:
斑码教育web前端课堂笔记-第66天-模块式开发

var Observer = (function() {
    // 设置一个存储绑定处理程序的对象,存储数据
    var obj = {

    }
    return {
        // 绑定事件
        on: function(type, fn) {
            obj[type] = fn;
        },
        // 触发事件
        trigger: function(type) {
            obj[type]();
        },
        // 辅助方法---用于查看对象obj
        log: function() {
            console.log(obj);
        }
    }
})();

DOM2级观察者:

/*
    使用DOM0 事件实现观察者
        1、绑定事件
        2、触发事件
    DOM2级绑定多个事件, 移除指定的事件
*/   
var OBserver = (function() {
    // 设置一个存储绑定处理程序的对象,存储数据
    var obj = {

    }
    return {
        // 绑定事件
        on: function(type, fn) {
            // 判断条件
            if (obj[type]) {
                // 不是第一次添加
                obj[type].push(fn);
            } else {
                // 第一次添加
                obj[type] = [fn];
            }
        },
        // 触发事件
        trigger: function(type) {
            // 由于事件是数组的形式,所以依次调用触发
            obj[type].forEach(function(fn) {
                fn();
            })
        },
        // 移除事件,移除指定type全部处理程序和移除type指定的处理程序,移除所有的程序
        /* 
            移除指定type: off(type)
            移除type中指定的处理程序: off(type, fn)
            清空所有: off()
        */
        off: function(type, fn) {
            if (arguments.length == 0) {
                // 清空所有
                obj = {};
            } else if (arguments.length == 1) {
                obj[type] = [];
            } else if (arguments.length == 2) {
                for (var i = 0; i < obj[type].length; i++) {
                    if (obj[type][i] == fn) {
                        // 移除
                        obj[type].splice(i, 1);
                    }
                }
            }
        },
        // 一次性事件
        one: function(type, fn) {
            // 绑定上事件,执行的时候,立即移除该事件
            // 跟bind类似,bind方法改变this的指向,绑定一个函数,但是在返回的时候,给的函数和我们传入的不是一个函数
            function _demo() {
                fn();
                // 执行完毕移除对应的函数
                OBserver.off(type);
            }
            // 将demo进行绑定
            OBserver.on(type, _demo);
        },
        // 辅助方法---用于查看对象obj
        log: function() {
            console.log(obj);
        }
    }
})();

三、模块化

早期js设计之初,为了解决表单验证的问题。ES6引入了块作用域,查找变量按照作用域链的方式进行查找,声明的时候也是同样的道理。没有类、没有包、更没有模块,带来代码的复用、依赖、冲突,代码的组织混乱。随着前端功能的膨胀,模块化被提出来了。

前端模块化:

  • 浏览器端
    • AMD: 异步模块规范 ---- RequireJS
    • CMD: 普通模块规范 ---- SeaJS
  • node端(服务器端)— CommonJS–同步模块规范
  • 浏览器和服务器端兼容:UMD规范–通用模块规范
  • ES6原生模块

3.1 模块概述

js没有实现包、类、模块这些概念,开发者模拟类似的功能,来隔离、组织复杂的js代码,称之为模块化。

模块就是一个实现特定功能的文件,有了模块我们就可以更方便的使用别人的代码,要什么功能就引入什么模块。

模块化的好处:

  • 避免变量的污染,命名冲突
  • 提高了代码的可维护性
  • 提高代码的复用
  • 方便依赖关系的管理

3.2 模块的发展历程

3.2.1 函数

// 功能1
function fn1() {
    
}

// 功能2
function fn2() {
    
}

污染全局变量,不能保证函数名不被覆盖,成员之间的依赖关系没有办法解决

3.2.2 对象

var Module = {
    // 属性
    property1: value1,
    property2: value2,
    // 方法
    method1: function() {
        
    },
    method2: function() {
        
    }
}

外部可以肆意的更改你的对象,安全问题

3.2.3 IIFE

隐藏细节,保护变量,只能通过制定方式进行读取和使用

var Module = (function() {
    var obj = {
        // 属性
        property1: value1,
        property2: value2,
        // 方法
        method1: function() {

        },
        method2: function() {

        }
	}
    return {
        method1: obj.method1,
        method2: obj.method2
    }
})()

封装过程复杂,使用了闭包增加了开销。

<script src="js/Bg.js"></script>
<script src="js/Bird.js"></script>
<script src="js/Game.js"></script>
<script src="js/Land.js"></script>
<script src="js/Pipe.js"></script>

但是,在工作中经常存在js文件之间的依赖关系,后面的文件需要依赖前面的文件,在整个的引入过程中,这些文件是不可以随意更改顺序的。

3.3 模块化规范

共同的特点: 一个js文件就是一个模块

  • 浏览器端
    • AMD: 异步模块规范 ---- RequireJS
    • CMD: 普通模块规范 ---- SeaJS
  • node端(服务器端)— CommonJS–同步模块规范
  • 浏览器和服务器端兼容:UMD规范–通用模块规范
  • ES6原生模块

3.3.1服务器端

CommonJS让js程序员可以使用js来执行python、java等服务器端的编程,nodejs采用的该规范。

加载是同步的

服务器端: 同步加载

3.3.2 浏览器端

加载的文件为远程加载,必须使用异步加载

AMD和CMD本质都是异步加载

AMD: Asynchronous Module Definition —异步模块定义

CMD: Common Module Definition — 通用模块定义

AMD和CMD最大的区别:

AMD提前加载(依赖前置),CMD依赖就近(懒加载)

3.3.3 UMD

UMD: Universal Module Definition 通用模块定义

UMD是AMD和CommonJS的产物,浏览器端和服务器端的兼容。

UMD是存在判断过程的,如果你是node定义的模块使用CommonJS规范,如果不是node定义的,是客户端,使用AMD规范。

四、模块化的学习

1、定义模块

2、引入模块

3、seajs和requirejs的插件和配置

上一篇:66. 加一


下一篇:使用深度学习进行图像去噪