Vue中常见的面试题及知识点
1 . MVC、MVP与MVVM模式 MVC:
MVC是应用最广泛的软件架构之一,一般MVC
分为:
Model( 模型 )
、Controller( 控制器 )
、View( 视图 )
。
这主要是基于分层的目的,让彼此的职责分开。View
一般通过 Controller
来和 Model
进行联系。Controller
是 Model
和 View
的协调者,View
和Model
不直接联系。基本联系都是单向的。
1、View 传送指令到 Controller
2、Controller 完成业务逻辑后,要求 Model 改变状态
3、Model 将新的数据发送到 View,用户得到反馈
MVP:
MVP 模式将 Controller 改名为 Presenter
,同时改变了通信方向。
1、各部分之间的通信,都是双向的。
2、View 与 Model 不发生联系,都通过 Presenter 传递。
3、View 非常薄,不部署任何业务逻辑,称为"被动视图"(Passive View),即没有任何主动性,而 Presenter非常厚,所有逻辑都部署在那里。
MVVM
MVVM
是把 MVC
的 Controller
和 MVP
的 Presenter
改成了 ViewModel
。
View
的变化会自动更新到 ViewModel
,ViewModel
的变化也会自动同步到 View
上显示。这种自动同步是因为 ViewModel
中的属性实现了 Observer
,当属性变更时都能触发对应的操作。
2、 MVVM模式的优点以及与MVC模式的区别
MVVM模式的优点:
1、低耦合:
视图(View)可以独立于 Model 变化和修改,一个 ViewModel 可以绑定到不同的"View"上,当View变化的时候Model可以不变,当Model变化的时候View也可以不变。
2、可重用性:
你可以把一些视图逻辑放在一个ViewModel里面,让很多 view 重用这段视图逻辑。
3、独立开发:
开发人员可以专注于业务逻辑和数据的开发(ViewModel),设计人员可以专注于页面设计。
4、可测试:
界面素来是比较难于测试的,而现在测试可以针对ViewModel来写。
MVVM 和 MVC 的区别:
mvc
和 mvvm
其实区别并不大。都是一种设计思想。
主要区别
-
mvc 中 Controller演变成 mvvm 中的 viewModel,
-
mvvm 通过数据来显示视图层而不是节点操作。
-
mvvm主要解决了: mvc中大量的DOM 操作使页面渲染性能降低,加载速度变慢,影响用户体验。
3 、常见的实现MVVM数据绑定的做法有哪些?
实现数据绑定的做法有大致如下几种:
发布者-订阅者模式(backbone.js)
脏值检查(angular.js)
数据劫持(vue.js)
1、发布者-订阅者模式:
一般通过sub
, pub
的方式实现数据和视图的绑定监听,
更新数据方式通常做法是 vm.set('property', value)
。
这种方式现在毕竟太low了,我们更希望通过 vm.property = value
这种方式更新数据,同时自动更新视图,于是有了下面两种方式。
2、脏值检查:
angular.js 是通过脏值检测的方式比对数据是否有变更,来决定是否更新视图,
最简单的方式就是通过 setInterval() 定时轮询检测数据变动,
angular只有在指定的事件触发时进入脏值检测,大致如下:
1、DOM事件,譬如用户输入文本,点击按钮等。( ng-click )
2、XHR响应事件 ( $http )
3、浏览器Location变更事件 ( $location )
4、Timer事件( $timeout , $interval )
5、执行 $digest() 或 $apply()
3、数据劫持:
vue.js 则是采用数据劫持
结合发布者-订阅者
模式的方式,
通过Object.defineProperty()
来劫持各个属性的setter
,getter
,
在数据变动时发布消息给订阅者,触发相应的监听回调。
4 、Object.defineProperty()方法的作用是什么?
Object.defineProperty() 方法`会直接在一个对象上定义一个新属性,或者修改一个对象的现有属性, 并返回这个对象。
语法:
Object.defineProperty(obj, prop, descriptor)
参数说明:
obj:必需。目标对象
prop:必需。需定义或修改的属性的名字
descriptor:必需。目标属性所拥有的特性
返回值:
传入函数的对象。即第一个参数obj
针对属性,我们可以给这个属性设置一些特性,比如是否只读不可以写;是否可以被for…in或Object.keys()遍历。
给对象的属性添加特性描述,目前提供两种形式:数据描述和存取器描述。
6. 请详细说下你对vue生命周期的理解?
6.6.1 什么是vue生命周期?
Vue实例有一个完整的生命周期,也就是从开始创建、初始化数据、编译模板、挂载Dom、渲染→更新→渲染、销毁等一系列过程,我们称这是Vue的生命周期。通俗说就是Vue实例从创建到销毁的过程,就是生命周期。
6.6.2 vue生命周期钩子函数都有哪些?分别是什么意思?
-
组件通过new Vue() 创建出来之后会初始化事件和生命周期,然后就会执行beforeCreate钩子函数,这个时候,数据还没有挂载呢,只是一个空壳,无法访问到数据和真实的dom,一般不做操作
-
挂载数据,绑定事件等等,然后执行created函数,这个时候已经可以使用到数据,也可以更改数据,在这里更改数据不会触发updated函数,在这里可以在渲染前倒数第二次更改数据的机会,不会触发其他的钩子函数,一般可以在这里做初始数据的获取
-
接下来开始找实例或者组件对应的模板,编译模板为虚拟dom放入到render函数中准备渲染,然后执行beforeMount钩子函数,在这个函数中虚拟dom已经创建完成,马上就要渲染,在这里也可以更改数据,不会触发updated,在这里可以在渲染前最后一次更改数据的机会,不会触发其他的钩子函数,一般可以在这里做初始数据的获取下来开始render,渲染出真实dom,然后执行mounted钩子函数,此时,组件已经出现在页面中,数据、真实dom都已经处理好了,事件都已经挂载好了,可以在这里操作真实dom等事情…
-
当组件或实例的数据更改之后,会立即执行beforeUpdate,然后vue的虚拟dom机制会重新构建虚拟dom与上一次的虚拟dom树利用diff算法进行对比之后重新渲染,一般不做什么事儿
-
当更新完成后,执行updated,数据已经更改完成,dom也重新render完成,可以操作更新后的虚拟dom
-
经过某种途径调用$destroy方法后,立即执行beforeDestroy,一般在这里做一些善后工作,例如清除计时器、清除非指令绑定的事件等等,组件的数据绑定、监听…去掉后只剩下dom空壳,这个时候,执行destroyed,在这里做善后工作也可以
如果觉得上面的太长,也可以如下回答:
总共分为8个阶段创建前/后,载入前/后,更新前/后,销毁前/后。
创建前/后: 在beforeCreated阶段,vue实例的挂载元素el还没有。在created阶段,vue实例的数据对象data有了,el还没有.
载入前/后:在beforeMount阶段,vue实例的$el和data都初始化了,但还是挂载之前为虚拟的dom节点,data.message还未替换。在mounted阶段,vue实例挂载完成,data.message成功渲染。
更新前/后:当data变化时,会触发beforeUpdate和updated方法。
销毁前/后:在执行destroy方法后,对data的改变不会再触发周期函数,说明此时vue实例已经解除了事件监听以及和dom的绑定,但是dom结构依然存在
6.6.3 vue生命周期的作用是什么?
生命周期中有多个事件钩子,让我们在控制整个 vue 实例的过程时更容易形成好的逻辑
6.6.4 第一次页面加载会触发哪几个钩子?
第一次加载会触发 beforeCreate、created、beforeMount、mounted
6.6.5 简述每个周期具体适合哪些场景?
生命周期钩子的一些使用方法:
-
beforecreate : 可以在这加个loading事件,在加载实例时触发
-
created : 初始化完成时的事件写在这里,如在这结束loading事件,异步请求也适宜在这里调用
-
mounted : 挂载元素,获取到DOM节点 updated : 如果对数据统一处理,在这里写上相应函数
-
beforeDestroy : 可以做一个确认停止事件的确认框 nextTick : 更新数据后立即操作dom
6.6.6 created和mounted的区别?
-
created:在模板渲染成html前调用,即通常初始化某些属性值,然后再渲染成视图。
-
mounted:在模板渲染成html后调用,通常是初始化页面完成后,再对html的dom节点进行一些需要的操作。
6.6.7 vue获取数据在哪个周期函数?
-
看实际情况,一般在 created(或beforeRouter) 里面就可以,如果涉及到需要页面加载完成之后的话就用 mounted。
-
在created的时候,视图中的html并没有渲染出来,所以此时如果直接去操作html的dom节点,一定找不到相关的元素
-
而在mounted中,由于此时html已经渲染出来了,所以可以直接操作dom节点,(此时document.getelementById 即可生效了)
6.7 说一下你对vue路由的理解吧
6.7.1 什么是vue路由?
“Vue路由就是指vue-router,其中router是指根据url分配到对应的处理程序,所以说路由就是用来解析URL以及调用对应的控制器并返回从视图对象中提取好的网页代码给web服务器,最终返回给客户端。
6.7.2 vue路由的优点以及缺点是什么?
-
优点:
- 不需要每次都从服务器获取,渲染页面更快速
-
缺点:
- 不利于SEO
- 使用浏览器前进、后退按键时重新发送请求,未合理利用缓存
- 单页面无法记住之前滚动的位置
6.7.3 请简单说一下vue路由的原理?
Vue的路由实现:hash模式 和 history模式
-
hash模式:在浏览器中符号“#”,#以及#后面的字符称之为hash,用window.location.hash读取;
-
特点:
- hash虽然在URL中,但不被包括在HTTP请求中;用来指导浏览器动作,对服务端安全无用,hash不会重加载页面。
- hash 模式下,仅 hash 符号之前的内容会被包含在请求中,如 http://www.xxx.com,因此对于后端来说,即使没有做到对路由的全覆盖,也不会返回 404 错误。
-
history模式:history采用HTML5的新特性;且提供了两个新方法:pushState(),replaceState()可以对浏览器历史记录栈进行修改,以及popState事件的监听到状态变更。
-
特点:
- history 模式下,前端的 URL 必须和实际向后端发起请求的 URL 一致,如 http://www.xxx.com/items/id。后端如果缺少对 /items/id 的路由处理,将返回 404 错误。Vue-Router 官网里如此描述:“不过这种模式要玩好,还需要后台配置支持……所以呢,你要在服务端增加一个覆盖所有情况的候选资源:如果 URL 匹配不到任何静态资源,则应该返回同一个 index.html 页面,这个页面就是你 app 依赖的页面。”
6.7.4 怎么定义 vue-router 的动态路由?如何获取动态路由传过来的值?
-
定义动态路由:
- 在 router 目录下的 index.js 文件中,对 path 属性加上 /:id。
-
获取动态路由传过来的值:
- 使用 router 对象的
params.id
获取
- 使用 router 对象的
//全局获取动态路由传递过来的值
$route.params.id
//局部或者是在方法内获取
this.$route.params.id
6.7.5 请描述vue-router路由守卫的作用?
vue-router 的导航钩子,主要用来作用是拦截导航,让他完成跳转或取消。
6.7.6 路由守卫使用的方式有几种?
-
全局的
-
单个路由独享的
-
组件级的