1、说说你对SPA单页应用的理解,他的优缺点是什么?
SPA(single-page application)仅在web页面初始化时加载响应的HTML、Javascript和CSS。一旦页面加载完成,SPA不会因为用户的操作而进行页面的重新加载或跳转;取而代之的是利用路由机制实现HTML内容的变换,UI与用户的交互,避免页面的重新加载。
优点:
- 用户体验好、快。内容的改变不需要重新加载整改页面,避免了不必要的跳转和重复渲染。
- 基于上面一点,SPA相对对服务器压力小。
- 前后端职责分离,架构清晰,前端进行交互逻辑,后端负责数据处理。
缺点:
- 初次加载耗时多:为实现单页web应用功能及显示效果,需要在加载页面的时候将Javascript、CSS统一加载,部分页面按需加载。
- 前进后退路由管理:由于单页应用在一个页面中显示所有的内容,所以不能使用浏览器的前进后退功能,所有的页面切换需要自己建立堆栈管理。
- SEO(Search Engine Optimization,搜索引擎优化)难度较大:由于所有的内容都在一个页面中动态替换显示所以在SEO上其有着天然的弱势。
2、Vue的父组件和子组件生命周期钩子函数执行顺序?
Vue的父组件和子组件生命周期钩子执行顺序可以归类为以下4部分:
(1)加载渲染过程
parent beforeCreate --> parent created --> parent beforeMount --> child beforeCreate --> child created --> child beforeMount --> child mounted --> parent mounted
(2)子组件更新过程
parent beforeUpdate --> child beforeUpdate --> child updated --> parent updated
(3)父组件更新过程
parent beforeUpdate --> parent updated
(4)销毁过程
parent beforeDestory --> child beforeDestory --> child destoryed --> parent destoryed
3、父组件可以监听到子组件的生命周期吗?如果可以,怎么监听?
// parent.vue
<Child @mounted="doSomething" />
// child.vue
mounted(){
this.$emit('mounted');
}
以上方式需要手动通过$emit触发父组件的事件,更简单的方式可以在父组件引用子组件时通过 @hook 来监听即可。
// parent.vue
<Child @hook:mounted="doSomething" />
doSomething(){
console.log('父组件监听到 mounted 钩子函数...')
}
// child.vue
mounted(){
console.log('子组件触发 mounted 钩子函数')
}
// 以上输出结果顺序为:
// 子组件触发 mounted 钩子函数...
// 父组件监听到 mounted 钩子函数...
当然 @hook 方法不仅仅是可以监听 mounted,其它的生命周期事件也都可以监听
4、谈谈你对 keep-alive 的了解。
keep-alive是Vue内置的一个组件,可以使被包含的组件保留状态,避免重新渲染,其有以下特性:
- 一般结合路由和动态组件一起使用,用于缓存组件。
- 提供include和exclude属性,两者都支持字符串或正则表达式,include表示只有名称匹配的组件会被缓存,exclude表示任何名称匹配的组件都不会被缓存,其中exclude的优先级比include高
- 对应两个钩子函数 activated 和 deactivated,当组件被激活时,触发钩子函数activated,当组件被移除时,触发 deactivated
5、使用过Vue SSR吗?说说SSR。
Vuejs是构建客户端应用程序的框架。默认情况下,可以在浏览器中输出Vue组件,进行生成DOM和操作DOM。然而,也可以将同一组件渲染为服务端的HTML字符串,将它们直接发送到浏览器,最后将这些静态标记“激活”为客户端上完全可交互的应用程序。
即:SSR大致的意思就是vue在客户端将标签渲染成的整改html片段的工作在服务端完成,服务端形成的html片段直接返回给客户端,这个过程就叫做服务端渲染。
服务端渲染SSR的优缺点如下:
(1)优点:
- 更好的SEO:因为SPA页面的内容是通过ajax获取,而搜索引擎爬取工具并不会等待ajax异步完成后再抓取页面内容,所以在SPA中抓取不到页面通过ajax获取到的内容;而SSR是直接由服务端返回已经渲染好的页面(数据已经包含在页面中),所以搜索引擎爬取工具可以抓取渲染好的页面。
- 更快的内容到达时间(首屏加载更快):SPA会等待所有Vue编译后的js文件都下载完成后,才开始进行页面的渲染,文件下载需要一定得时间,所以首屏渲染需要一定的时间;而SSR直接由服务器渲染好页面直接返回显示,无需等待下载js文件及再去渲染,所以SSR有更快的内容到达时间。
(2)缺点:
- 更多的开发条件限制:例如服务端渲染只支持 beforeCreate 和 created 两个钩子函数,这会导致一些外部扩展库需要特殊处理,才能在服务端渲染应用程序中运行;并且与可以部署在任何静态文件服务器上的完全静态单页面应用程序SPA不同,服务端渲染应用程序,需要处于Node.js Server运行环境。
- 更多的服务器负载:在Node.js中渲染完整的应用程序,显然会比仅仅提供静态文件的server更加大量占用CUP资源,因此如果你预料在高流量环境下使用,请准备相应的服务器负载,并明智地采用缓存策略。
6、vue-router路由模式有几种?
- hash:使用URL hash值来作为路由。支持所有浏览器,包括不支持HTML5 History Api 的浏览器。
- history:依赖HTML5 History Api 和服务器配置。具体可以查看HTML5 History模式。
- abstract:支持所有Javascript运行环境,如Nodejs服务器端。如果发现没有浏览器的API,路由会强制进入这个模式。
7、什么是MVVM?
Model-View-ViewModel(MVVM)是一个软件架构设计模式,由微软WPF和Silverlight 架构师 Ken Cooper 和 Ted Peters 开发,是一种简化用户界面的事件驱动编程方式。
MVVM源自于经典的Model-View-Controller(MVC)模式,MVVM的出现促进了前端开发与后端业务逻辑的分离,极大地提高了前端开发效率,MVVM的核心是ViewModel层,它就像是一个中转站,负责转换Model中的数据对象来让数据变得更容易管理的使用,该层向上与视图层进行双向数据绑定,向下与Model层通过接口请求进行数据交互,起承上启下作用。
(1)View层
View是视图层,也就是用户界面。前端主要有HTML和CSS来构建。
(2)Model层
Model是指数据模型,泛指后端进行的各种页面逻辑处理和数据操控,对于前端来说就是后端提供的api接口。
(3)ViewModel层
ViewModel是由前端开发人员组织生成和维护的视图数据层。在这一层,前端开发者对从后端获取的Model数据进行转换出来,做二次封装,以生成符合View层使用预期的视图数据模型。
需要注意的是ViewModel所封装的数据模型包括视图的状态和行为两部分,而Model层的数据模型是只包含状态的,比如页面的这一块展示什么,而页面加载进来时发生什么,点击这一块发生什么。这些都属于视图行为(交互),视图状态和行为都封装在了ViewModel里。这样的封装使得ViewModel可以完整地描述View层。
MVVM框架实现了双向绑定,这样ViewModel的内容会实时展现在View层,前端开发者再也不必低效又麻烦地通过操作DOM去更新视图。MVVM框架已经把最脏最累的活做好了,我们开发者只需要处理和维护ViewModel,更新数据视图就会自动得到相应更新。
这样View层展现的部署Model层的数据,而是ViewModel的数据,由ViewModel负责与Model层交互,这就完全解耦了View层和Model层,这个解耦是至关重要的,他是前后端分离方案实施的重要一环。
通过一个Vue实例来说明MVVM的具体实现:
(1)View层
<div id="app">
<p>{{message}}</p>
<button @click="showMessage">click me</button>
</div>
(2)ViewModel层
var app = new Vue({
el: '#app',
data: { // 用于描述视图状态
message: 'hello vue !'
},
methods: { // 用于描述视图行为
showMessage(){
let vm = this
alert(vm.message)
}
},
created(){
let vm = this
// ajax 获取 Model 层的数据
ajax({
url: '/your/server/data/api',
success(res){
vm.message = res
}
})
}
})
(3)Model层
{
"url": "/your/server/data/api",
"res": {
"success": true,
"name": "Dylan",
"age": 36
}
}
8、Proxy与Object.defineProperty
Proxy的优势如下:
- Proxy可以直接监听对象而非属性。
- Proxy可以直接监听数组的变化。
- Proxy有多达13种拦截方法,不限于 apply、ownKeys、deleteProperty、has等等,是Object.defineProperty不具备的。
- Proxy返回的是一个新对象,我们可以只操作新的对象达到目的,而Object.defineProperty只能遍历对象属性直接修改。
- Proxy作为新标准将受到浏览器厂商重点持续的性能优化,也就是新标准的性能红利。
Object.defineProperty的优势如下:
- 兼容性好,支持IE9,而Proxy存在浏览器兼容性问题,而且无法用polyfill磨平。
9、你对Vue项目进行过哪些优化?
(1)代码层面的优化
- v-if 和 v-show 区分使用场景
- computed 和 watch 区分使用场景
- 使用v-for的时候,避免使用v-if
- 事件的销毁
- 图片资源懒加载
- 路由懒加载
- 第三方插件按需引入
- 服务端渲染SSR or 预渲染
- 长列表性能优化
(2)webpack层面的优化
- webpack对图片进行压缩
- 减少ES6转为ES5的冗余代码
- 提取公共代码
- 优化SourceMap
- 使用happypack加速打包
(3)基础的web技术优化
- 开启gzip压缩
- 浏览器缓存
- CDN的使用