又到了金三银四跳槽黄金时期,are you ready 😊😊? 想必又有大批同行要跳槽~涨薪💲💲💲。。。。。。 所以小编给大家总结了一份Vue面试礼包💟,这篇文章小编是自己经过查阅资料、参考官方文档以及自己动手实践总结的。如果发现有问题,欢迎到评论区交流😁😁
小编希望读者看到题目时,自己先思考一下,想想你的答案是啥?然后再查看小编给提供的答案。
话不多说,直接上题 🏆
一、Vue基础知识
1. 什么是MVVM?
展开查看
参考文章
MVVM是Model-View-ViewModel
的简写。Model
是数据模型, View
是UI组件,View-Model
是View和Model层的桥梁;数据会绑定到ViewModel层并自动将数据渲染到页面中,视图变化的时候会通知viewModel层更新数据。
总结: 在MVVM的框架下视图和模型是不能直接通信的,它们通过
ViewModel
来通信,ViewModel通常要实现一个observer观察者
, 当数据变化时,ViewModel
能够监听到数据的变化,然后通知到对应的视图做自动更新
。
2. Vue的优点是什么?
展开查看
轻量级框架: 只关注视图层,是一个构建数据的视图集合,大萧只有几十kb;
简单易学:国人开发,中文文档,不存在语言障碍,已于理解和学习;
双向数据绑定: 保留angular的特点,在数据操作方面更为简单;
组件化: 保留了react的优点,实现了html的封装和重用,在构建单页面应用方面有着独特的优势;
视图、数据、结构分离: 使数据的更改更为简单,不需要进行逻辑代码的修改,只需要操作数据就能完成相关操作;
虚拟DOM: dom操作是非常耗费性能的,不在使用原生的dom操作节点,极大解放dom操作,但具体操作的还是dom,只不过是换了一种方式;
运行速度更快: 相对比较与react而言,同样操作虚拟dom,就性能而言,vue存在很大的优势。
3. Vue的两个核心点是什么?
展开查看
数据驱动
和 组件系统
。
数据驱动: ViewModel,保证数据和视图一致性。
组件系统: 引用类UI可以看作全部是由组件树构成的。
4. 三大框架的优缺点?(vue、React、Angular)
展开查看
4.1 与angularJs的区别:
相同点:
- 都支持指令(内置指令和自定义指令);
- 都支持过滤器(内置过滤器和自定义过滤器);
- 都支持双向数据绑定;
- 都不支持地段浏览器;
不同点:
-
angularJs学习成本高,而vue本身提供的API都比较简单、直观;
-
在性能上,AngularJS依赖对数据做脏检查,所以Watch越多越慢;
-
Vue.js使用基于依赖追踪的观察并且使用异步队列更新, 所有的数据都是独立开发的。
4.2 与React的区别:
相同点: React采用特殊的JSX语法, Vue.js在组件中开发也是推崇写.vue特殊文件格式,对文件内容都有一些约定,两种都需要编译后使用;中心思想相同;一切都是组件,组件实例之间可以嵌套;都是提供合理的生命周期钩子函数,可以让开发者定制化的去处理需求;都不是内置ajax、router等功能到核心包,而是以插件的方式加载;在组件开发中都支持mixins的特性;
不同点: React采用虚拟DOM会对渲染出来的结果做脏检查;Vue.js在模板中提供了指令,过滤器等,可以非常方便,快捷的操作虚拟DOM
5. Vue和Jquery的区别?
展开查看
1. 操作、性能
-
jQuery是使用选择器($)选取DOM对象,对其进行复制、取值、事件绑定等操作,其实和原生的HTML的区别只在于可以方便的选择和操作DOM元素,而数据和界面是在一起的。
-
Vue则是通过Vue对象将数据和View完全分离开来。对数据进行操作不在需要引用相应的DOM对象,可以说数据和View是分离的,他们通过Vue对象的Vm实现相互绑定。这就是MVVM.
2. Vue支持组件化、模块化
3. vue支持双向数据绑定
6. SPA首屏加载慢如何解决?
展开查看
首屏时间:
指的是浏览器从响应用户输入网址地址,到首屏内容渲染完成的时间,此时整个网页不一定要全部渲染完成,但是需要展示当前视窗需要的内容。
首屏加载慢的原因:
- 网络延时的问题;
- 资源文件体积是否过大
- 资源是否重复发送请求去加载了
- 加载脚本的时候,渲染内容堵塞了。
常见的首屏优化方式:
- 减小入口文件;
- 静态资源本地缓存
- UI框架按需加载;
- 图片资源的压缩;
- 组件重复打包;
- 开启GZIP压缩
- 使用SSR
7.Scss的安装以及如何使用?
展开查看
在Vue项目种的引用方式, 指定语言为scss;
安装依赖包
npm i node-sass sass-loader style-loader -D
配置loader
{
test: /\.scss$/,
loader: 'sass-loader!style-loader!css-loader',
}
scss基本用法
-
- 变量的使用 以$开头申明变量 变量具有作用域的 变量种连接符种划线和下划线是胡同的
-
- 样式嵌套
-
- 混入样式
-
- 样式继承
-
- 导入文件
8.vue常用的UI组件库
展开查看
Mint UI、iview 、Element UI、Vant、Weex/wiːks/
9. Vue构建初始化工程步骤
展开查看
第一种方法:通过脚手架创建
-
全局安装 vue-cli npm install -g vue-cli
-
创建一个基于 webpack模板的新项目 vue init webpack demo
-
进入项目文件夹 cd demo
-
安装依赖包 npm install
-
npm run dev
第二种方法:通过Gui可视化面板创建项目
-
在终端窗口输入vue ui,打开可视化窗口;
-
点击创建按钮
-
2.1 选择要创建项目的目的路径
-
2.2 填写项目名称
-
2.3 下一步 ...下一步...配置路由等配置
10. 聊聊 keep-alive
展开查看
keep-alive是一个抽象组件:它自身不会渲染一个DOM元素,也不会出现在父组件链中;使用keep-alive包裹动态组件时,会缓存不活动的组件实例,而不是销毁它们。
Props:
include:
字符串或正则表达式。只有名称匹配的组件会被缓存。
exclude:
字符串或正则表达式。任何名称匹配的组件都不会被缓存。
max
:数字。最多可以缓存多少个实例。
有关的生命周期:
activated钩子
:keep-alive 组件激活时调用。
deactivated钩子
:keep-alive 组件停用时调用。
以上钩子服务器端渲染期间不被调用。
为什么keep-alive组件自身不会被渲染?
Vue在初始化生命周期的时候,为组件实例建立父子关系会根据abstract
属性决定是否忽略某个组件。在keep-alive
中,设置了abstract: true,
那么Vue就会跳过
该组件实例。
Vue.js内部将DOM节点
抽象成一个个的VNode节点
,keep-alive组件
的缓存也是基于VNode节点
的而不是直接存储DOM结构
。它将满足条件的组件在cache对象
中缓存起来,在需要重新渲染的时候再将vnode节点
从cache对象
中取出来并渲染。
11. v-show与v-if的区别
展开查看
v-if
(1)是真正得条件渲染,因为它会确保在切换过程中条件块内的事件监听器和子组件适当的被销毁和重建;
(2)也是惰性的:如果初始渲染条件为假,则什么也不做;直到第一次变为真时,才会开始渲染条件块;
v-show
不管初始条件时什么,元素总会被渲染,并且只是简单的基于css
的display
属性进行切换。
综上:
v-if
适用于在运行时很少改变条件,不需要频繁切换条件的场景;
v-show
则适用于需要非常频繁的切换条件的场景;
12. 绑定class的数组方法
展开查看
对象方法 v-bind:class="{'orange': isShow, 'active': isActive}"
数组方法 v-bind:class="[ class1, class2]"
行内 v-bind:style="{ color: color, fontSize: fontSize+'px'}"
13. 计算属性computed和监听watch的区别?
展开查看
computed:
computed
是计算属性,也就是计算值,它更多用于计算值的场景.
computed具有缓存性
, comouted的值在getter执行后是会缓存的,只有在它依赖的属性值变化之后,下一次获取computed的值才会重新调用对应的getter来计算。
computed
适用于当表达式过于复杂,在模板中放入过多的逻辑会让模板难以维护,可以将复杂的逻辑放入计算属性中处理。
watch:
watch
更多的是[观察]的作用,类似于某些数据的监听回调,用于观察props、$emit
或者本组件的值,当数据变化时来执行回调进行后续操作。当我们需要深度监听对象的属性时,可以打开deep: true
选项。
无缓存性,页面重新渲染时值不变化也会执行;
小结:
当我们要进行数值计算,而且依赖于其他数据,那么把这个数据涉及为computed
;
如果你需要在某个数据变化时做一些事情,使用watch
来观察这个数据变化;
14.组件中data为什么是函数?
展开查看
为什么组件中的data必须时一个函数,然后return一个对象, 而new Vue实例里,data可以直接是一个对象?
因为组件是用来复用
的,JS里对象是引用
关系,这样作用域没有隔离,而new Vue的实例,是不会被复用的,因此不存在引用对象的问题。
15.Vue中key值的作用?
展开查看
key 主要是应用在 Diff 算法
中,作用是为了更快速定位出相同的新旧节点,尽量减少 DOM
的创建和销毁的操作。
另外vue中在使用相同标签名元素的过度切换时,也会使用key属性
,其目的也是为了让vue
可以区分它们,否则vue只会替换
其内部属性而不会触发过度效果。
-
用组件唯一的id(一般由后端返回)作为它的key, 是在没有的情况下可以获取到列表的时候通过某种规则为他们创建一个key, 并保证key在整个生命周期中都保持稳定;
-
如果你的列表顺序回边,别用index作为key,和没写基本上没有区别,因为不管你的数组顺序怎么颠倒,index都是0,1,2这样排...
-
千万别用随机数作为key,不然就节点会被全部删除,新节点重新创建。
16. vue.cli项目中src目录每个文件夹和文件的用法?
展开查看
assets
文件夹是放静态资源;
components
是放组件;
router
是定义路由相关配置;
app.vue
是一个应用的主组件;
main.js
是入口文件;
17.事件修饰符
展开查看
.once:
只触发一次;
.self:
只会触发自己范围内的事件,不包含子元素;
.capture:
与事件冒泡的方向相反,事件捕获由外到内;
.prevent:
防止执行预设的行为;
.stop:
防止事件冒泡;
18. 组件通信方式
展开查看
1. 子组件调用父组件的方法和属性:
(1)直接在子组件中通过this.$parent.方法/this.$parent.属性
来调用父组件的方法或属性;
(2)在子组件里用$emit
向父组件触发一个事件,父组件监听这个事件就行;
(3) 父组件把方法传入子组件中,在子组件里直接调用这个方法;
2. 子组件给父组件传值:
2.1 使用ref
父组件调用子组件时绑定属性ref
<banner :ref="bannerCom"/>
在父组件中使用`this.$refs.bannerCom.属性/ this.$refs.bannerCom.方法`
2.2 使用$emit方法
子组件调用`this.$emit("方法名",传值)`
父组件通过子组件绑定的方法名获取值
3. 父组件调用子组件的方法
(1) 父组件利用ref属性操作子组件的方法
`this.$refs.childMethod.test() `
4. 父组件给子组件传值
`<parent :dataList='dataList'></parent>`
19. assets和static的区别:
展开查看
相同点:
assets和static两个都是存放静态资源文件。项目中所需要的资源文件图片,字体图标,样式文件等都可以放在这两个文件下,这是相同点。
不同点:
assets中存放的静态资源文件在项目打包时,也就是运行npm run build时将会assets中防止的静态资源文件进行打包上传。所谓打包简单点可以理解为压缩体积,代码格式化。而压缩后的静态资源文件最终也会放置在static文件中跟着index.html一同上传至服务器。static中防止的静态资源文件就不会走打包压缩等流程,而是直接进入打包好的目录,直接上传至服务器。因为避免了压缩直接进行上传,在打包时会提高一定的效率,但是static中的资源文件由于没有进行压缩等操作,所以文件的体积也就i选哪个对于assets中打包后的文件提交较大点。在服务器就会占据更大的空间。
建议:
尽量将需要的静态资源放在assets中走打包流程,这样会减少空间。
20.在使用计算属性时,函数名和data数据源中的数据可以同名吗?
展开查看
不能同名。因为不管是计算属性还是
data还是props都会被挂在到vm实例上
,因此这三个都不能同名。
21. 怎么解决vue打包后静态资源图片失效的问题
展开查看
找到config/index.j
s配置文件,找到build打包对象里的assetsPublicPath
属性默认值为/,更改为./
就好了。
22. 怎么解决vue动态设置img的src不生效的问题?
展开查看
因为动态添加src被当作静态资源处理了,没有进行编译,所以要加上require
.
<img :src="require('../../../assets/images/xxx.png')" />
23. 如何给vue定义全局的方法?
展开查看
(1)挂在到Vue的protype上。
把全局方法写在一个文件里面,然后for循环挂在带Vue的prototype
上。缺点就是调用这个方法的时候没有提示。
Object.keys(tools).forEach(key => {
Vue.prototype[key] = tools[key]
})
(2)利用全局混入mixin.
因为mixin
里面的methods会和创建的每个但文件组合合并。这样做的有点时调用这个方法的时候有提示。
Vue.mixin(mixin)
new Vue({
store,
router,
render: h => h(App),
}).$mount('#app')
24. 对Vue项目进行那些优化?
展开查看
(1)代码层面的优化
-
v-if和v-show区分使用场景
-
computed和watch区分使用场景
-
v-for遍历必须为item添加key,且便面同时使用v-if
-
长列表性能优化
-
事件的销毁
-
图片资源懒加载
-
路由懒加载
-
第三方插件的按需引入
-
优化无线列表性能
-
服务端渲染SSR or 预渲染
(2) Webpack层面的优化
-
Webpack对图片进行压缩 (使用image-webpack-loader,在webpack.config.js中配置)
-
减少ES6转为ES5的冗余代码
-
提取公共代码
-
模板预编译
-
提取组件的CSS
-
优化SourceMap
-
构建结果输出分析
-
Vue项目的编译优化
(3)基础的web技术优化
-
开启gzi压缩
-
浏览器缓存
-
CDN的使用
25. vue有哪些指令,简单介绍一下
展开查看
v-if:
条件为true时,才会渲染,否则不会渲染,条件为false时,压根不回由对应的DOM中。
v-else
: 和v-if一起使用
v-for:
用于遍历渲染,渲染组件必须带上key
v-show:
决定一个元素是否展示;条件为false,仅仅将元素的dispaly属性设置为none;
v-on:
绑定事件监听器 。语法糖是@click
v-bind:
绑定一个或者多个属性,语法糖是:
v-slot:
插槽,作用是占位,用于封装组件
v-text:
和{{}}相似,都是用于将数据现实在界面中
v-html:
将string的html解析出来并进行渲染
v-once:
元素和组件只渲染一次
v-model:
用来实现表单元素和数据的双向绑定。
26. 怎么监听数据变化(watch)?
展开查看
watch的作用可以监听一个值的变换,并调用因为变化需要执行的方法。可以通过watch动态改变关联的状态。
(1)watch的基本使用:
<template>
<div>
<p>FullName: {{fullName}}</p>
<p>FirstName: <input type="text" v-model="firstName"></p>
</div>
</template>
<script>
export default {
data(){
return{
firstName: 'Zhang',
lastName: 'San',
fullName: ''
}
},
watch: {
firstName(newName, oldName) {
this.fullName = newName + ' ' + this.lastName;
}
}
}
(2)watch中的deep属性
当检测为对象的时候(非数组情况), deep = true
可以监听对象中属性的变化
,并且检测为对象的时候, newVal == oldValue.
deep的意思就是深入观察,监听器会一层一层的往下遍历,给对象的所有属性都加上这个监听器,但是这样性能开销就会非常大了。
watch: {
obj: {
handler(newName, oldName) {
console.log('obj.a changed');
},
deep: true
}
}
(3)watch中的immediate属性
进入组件的时候,第一次并不会执行watch,因为immediate默认为false,当immediate=true
的时候,进入组件会立即执行。并且可以监听到组件传递数据。
firstName:{
handler(newName, oldName){
console.log(newName, oldName);
this.fullName = newName + ' ' + this.lastName;
},
immediate: true
},
温馨提示:
在watch中不要使用箭头函数,因为箭头函数中的this是指向当前作用域
。
watch中this表示vue实例
。
27. 如何使用计算属性?
展开查看
使用场景: 有些情况下,我们可能需要对数据进行计算或者转化后在现实到页面上,或者需要将多个数据结合起来显示。避免在模板中放入太多的逻辑,导致模板国中且难以维护。
计算属性的优势: 计算属性会进行缓存,如果多次使用时,只会调用一次。
每个计算属性都包含一个getter和一个setter,计算属性一般没有set方法
第一种使用方法:
<p>名字: {{fullName}}</p>
fullName(){
return this.firstName + ' ' +this.lastName;
},
第二种使用方法(传参):
<p>{{ getNewIndex(data) }}</p>
computed: {
getNewIndex() {
// data是使用的时候的参数
retun (data) => {
return data.index;
}
},
}
28. 如何动态绑定class和style?
展开查看
<template>
<div>
<!--第一种对象语法 -->
<div class="test" :class="{
active: actived ,
'active-click': clicked && actived
}"></div>
<!-- 第二种数组语法 -->
<div class="test" :class="[
actived? activeClass : '',
clicked && actived ? activeClickClass : ''
]"></div>
<!-- 第三种对象和数组混合 -->
<div :class="[
testClass ,
{active: actived} ,
{'active-click': clicked && actived}
]"></div>
<!-- 第四种对象和计算属性(推荐) -->
<div :class="classObject"></div>
</div>
</template>
<script>
export default {
data() {
return {
actived: true,
clicked: true,
testClass: 'test',
activeClass: 'active',
activeClickClass: 'active-click',
}
},
computed: {
classObject: function() {
return {
test: true,
active: this.actived,
'active-click': this.actived && this.clicked,
}
}
},
}
</script>
30. 怎么缓存当前打开的路由组件,缓存后想更新当前组件怎么办呢?
展开查看
用
<keep-alive></keep-alive>
内置组件包裹路由组件,在钩子函数activated
中更新
31. 组件会在什么时候下被销毁?
展开查看
- 没有使用
keep-alive
时的路由切换; v-if='false'
;- 执行
vm.$destroy()
;
32. prop验证的type类型有几种?是怎么做验证的
展开查看
String、Number、Boolean、Array、Object、Date、Function、Symbol
, 此外还可以是一个自定义的构造函数Personnel,
export default {
props:{
propA:[String,Number],
propB:{
type:Number,
default:1,
},
propC:Boolean,
propD:{
type:Object,
default(){
return{}
}
}
}
}
其他面试题
如果这篇文章有帮助到你,给个❤️关注,❤️点赞,❤️鼓励一下小编。💦💦
❤️ 笔芯 ❤️