vue面试题
day1
vue.js 是什么
vue是一个数据驱动构建用户界面的渐进式框架,
尽可能通过简单的API实现响应式的数据绑定和组合的视图组件
核心是响应的数据绑定系统和组件化的开发模式
简述vue.js的优点
1.轻量级的框架
2.简单易学上手快
3.双向数据绑定
4.组件化的开发模式
5.视图、数据、结构分离
6.虚拟DOM
7.运行速度快
对于MVVM的理解
-
首先MVVM是Model-View-ViewModel的缩写
-
MVVM是一种设计思想
-
Model代表数据模型,数据和业务逻辑都在model层中定义
-
View代表UI组件,负责数据的展示
-
ViewModel监听模型数据的改变和控制视图行为,简单来说就是一个双向数据绑定,ViewModel的作用就是把Model对象封装成可以显示和接受输入的界面数据对象
-
View和Model之间没有直接的联系,而是通过viewmodel进行交互的,Model和ViewModel之间的交互式双向的,因此view数据的变化会同步到Model,而Model数据的变化也会立即反应到View上
什么是vue的生命周期
生命周期就是vue实例从创建到销毁的过程 从开始创建、初始化数据、编译模板、挂载DOM->渲染、更新->渲染、销毁等一系列过程,称之为vue的生命周期
vue的生命周期
vue的生命周期分为8个阶段: 创建前/创建后 挂载前/挂载后 更新前/更新后 销毁前/销毁后
所有的生命周期钩子自动绑定this上下文到实例中,因此可以访问数据,对属性和方法运算。不能使用箭头函数来定义一个生命周期。因为箭头函数绑定了父上下文,会报错。
-
beforeCrete创建前:在实例初始化之后,数据观测(data observer)和event/watcher事件配置之前被调用 -
creted创建后:在实例创建完成后被立即调用。在这一步,实例已完成以下配置:数据观测(data observer),属性和方法的运算,watch/event事件回调。挂载还没开始,$el属性不可用 -
beforeMount挂载前:在挂载开始之前被调用:相关的render函数首次被调用 -
mounted挂载后:实例被挂载后调用,这是el被新创建的vm.el也在文档内。mounted不会保证所有的子组件也都一起被挂载,如果希望整个视图都渲染完毕,可以在mounted内部使用vm.$nextTick
-
beforeUpdate更新前:数据更新时被调用,发生在虚拟DOM更新之前,这里适合在更新之前访问现有的DOM,比如手动移出已添加的事件监听器 -
updated更新后:由于数据更改导致虚拟DOM重新渲染,在这之后会调用该钩子。当这个钩子被调用时,组件DOM已经更新,所以现在可以执行依赖DOM的操作。但是应该避免在此时更改状态,最好使用计算属性和watch来替代 -
beforeDstory销毁前:实例销毁之前调用。这一步实例仍然可用 -
destoryed销毁后:实例销毁后调用。被调用后,该对应vue实例的所有指令都被解绑,所有事件监听器都被移除。所有的子实例也都被销毁
一上来就执行的只有前四个 beforeCreate created beforeMount mounted
服务器端渲染只有beforeCreate created执行
vue生命周期的作用是什么
生命周期中有多个事件钩子,让我们在控制整个vue实例的过程中更容易形成好的逻辑
第一次页面加载会触发哪几个钩子函数
breforeCrete creted beforeMount mounted
DOM渲染在哪个周期就已经完成了
DOM渲染在mounted中就已经完成了
day2
vue实现数据双向绑定的原理
Object.defineProperty() vue 实现双向绑定的主要采用数据劫持结合发布订阅模式的方式。 通过Object.defineProperty()来劫持各个属性的getter,setter,在数据变动时发布消息给订阅者,触发相应的监听回调。当一个普通的javascript对象传给vue实例来作为它的dota选项时,vue将遍历它的属性,用Object.defineProperty将他们转为getter/setter.用户看不到getter/setter 但是在内部他们让vue 追踪以来,在属性被访问和修改时通知变化
vue的数据双向绑定将MVVM作为数据绑定的入口,整合Observer,Compile和watch三者,通过Observer来监听自己的model的数据变化,通过Compile来解析编译模板指令,最终watcher搭起observer和compile之间的通信桥梁,达到数据变化->视图更新;视图交互变化->数据model变更双向绑定效果
<body>
<div id="app">
<input type="text" id="txt"/>
<p id="show"></p>
</div>
</body>
<script>
var obj = {}
Object.defineProperty(obj,'txt',{
get(){
return obj
},
set(newValue){
document.getElementById('txt').value=newValue;
document.getElementById('show').innerHTML = newValue;
}
})
document.addEventListner('keyup',function(){
obj.txt = e.target.value
})
</script>
vue组件之间的通信
常见的使用场景可以分为三类:
- 父子组件通信
- 兄弟组件同喜
- 跨级组件通信
具体组件方法:
1.父传子 props
2.子传父 parent
4.
refs
7.
listeners
8.eventBus
9.vuex
10.localStorage
v-show 与 v-if 区别
1.v-show是css切换diplay,v-if是完整的销毁和重新创建
2.频繁切换用v-show 运行较少改变时用v-if
3.v-if只有为true的时候才会真实的渲染DOM,v-show不管是否为真都会渲染真实DOM
请问 v-if 和 v-show 有什么区别
-
共同点:
v-if和v-show都是动态显示DOM元素
-
不同点:
1.编译过程:v-if是真正的条件渲染;v-show的元素始终会被渲染并保留DOM,v-show只是简单的切换display属性 2.编译条件:v-if是惰性的,如果初始渲染条件为假,则什么也不做,直到条件第一次变为真,才开始渲染条件块代码。v-show不管初始条件是什么,元素总是会被渲染,并且只是简单的基于css进行切换。 3.性能消耗:v-if有更高的切换消耗。v-show有更高的初始渲染消耗 4.应用场景:v-if适合运行时条件很少改变时使用。v-show适合频繁切换
绑定class的数组用法
- 数组用法:
<div v-bind="[class1,class2]"></div> - 对象用法:
<div v-bind="{'orange':boolean,'green':boolean}"></div> - 行内用法:
<div style="{color:color,fontSize:fontSize+'px'}"></div>
计算属性computed和watch的区别
计算属性是自动监听依赖值得变化,从来动态返回内容,监听是一个过程,在监听的值变化时,可以触发一个回调,并做一些事 所以区别来源于用法,只是需要动态值,那就用计算属性 需要知道值得改变后执行业务逻辑,才用watch
当有一些数据需要随着另外一些数据变化的时候,建议用computed 当有一个通用的响应数据变化的时候,要执行一些业务逻辑或者异步操作时候建议用watch
computed是一个对象时,有哪些选项
有get和set两个选项
computed和methods有什么区别
methods是一个方法,他可以接收参数,而computed不能,computed是可以缓存的,methods不会
computed是否依赖其它组件的数据
computed可以依赖其它computed,甚至是其它组件的data
watch是一个对象时,它有哪些选项
handle deep:是否深度监控 immeditate 是否立即执行
组件中的data为什么是函数
因为组件是可以服用的,js里对象时引用的关系,这样作用域没有隔离,而new Vue的实例,是不会服用的,因此不存在引用对象的问题
v-model是怎样实现的
v-model 就是一个语法糖 分开写就是 v-bind="value" v-on:input="" 既绑定了数据,又添加了一个input事件监听
怎么理解单向数据流
父组件通过prop把数据传递到子组件,但是这个prop只能由父组件修改,子组件不能修改,否则会报错。子组件想修改时,只能通过$emit派发一个自定义事件,父组件接收之后,由父组件修改。
一般来说,对于子组件想修改父组件的场景,可以有两种方案:
在子组件的data中拷贝一份prop,data是可以修改的,但prop不能:
export default{
props:{
value:String
},
data(){
return {
currentVal:this.value
}
}
}
如果是对prop值得转换,可以使用计算属性:
export default{
props:['size'],
computed:{
normalLizedSize(){
return this.size.trim().toLowerCase()
}
}
}
day3
vue几种常用的指令
- v-bind 简写":"
- v-on 简写"@"
- v-model
- v-for
- v-if
- v-else
- v-if-else
- v-show
- v-text
- v-html
- v-slot
- v-pre
- v-cloak
- v-once
vue常用的修饰符
v-on指令常用修饰符:
- .stop 调用event.stopPropagation() 阻止事件冒泡
- .prevent 调用event.preventDefault() 阻止事件默认行为
- .capture 添加事件侦听器使用capture模式
- .self 只当事件是从侦听器绑定的元素本身触发时才触发回调
- .{keyCode | keyAlias}只当事件是从特定键触发时才触发回调
- .native 监听是组件根元素的原生事件
- .once 只触发一次回调
- .left 点击鼠标左键触发
- .right 点击鼠标右键触发
- .middle 点击鼠标中键触发
- .passive 以{passive:true}模式添加侦听器
v-bind指令常用修饰符:
- .prop 被用于绑定DOM属性
- .camel 将kebab-case特性转换为camelCase
- .sync 语法糖 会扩展成为一个更新父组件绑定值得v-on侦听器
v-model指令常用修饰符:
- .lazy 取代input监听change事件
- .number 输入字符串转为数字
- .trim 过滤首尾空格过滤
v-on可以监听多个方法吗
可以监听多个方法,但是同一种事件类型的方法,vue-cli会报错
vue中key值的作用
key值:用于管理可复用的元素。 因为vue会尽可能高效的渲染元素,通过会复用已有的元素而不是从头开始渲染。这么做使vue 变得非常快,但是也不是总是符合实际需求。
当前组件中使用v-for时,key现在是必须的。
要解释key的作用,你得先了解虚拟DOM的Diff算法 vue实现了一套虚拟DOM,使我们可以不直接操作DOM,只操作数据便可以重新渲染页面。 vue的虚拟DOM的Diff算法,其核心是基于两个简单的假设: 1.两个相同的组件产生类似的DOM结构,不用的组件产生不同的DOM结构。 2.同一层级的一组节点,他们可以用过唯一的id进行区分
当页面的数据发生变化时,Diff算法只会比较用一层级的节点:
- 如果节点类型不同,直接干掉前面的节点,再创建并插入新的节点,不会再比较找个节点以后的节点。
- 如果节点类型相同,则会重新设置该节点的属性,从而实现节点的更新 当某一层有很多相同节点时,也就是列表节点时,Diff算法的更新过程默认情况下也是遵循以上原则
所以一句话key的作用主要是为了高效的更新虚拟DOM。 另外vue在使用相同标签名元素的过渡切换时,也会使用到key,其目的时为了让vue可以区分它们
vue事件中如何使用event对象
// html
<a data-id="12" @click="showEvent($event)">
// js
showEvent(event){
console.log(event.target.dataset.id);
event.stopPropagation()
event.preventDefault()
}
nextTick的使用
因为vue时异步更新队列,$nextTick是用来知道什么时候DOM更新完成的
异步更新队列: vue在观察到数据变化时并不是直接更新DOM,而是开启一个队列,并缓冲在同一个事件循环中发生的所有数据改变。在缓冲时会去除重复数据,从而避免不必要的计算和DOM操作。然后在下一个事件循环tick中,vue刷新队列并执行实际工作。所以用一个for循环来动态改变数据100次,其实它只会应用最后一次改变,如果没有这种机制,DOM就要重绘100次,这固然时一个很大的开销。
vue组件中的data为什么必须是函数
因为组件是可以共享的,但他们的data是私有的,所以每个组件都要return一个新的data对象, 返回一个唯一的对象,不要和其它组件共用一个对象。
v-for和v-if的优先级
当他们处于同一节点,v-for的优先级比v-if更高,这意味着v-if将分别重复运行与每个v-for循环中。
day4
vue中keep-alive组件的作用
keep-alive主要用于保留组件或避免重新渲染
属性:
- include:只有匹配到的组件会被缓存
- exclude:任何匹配到的都不会被缓存
包裹动态组件时,会缓存不活动的组件实例,而不是销毁。和<transition></transition>类似,
<keep-alive></keep-alive>时一个抽象组件,本身不会渲染一个DOM元素
vue如何监听键盘事件中的按键
按键修饰符: vue允许v-on在监听键盘事件时,添加按键修饰符:
- .enter
- .tab
- .delete
- .esc
- .up
- .down
- .left
- .right
可以通过全局config。keyCodes对象自定义按键修饰符别名:Vue.config.keyCodes.f1 = 112
系统修饰符:
- .ctrl
- .alt
- .shift
- .meta
鼠标按钮修饰符:
- .left
- .right
- .middle
vue更新数组时触发视图更新的方法
- pop()
- push()
- shift()
- unshift()
- splice()
- reverse()
- sort()
这几个方法会触发视图更新
替换数组:
filter() concat() slice() 这些不会改变原数组,但是会返回一个新的数组,当使用这些非变异方法时,可以用新数组替换旧数组
注意事项: 不要直接修改data的数据值,因为直接修改数组的某一项或者数组的长度,修改之后不是响应的值,页面不会更新。 可以使用Vue.set(vm.items,indexOfItem,newValue)或者vm.$set(vm.items,indexOfItem,newValue)
vue中对于对象的更改检测
由于javascript的限制,vue不能检测对象属性的添加或删除:
对于已创建的实例,vue不能动态添加根级别的响应式属性,但是可以用Vue.set(object,key,value)方法向嵌套对象添加响应式属性。
let vm = new Vue({
data(){
userProfile:{
name:'hulongfei'
}
}
})
Vue.set(vm.userProfile,'age',29)
vm.$set(vm.userProfile,'age',29)
// 给已有对象赋予多个新属性
`Object.assign()`
vm.userProfile = Object.assign({},vm.userProfile,{
age:29,
like:'Vue Green'
})
非工程化项目初始化页面闪动问题
// css
[v-cloak]{
display:none
}
// html
<div id="app" v-cloak>{{message}}</div>
// js
let vm = new Vue({
data(){
return{
message:'this is text!'
}
}
})
v-cloak时解决初始化慢导致页面闪动的最佳实践,对于简单的项目很实用
v-for产生的列表,实现active的切换
通过设置当前currentIndex实现:
<template>
<div class="toggleClassWrap">
<ul>
<li @click="currentIndex = index" :class="clicked:index === currentIndex" v-for="(item,index) in desc" :key="index">
<a href="javascript:;">{{item.ctrlValue}}</a>
</li>
</ul>
</div>
</template>
<script>
export default{
data(){
return {
desc:[
{
ctrlValue:'test1'
},
{
ctrlValue:'test2'
},
{
ctrlValue:'test3'
},
{
ctrlValue:'test4'
}
],
currentIndex:0
}
}
}
</script>
<style lang="less">
.clicked{
color:red
}
</style>
v-model语法糖的使用
v-model仅仅是个语法糖
<input v-model="something"/>
<input :value="something" @input="something=$event.target.value"/>
<custom :value="sonmething" @input="something=$event.target.value'"></custom>
day5
vue单页应用机器优缺点
单页web应用(SPA): 就是只有一张web页面的应用。单页应用程序是加载单个HTML页面并在用户和应用程序交互时动态更新该页面的web应用程序。浏览器一开始会加载必须的HTML、CSS、JS所有操作都在这张页面上完成,都由js来控制。因此,对单页应用来说模块化的开发和设计显得相当重要。
单页应用的优点:
- 提供了更加吸引人的用户体验:具有桌面应用的即时性,网站的可移植性和可访问性。
- 单页应用的内容的改变不需要重新加载整个页面,web应用更具响应性
- 单页应用没有页面之间的切换,就不会出现“白屏现象”也不会出现假死现象
- 单页应用相对服务器压力小,服务器只用出数据就可以,不用管展示逻辑和页面合成,吞吐能力会提高几倍。
- 良好的前后端分离。后端不负责模板渲染输出页面功能,后端API通用化,即同一套后端程序代码,不用修改就可以用web页面、手机、平板灯多种客户端
单页web应用的缺点:
- 首次加载耗时比较多
- SEO问题,不利于百度,360等搜索引擎收录
- 容易造成css命名冲突
- 前进,后退,地址栏,书签,都需要程序进行管理,页面的复杂度很高,需要一定的技能水平和开发成本高
什么是vue的计算属性
计算属性:
模板内的表达式非常便利,但是设计它们的初中时用于简单运算的,在模板中中放入太多的逻辑会让模板过重而且难以维护。
计算属性的缓存和方法调用有什么区别
- 计算属性必须返回结果
- 计算属性是基于它的依赖缓存的,一个计算属性所依赖的数据发生变化时,他才会重新取值
- 使用计算属性还是methods取决于是否需要缓存,当便利大数组和做大量计算式,应当使用计算属性,除非你不希望得到缓存
- 计算属性是根据依赖自动执行的,methods需要事件调用