• 了解Browserify


    Browserify是一个Javascript的库,可以用来把多个Module打包到一个文件中,并且能很好地应对Modules之间的依赖关系。而Module是封装了属性和功能的单元,是一个Javascript对象,Modules之间可以相互依赖。某种程度上来说,Browserify模仿了Node.js加载Module的方式。一个js文件包含一个Module。所以,Browserify通过读取文件来加载该文件内的Module。

    【module的写法】

    'use strict';
    exports.save = function(tasks){};
    exports.load = function(){};
    exports.clear = function(){};
    

    还可以这么写:

    'use strict';
    module.exports = {
    	save: function(tasks){},
    	load: function(){},
    	clear: function(){}
    };
    

    【module的缓存】

    1、单例模式缓存

    module a

    exports.value = "original";
    

    module b

    var a = require('./a');
    a.value = "changed";
    console.log(a.value);//changed
    

    module c

    var a = require('./a');
    console.log(a.value);//original
    

    module c中的a.value值之所以是original,是因为module c对module a有依赖,而且依赖的是缓存。所以,在默认情况下,module是有缓存的,也可以理解成单例模式。

    2、实例模式缓存

    还可以通过构造函数来创建一个module。

    module a

    module.exports = function(){
      this.value = "original value";  
    };
    

    module b

    var A = require('./a');
    var a = new A();
    a.value = "changed";
    console.log(a.value);//changed
    

    module c

    var A = require('./a');
    var a = new A();
    console.log(a.value);//original
    

    【准备工作】

    • 安装Node.js
    • 安装Browserify:npm install -g browserify

    【明确目标】

    • app这个module包含了和视图交互的逻辑,是整个程序的entry point
    • app这个module依赖tasks这个module,tasks这个module用来管理task list
    • taskRender这个module用来渲染页面,taskData这个module用来保存加载有关task list的数据

    【文件结构】

    .....css/
    ..........tasks.css
    .....js/
    ..........data/
    ...............taskData.js
    ..........renderers/
    ...............taskRenderer.js
    ..........tasks.js
    ..........app.js
    .....index.html

    【代码实现】

    文件结构有了,module的写法也搞清楚了,接下来就实现一遍。

    ① taskData.js 是用来处理数据的一个module

    'use strict';
    
    var STORE_NAME = "tasks";
    
    exports.save = function(tasks){
        localStorage.setItem(STORE_NAME, JSON.stringify(tasks));
    };
    
    exports.load = function(){
        var storedTasks = localStorage.getItem(STORE_NAME);
        if(storedTasks){
            return JSON.parse(storedTasks);
        }
        return [];
    };
    
    exports.clear = function(){
        localStorage.removeItem(STORE_NAME);
    };
    

    ② taskRenderer.js 是用来处理页面相关的一个module

    'use strict';
    
    var $ = require('jquery');
    var taskTemplate = '<li class="task"><input class="complete" type="checkbox" /><input class="description" type="text" /></li>';
    
    //返回一段带值的html
    //task是传入的一个object对象
    function _renderTask(task){
        var $task = $(taskTemplate);
        if(task.complete){
            $task.find(".complete").attr("checked", "checked");
        }
        $task.find(".description").val(task.description);
        return $task;
    }
    
    exports.renderTasks = function(tasks){
        
        //遍历任务获得带值html的数组
        var elementArray = $.map(tasks, _renderTask);
        
        $("#task-list")
            .empty()
            .append(elementArray);
    };
    
    exports.renderNew = function(){
        var $taskList = $("#task-list");
        $taskList.prepend(_renderTask({}));
    }
    

    ③ tasks.js 用到了以上2个module

    'use strict';
    
    var $ = require('jquery');
    var taskData = require('./data/taskData');
    var taskRenderer = require('./renderers/taskRenderer');
    
    exports.add = function () {
        taskRenderer.renderNew();
    };
    
    exports.remove = function (clickEvent) {
        var taskElement = clickEvent.target;
        $(taskElement).closest(".task").remove();
    };
    
    exports.clear = function(){
        taskData.clear();
        exports.render();
    };
    
    exports.save = function(){
        var tasks=[];
        $("#task-list .task").each(function(index, task){
            var $task = $(task);
            tasks.push({
                complete: $task.find(".complete").prop('checked'),
                description: $task.find(".description").val()
            });
        });
        taskData.save(tasks);
    };
    
    exports.cancel = function(){
      exports.render();  
    };
    
    exports.render = function(){
      taskRenderer.renderTasks(taskData.load()); 
    };
    

    ④ app.js 只需要和tasks.js打交道就可以

    'use strict';
    
    var $ = require('jquery');
    var tasks =require('./tasks');
    
    function _addTask(){
        tasks.add();
    }
    
    function _deleteAllTasks(){
        tasks.clear();
    }
    
    function _saveChanges(){
        tasks.save();
    }
    
    function _cancelChanges(){
        tasks.cancel();
    }
    
    function _deleteTask(clientEvent){
        tasks.remove(clientEvent);
    }
    
    
    function _registerEventHandlers(){
        $('#new-task-button').on("click", _addTask);
        $('#delete-all-button').on("click", _deleteAllTasks);
        $('#save-button').on("click",_saveChanges);
        $('#cancel-button').on("click", _cancelChanges);
        $('#task-list').on("click", ".delete-button", _deleteTask);
    }
    
    _registerEventHandlers();
    tasks.render();
    

    ⑤ 使用browserify把所有module捆绑到一个js文件中去:

    browserify srcjsapp.js -o srcjsapp.bundle.js

    ⑥ index.html 只需要引用srcjsapp.bundle.js就可以

    <!DOCTYPE html>
    <html>
        <head>
            <title>Task List</title>
            <link rel="stylesheet" href="css/tasks.css">
        </head>
        <body>
            <header>
                <h1>TaskList</h1>
            </header>
            
            <div class="toolbar">
                <button id="new-task-button">New Task</button>
                <button id="delete-all-button">Delete All</button>
            </div>
            
            <div id="content">
                <ul id="task-list">
                    
                </ul>
                
                <ul id="log-list">
                    
                </ul>
            </div>
            
            <div class="toolbar">
                <button id="save-button">Save</button>
                <button id="cancel-button">Cancel</button>
            </div>
            
            <script src="js/app.bundle.js"></script>
        </body>
    </html>
    

    【如果有很多文件,调试时出错】

    当有很多文件的时候,调试出错,使用Source Map可以方便找到出错的文件和出错的地方。

    现在,有了app.bundle.js文件,以及有了app.js, tasks.js, taskRenderer.js, taskData.js文件们,我们可以在app.bundle.js和其它js文件中创建一个Souce Map.

    browserify srcjsapp.js -o srcjsapp.bundle.js --debug

    这样,会在app.bundle.js文件最后面追加上类似//# sourceMappingURL=data:application/json;,这样在调试的时候会很容易找到出错的文件和出错的位置。

    【修改文件】

    如果此时修改某个js文件呢?我们还需要使用browserify把所有的module依赖关系捆绑到一个文件中,执行如下的命令:

    browserify srcjsapp.js -o srcjsapp.bundle.js

    解决思路:Watchify为此而生,当发现有文件变化,自动运行Browserify。

    全局安装Watchify:npm install -g watchify

    在命令行窗口运行Watchify命令:watchify srcjsapp.js -o srcjsapp.bundle.js --debug -v

    此时保持命令窗口打开着。

    修改某个文件,并保存,发现命令窗口会自动运行:watchify srcjsapp.js -o srcjsapp.bundle.js --debug -v

    【Grunt Browserify】

    Grunt是Javascript Task Runner,也是运行在Node.js之上。

    如何安装Grunt?

    1. npm install -g grunt-cli
    2. npm install grunt --save-dev

    检测版本?

    grunt --version

    在哪个文件中配置?

    一般在根目录下的Gruntfile.js

    Grunt与Browserify的结合?

    npm install grunt-browserify --save-dev

    在根目录下的Gruntfile.js文件:

    module.exports=function(grunt){
        
        //配置
        grunt.initConfig({
            browserify: {
                app: {
                    src: 'templates/src/js/app.js',
                    dest: 'templates/src/js/app.bundle.js',
                    options: {
                        browserifyOptions:{
                            debug: true
                        }
                    }
                }
            }
        });
        
        //加载其它module/plugins
        grunt.loadNpmTasks('grunt-browserify');
        
        //定义task
        grunt.registerTask('default',['browserify']);
    }
    

    【Grunt Watch】

    使用了Grunt以及用Gruntfile.js进行配置之后,每次有文件变化,我们需要在命令行窗口输入gulp命令。能不能自动为我们运行gulp命令呢?

    Grunt Watch出场。

    如何安装Grunt Watch?

    npm install grunt-contrib-watch --save-dev

    修改Gruntfile.js文件

    module.exports=function(grunt){
        
        //配置
        grunt.initConfig({
            browserify: {
                app: {
                    src: 'templates/src/js/app.js',
                    dest: 'templates/src/js/app.bundle.js',
                    options: {
                        browserifyOptions:{
                            debug: true
                        }
                    }
                }
            },
            watch: {
                app: {
                    files: ['templates/src/js/*/*.js'],
                    tasks: ['browserify']
                }
            }
        });
        
        //加载其它module/plugins
        grunt.loadNpmTasks('grunt-browserify');
        grunt.loadNpmTasks('grunt-contrib-watch');
        
        //定义task
        grunt.registerTask('default',['browserify']);
    }
    

    在命令行窗口输入:grunt watch

    现在,修改templates/src/js中的任何js文件,会自动运行browserify命令。

    【Grunt Connect】

    Grunt Connect可以让我们搭建一个web server。

    如何安装?

    npm install grunt-contrib-connect --save-dev

    修改Gruntfile.js文件

    module.exports=function(grunt){
        
        //配置
        grunt.initConfig({
            browserify: {
                app: {
                    src: 'templates/src/js/app.js',
                    dest: 'templates/src/js/app.bundle.js',
                    options: {
                        browserifyOptions:{
                            debug: true
                        }
                    }
                }
            },
            watch: {
                app: {
                    files: ['templates/src/js/*/*.js'],
                    tasks: ['browserify']
                }
            },
            connect: {
                app: {
                    options: {
                        port: 9001,
                        base: 'templates/src'
                    }
                }
            }
        });
        
        //加载其它module/plugins
        grunt.loadNpmTasks('grunt-browserify');
        grunt.loadNpmTasks('grunt-contrib-watch');
        grunt.loadNpmTasks('grunt-contrib-connect');
        
        //定义task
        grunt.registerTask('default',['browserify']);
        grunt.registerTask('serve',['browserify:app', 'connect:app', 'watch:app']);
    }
    

    在命令行窗口输入:grunt serve

    在浏览器窗口输入:localhost:9001

    【Connect Live Reload】

    现在,可以在浏览器中输入localhost:9001浏览到网页内容,此时,如果某个文件有变化,我们需要重新刷新浏览器。web server可以有自动刷新的功能吗?

    Connect Live Reload就是解决这个问题的。

    如何安装?

    npm install connect-livereload --save-dev

    修改Gruntfile.js文件

    module.exports=function(grunt){

        //配置
        grunt.initConfig({
            browserify: {
                app: {
                    src: 'templates/src/js/app.js',
                    dest: 'templates/src/js/app.bundle.js',
                    options: {
                        browserifyOptions:{
                            debug: true
                        }
                    }
                }
            },
            watch: {
                app: {
                    files: ['templates/src/js/*/*.js'],
                    tasks: ['browserify'],
                    options: { //为保持web server 的自动刷新而设置
                        livereload: true
                    }
                }
            },
            connect: {
                app: {
                    options: {
                        port: 9001,
                        base: 'templates/src',
                        middleware: function(connect, options, middlewares){//为保持web server 的自动刷新而设置
                            middlewares.unshift(require('connect-livereload')());
                            return middlewares;
                        }
                    }
                }
            }
        });
        
        //加载其它module/plugins
        grunt.loadNpmTasks('grunt-browserify');
        grunt.loadNpmTasks('grunt-contrib-watch');
        grunt.loadNpmTasks('grunt-contrib-connect');
        
        //定义task
        grunt.registerTask('default',['browserify']);
        grunt.registerTask('serve',['browserify:app', 'connect:app', 'watch:app']);
    }
    

    在命令行窗口输入:grunt serve

    在浏览器中打开:http://localhost:9001/

    修改某个文件,浏览器中自动有变化。

  • 相关阅读:
    Intellij 常用技巧-持续更新
    Android界面组件的四种启动方式
    Preference Screen 首选项
    Oracle OCI-22053:溢出错误
    SQLPLUS使用
    Oracle中数字格式的文本化处理
    MP4V2 移植 (基于imx6 平台)
    IMX6Q camera 应用编程之 摄像头裁剪
    IMX6Q camera驱动分析 (4)
    IMX6Q Camera驱动分析 (3)
  • 原文地址:https://www.cnblogs.com/darrenji/p/5492028.html
Copyright © 2020-2023  润新知