1. 简述MVVM
MVVM 是 Model-View-ViewModel缩写,也就是把MVC中的Controller演变成ViewModel。Model层代表数据模型,View代表UI组件,ViewModel是View和Model层的桥梁,数据会绑定到ViewModel层并自动将数据渲染到页面中,视图变化的时候会通知ViewModel层更新数据。
2. Vue生命周期
-
beforeCreate阶段: vue实例的挂载元素el和数据对象data都是undefined,还没有初始化。 -
created阶段: vue实例的数据对象data有了,可以访问里面的数据和方法,未挂载到DOM,el还没有。 -
beforeMount阶段: vue实例的el和data都初始化了,但是挂载之前为虚拟的dom节点。 -
mounted阶段: vue实例挂载到真实DOM上,就可以通过DOM获取DOM节点。 -
beforeUpdate阶段: 响应式数据更新时调用,发生在虚拟DOM打补丁之前,适合在更新之前访问现有的DOM,比如手动移除已添加的事件监听器。 -
updated阶段: 虚拟DOM重新渲染和打补丁之后调用,组成新的DOM已经更新,避免在这个钩子函数中操作数据,防止死循环。 -
beforeDestroy阶段: 实例销毁前调用,实例还可以用,this能获取到实例,常用于销毁定时器,解绑事件。 -
destroyed阶段: 实例销毁后调用,调用后所有事件监听器会被移除,所有的子实例都会被销毁。
3. Vue 是如何实现数据双向绑定的
- Vue 数据双向绑定主要是指:数据变化更新视图,视图变化更新数据
- 输入框内容变化时,Data 中的数据同步变化。即 View => Data 的变化。
- Data 中的数据变化时,文本节点的内容同步变化。即 Data => View 的变化。
- View 变化更新 Data,可以通过事件监听的方式实现,所以
Vue 的数据双向绑定的主要工作是如何让 Data 变化更新 View。
4. Vue 实现双向绑定的原理
-
实现一个
监听器 Observer: 对数据对象进行遍历,包括子属性对象属性,利用 Object.defineProperty 对属性都加上 setter 和 getter。这样之后,给这个对象某个属性赋值,就会触发它的 setter ,那么就能监听到数据变化。 -
实现一个
解析器 Compile: 解析 Vue 模板指令,将模板中的变量都替换成数据,然后渲染页面视图,并将每个指令对应的节点绑定更新函数,添加监听数据的订阅者,一旦数据发生变动,收到通知调用更新函数进行更新. -
实现一个
订阅者 Watcher: Watcher 订阅者是 Observer 和 Compile 之间通信的桥梁,主要任务是订阅 Observer 中的属性值变化的消息,当收到变化时,触发解析器 Compile 中对应的更新函数。
5. Vue 中的 computed 和 watch 的区别
- 功能上:computed 是计算属性,也就是依赖其它的属性计算后所得出的值。 watch是去监听一个值的变化,然后执行相应的函数
- 使用上:computed 中的函数必须使用 return 返回;,watch 的回调里面传入监听属性的新旧值,通过这两个值可以做一些特定的操作,不是必须要return
- 性能上:computed 中的函数所依赖的属性没有发生变化,那么调用当前函数的时候回从缓存中读取,而 watch 在每次监听值发生变化的时候都会执行回调,支持对属性的深度监听。
- 场景上:computed 当一个属性受多个属性影响的时候,例如:商品结算;watch:当一条数据影响多个数据的时候。例如:分页
6. Vuex的流程
- 页面通过mapAction异步提交事件到action。
- action通过commit把对应参数同步提交到mutation。
- mutation会修改state中对于的值。
- 最后通过getter把对应值跑出去,在页面的计算属性中通过mapGetter来动态获取state中的值
7. Vuex有哪几种状态和属性
- state中保存着共有数据,数据是响应式的
- getter可以对state进行计算操作,主要用来过滤一些数据,可以在多组件之间复用
- mutations定义的方法动态修改state中的数据,通过commit提交方法,
方法必须是同步的 - actions将mutations里面处理数据的方法变成异步的,就是异步操作数据,
通过store.dispatch来分发actions,把异步的方法写在actions中,通过commit提交mutations,进行修改数据。 - modules:模块化vuex
8. 常用指令
- v-if:判断是否隐藏
- v-for:数据循环出来
- v-bind:绑定数据
- v-model:实现双向绑定
- v-on:事件
9. Vue修饰符
- stop:阻止事件的冒泡
- prevent:阻止事件的默认行为
- once:只触发一次
- self:只触发自己的事件行为时,才会执行
10. v-for中key的作用
key 是 Vue 使用 v-for 渲染列表时的节点标识。使用了 key 之后,当列表项发生变化时,Vue 会基于 key 的变化而重新排列元素顺序,并且移除 key 不存在的元素,提升运行效率。
11. v-if 和 v-show 有什么区别
v-if在进行切换时,会直接对标签进行创建或销毁,不显示的标签不会加载在 DOM 树中。v-show在进行切换时,会对标签的 display 属性进行切换,通过 display 不显示来隐藏元素。
一般来说,v-if 的性能开销会比 v-show 大,切换频繁的标签更适合使用 v-show。
12. $route和$router的区别
$route是“
路由信息对象”,包括path,params,hash,query,fullPath,matched,name等路由信息参数。
$router是“路由实例”对象包括了路由的跳转方法,钩子函数等。
13. $nextTick的实现
Vue 实现响应式并不是在数据发生后立即更新 DOM,使用
vm.$nextTick是在下次 DOM 更新循环结束之后立即执行延迟回调。在修改数据之后使用,则可以在回调中获取更新后的 DOM。
14. Vue组件中data必须是一个函数
如果 data 是
一个对象,当复用组件时,因为 data 都会指向同一个引用类型地址,其中一个组件的 data 一旦发生修改,则其他重用的组件中的 data 也会被一并修改。
如果 data 是一个返回对象的函数,因为每次重用组件时返回的都是一个新对象,引用地址不同,便不会出现如上问题
15. Vue-router 路由有哪些模式?
一般有两种模式:
hash 模式:后面的 hash 值的变化,浏览器既不会向服务器发出请求,浏览器也不会刷新,每次 hash 值的变化会触发 hashchange 事件。history 模式:利用了 HTML5 中新增的pushState()和replaceState()方法。这两个方法应用于浏览器的历史记录栈,在当前已有的 back、forward、go的基础之上,它们提供了对历史记录进行修改的功能。只是当它们执行修改时,虽然改变了当前的 URL,但浏览器不会立即向后端发送请求。
16. SPA 单页面的理解,优缺点分别是什么
single-page application仅在 web 页面初始化时加载响应的 HTML、JavaScript 和 CSS。一旦页面加载完成,SPA 不会因为用户的操作而进行页面的重新加载或跳转;取而代之的是利用路由机制实现 HTML 内部的变换,UI与用户的交互,避免页面的重新加载。优点:
- 用户体验好,快,内容的改变不需要重新加载整个页面,避免了不必要的跳转和重复渲染;
- 基于1的优点,SPA 相对对服务器的压力小;
- 前后端分离,架构清晰,前端进行交互逻辑,后端负责数据处理;
缺点:
- 初次加载消耗多,问了实现单页 web 应用功能及显示效果,需要在加载页面的时候将 JavaScript、CSS 同一加载,部分页面按需加载
- 前进后退路由管理: 由于单页面应用在一个页面上显示所有的内容,所以不能使用浏览器的前进后退功能,所有的页面切换需要自己建立堆栈管理。
- SEO 难度较大: 由于所有的内容都在一个页面中动态替换显示,所以在 SEO 上有着天然的劣势。
17. SSR(服务端渲染)
SSR(服务端渲染) 将 Vue 在客户端将标签渲染成HTML 片段的工作放到了服务端完成,服务端形成的 HTML 片段直接返回给客户端这个过程,叫做服务端渲染。
优点:
- 更好的 SEO:因为 SPA 页面的内容是通过 Ajax 获取,而搜索引擎爬取并不会等待异步完成后再去抓取结果,所以在 SPA 中抓取不到页面 Ajax 的请求内容,而 SSR 是结果从服务端渲染,返回时已经渲染好的页面(数据也包含在内),所以搜索引擎爬取可以抓到渲染好的页面;
- 更快的内容到达时间(首屏加载更快):SPA 等待所有 Vue 编译后的 js 文件都要下载完成后,才会进行页面的渲染,需要等待一段时间,SSR 直接由服务端渲染好页面直接返回显示,无需等待下载js 过程再去渲染,所以 SSR 更快。
缺点:
- 更多的开发条件限制: 只能在某些生命周期钩子函数 (lifecycle hook) 中使用;一些外部扩展库 (external library) 可能需要特殊处理,才能在服务器渲染应用程序中运行。
- 涉及构建设置和部署的更多要求:与可以部署在任何静态文件服务器上的完全静态单页面应用程序 (SPA) 不同,服务器渲染应用程序,需要处于 Node.js server 运行环境。
- 更多的服务器端负载:在 Node.js 中渲染完整的应用程序,显然会比仅仅提供静态文件的 server 更加大量占用 CPU 资源 (CPU-intensive - CPU 密集),因此如果你预料在高流量环境 (high traffic) 下使用,请准备相应的服务器负载,并明智地采用缓存策略。