Vue面试题整理!!!!
注意:问题重点程度不分先后,但我觉得重点的会加以说明!!!
一、Vue理论部分
==1、MVC、MVP 和 MVVM?(重点)==
复杂的软件必须有清晰合理的架构,否则无法开发和维护
MVC(Model-View-Controller)最常见的软件架构之一,业界有这广泛应用。
后续衍生出了MVP和MVVM架构。
MVC模式的意思是,软件可以分为三个部分。
- 视图(View): 用户界面
- 控制器(Controller):业务逻辑
- 模型(Model):数据保存
各个部分之间的通讯方式如下。
- View传送指令到Controller
- Controller完成业务逻辑后,要求Model改变状态
- Model将新的数据发送给View,用户得到反馈
代码展示:
1 | // 模拟 Model, View, Controller |
==1、说下对Vue的理解?(重点)==
1 | 答: |
==2、那些项目适合使用Vue?==
1 | 答: |
==3、Vue双向数据绑定(数据驱动)的原理?(重点)==
vue将普通的对象的属性通过Object.defineProperty转换为ES5特性之一的 getter/setter,模板中每个指令/数据绑定都有一个对应的 watcher 对象, 当修改对象值的时,首先会触发属性的setter,在setter被调用时,会触发 watcher 重新计算 ,也就会导致它的关联指令更新 DOM。
Vue.js 的核心是一个响应的数据绑定系统,它让数据与 DOM 保持同步非常简单。在使用 jQuery 手工操作 DOM 时,我们的代码常常是命令式的、重复的与易错的。Vue.js 拥抱数据驱动的视图概念。通俗地讲,它意味着我们在普通 HTML 模板中使用特殊的语法将 DOM “绑定”到底层数据。一旦创建了绑定,DOM 将与数据保持同步。每当修改了数据,DOM 便相应地更新。这样我们应用中的逻辑就几乎都是直接修改数据了,不必与 DOM 更新搅在一起。这让我们的代码更容易撰写、理解与维护。
==4、 vue.cli中怎样使用自定义的组件?有遇到过哪些问题吗?==
1 | 答:第一步:在components目录新建你的组件文件(smithButton.vue),script一定要export default { |
==5、说下vue组件之间的通信?(重点)==
props、自定义事件
==6、异步更新机制Vue.nextTick(重点!!)==
- Vue 对DOM的更新是异步的! 这个异步是在一个异步队列中进行的,不过这个异步队列会在当前的
Event Loop
中执行完,所以如果修改了 Data 立刻去DOM中做查询操作是不对的,这个时候DOM还没有更新,正确的做法是这样做:
1 | vm.msg = 'new message' // change data |
或者这样:
1 | vm.$nextTick(function () { |
==7、怎么定义vue-router的动态路由?怎么获取传过来的动态参数?==
1 | 答:在router目录下的index.js文件中,对path属性加上/:id。 使用router对象的params.id |
==8、vue-router有哪几种导航钩子? ==
答:三种,一种是全局导航钩子(路由的前置守卫):router.beforeEach(to,from,next),作用:跳转前进行判断拦截。第二种:组件内的钩子;第三种:单独路由独享组件
9、请说下封装 vue 组件的过程?
答:首先,组件可以提升整个项目的开发效率。能够把页面抽象成多个相对独立的模块,解决了我们传统项目开发:效率低、难维护、复用性等问题。
然后,使用Vue.extend方法创建一个组件,然后使用Vue.component方法注册组件。子组件需要数据,可以在props中接受定义。而子组件修改好数据后,想把数据传递给父组件。可以采用emit方法。
10、vue-loader是什么?使用它的用途有哪些?
答:解析.vue文件的一个加载器,跟template/js/style转换成js模块。
用途:js可以写es6、style样式可以scss或less、template可以加jade等
11、vuejs与angularjs的区别?
答:
一、定位 :
虽然Vue.js被定义为MVC framework,但其实Vue本身还是一个library,加了一些其他的工具,可以被当成一个framework,而Angular 2虽然还是一个framework,但其实在设计之初,Angular 2的团队站在了更高的角度,希望做一个platform。
二、文档:
vue.js的更加亲切
三、性能:
angular所有的数据和方法都是挂载在$scope上。而vue的数据和方法都是挂载在vue上,只是数据挂载在vue的data,方法挂载在vue的methods上,vue的代码风格更加优雅,json格式书写代码。Vue.js 有更好的性能,并且非常非常容易优化,因为它不使用脏检查。Angular,当 watcher 越来越多时会变得越来越慢,因为作用域内的每一次变化,所有 watcher 都要重新计算。
其它区别:
渲染性能:Vue> react >angular。
使用场景:Vue React 覆盖中小型,大型项目。angular 一般用于大型(因为比较厚重)。
12、你觉得哪些项目适合vue框架?
答:1、数据信息量比较多的,反之类似企业网站就无需此框架了。
2、手机web和app应用多端共用一套界面的项目,因为使用vue.cli+webpack后的前端目录,非常有利于项目的跨平台部署。
13、PC端项目你会在哪些场景使用Vue框架?
答:上万级数据需要瀑布流更新和搜索的时候,因为数据庞大的时候,用原生的dom操作js和html都会有列表的html布局,迭代很困难。再一个dom节点的大面积添加会影响性能。
那么vue为什么解决这些问题呢?
第一:只需用v-for在view层一个地方遍历数据即可,无需复制一段html代码在js和html两个地方。
第二:vue通过Virtual Dom
就是在js中模拟DOM
对象树来优化DOM
操作。
14、虚拟节点Virtual Dom?(重点)
直接看这个文章:https://segmentfault.com/a/1190000008291645
15、Vue中如何使用jsonp?
安装jsonp模块
1
$ npm install --save jsonp
在
main.js
引入1
2import jsonp from 'jsonp'
Vue.prototype.jsonp = jsonp编写代码发起网络请求
1
2
3
4this.jsonp('https://shop.juanpi.com/gsort?key=zuixinzhekou&type=1&zhouyi_ids=p8_c4_l1_18_51_5&machining=hotcoupon&page=1&rows=10&dtype=JSONP&cm=1&cm_channel=1&callback=gsort_callback', (err, data) => {
console.log(err);
console.log(data);
})
二、生命周期相关
1、什么是Vue的生命周期?(重点)
答: Vue 实例从创建到销毁的过程,就是生命周期。也就是从开始创建、初始化数据、编译模板、挂载Dom→渲染、更新→渲染、卸载等一系列过程,我们称这是 Vue 的生命周期。
2、Vue声明周期的作用是什么?(重点)
答:它的生命周期中有多个事件钩子,让我们在控制整个Vue实例的过程时更容易形成好的逻辑。
3、Vue的生命周期共有几个阶段?(重点)
答:总共分为8个阶段创建前/后,载入前/后,更新前/后,销毁前/后。
创建前/后: 在beforeCreated阶段,vue实例的挂载元素$el和数据对象data都为undefined,还未初始化。在created阶段,vue实例的数据对象data有了,$el还没有。
载入前/后:在beforeMount阶段,vue实例的$el和data都初始化了,但还是挂载之前为虚拟的dom节点,data.message还未替换。在mounted阶段,vue实例挂载完成,data.message成功渲染。
更新前/后:当data变化时,会触发beforeUpdate和updated方法。
销毁前/后:在执行destroy方法后,对data的改变不会再触发周期函数,说明此时vue实例已经解除了事件监听以及和dom的绑定,但是dom结构依然存在
4、第一次页面加载会触发哪几个钩子?(重点)
答:第一次页面加载时会触发 beforeCreate, created, beforeMount, mounted 这几个钩子
5、DOM渲染在哪个钩子中就已经完成?(重点)
答:DOM 渲染在 mounted 中就已经完成了。
6、描述下每个钩子具体适合哪些场景?(重点)
答:生命周期钩子的一些使用方法: beforecreate : 可以在这加个loading事件,在加载实例时触发 created : 初始化完成时的事件写在这里,如在这结束loading事件,异步请求也适宜在这里调用 mounted : 挂载元素,获取到DOM节点 updated : 如果对数据统一处理,在这里写上相应函数 beforeDestroy : 可以做一个确认停止事件的确认框 nextTick : 更新数据后立即操作。
三、Vuex相关
1、Vuex是什么?(重点)
Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。
2、Vuex有几种属性?(重点)
答:有五种,分别是 State、 Getter、Mutation 、Action、 Module
3、Vuex的State特性?(重点)
答:
一、Vuex就是一个仓库,仓库里面放了很多对象。其中state就是数据源存放地,对应于与一般Vue对象里面的data
二、state里面存放的数据是响应式的,Vue组件从store中读取数据,若是store中的数据发生改变,依赖这个数据的组件也会发生更新
三、它通过mapState把全局的 state 和 getters 映射到当前组件的 computed 计算属性中
4、Vuex的getter特性?(重点)
答:
一、getters 可以对State进行计算操作,它就是Store的计算属性
二、 虽然在组件内也可以做计算属性,但是getters 可以在多组件之间复用
三、 如果一个状态只在一个组件内使用,是可以不用getters
5、 Vuex的mutation特性?(重点)
答:
在这里可以直接变更state里的数据(状态),是同步操作。
6、Vuex的Action特性?(重点)
答:
一、Action 类似于 mutation,不同在于:
二、Action 提交的是 mutation,而不是直接变更状态。
三、Action 可以包含任意异步操作
7、Vue.js中ajax请求代码应该写在组件的methods中还是vuex的actions中?(重点)
答:
一、如果请求来的数据是不是要被其他组件公用,仅仅在请求的组件内使用,就不需要放入vuex 的state里。
二、如果被其他地方复用,这个很大几率上是需要的,如果需要,请将请求放入action里,方便复用,并包装成promise返回,在调用处用async await处理返回的数据。如果不要复用这个请求,那么直接写在vue文件里很方便。
8、不用Vuex会带来什么问题?(重点)
答:一、可维护性会下降,你要想修改数据,你得维护三个地方二、可读性会下降,因为一个组件里的数据,你根本就看不出来是从哪来的三、增加耦合,大量的上传派发,会让耦合性大大的增加,本来Vue用Component就是为了减少耦合,现在这么用,和组件化的初衷相背。
但兄弟组件有大量通信的,建议一定要用,不管大项目和小项目,因为这样会省很多事
四、Vue-cli相关 (重点)
参考项目是用vue-cli的webpack模板构建的,项目地址:https://github.com/hieeyh/tong2-family
在线访问:http://119.29.57.165:8080/family 该项目还用到了eCharts这个报表库
1、vue-cli 2.0项目结构分析
项目结构
1 | . |
2、package.json
package.json文件是项目根目录下的一个文件,定义该项目开发所需要的各种模块以及一些项目配置信息(如项目名称、版本、描述、作者等)。
scripts字段
package.json文件里有一个scripts字段。
1 | "scripts": { |
在开发环境下,在命令行中运行npm run dev
就相当于在执行node build/dev-server.js
。所以script字段是用来指定npm相关命令的缩写的。
dependencies字段和devDependencies字段
dependencies字段指定了项目运行时所依赖的模块,devDependencies字段指定了项目开发时所依赖的模块。在命令行中运行npm install命令,会自动安装dependencies和devDependencies字段中的模块。
package.json还有很多配置相关项,想进一步了解package.json的可参考:https://docs.npmjs.com/files/package.json
3、webpack配置相关
dev-server.js
1 | ... |
webpack.base.conf.js
1 | ... |
check-version.js
这个文件主要是用来检测当前环境中的node和npm版本和我们需要的是否一致的。
1 | // 加载语义化版本测试库 |
4、 .babelrc
Babel解释器的配置文件,存放在根目录下。Babel是一个转码器,项目里需要用它将ES6代码转为ES5代码。这里有一篇阮一峰老师写的相关文章供参考:Babel 入门教程
1 | // 设定转码规则 |
5、.editorconfig
该文件定义项目的编码规范,编辑器的行为会与.editorconfig 文件中定义的一致,并且其优先级比编辑器自身的设置要高,这在多人合作开发项目时十分有用而且必要。
1 | root = true |
了解更多请参考官方配置文档http://editorconfig.org/
五、前端模块化
1、CommonJS
服务器端的 Node.js 遵循 CommonJS规范,该规范的核心思想是允许模块通过 require
方法来同步加载所要依赖的其他模块,然后通过 exports
或 module.exports
来导出需要暴露的接口。
使用
引入模块
1 | let express = require('express'); |
导出模块
1 | module.exports.test1 = function () {} |
优缺点
优点
- 服务器端模块便于重用
- NPM中已经有超过45万个可以使用的模块包
- 简单并容易使用
缺点
- 同步的模块加载方式不适合浏览器环境,同步意味着阻塞加载,浏览器资源是异步加载的
- 不能非阻塞的并行加载多个模块
实现
- 服务器端的 Node.js
- Browserify,浏览器端的 CommonJS 实现,可以使用 NPM 的模块,但是编译打包后的文件体积可能很大
- modules-webmake,类似Browserify,还不如 Browserify 灵活
- wreq,Browserify 的前身
2、AMD
Asynchronous Module Definition 规范其实只有一个主要接口,define(id?, dependencies?, factory)
,它要在声明模块的时候指定所有的依赖dependencies
,并且还要当做形参传到factory
中,对于依赖的模块提前执行,依赖前置。AMD是提前执行,它本身依赖的模块会比它本身提前加载完成,而CMD是依赖执行 当我们的代码执行到require这一步的时候才会引进我们的所要依赖的模块,CMD跟AMD非常的相似,但是语法跟commonjs由非常相似
使用
定义模块
1 | define('module', ['dep1', 'dep2'], function (d1, d2) { |
引入模块
1 | require(['module', '../file'], funtion(module, file) { |
优缺点
优点
- 适合在浏览器环境中异步加载模块
- 可以并行加载多个模块
缺点
提高了开发成本,代码的阅读和书写比较困难,模块定义方式的语义不顺畅
不符合通用的模块化思维方式,是一种妥协的实现
实现
3、CMD
Common Module Definition 规范和 AMD 很相似,尽量保持简单,并与 CommonJS 和 Node.js 的 Modules 规范保持了很大的兼容性。
使用
定义
1 | define(function (require, exports, module) { |
引入
1 | define(function (require, exports, module) { |
优缺点
优点
- 依赖就近,延迟执行
- 可以很容易在Node.js中运行
缺点
- 依赖SPM打包,模块的加载逻辑偏重
实现
4、ES6 模块
EcmaScript6 标准增加了 JavaScript 语言层面的模块体系定义。ES6 模块的设计思想,是尽量的静态化,使得编译时就能确定模块的依赖关系,以及输入和输出的变量。CommonJS 和 AMD 模块,都只能在运行时确定这些东西。
使用
定义
1 | export default { |
引入
1 | import 'jquery'; |
优缺点
优点
- 容易进行静态分析
- 面向未来的ECMAScript标准
缺点
原生浏览器还没有实现标准
全新的命令字,新版的Node.js才支持
实现
期望的模块系统
可以兼容多种模块风格,尽量可以利用已有的代码,不仅仅只是 JavaScript 模块化,还有 CSS、图片、字体等资源也需要模块化。
五、其他
1、Vue在各地企业的需求占比
其中广东、北京、上海三个省份是企业需求最多,还有学者最多的三个省份。
现在我们来具体透析下前三个省份中,具体的市区分布情况:
1、广东省的vue在各市区的前三位:
深圳、广州、江门,佛山、东莞、珠海分别紧随其后。
2、浙江省的vue在各市区的前三位:
杭圳、金华、宁波,温州、台州、嘉兴分别紧随其后。
3、江苏省的vue在各市区的前三位:
南京、金华、宁波,连云港、泰州、盐城分别紧随其后。