VUE基础面试题总结
- 对于MVVM的理解?
- VUE的生命周期及理解?
- 第一次页面加载会触发哪几个钩子?
- Vue实现数据双向绑定的原理
- 虚拟DOM及其优缺点
- Vue组件间的参数传递
- Vue路由的两种模式
- v-if和v-show的区别?
- v-if和v-for同时使用在同一个标签上的表现?
- v-for中的key的理解?
- v-model的理解
- computed和watch的用法和区别?
- computed和methods的区别?
- data为什么是一个函数?
- vue单页面和传统的多页面的区别?
- vue的修饰符
- vue更新数组时触发视图更新的方法?
- vue-router有哪几种导航钩子?
- vuex是什么?怎么使用?哪种功能场景使用它?
- 对keep-alive 的了解?
- r o u t e 和 route和 route和router的区别
- 怎么定义 vue-router 的动态路由? 怎么获取传过来的值
- 如何获取dom?
- vue-loader是什么?使用它的用途有哪些?
- v-on可以监听多个方法吗?
- $nextTick的使用
- axios的特点有哪些
- 请说下封装 vue 组件的过程?
- params和query的区别
- active-class 是哪个组件的属性?
- vue-router实现路由懒加载( 动态加载路由 )
- vuex有哪几种属性?
- vuex actions和mutations的区别?
- 为什么 Vuex 的 mutation 中不能做异步操作?
- vue , 微信小程序 , uni-app的页面生命周期函数
对于MVVM的理解?
MVVM 是 Model-View-ViewModel 的缩写。
MVVM是model-view-viewmodel的缩写,即将数据原型与数据表现层通过数据驱动进行分离,从而只需要关心数据模型的开发,而不需要考虑页面的表现,具体如下:
Model代表数据模型:主要用于定义数据和操作的业务逻辑。
View代表页面展示组件(即DOM展现形式):负责将数据模型转化成UI展现出来。
ViewModel为model和view的桥梁:监听模型数据的改变和控制视图行为、处理用户交互。通过数据双向绑定把view层和model层连接了起来,而view和model之间的同步工作完全是自动的,无需人为干涉。
在MVVM框架下,view和model之间并没有直接的联系,而是通过ViewModel进行交互,Model和ViewModel之间的交互是双向的,因此View数据的变化会同步到model中,而Model数据的变化也会立即反应到view上。
VUE的生命周期及理解?
- beforeCreate:在new一个vue实例后,只有一些默认的生命周期钩子和默认事件,其他的东西还没有创建,其他的东西还没创建,data和methods中的数据还没有初始化,不能在这个阶段使用data中的数据和methods中的方法。
- created:data和methods都已经初始化好了,如果要调用methods中的方法,或者操作data中的数据,最早可以在这个阶段操作。
- beforeMount:执行到这个钩子的时候,在内存中已经编译好模版了,但是还没有挂载到页面,此时页面还是旧的,不能直接操作页面的DOM和获取DOM对象。
- mounted:执行到这个钩子的时候,就表示VUE实例已经初始化完成了。此时组件脱离了创建阶段,进入到了运行阶段,如果想要通过插件操作页面上的DOM节点,最早可以在这个阶段执行。
- beforeUpdate:当执行到这个钩子时,页面显示的数据还是旧的,data的数据是更新之后的,页面还没有和最新数据保持同步。
- updated:页面显示的数据和data的数据已经保持同步了,都是最新的。
- beforeDestroy:Vue实例从运行阶段进入到了销毁阶段,这个时候所有的data和methods、指令、过滤器…都是处于可用状态,还没有被真正销毁。
- destroyed:这个时候所有的data、methods、指令、过滤器…都是处于不可用状态,组件已经被销毁了。
第一次页面加载会触发哪几个钩子?
beforeCreate, created, beforeMount, mounted
Vue实现数据双向绑定的原理
- vue.js是采用数据劫持结合发布者-订阅者模式的方式,通过Object.defineProperty()来劫持各个属性的setter、getter,在数据变动时发布消息给订阅者,触发相应的监听回调。
- 具体步骤:
1.需要observe的数据对象进行递归遍历,包括子属性对象的属性,都加上setter和getter,这样的话,给这个对象的某个值赋值,就会触发setter,那么就能监听到数据变化。
2.compile解析模版指令,将模版中的变量替换成数据,然后初始化渲染页面视图,并将每个指令对应的节点绑定更新数据,添加监听数据的订阅者,一旦数据有变动,收到通知,更新视图。
3.watcher订阅者是observe和compile之间通信的桥梁,主要做的事情是:
在自身实例化时往属性订阅器(dep)里面添加自己;
自身必须有一个update()方法;
待属性变动dep.notice()通知时,能调用自身的update()方法,并触发compile中绑定的回调
4.MVVM作为数据绑定的入口,整合observe、compile和watcher三者,通过observe来监听自己的model数据变化,通过compile来解析编译模版指令,最后利用watcher搭建起observe和compile之间的通信桥梁,达到数据变化-视图更新;视图交互变化(input)-数据model变更的双向绑定效果。
虚拟DOM及其优缺点
虚拟DOM就是用JS对象模拟真实的DOM节点,也就是将所有更新DOM的操作全部反映在JS对象上。
虚拟DOM可以省去多余的操作;可以减少DOM操作(合并)。
为什么用虚拟DOM?
web界面由DOM树构建,当其中一部分发生变化时,其实就是对应的某个DOM节点发生了变化,虚拟DOM就是为了解决浏览器性能问题而被设计出来的。若一次操作中有10次更新DOM的操作,虚拟DOM不会立即操作DOM,而是将这10次更新的内容保存到本地的一个JS对象,最终将这个对象一次性反映到DOM树上,再进行后续的操作,避免了大量无谓的计算。
diff算法是什么?
diff算法就是用于比较新旧两个虚拟DOM之间差异的一种算法,本质是一个函数,输入参数是两个虚拟DOM。
diff算法有一个明显的缺点:横向比较存在BUG。
解决方案:加key。
使用key来给每个节点做一个唯一标识,diff算法就可以正确识别此节点,快速找到正确的位置。一句话:key的作用是为了高效的更新虚拟DOM。
Vue组件间的参数传递
- 父组件与子组件传值
父组件传给子组件:子组件通过props方法接受数据;
子组件传给父组件:$emit方法传递参数 - 非父子组件间的数据传递,兄弟组件传值
建立一个vue实例空白页作为中央事件处理线,数据发送方通过使用 e m i t 自定义事件把数据带过去,数据接收方使用而通过 emit自定义事件把数据带过去,数据接收方使用而通过 emit自定义事件把数据带过去,数据接收方使用而通过on监听自定义事件的callback接收数据
Vue路由的两种模式
- hash模式:在浏览器中符号“#”,#以及#后面的字符称之为hash,用window.location.hash读取;
特点:hash虽然在URL中,但不被包括在HTTP请求中;用来指导浏览器动作,对服务端安全无用,hash不会重加载页面。 - history模式:history采用HTML5的新特性;且提供了两个新方法:pushState(),replaceState()可以对浏览器历史记录栈进行修改,以及popState事件的监听到状态变更。
history 模式下,前端的 URL 必须和实际向后端发起请求的 URL 一致,否则会报404
v-if和v-show的区别?
- 共同点:都能控制元素的显示与隐藏。
- 不同点:实现本质方法不同,v-show本质就是通过控制css的display为none,控制隐藏,只会编译一次;v-if是动态的向DOM树内添加或删除DOM元素,若初始值为false,就不会编译了。而且v-if不停的销毁和创建比较消耗性能。
- 如果要频繁的切换某节点,使用v-show(切换开销比较小,初始开销比较大)。如果不需要频繁的切换某节点使用v-if,(初始渲染开销较小,切换开销比较大)。
- 分别会触发什么什么周期?
v-if是真正的条件渲染,能够保证在切换的过程中适当销毁和重建内部监听事件和子组件
v-show在true和false的切换中,不会触发生命周期
v-if在true变为false的时候卸载dom,触发beforeDestoryed和destoryed
v-if在false变成true的时候重建dom,触发beforeCreate、create、beforeMount、mounted
v-if和v-for同时使用在同一个标签上的表现?
当v-if和v-for一起使用时,v-for具有比v-if更高的优先级,这意味着v-if将分别重复运行于每个v-for循环中。
所以,不推荐两者同时使用。如果v-for和v-if同时使用,vue会自动提示v-if应放到外层去。
v-for中的key的理解?
需要使用key来给每个节点做个唯一标识,Diff算法就可以正确的识别此节点。主要是为了高效的更新虚拟DOM。
在循环数组时,使用index作为key,可以这样做,但是你要保证你的数组是静态的,没有新增,删除,插入,排序等情况,否则不能使用index作为key。有新增,删除,插入,排序等情况,会改变原有的key值,使原来的key值和现在不一样,影响diff算法的效率,而且会造成当前元素的key值变成另一个元素的key值了,让vue误认为这个元素可以复用另一个元素,造成不必要的bug。如果只是展示的静态数组,是可以使用index作为key值的。
v-model的理解
v-model用于表单数据的双向绑定,其实它就是一个语法糖,这背后就做了两个操作:
v-bind绑定一个value属性;
v-on指令给当前元素绑定input事件
computed和watch的用法和区别?
- computed计算属性:
1)变量不在data中定义,而是定义在computed中,写法跟写方法一样,有返回值。函数名直接在页面模版中渲染,不加小括号。
2)根据传入的变量的变化,进行结果的更新。
3)计算属性基于响应式依赖进行缓存。如其中的任意一个值未发送变化,它调用的就是上一次计算缓存的数据,因此提高了程序的性能。而methods中每调用一次就会重新计算一次。为了进行不必要的资源消耗,选择用计算属性。 - watch属性监听:
- 1)计算属性的时候、初始化的时候就可以被监听到并且计算,但是watch是发生改变的时候才会触发。
2)当有一些数据需要随着其他数据变动而变化时,或者当需要在数据变化时执行异步或开销较大的操作时,使用watch。 - 区别:
1)计算属性变量在computed中定义,监听属性变量在data中定义或是父组件传递来的props的数据
2)计算属性是声明式的描述一个值依赖了其他值,依赖的值改变后重新计算结果更新DOM。
属性监听的是定义的变量,当定义的值发生变化时,执行相应的函数。
3)computed不支持异步,watch支持异步,接收两个参数,最新的值和旧值
4)计算属性的时候、初始化的时候就可以被监听到并且计算,但是watch是发生改变的时候才会触发
5)计算属性基于响应式依赖进行缓存。如其中的任意一个值未发送变化,它调用的就是上一次计算缓存的数据;
computed和methods的区别?
(1)调用方式不同。computed是属性访问,直接以对象属性方式调用,不需要加括号,而methods是函数调用,必须要函数执行才能得到结果。
(2)是否存在缓存。methods没有缓存,每次都会重新计算。computed有缓存,在值不变的情况下不会再次计算,而是直接使用缓存中的值。
(3)绑定方式不同。methods和computed纯get方式都是单项绑定,computed的get和set方式才是真正的双向绑定。
data为什么是一个函数?
这是由JavaScript的特性所导致的,在component中,data必须以函数的形式存在,不可以是对象。组件中的data写成一个函数,数据以函数返回值的形式定义,这样每次复用组件的时候,都会返回一份新的data,相当于每个组件实例都有自己私有的数据空间,它们只负责各自维护的数据,不会造成混乱。而单纯的写成对象形式,就是所有的组件实例共用了一个data,这样改一个就全改了。
vue单页面和传统的多页面的区别?
- 单页面应用(SPA):
通俗一点说就是指只有一个主页面的应用。浏览器一开始要加载所有必需的JS、CSS、HTML。所有的页面内容都包含在这个所谓的主页面中。但是在写的时候,还是会分开写(页面片段),然后在交互的时候由路由程序动态载入,单页面的页面跳转,仅刷新局部资源。多应用于PC端。 - 多页面(MPA):
指一个应用中有多个页面,页面跳转时是整页刷新。 - 单页面的优点:
用户体验好、快,内容的改变不需要重新加载整个页面,基于这一点SPA对服务器压力较小;前后端分离;页面效果会比较酷炫(比如切换页面内容时的专场动画) - 单页面缺点:
不利于SEO;导航不可用;初次加载时耗时多;页面复杂度提高很多
vue的修饰符
.stop:等同于JavaScript中的event.stopPropagation(),防止事件冒泡。
.prevent:等同于JS中的event.preventDefault(),防止执行预设的行为。取消默认事件。
.capture:与事件冒泡的方向相反,,事件捕获由外向内。
.self:只会触发自己范围内的事件,不包含子元素。
.once:只会触发一次。
.number:将输入的值转换为数字类型,可以给v-model添加number修饰符。
vue更新数组时触发视图更新的方法?
push():向数组的末尾添加一个或多个元素,并返回新的长度
pop():从数组删除最后一个元素,返回被删除的值。
shift():删除首个元素,并把其他元素位移到更低的索引,返回被删除的值
unshift():在数组开头添加新元素,并反向位移旧元素,返回新数组的长度
splice(添加新元素的位置,应删除多少元素,要添加的新元素):向数组添加或删除新元素,返回包含已删除项的元素
sort():以字母顺序对数组进行排序
reverse():反转数组中的元素
vue-router有哪几种导航钩子?
vue-router的导航钩子主要作用是拦截导航,让它完成取消或跳转。
1.全局导航钩子
2.路由独享的钩子
3.组件内的导航钩子
vuex是什么?怎么使用?哪种功能场景使用它?
- 1)vue框架中状态管理。vuex就是一个仓库,仓库里放了很多对象。其中state就是数据源存放地,对应于一般vue对象里的data。
2)state里存放的数据是响应式的,vue组件从store读取数据,若是store的数据发生改变,依赖这数据的组件也会发生更新。
3)它通过mapState把全局的state和getters映射到当前组件的computed计算属性。 - vuex里的属性:
state:是一个数据存放的地方,类似于页面中的data。这个数据是可以共享的,组件之间都是可以共享的,但是不可以直接的去修改state里的数据。
getters:类似于vue的计算属性,主要用来过滤一些数据。组件可以通过此方法来获取想要的数据。
mutations:mutations定义的方法动态修改vuex的store中的状态和数据。
actions:可以理解为通过将mutations里面处理数据的方法变成可异步的处理数据的方法,简单来说就是异步操作数据。view层通过store.dispath来分发action。 - 在main.js引入store,注入。新建一个目录store,…export。
- vuex一般用于中大型web单页应用中对应用的状态进行管理,对于一些组件关系简单的小型应用使用vuex的必要性不是很大,因为完全可以使用组件props属性或事件来完成父子组件之间的通信,vuex更多的用于解决跨组件通信以及作为数据中心集中式存储数据。
- 场景:组件之间全局共享的数据,通过后端异步请求的数据,比如做购物车、登录状态都可以使用。
对keep-alive 的了解?
keep-alive是 Vue 内置的一个组件,可以使被包含的组件保留状态,或避免重新渲染。
在vue 2.1.0 版本之后,keep-alive新加入了两个属性: include(包含的组件缓存) 与 exclude(排除的组件不缓存,优先级大于include) 。
r o u t e 和 route和 route和router的区别
- $route是“路由信息对象”,包括path,params,hash,query,fullPath,matched,name等路由信息参数。
- $router是“路由实例”对象包括了路由的跳转方法,钩子函数等。
怎么定义 vue-router 的动态路由? 怎么获取传过来的值
在 router 目录下的 index.js 文件中,对 path 属性加上 /:id,使用 router 对象的 params.id 获取。
如何获取dom?
ref=“domName” 用法:this.$refs.domName
vue-loader是什么?使用它的用途有哪些?
- vue文件的一个加载器,将template/js/style转换成js模块。
- 用途:js可以写es6、style样式可以scss或less、template可以加jade等
v-on可以监听多个方法吗?
可以,栗子:
<input type="text" v-on="{ input:onInput,focus:onFocus,blur:onBlur, }" >。
$nextTick的使用
当你修改了data的值然后马上获取这个dom元素的值,是不能获取到更新后的值,你需要使用$nextTick这个回调,让修改后的data值渲染更新到dom元素之后在获取,才能成功。
axios的特点有哪些
axios 是一个基于 promise 的 HTTP 库
- 特点:
从浏览器中创建XMLHttpRequests;
node.js创建http请求;
支持Promise API;
拦截请求和响应;
转换请求数据和响应数据;
取消请求;
自动换成json;
axios中的发送字段的参数是data跟params两个,两者的区别在于params是跟请求地址一起发送的,data的作为一个请求体进行发送;
params一般适用于get请求,data一般适用于post put 请求。
请说下封装 vue 组件的过程?
- 建立组件的模板,先把架子搭起来,写写样式,考虑好组件的基本逻辑。
- 准备好组件的数据输入。即分析好逻辑,定好 props 里面的数据、类型。
- 准备好组件的数据输出。即根据组件逻辑,做好要暴露出来的方法。
- 封装完毕了,直接调用即可
params和query的区别
- 用法:query要用path来引入,params要用name来引入,接收参数都是类似的,分别是this. r o u t e . q u e r y . n a m e 和 t h i s . route.query.name和this. route.query.name和this.route.params.name。
- url地址显示:query更加类似于我们ajax中get传参,params则类似于post,说的再简单一点,前者在浏览器地址栏中显示参数,后者则不显示
- 注意点:query刷新不会丢失query里面的数据
params刷新 会 丢失 params里面的数据。
active-class 是哪个组件的属性?
active-class是vue-router模块的router-link组件中的属性,用来做选中样式的切换
vue-router实现路由懒加载( 动态加载路由 )
- vue异步组件技术 ==== 异步加载,vue-router配置路由 , 使用vue的异步组件技术 , 可以实现按需加载 .但是,这种情况下一个组件生成一个js文件。
- 路由懒加载(使用import)。
- webpack提供的require.ensure(),vue-router配置路由,使用webpack的require.ensure技术,也可以实现按需加载。这种情况下,多个路由指定相同的chunkName,会合并打包成一个js文件。
vuex有哪几种属性?
有五种,分别是 State、 Getter、Mutation 、Action、 Module
state => 基本数据(数据源存放地)
getters => 从基本数据派生出来的数据
mutations => 提交更改数据的方法,同步!
actions => 像一个装饰器,包裹mutations,使之可以异步。
modules => 模块化Vuex
vuex actions和mutations的区别?
actions:通过提交mutation改变数据;会将自身封装成一个promise;可以包含异步操作;
mutations:通过提交commit改变数据;只是一个单纯的函数;不要使用异步操作,会导致变量不能追踪
为什么 Vuex 的 mutation 中不能做异步操作?
(1) Vuex中所有的状态更新的唯一途径都是mutation,异步操作通过Action来提交mutation实现,这样可以方便地跟踪每一个状态的变化,从而能够实现一些工具帮助更好地了解我们的应用。
(2) 每个mutation执行完成后都会对应到一个新的状态变更,这样devtools就可以打个快照存下来,然后就可以实现time-travel 了。如果mutation支持异步操作,就没有办法知道状态是何时更新的,无法很好的进行状态的跟踪,给调试带来困难。
vue , 微信小程序 , uni-app的页面生命周期函数
Vue:
beforeCreate(创建前)
created(创建后)
beforeMount(载入前,挂载)
mounted(载入后)
beforeUpdate(更新前)
updated(更新后)
beforeDestroy(销毁前)
destroyed(销毁后)
小程序/uni-app:
1. onLoad:首次进入页面加载时触发,可以在 onLoad 的参数中获取打开当前页面路径中的参数。
2. onShow:加载完成后、后台切到前台或重新进入页面时触发
3. onReady:页面首次渲染完成时触发
4. onHide:从前台切到后台或进入其他页面触发
5. onUnload:页面卸载时触发
6. onPullDownRefresh:监听用户下拉动作
7. onReachBottom:页面上拉触底事件的处理函数
8. onShareAppMessage:用户点击右上角转发