前端小姐姐五万字面试宝典:VUE进阶、性能优化

1.VUE

(1).vue的生命周期

Vue实例有一个完整的生命周期,也就是从开始创建、初始化数据、编译模板、挂载Dom、渲染→更新→渲染、销毁等一系列过程,我们称这是Vue的生命周期。通俗说就是Vue实例从创建到销毁的过程,就是生命周期。

每一个组件或者实例都会经历一个完整的生命周期,总共分为三个阶段:初始化、运行中、销毁。

  • 1.实例、组件通过new Vue() 创建出来之后会初始化事件和生命周期,然后就会执行beforeCreate钩子函数,这个时候,数据还没有挂载呢,只是一个空壳,无法访问到数据和真实的dom,一般不做操作
  • 2.挂载数据,绑定事件等等,然后执行created函数,这个时候已经可以使用到数据,也可以更改数据,在这里更改数据不会触发updated函数,在这里可以在渲染前倒数第二次更改数据的机会,不会触发其他的钩子函数,一般可以在这里做初始数据的获取
  • 3.接下来开始找实例或者组件对应的模板,编译模板为虚拟dom放入到render函数中准备渲染,然后执行beforeMount钩子函数,在这个函数中虚拟dom已经创建完成,马上就要渲染,在这里也可以更改数据,不会触发updated,在这里可以在渲染前最后一次更改数据的机会,不会触发其他的钩子函数,一般可以在这里做初始数据的获取
  • 4.接下来开始render,渲染出真实dom,然后执行mounted钩子函数,此时,组件已经出现在页面中,数据、真实dom都已经处理好了,事件都已经挂载好了,可以在这里操作真实dom等事情...
  • 5.当组件或实例的数据更改之后,会立即执行beforeUpdate,然后vue的虚拟dom机制会重新构建虚拟dom与上一次的虚拟dom树利用diff算法进行对比之后重新渲染,一般不做什么事儿
  • 6.当更新完成后,执行updated,数据已经更改完成,dom也重新render完成,可以操作更新后的虚拟dom
  • 7.当经过某种途径调用$destroy方法后,立即执行beforeDestroy,一般在这里做一些善后工作,例如清除计时器、清除非指令绑定的事件等等
  • 8.组件的数据绑定、监听...去掉后只剩下dom空壳,这个时候,执行destroyed,在这里做善后工作也可以

(2).Vue 双向绑定原理

vue数据双向绑定是通过数据劫持结合发布者-订阅者模式的方式来实现的。利用了 Object.defineProperty() 这个方法重新定义了对象获取属性值(get)和设置属性值(set)。

2.Webpack

webpack 是一个现代 JavaScript 应用程序的静态模块打包器(module bundler)。当 webpack 处理应用程序时,它会递归地构建一个依赖关系图(dependency graph),其中包含应用程序需要的每个模块,然后将所有这些模块打包成一个或多个bundle。

(1).webpack 和 gulp 区别

gulp强调的是前端开发的工作流程,我们可以通过配置一系列的task,定义task处理的事务(例如文件压缩合并、雪碧图、启动server、版本控制等),然后定义执行顺序,来让gulp执行这些task,从而构建项目的整个前端开发流程。

webpack是一个前端模块化方案,更侧重模块打包,我们可以把开发中的所有资源(图片、js文件、css文件等)都看成模块,通过loader(加载器)和plugins(插件)对资源进行处理,打包成符合生产环境部署的前端资源。

3.模块化

(1).如何理解前端模块化

前端模块化就是复杂的文件编程一个一个独立的模块,比如js文件等等,分成独立的模块有利于重用(复用性)和维护(版本迭代),这样会引来模块之间相互依赖的问题,所以有了commonJS 规范,AMD,CMD规范等等,以及用于js打包(编译等处理)的工具 webpack

(2).说一下 Commonjs、AMD 和 CMD

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

  • 1.Commonjs:开始于服务器端的模块化,同步定义的模块化,每个模块都是一个单独的作用域,模块输出,modules.exports,模块加载require()引入模块。
  • 2.AMD:中文名异步模块定义的意思。
    • 1.require JS 实现了 AMD 规范
      • 1.主要用于解决下述两个问题。
        • 1.多个文件有依赖关系,被依赖的文件需要早于依赖它的文件加载到浏览器
        • 2.加载的时候浏览器会停止页面渲染,加载文件越多,页面失去响应的时间越长。
      • 2.语法:requireJS 定义了一个函数 define,它是全局变量,用来定义模块。
      //定义模块
      define(['dependency'], function(){
        var name = 'Byron';
        function printName(){
          console.log(name);
        }
        return {
          printName: printName
        };
      });
      
      复制代码
      //加载模块
      require(['myModule'], function (my){
        my.printName();
      }
      复制代码
    • 2.总结 AMD 规范:require()函数在加载依赖函数的时候是异步加载的,这样浏览器不会失去响应,它指定的回调函数,只有前面的模块加载成功,才会去执行。因为网页在加载js的时候会停止渲染,因此我们可以通过异步的方式去加载js,而如果需要依赖某些,也是异步去依赖,依赖后再执行某些方法。

4.简单实现Node的Events模块

简介:观察者模式或者说订阅模式,它定义了对象间的一种一对多的关系,让多个观察者对象同时监听某一个主题对象,当一个对象发生改变时,所有依赖于它的对象都将得到通知。

node中的Events模块就是通过观察者模式来实现的:

微信公众号:世界上有意思的事

var events=require('events');
var eventEmitter=new events.EventEmitter();
eventEmitter.on('say',function(name){
  console.log('Hello',name);
})
eventEmitter.emit('say','Jony yu');
复制代码

这样,eventEmitter发出say事件,通过On接收,并且输出结果,这就是一个订阅模式的实现,下面我们来简单的实现一个Events模块的EventEmitter。

  • 1.实现简单的Event模块的emit和on方法
    function Events(){
        this.on=function(eventName,callBack){
            if(!this.handles){
                this.handles={};
            }
            if(!this.handles[eventName]){
                this.handles[eventName]=[];
            }
            this.handles[eventName].push(callBack);
        }
        this.emit=function(eventName,obj){
            if(this.handles[eventName]){
                for(var i=0;o<this.handles[eventName].length;i++){
                    this.handles[eventName][i](obj);
                }
            }
        }
        return this;
    }
    复制代码
  • 2.这样我们就定义了Events,现在我们可以开始来调用:
    var events=new Events();
    events.on('say',function(name){
        console.log('Hello',nama)
    });
    
    //结果就是通过emit调用之后,输出了Jony yu
    events.emit('say','Jony yu');
    复制代码
  • 3.每个对象是独立的

    因为是通过new的方式,每次生成的对象都是不相同的,因此:

    var event1=new Events();
    var event2=new Events();
    event1.on('say',function(){
        console.log('Jony event1');
    });
    event2.on('say',function(){
        console.log('Jony event2');
    })
    
    //event1、event2之间的事件监听互相不影响
    //输出结果为'Jony event1' 'Jony event2'
    event1.emit('say');
    event2.emit('say');
    复制代码

5.性能优化

  • 1.降低请求量:合并资源,减少HTTP 请求数,minify / gzip 压缩,webP,图片lazyLoad。
  • 2.加快请求速度:预解析DNS,减少域名数,并行加载,CDN 分发。
  • 3.缓存:HTTP 协议缓存请求,离线缓存 manifest,离线数据缓存localStorage。
  • 4.渲染:JS/CSS优化(避免使用CSS表达式),加载顺序(将CSS样式表放在顶部,把javascript放在底部),服务端渲染,pipeline。

作者:何时夕
链接:https://juejin.im/post/5e91b01651882573716a9b23
来源:掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

THE END