前端小姐姐五万字面试宝典: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(); } 复制代码
- 1.主要用于解决下述两个问题。
- 2.总结 AMD 规范:require()函数在加载依赖函数的时候是异步加载的,这样浏览器不会失去响应,它指定的回调函数,只有前面的模块加载成功,才会去执行。因为网页在加载js的时候会停止渲染,因此我们可以通过异步的方式去加载js,而如果需要依赖某些,也是异步去依赖,依赖后再执行某些方法。
- 1.require JS 实现了 AMD 规范
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
来源:掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。