# Vue 的最大的优势是什么?(必会)

  • Vue 作为一款轻量级框架、简单易学、双向数据绑定、组件化、数据和结构的分离、虚拟 DOM、运行速度快,并且作者是中国人尤雨溪,对应的 API 文档对国内开发者优化,作为前端开 发人员的首选入门框架
  • Vue 的优势:
    • 1、Vue.js 可以进行组件化开发,使代码编写量大大减少,读者更加易于理解。
    • 2、Vue.js 最突出的优势在于可以对数据进行双向绑定。
    • 3、使用 Vue.js 编写出来的界面效果本身就是响应式的,这使网页在各种设备上都能 显示出非常好看的效果。
    • 4、相比传统的页面通过超链接实现页面的切换和跳转,Vue 使用路由不会刷新页面。
    • 5、vue 是单页面应用,使页面局部刷新,不用每次跳转页面都要请求所有数据和 dom, 这样大大加快了访问速度和提升用户体验。
    • 6、而且他的第三方 UI 组件库使用起来节省很多开发时间,从而提升开发效率。

# Object.defineProperty 和 Proxy 的区别(必会)

  • Object.defineProperty 和 Proxy 的区别如下:
    • 1、Proxy 可以直接监听对象而非属性;
    • 2、Proxy 可以直接监听数组的变化;
    • 3、Proxy 有多达 13 种拦截方法,不限于 apply、ownKeys、deleteProperty、has 等等是 Object.defineProperty 不具备的
    • 4、Proxy 返回的是一个新对象,我们可以只操作新的对象达到目的,而 Object.defineProperty 只能遍历对象属性直接修改
    • 5、Proxy 作为新标准将受到浏览器厂商重点持续的性能优化,也就是传说中的新标准的 性能红利;
    • 6、Object.defineProperty 兼容性好,支持 IE9,而 Proxy 的存在浏览器兼容性问题,而且 无法用 polyfill 磨平,因此 Vue 的作者才声明需要等到下个大版本( 3.0 )才能用 Proxy 重写

# Vue 常用的修饰符都有哪些?(必会)

  • .prevent: 提交事件不再重载页面;
  • .stop: 阻止单击事件冒泡;
  • .self: 当事件发生在该元素 本身而不是子元素的时候会触发;
  • .capture: 事件侦听,事件发生的时候会调用

# Vue 常用的指令都有哪些?并且说明其作用(必会)

  • 1、v-model 多用于表单元素实现双向数据绑定(同 angular 中的 ng-model)
  • 2、v-for 格式:v-for="字段名 in(of) 数组 json" 循环数组或 json(同 angular 中的 ng-repeat), 需要注意从 vue2 开始取消了$index
  • 3、v-show 显示内容 (同 angular 中的 ng-show)
  • 4、v-if 显示与隐藏 (dom 元素的删除添加 同 angular 中的 ng-if 默认值为 false)v-else-if 必须和 v-if 连用 v-else 必须和 v-if 连用 不能单独使用 否则报错 模板编译错误
  • 5、v-bind 动态绑定 作用: 及时对页面的数据进行更改
  • 6、v-on:click 给标签绑定函数,可以缩写为@,例如绑定一个点击函数 函数必须写在 methods 里面
  • 7、v-text 解析文本
  • 8、v-html 解析 html 标签
  • 9、v-bind:class 三种绑定方法 1、对象型 '{red:isred}' 2、三元型 'isred?"red":"blue"' 3、数 组型 '[{red:"isred"},{blue:"isblue"}]'
  • 10、v-once 进入页面时 只渲染一次 不在进行渲染 11、v-cloak 防止闪烁 12、v-pre 把标签内部的元素原位输出

# 自定义指令(v-check、v-focus)的方法有哪些?它有哪些 钩子函数?还有哪些钩子函数参数?(必会)

  • 1、全局定义指令:在 vue 对象的 directive 方法里面有两个参数,一个是指令名称,另外一 个是函数。
  • 2、组件内定义指令:directives:钩子函数:bind(绑定事件触发)、inserted(节点插入的时候 触发)、update(组件内相关更新)钩子函数参数:el、binding

# v-show 和 v-if 指令的共同点和不同点?(必会)

  • 1、相同点: v-show 和 v-if 都能控制元素的显示和隐藏。
  • 2、不同点:
    • 2.1)实现本质方法不同 v-show 本质就是通过设置 css 中的 display 设置为 none,控制隐藏 v-if 是动态的向 DOM 树内添加或者删除 DOM 元素
    • 2.2)编译的区别 v-show 其实就是在控制 css v-if 切换有一个局部编译/卸载的过程,切换过程中合适地销毁和重建内部的事件 监听和子组件
    • 2.3)编译的条件 v-show 都会编译,初始值为 false,只是将 display 设为 none,但它也编译了 v-if 初始值为 false,就不会编译了
    • 2.4)性能比较 v-show 只编译一次,后面其实就是控制 css,而 v-if 不停的销毁和创建,故 v-show 性能更好一。
  • 3、注意点: 因为 v-show 实际是操作 display:" "或者 none,当 css 本身有 display:none 时,v-show 无法让显示
  • 4、总结(适用场景): 如果要频繁切换某节点时,使用 v-show(无论 true 或者 false 初始都会进行渲染,此 后通过 css 来控制显示隐藏,因此切换开销比较小,初始开销较大),如果不需要频繁切换某节 点时,使用 v-if(因为懒加载,初始为 false 时,不会渲染,但是因为它是通过添加和删除 dom 元素来控制显示和隐藏的,因此初始渲染开销较小,切换开销比较大)

# watch、methods 和 computed 的区别?(必会)

  • 1、基本说明
    • 1.1)computed: 计算属性将被混入到 Vue 实例中,所有 getter 和 setter 的 this 上下文自动地绑定 为 Vue 实例
    • 1.2)methods: methods 将被混入到 Vue 实例中。可以直接通过 VM 实例访问这些方法,或者在指 令表达式中使用。方法中的 this 自动绑定为 Vue 实例。
    • 1.3)watch: 观察和响应 Vue 实例上的数据变动,一个对象,键是需要观察的表达式,值是对应 回调函数,值也可以是方法名,或者包含选项的对象,Vue 实例将会在实例化时调,$watch(),遍 历 watch 对象的每一个属性
  • 2、三者的加载顺序
    • 2.1)computed 是在 HTML DOM 加载后马上执行的,如赋值;(属性将被混入到 Vue 实 例)
    • 2.2)methods 则必须要有一定的触发条件才能执行,如点击事件,watch 呢?它用于观 察 Vue 实例上的数据变动,
    • 2.3)默认加载的时候 先 computed 再 watch,不执行 methods;
    • 2.4)触发某一事件后 先 computed 再 methods 再到 watch,computed 属性 vs method 方,computed 计算 属性是基于它们的依赖进行缓存的
  • 3、总结计算属性 computed 只有在它的相关依赖发生改变时才会重新求值,当有一个性能开销 比较大的的计算属性 A ,它需要遍历一个极大的数组和做大量的计算,然后我们可能有其他的 计算属性依赖于 A ,这时候,我们就需要缓存,每次确实需要重新加载,不需要缓存时用 methods

# Vue 中 key 值的作用是什么?(必会)

  • 当 Vue.js 用 v-for 正在更新已渲染过的元素列表时,它默认用“就地复用”策略。如果数据 项的顺序被改变,Vue 将不会移动 DOM 元素来匹配数据项的顺序, 而是简单复用此处每个元 素,并且确保它在特定索引下显示已被渲染过的每个元素,key 的作用主要是为了高效的更新虚 拟 DOM

# 你是怎么认识 Vuex 的?(必会)

  • vuex 可以理解为一种开发模式或框架。比如 PHP 有 thinkphp,java 有 spring 等,通过状态(数 据源)集中管理驱动组件的变化(好比 spring 的 IOC 容器对 bean 进行集中管理)
  • 1、应用级的状态集中放在 store 中
  • 2、改变状态的方式是提交 mutations,这是个同步的事物
  • 3、异步逻辑应该封装在 action 中

# Vuex 的 5 个核心属性是什么?(必会)

  • 分别是 State、 Getter、Mutation 、Action、 Module
  • 1、state state 为单一状态树,在 state 中需要定义我们所需要管理的数组、对象、字符串等等, 只有在这里定义了,在 vue.js 的组件中才能获取你定义的这个对象的状态
  • 2、getter getter 有点类似 vue.js 的计算属性,当我们需要从 store 的 state 中派生出一些状态,那 么我们就需要使用 getter,getter 会接收 state 作为第一个参数,而且 getter 的返回值会根据 它的依赖被缓存起来,只有 getter 中的依赖值(state 中的某个需要派生状态的值)发生改变 的时候才会被重新计算
  • 3、mutation 更改 store 中 state 状态的唯一方法就是提交 mutation,就很类似事件。每个 mutation 都有一个字符串类型的事件类型和一个回调函数,我们需要改变 state 的值就要在回调函数 中改变。我们要执行这个回调函数,那么我们需要执行一个相应的调用方法 store.commit
  • 4、action action 可以提交 mutation,在 action 中可以执行 store.commit,而且 action 中可以有任 何的异步操作。在页面中如果我们要嗲用这个 action,则需要执行 store.dispatch
  • 5、module module 其实只是解决了当 state 中很复杂臃肿的时候,module 可以将 store 分割成模 块,每个模块中拥有自己的 state、mutation、action 和 getter

# Vuex 的出现解决了什么问题?(必会)

  • 主要解决了以下两个问题
  • 1、多个组件依赖于同一状态时,对于多层嵌套的组件的传参将会非常繁琐,并且对于兄弟 组件间的状态传递无能为力
  • 2、来自不同组件的行为需要变更同一状态。以往采用父子组件直接引用或者通过事件来变 更和同步状态的多份拷贝。以上的这些模式非常脆弱,通常会导致无法维护的代码

# 简述 Vuex 的数据传递流程(必会)

  • 当组件进行数据修改的时候我们需要调用 dispatch 来触发 actions 里面的方法。actions 里面 的每个方法中都会 有一个
  • 1、commit 方法,当方法执行的时候会通过 commit 来触 mutations 里面的方法进行数据的修 改
  • 2、mutations 里面的每个函数都会有一个 state 参数,这样就可以在 mutations 里面进行 state 的数据修改 ,当数据修改完毕后,会传导给页面,页面的数据也会发生改变

# Vuex 的 Mutation 和 Action 之间的区别是什么?(必会)

  • 1、流程顺序 “相应视图—>修改 State”拆分成两部分,视图触发 Action,Action 再触发 Mutation
  • 2、角色定位 基于流程顺序,二者扮演不同的角色
  • 1)Mutation:专注于修改 State,理论上是修改 State 的唯一途径
  • 2)Action:业务代码、异步请求
  • 3、限制
  • 1)角色不同,二者有不同的限制
  • 2)Mutation:必须同步执行
  • 3)Action:可以异步,但不能直接操作 State;

# Vue-router 是干什么的,原理是什么?(必会)

  • Vue-router 是 Vue.js 官方的路由插件,它和 vue.js 是深度集成的,适合用于构建单页面 应用,vue 的单页面应用是基于路由和组件的,路由用于设定访问路径,并将路径和组件映射起 来,传统的页面应用,是用一些超链接来实现页面切换和跳转的,在 vue-router 单页面应用中, 则是路径之间的切换,也就是组件的切换,
  • 路由模块的本质 就是建立起 url 和页面之间的映射关 系 “更新视图但不重新请求页面”是前端路由原理的核心之一,目前在浏览器环境中这一功能的 实现主要有两种方式:
  • 1、利用 URL 中的 hash(“#”)
  • 2、利用 History interface 在 HTML5 中新增的方法

# 路由传值的方式有哪几种(必会)

  • Vue-router 传参可以分为两大类,
    • 分别是编程式的导航 router.push 和声明式的导航
    • 1、router.push
    • 1.1)字符串:直接传递路由地址,但是不能传递参数 this.$router.push("home") 对象;
    • 1.2)命名路由 这种方式传递参数,目标页面刷新会报错 this.$router.push({name:"news",params:{userId:123})
    • 1.3)查询参数 和 name 配对的式 params,和 path 配对的是 query this.$router.push({path:"/news',query:{uersId:123})
    • 1.4)接收参数 this.$route.query
    • 2、声明式导航
    • 2.1)字符串 <router-link to:"news">
    • 2.2)命名路由 <router-link :to:"{name:'news',params:{userid:1111}}">
    • 2.3)查询参 数

# query 和 params 之间的区别是什么?(必会)

  • 1、query 要用 path 来引入,params 要用 name 来引入
  • 2、接收参数时,分别是 this.$route.query.name 和 this.$route.params.name(注意:是$route 而不是$router
  • 3、query 更加类似于我们 ajax 中 get 传参,params 则类似于 post,前者在浏览器的地址栏中 显示,params 不显示 4、params 传值一刷新就没了,query 传值刷新还存在

# $route 和$router 的区别是什么?(必会)

  • $route 是“路由信息对象”,包括 path,params,hash,query,fullPath,matched,name 等路由 信息参数
  • $router 为 VueRouter 的实例,相当于一个全局的路由器对象,里面含有很多属性和子对象, 例如 history 对象,经常用的跳转链接就可以用 this.router.push 会往 history 栈中添加一个新的记 录。返回上一个 history 也是使用$router.go 方法

# Vue 的路由实现模式:hash 模式和 history 模式(必会)

  • 1、hash 模式:在浏览器中符号“#”,#以及#后面的字符称之为 hash, 用 window.location.hash 读取。特点:hash 虽然在 URL 中,但不被包括在 HTTP 请求中;用来指 导浏览器动作,对服务端安全无用,hash 不会重加载页面
  • 2、history 模式:history 采用 HTML5 的新特性,且提供了两个新方法:
    • 2.1)pushState()
    • 2.2)replaceState()可以对浏览器历史记录栈进行修改,以及 popState 事件的监听到状态 变更

# Vue 如何去除 URL 中的#(必会)

  • vue-router 默认使用 hash 模式,所以在路由加载的时候,项目中的 URL 会自带 “#”,如果 不想使用 “#”, 可以使用 vue-router 的另一种模式 history:new Router ({ mode : 'history', routes: [ ]}) 需要注意的是,当我们启用 history 模式的时候,由于我们的项目是一个单页面应用,所以 在路由跳转的时候,就会出现访问不到静态资源而出现 “404” 的情况,这时候就需要服务端增 加一个覆盖所有情况的候选资源:如果 URL 匹配不到任何静态资源,则应该返回同一个 “index.html” 页面

# 说一下你在 Vue 中踩过的坑(必会)

  • 1、第一个是给对象添加属性的时候,直接通过给 data 里面的对象添加属性然后赋值,新添 加的属性不是响应式的
  • 1.1)解决办法:通过 Vue.set(对象,属性,值)这种方式就可以达到,对象新添加的属 性是响应式的
  • 2、在 created 操作 dom 的时候,是报错的,获取不到 dom,这个时候实例 vue 实例没有挂载
    • 2.2)解决办法:通过:Vue.nextTick(回调函数进行获取)

# Vue 项目优化的解决方案都有哪些?(必会)

  • 1、 使用 mini-css-extract-plugin 插件抽离 css
  • 2、 配置 optimization 把公共的 js 代码抽离出来
  • 3、 通过 webpack 处理文件压缩
  • 4、 不打包框架、库文件,通过 cdn 的方式引入
  • 5、 小图片使用 base64
  • 6、 配置项目文件懒加载
  • 7、 UI 库配置按需加载
  • 8、 开启 Gzip 压缩

# 使用 Vue 的时候一下加载造成页面卡顿,该如何解决? (必会)

  • vue-router 解决首次加载缓慢的问题。懒加载简单来说就是按需加载
  • 1、像 vue 这种单页面应用,如果没有应用懒加载,运用 webpack 打包后的文件将会异常的大,造成进入首页时, 需要加载的内容过多,时间过长,会出现长时间的白屏, 即使做了 loading 也是不利于用户体验,
  • 2、而运用懒加载 则可以将页面进行划分,需要的时候加载页面,可以有效的分担 首页所承担的加载压力,减少首页加载用时。
  • 3、用法:在配置路由时使用:component:resolve=>require([“@components/路由的 路径”],resolve)。 就是用了懒加载后打完包直接运行那个 index.html 会报错,报文件引用 错误其实是打包时候路径配置有点问 题,找到 build 下面的 webpack.prod.conf.js 添 加 publicPath:"./",

# 你知道 style 上加 scoped 属性的原理吗?(必会)

  • 1、什么是 scoped 在 Vue 组件中,为了使样式私有化(模块化),不对全局造成污染,可以在 style 标签 上添加 scoped 属性以表示它的只属于当下的模块,局部有效。如果一个项目中的所有 vue 组件 style 标签全部加上了 scoped,相当于实现了样式的私有化。如果引用了第三方组件,需要在当 前组件中局部修改第三方组件的样式,而又不想去除 scoped 属性造成组件之间的样式污染。此 时只能通过穿透 scoped 的方式来解决,选择器。
  • 2、scoped 的实现原理: Vue 中的 scoped 属性的效果主要通过 PostCSS 转译实现,如下是转译前的 Vue 代码:
<template><div>Vue.js scoped</div></template> <style scoped>.scoped {font-size:14px;}

浏览器渲染后的代码:

<div data-v-fed36922>Vue.js scoped</div> .scoped[data-v-fed36922]{font-size:14px;} 

即:PostCSS 给所有 dom 添加了一个唯一不重复的动态属性,然后,给 CSS 选择器额外添加一个 对应的属性选择器来选择该组件中 dom,这种做法使得样式私有化

# 说说你对 SPA 单页面的理解,它的优缺点分别是什么? (必会)

  • 单页 Web 应用 (single-page application 简称为 SPA) 是一种特殊的 Web 应用,它将所有 的活动局限于一个 Web 页面中,仅在该 Web 页面初始化时加载相应的 HTML、JavaScript 和 CSS, 一旦页面加载完成了,SPA 不会因为用户的操作而进行页面的重新加载或跳转,取而代之的是利 用 JavaScript 动态的变换 HTML 的内容,从而实现 UI 与用户的交互,由于避免了页面的重新加 载,SPA 可以提供较为流畅的用户体验,得益于 ajax,我们可以实现无跳转刷新,又多亏了浏 览器的 histroy 机制,我们用 hash 的变化从而可以实现推动界面变化,从而模拟元素客户端的单 页面切换效果: SPA 被人追捧是有道理的,但是它也有不足之处,当然任何东西都有两面性,以下是卤煮 总结的一些目前 SPA 的优缺点:
  • 1、 优点:
    • 1,1)无刷新界面,给用户体验原生的应用感觉
    • 1,2)节省原生(android 和 ios)app 开发成本
    • 1,3)提高发布效率,无需每次安装更新包
    • 1,4)容易借助其他知名平台更有利于营销和推
    • 1,5)符合 web2.0 的趋势
  • 2、 缺点:
    • 1) 效果和性能确实和原生的有较大差距
    • 2) 各个浏览器的版本兼容性不一样
    • 3) 业务随着代码量增加而增加,不利于首屏优化
    • 4) 某些平台对 hash 有偏见,有些甚至不支持 pushstate
    • 5) 不利于搜索引擎抓取

# 如何对 Vue 首屏加载实现优化? (高薪常问)

  • 1、把不常改变的库放到 index.html 中,通过 cdn 引入
  • 2、vue 路由的懒加载
  • 3、不生成 map 文件
  • 4、vue 组件尽量不要全局引入
  • 5、使用更轻量级的工具库
  • 6、开启 gzip 压缩
  • 7、首页单独做服务端渲染

# Vue 的 nextTick 的原理是什么? (高薪常问)

  • 1、为什么需要 nextTick Vue 是异步修改 DOM 的并且不鼓励开发者直接接触 DOM,但有时候业务需要必须对 数据更改--刷新后的 DOM 做相应的处理,这时候就可以使用 Vue.nextTick(callback)这个 api 了
  • 2、理解原理前的准备 首先需要知道事件循环中宏任务和微任务这两个概念
  • 2,1)常见的宏任务有:script, setTimeout, setInterval, setImmediate, I/O, UI rendering
  • 2,2)常见的微任务有:process.nextTick(nodejs),Promise.then(), MutationObserver
  • 3、理解 nextTick 的原理 正是 vue 通过异步队列控制 DOM 更新和 nextTick 回调函数先后执行的方式。如果大 家看过这部分的源码,会发现其中做了很多 isNative()的判断,因为这里还存在兼容性优雅 降级的问题