24、设计模式、webpack

利用静态属性:长驻内存

(一) 单例模式

概念:单个实例,只有一个对象,多次创建,返回同一个对象。

单例模式的核心:==确保只有一个实例==,并提供全局访问。

//利用了静态属性:长驻内存
            function Dog(){
                if(!Dog.instance){
                    Dog.instance = {
                        name : '小黑',
                        age : 3
                    }
                }
                return Dog.instance;
            }
            var dog1 = new Dog();
            var dog2 = new Dog();
            alert(dog1 == dog2);//true
浮窗(面向对象)
        <input type="button" name="btn" id="btn" value="飞秋" />
        <script type="text/javascript">
            var oBtn = document.getElementById("btn");
            oBtn.onclick = function(){
                new Float().init();
            }
            function Float(){
                if(!Float.instance){
                    Float.instance = {
                        ele : document.createElement('div'),
                        init : function(){
                            document.body.appendChild(this.ele);
                            this.ele.style.cssText = "width : 100px;height : 100px; background : pink;position : absolute;left : 300px";
                        }
                    }
                }
                return Float.instance;
            }
        </script>
浮窗(面向过程)
        <input type="button" name="btn" id="btn" value="飞秋" />
        <script type="text/javascript">
            var oBtn = document.getElementById("btn");
            oBtn.onclick = (function(){
                var div = null;
                return function(){
                    if(!div){
                        div = document.createElement('div');
                        div.style.cssText = "width: 100px; height: 100px; background: red; position: absolute; left: 400px;";
                        document.body.appendChild(div);
                    }
                    return div;
                }
            })();
        </script>

(二) 组合模式

组合多个对象形成树形结构以表示具有“整体-部分”关系的层次结构。组合模式对单个对象(即叶子对象)和组合对象(即容器对象)的使用具有一致性,组合模式又可以称为“整体-部分”模式,它是一种对象结构型模式。

<script type="text/javascript">
            //文件夹
            function Fold(name){
                this.name = name;
                this.folds = [];
            }
            Fold.prototype.add = function(file){
                this.folds.push(file);
            }
            Fold.prototype.scan = function(){
                console.log("扫描文件夹:" + this.name);
                for(var i = 0,file,folds = this.folds;file = folds[i ++];){
                    file.scan();
                }
            }
            
            //文件
            function File(name){
                this.name = name;
            }
            File.prototype.add = function(file){
                console.log("文件中不能添加其它任何文件");
            }
            File.prototype.scan = function(){
                console.log('扫描文件:' + this.name);
            }
            
            //创建三个文件夹
            var fold1 = new Fold("JS");
            var fold2 = new Fold("jQ");
            var fold = new Fold("学习资料");
            
            //创建三个文件
            var file1 = new File('JavaScript从入门到精通');
            var file2 = new File('锋利的jQuery');
            var file3 = new File('计算机算法与应用');
            
            fold1.add(file1); //将js书放到JS目录中
            fold2.add(file2); //将jQ书放到jQ目录中
            fold.add(fold1);
            fold.add(fold2);
            fold.add(file3);
            
            fold.scan();
        </script>

(三) 观察者模式

观察者模式又叫发布-订阅模式,它定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都将得到通知。

1.  小明最近看上了一套房子,到了售楼处之后才被告知,该楼盘的房子早已售罄
。好在售楼MM告诉小明,不久后还有一些尾盘推出,开发商正在办理相关手续,
手续办好后便可以购买。但到底是什么时候,目前还没有人能够知道。
于是小明记下了售楼处的电话,以后每天都会打电话过去询问是不是已经到了购
买时间。除了小明,还有小红、小强、小龙也会每天向售楼处咨询这个问题。一个
星期后,售楼MM决定辞职,因为厌倦了每天回答1000个相同内容的电话。当然现实
中没有这么笨的销售公司,实际上故事是这样的:小明离开之前,把电话号码留在
了售楼处。售楼MM答应他,新楼盘一推出就马上发信息通知小明。小红、小强和小
龙也是一样,他们的电话号码都被记在售楼处的花名册上,新楼盘推出的时候,
售楼MM会翻开花名册,遍历上面的电话号码,依次发送一条短信来通知他们。
——这种发送短信通知就是一个典型的发布-订阅模式(观察者模式)。
小明、小红等购买者都是订阅者,他们订阅了房子开售的消息。售楼处作为发布
者,会在合适的时候遍历花名册上的电话号码,依次给购房者发布消息。

            //发布者(对象)
            //电话簿(对象.属性)
            //接待人员--》负责将来访用户的信息记录在电话簿中 (对象.方法())
            //发布信息————》遍历电话簿,依次调用来访用户 (对象.方法())
            

<script type="text/javascript">
            //
            
//          var SalesOffice = {};
//          SalesOffice.arr = [];
//          SalesOffice.reception = function(fn){
//              this.arr.push(fn);
//          }
//          SalesOffice.publish = function(){
//              for(var i = 0,fn,list = this.arr;fn = list[i ++];){
//                  fn.apply(this,arguments);
//              }
//          }
//          SalesOffice.reception(function(square,money){
//              console.log("平米数:" + square + '\n多少钱:' + money);
//          })
//          SalesOffice.reception(function(square,money){
//              console.log("平米数:" + square + '\n多少钱:' + money);
//          })
//          SalesOffice.reception(function(square,money){
//              console.log("平米数:" + square + '\n多少钱:' + money);
//          })
//          SalesOffice.reception(function(square,money){
//              console.log("平米数:" + square + '\n多少钱:' + money);
//          })
//          
//          SalesOffice.publish('80平',5000000);
            function SalesOffice(){
                this.arr = [];
            }
            SalesOffice.prototype.reception = function(fn){
                this.arr.push(fn);
            }
            SalesOffice.prototype.publish = function(){
                for(var i = 0,fn,list = this.arr;fn = list[i ++];){
                    fn.apply(this,arguments);
                }
            }
            var so = new SalesOffice();
            so.reception(function(square,money){
                console.log("平米数:" + square + '\n多少钱:' + money);
            })
            so.reception(function(square,money){
                console.log("平米数:" + square + '\n多少钱:' + money);
            })
            so.reception(function(square,money){
                console.log("平米数:" + square + '\n多少钱:' + money);
            })
            so.reception(function(square,money){
                console.log("平米数:" + square + '\n多少钱:' + money);
            })
            
            so.publish('80平',5000000);
        </script>

(四) MV*模式

(一) MVC模式的意思是,软件可以分成三个部分:

  1. 视图(view):用户界面
  2. 控制器(controller):业务逻辑
  3. 模型(Model):数据保存
  4. 各部分之间的通信方式如下:
    image
1)  View传送指令到Controller
2)  Controller完成业务逻辑后,要求Model改变状态
3)  Model将新的数据发送到View,用户得到反馈
4)  所有通信都是单向的。
  1. Model
1)  Model管理应用程序的数据。
2)  Model不涉及用户界面,也不涉及表示层,而是代表应用程序可能需要的独特形式的数据。
3)  当Model改变时,它通常会通知它的观察者(如View)。
4)  一个Model模型可能有多个观察它的View。
5)  总而言之,Model主要与业务数据有关。
  1. View
1)  View是Model的可视化表示
2)  一个View通常检测一个Model,并在Model更改时进行通知,使View本身能够相应地更新。
3)  用户可以和View进行交互,包括读取和编辑Model。
4)  由于View是表示层,通常我们能够以一种更友好的方式进行编辑和更新。
5)  而更新Model的实际任务其实是在Controller上的。
6)  View是应用程序数据的可视化表

  1. Controller
1)  Controller是Model和View之间的中介,当用户操作View时,它通常负责更新Model。
  1. MVC的优点
1)  MVC这种关注点分离有利于进一步简化应用程序功能的模块化,并能够实现:
整体维护更容易。
2)  解耦Model和View,意味着它能够更直接地编写业务逻辑的单元测试
3)  这种模块性可以让负责核心逻辑的开发人员和负责用户界面的开发人员同时工作。

(二) MVP

  1. MVP是MVC的一种衍生模式,专注于改进表示逻辑。
  2. Presenter
    MVP中的P代表表示器。这是一个包含用于View的用户界面业务逻辑的组件。
    image
a)  各部分之间的通信,都是双向的。
b)  View与Model不发生联系,都通过Presenter传递。
c)  View非常薄,不部署任何业务逻辑,称为“被动视图”(Passive View),即没有任何主动性,而Presenter非常厚,所有逻辑都部署在那里。

(三) MVP与MVC

  1. MVP适用于有非常复杂的View和大量用户交互的应用程序。
  2. 这样的程序如果用MVC的话意味着要极度依赖于多个控制器。而在MVP中,所有这些复杂的逻辑可以封装在一个表示器中,大大简化维护工作。

(四) MVVM

  1. MVVM模式将Presenter改名为ViewModel,基本上与MVP模式完全一致。
    image
  2. 唯一的区别是,它采用双向绑定(data-binding):View的变动,自动反映在ViewModel,反之亦然。
  3. MVVM由Model,View,ViewModel三部分构成:
1)  Model层代表数据模型,也可以在Model中定义数据修改和操作的业务逻辑
2)  View代表UI组件,它负责将数据模型转化成UI展现出来
3)  ViewModel是一个同步View和Model的对象。
  1. 在MVVM架构下,View和Model之间并没有直接的联系,而是通过ViewModel进行交互,Model和ViewModel之间的交互是双向的,因此View数据的变化会同步到Model中,而Model数据的变化也会立即反应到View上。
  2. ViewModel通过双向数据绑定把View层和Model层连接了起来,而View和Model之间的同步工作完全是自动的,无需人为干涉,因此开发者只需关注业务逻辑,不需要手动操作DOM,不需要关注数据状态的同步问题,复杂的数据状态维护完全由MVVM来统一管理。
  3. View与ViewModel
1)  MVVM中的View是主动而不是被动的。
2)  被动View只输出显示并不接受任何用户输入
3)  而MVVM中的View和ViewModel之间通过数据绑定和事件进行通信。
4)  优点:
    a)  MVVM使得UI和为UI提供驱动的行为模块的并行开发变得更容易。
    b)  MVVM使View抽象化,从而减少代码背后所需的业务逻辑量。
    c)  ViewModel在单元测试中的使用更容易
5)  缺点:
    a)  对于简单的UI来说,使用MVVM有些大材小用
    b)  数据绑定难以调试
6)  VUE是典型的MVVM框架,它实现双向数据绑定的技术是数据劫持。也就是通过ES5提供的Object.defineProperty()方法来劫持(监控)各属性的getter、setter,并在数据(对象)发生变动时通知订阅者,触发相应的监听回调。

(五) Webpack的安装及使用

Webpack的优势是什么?

  1. 丰富的插件,方便进行开发工作
  2. 大量的加载器,包括加载各种静态资源
  3. 代码分割,提供按需加载的能力
一.全局安装

webpack(电脑中只安装一次): npm install -g webpack@3

二.创建项目,

在项目的根目录中(shift + 右键--选择在此处打开命令窗口),局部安装webpack:
npm install --save-dev webpack@3

三.项目根目录中:

初始化package.json : npm init -y

四.项目根目录中创建webpack.config.js配置文件
var path = require('path');
    module.exports = {
        entry : '入口文件的URL',
        output : {
            path : path.resolve(__dirname,'出口路径'),
            filename : '打包后的文件名'
        }
    }
五.运动webpack : webpack
六.自动监听: webpack --watch
七.安装插件
1.html-webpack-plugin  : npm install --save-dev html-webpack-plugin
//自动快速的帮我们生成HTML。
var path = require('path');
    var HtmlWebpackPlugin = require('html-webpack-plugin');
    module.exports = {
        entry : '入口文件的URL',
        output : {
            path : path.resolve(__dirname,'出口路径'),
            filename : '打包后的文件名'
        }
        plugins : [
            new HtmlWebpackPlugin({
                template : "模板文件的URL"
            })
        ]
    }
    2. style-loader css-loader : npm install --save-dev style-loader css-loader
    //样式文件,我们需要两种loader,css-loader 和 style-loader,css-loader会遍历css文件,找到所有的url(...)并且处理。style-loader会把所有的样式插入到你页面的一个style tag中。
    在入口文件中  require('!style-loader!css-loader!css文件的URL');

Webpack打包封装

(一) 实现打包多个相互依赖的js文件过程
通过require()方法,在入口文件中引入

(二) 样式的打包:通过安装loader加载器,可以将静态的样式文件一同打包到bundle.js文件中,通过下面命令安装加载器
在entry.js中导入样式:
Require(‘!style-loader!css-loader!../css/style.css’); //静态资源导入需要加!,必须先导入style-loader

猜你喜欢

转载自www.cnblogs.com/zhongchao666/p/9275598.html