Vue 面试题


vuejs-interview-questions

vuejs-interview-questions-chinese

介绍 — Vue.js

Introduction — Vue.js

  • 能熟练使用 Vue 进行项目开发,掌握 Vue 各生命周期函数的调用,掌握 Vue 常用的 api
  • 掌握 Vue 组件间的各种传值方式,掌握 v-model 的实现,理解 computed 和 Watch 在作用场景上的区别,能够自定义 Vue 指令
  • 掌握 Vuex 常用 api 使用,掌握 vue router 常用 api 的使用及各种传值方式

🔥Vue

v-model 原理

详解

v-model 是 v-bind:vlue 和 v-on:input 的语法糖。可以通过 model 属性的 prop 和 event 属性来进行自定义。原生的 v-model 会根据标签的不同生成不同的事件和属性。

v-model 就是 vue 的双向绑定的指令,能将页面上控件输入的值同步更新到相关绑定的 data 属性,也会在更新 data 绑定属性时候,更新页面上输入控件的值。

v-model 作为双向绑定指令也是 vue 两大核心功能之一,使用非常方便,提高前端开发效率。在 view 层,model 层需要数据交互,即可使用 v-model。

input 输入值后更新 data   首先在页面初始化时候,vue 的编译器会编译该 html 模板文件,将页面上的 dom 元素遍历生成一个虚拟的 dom 树。再递归遍历虚拟的 dom 的每一个节点。当匹配到其是一个元素而非纯文本,则继续遍历每一个属性。  如果遍历到 v-model 这个属性,则会为这个节点添加一个 input 事件,当监听从页面输入值的时候,来更新 vue 实例中的 data 想对应的属性值。

data 的属性赋值后更新 input 的值    同样初始化 vue 实例时候,会递归遍历 data 的每一个属性,并且通过 defineProperty 来监听每一个属性的 get,set 方法,从而一旦某个属性重新赋值,则能监听到变化来操作相应的页面控制。

其核心就是,一方面 modal 层通过 defineProperty 来劫持每个属性,一旦监听到变化通过相关的页面元素更新。另一方面通过编译模板文件,为控件的 v-model 绑定 input 事件,从而页面输入能实时更新相关 data 属性值。

表单重编辑时需要先从 model 获取 展示表单原数据 表单提交时从 view 回去传回 model


Vue 双向绑定数据原理

解析

Vue 2.x 如何追踪变化

当你把一个普通的 JavaScript 对象传入 Vue 实例作为 data 选项,Vue 将遍历此对象所有的 property,并使用 Object.defineProperty 把这些 property 全部转为 getter/setter.

这些 getter/setter 对用户来说是不可见的,但是在内部它们让 Vue 能够追踪依赖,在 property 被访问和修改时通知变更。

每个组件实例都对应一个 watcher 实例,它会在组件渲染的过程中把 “接触” 过的数据 property 记录为依赖。之后当依赖项的 setter 触发时,会通知 watcher,从而使它关联的组件重新渲染。

Vue 3.x 如何跟踪变化

当我们从一个组件的 data 函数中返回一个普通的 JavaScript 对象时,Vue 会将该对象包裹在一个带有 getset 处理程序的 Proxy 中。Proxy 是在 ES6 中引入的,它使 Vue 3 避免了 Vue 早期版本中存在的一些响应性问题。

Proxy 是一个对象,它包装了另一个对象,并允许你拦截对该对象的任何交互。


Vue 单向数据流原理

解析

单向数据流

所有的 prop 都使得其父子 prop 之间形成了一个 单向下行绑定 :父级 prop 的更新会向下流动到子组件中,但是反过来则不行。这样会防止从子组件意外变更父级组件的状态,从而导致你的应用的数据流向难以理解。

额外的,每次父级组件发生变更时,子组件中所有的 prop 都将会刷新为最新的值。这意味着你不应该在一个子组件内部改变 prop.

父传子的 props 就是单向流动。父变子亦变,子变父不变。且不应该在子组件中更新父属性。v-model 就是双向数据流


再说一下 Vue2.x 中如何监测数组变化

详解

使用了函数劫持的方式,重写了数组的方法,Vue 将 data 中的数组进行了原型链重写,指向了自己定义的数组原型方法。

这样当调用数组 api 时,可以通知依赖更新。如果数组中包含着引用类型,会对数组中的引用类型再次递归遍历进行监控。这样就实现了监测数组变化。


data 必须是一个函数

详解

我们能抽离出来的组件肯定是具有复用性的,它在项目中可能会存在多个实例。如果 data 属性值是一个对象时,那么它所有的实例都会共享这些数据,即使是该组件被多次引用,而其实操作的是同一个对象,最终导致了引用该组件的所有位置都同步的显示了。
我们的期望是,组件的每个实例都能独立的维护自己的数据。
解决方案:组件中的 data 返回一个函数,他的每个实例就会有自己的作用域空间,也就是独立的数据,每个实例之间不会相互影响。

所以,组件中的 data 属性必须是一个函数。

data 必须是一个函数 一个组件实例数据的更改将影响所有其他实例的数据。


🔥 Vue 生命周期总共有几个阶段

生命周期图示

详解
  1. beforeCreate(创建前)此阶段为实例初始化之后,此时的数据观察和事件机制都未形成,不能获得 DOM 节点。(没有 data,没有 el)使用场景:因为此时 data 和 methods 都拿不到,所以通常在实例以外使用,可以在这加个 loading 事件,在加载实例时触发
  2. created(创建后)在这个阶段 vue 实例已经创建,仍然不能获取 DOM 元素。(有 data,没有 el)使用场景:模板渲染成 html 前调用,此时可以获取 data 和 methods,可以初始化某些属性值,然后再渲染成视图,异步操作可以放在这里,初始化完成时的事件写在这里,如在这结束 loading 事件服务端渲染时异步请求也适宜在这里调用
  3. beforeMount(载入前)我们虽然依然得不到具体的 DOM 元素,但 vue 挂载的根节点已经创建,下面 vue 对 DOM 的操作将围绕这个根元素继续进行;beforeMount 这个阶段是过渡性的,一般一个项目只能用到一两次。(有 data,有 el)
  4. mounted(载入后)mounted 是平时我们使用最多的函数了,一般我们的异步请求都写在这里。在这个阶段,数据和 DOM 都已被渲染出来。使用场景:模板渲染成 html 后调用,通常是初始化页面完成后再对数据和 DOM 做一些操作,需要操作 DOM 的方法可以放在这里
  5. beforeUpdate(更新前)在这一阶段,vue 遵循数据驱动 DOM 的原则。beforeUpdate 函数在数据更新后虽然没立即更新数据,但是 DOM 中的数据会改变,这是 Vue 双向数据绑定的作用。
  6. updated(更新后)在这一阶段 DOM 会和更改过的内容同步。使用场景:需要对数据更新做统一处理的;如果需要区分不同的数据更新操作可以使用$nextTick
  7. beforeDestroy(销毁前)在上一阶段 Vue 已经成功的通过数据驱动 DOM 更新,当我们不再需要 vue 操纵 DOM 时,就要销毁 Vue, 也就是清除 vue 实例与 DOM 的关联,调用 destroy 方法可以销毁当前组件。在销毁前,会触发 beforeDestroy 钩子函数。使用场景:可以做一个确认停止事件的确认框
  8. destroyed(销毁后)对应的钩子函数是 destroyed。在销毁后,会触发 destroyed 钩子函数。定时器销毁
  9. activated:在使用 vue-router 时有时需要使用<keep-alive></keep-alive>来缓存组件状态,这个时候 created 钩子就不会被重复调用了。如果我们的子组件需要在每次加载的时候进行某些操作,可以使用 activated 钩子触发。
  10. deactivated:<keep-alive></keep-alive>组件被移除时使用。

计算属性 computed 和侦听器 watch 区别

计算属性缓存 vs 方法

计算属性缓存 vs 方法

解析
计算属性 computed 侦听属性 watch
支持缓存,只有依赖数据发生改变,才会重新进行计算 不支持缓存,被侦听数据变,直接会触发相应的操作
不支持异步 支持异步; 在数据变化时执行异步或开销较大的操作
基于 data 中声明过或者父组件传递的 props 中的数据 接收两个参数,第一个参数是最新的值;第二个参数是输入之前的值
依赖其他属性,是多对一或者一对一 当一个属性发生变化时,需要执行对应的操作;一对多;

计算属性和侦听器


⭕️component 和 components 区别

详解

全局组件
所有实例都能用全局组件。

全局组件实例
注册一个 全局组件 my-component,并使用它:

<div id="app">
  <my-component></my-component>
</div>

<script>
  // 注册
  Vue.component('my-component', {
    template: '<h1> 自定义组件!</h1>',
  });
  // 创建根实例
  new Vue({
    el: '#app',
  });
</script>

局部组件
我们也可以在实例选项中注册局部组件,这样组件只能在这个实例中使用:

局部组件实例
注册一个 局部组件 my-component,并使用它:

<div id="app">
  <my-component></my-component>
</div>

<script>
  var Child = {
    template: '<h1> 自定义组件!</h1>',
  };
  // 创建根实例
  new Vue({
    el: '#app',
    components: {
      // <my-component> 将只在父模板可用
      my-component: Child,
    },
  });
</script>

🔥 v-if 和 v-show 的区别

详解
  1. v-if 只在表达式通过的情况下将元素渲染到 DOM 中,而 v-show 渲染全部元素到 DOM 中并基于表达式使用 CSS display 属性来 显示 / 隐藏 元素。
  2. v-if 支持 v-elsev-else-if 指令,而 v-show 不支持 else 指令。
  3. v-if 有更高的切换开销,而 v-show 有更高的初始化渲染开销。换言之,如果元素会被频繁切换开关则 v-show 有优势,在初始渲染时间方面 v-if 有优势。
  4. v-if 支持 <template> 选项卡,但 v-show 不支持。

v-if vs v-show


组件中的 data 为什么是一个函数

详解

一个组件被复用多次的话,也就会创建多个实例。本质上,这些实例用的都是同一个构造函数。如果 data 是对象的话,对象属于引用类型,会影响到所有的实例。

所以为了保证组件不同的实例之间 data 不冲突,data 必须是一个函数。


new Vue() 实例中,data 可以直接是一个对象,为什么在 Vue 组件中,data 必须是一个函数呢

因为组件是可以复用的,JS 里对象是引用关系,如果组件 data 是一个对象,那么子组件中的 data 属性值会互相污染,产生副作用。

所以一个组件的 data 选项必须是一个函数,因此每个实例可以维护一份被返回对象的独立的拷贝。new Vue 的实例是不会被复用的,因此不存在以上问题。


Vue 事件绑定原理说一下

详解
  1. 原生 dom 事件的绑定,采用的是 addEventListener 实现
  2. 组件绑定事件采用的是 $on 方法

Vue 中组件生命周期调用顺序说一下

详解

组件的调用顺序都是先父后子,渲染完成的顺序是先子后父。

组件的销毁操作是先父后子,销毁完成的顺序是先子后父。

加载渲染过程 父 beforeCreate-> 父 created-> 父 beforeMount-> 子 beforeCreate-> 子 created-> 子 beforeMount- > 子 mounted-> 父 mounted

子组件更新过程 父 beforeUpdate-> 子 beforeUpdate-> 子 updated-> 父 updated

父组件更新过程 父 beforeUpdate -> 父 updated

销毁过程 父 beforeDestroy-> 子 beforeDestroy-> 子 destroyed-> 父 destroyed


Vue2.x 组件通信

解析

用 props 和 events 实现父子组件通信

通过使用事件中心,允许组件自由交流,无论组件处于组件树的哪一层。由于 Vue 实例实现了一个事件分发接口,你可以通过实例化一个空的 Vue 实例来实现兄弟组件间的通信。然后在组件中,可以使用 $emit$on$off 分别来分发。监听。取消监听事件:


Vue 性能优化

解析

一。编码优化:

  1. 不要将所有的数据都放在 data 中,data 中的数据都会增加 getter 和 setter,会收集对应的 watcher,这样就会降低性能。

  2. vue 在 v-for 时给每项元素绑定事件需要用事件代理,节约性能。

  3. 单页面采用 keep-alive 缓存组件。

  4. 尽可能拆分组件,来提高复用性。增加代码的可维护性,减少不必要的渲染。因为组件粒度最细,改组件的数组,它只会渲染当前的组件。

  5. v-if 当值为 false 时内部指令不会执行,具有阻断功能,很多情况下使用 v-if 替代 v-show,合理使用 if 和 show.

  6. key 保证唯一性,不要使用索引 ( vue 中 diff 算法会采用就地复用策略).

  7. data 中的所以数据都会被劫持,所以将数据尽可能扁平化,如果数据只是用来渲染可以使用 Object.freeze,可以将数据冻结起来,这样就不会增加 getter 和 setter.

  8. 合理使用路由懒加载。异步组件。

  9. 尽量采用 runtime 运行时版本。

  10. 数据持久化的问题,使用防抖。节流进行优化,尽可能的少执行和不执行。

二。加载性能:

  1. 使用第三方插件实现按需加载

  2. 滚动到可视区域动态加载

  3. 图片懒加载

三。用户体验:

  1. app-skeleton 骨架屏

  2. app-shell app 壳

  3. pwa 可以实现 H5 的离线缓存,使用 servicewor

四。SEO 优化:

  1. 预渲染插件 prerender-spa-plugin,可以把我们代码提前运行起来,最后将代码保存下来,缺陷就是不实时。

  2. 服务端渲染 ssr

五。. 打包优化:

  1. 使用 cdn 的方式加载第三方模块

  2. 多线程打包 happypack

  3. 抽离公共文件 splitChunks

  4. sourceMap 生成

六。缓存和压缩:

  1. 客户端缓存。服务端缓存

  2. 服务端 gzip 压缩


Vue 定义全局的方法

解析
  1. 通过 prototype, 这个非常方便。Vue.prototype[method]=method;
  2. 通过插件 Vue.use(plugin);
  3. 通过 mixin,Vue.mixin(mixins);

怎么解决 Vue 打包后静态资源图片失效的问题

Vue 首页白屏是什么问题引起的如何解决呢

解析
  1. vue-cli 2.x 版本

在 config 文件夹下的 index.js 中修改 assetsPublicPath: ‘./‘

  1. vue-cli 3.x 版本

在 vue.config.js 添加 baseUrl 属性 设为 ‘./’ 即可

  1. vue-cli 4.x 版本

修改 vue.config.js 文件 ,但将属性换为 publicPath:’./‘


Vue 风格指南

解析

Vue 3.x 风格指南

Vue 2.x 风格指南


Vue methods watch 用箭头函数定义结果会怎么样

详解

不应该使用箭头函数来定义 watcher 函数 理由是箭头函数绑定了父级作用域的上下文,所以 this 将不会按照期望指向 Vue 实例,this 将指向 undefined.


Vue 怎么实现强制刷新组件

详解

强制重新渲染

this.$forceUpdate();

强制重新刷新某组件

// 模版上绑定 key
<SomeComponent :key="theKey"/>
// 选项里绑定 data
data(){
  return{
      theKey:0
  }
}
// 刷新 key 达到刷新组件的目的
theKey++;

Vue 自定义事件中父组件接收子组件的多个参数

详解

很多时候用 $emit 携带参数传出事件,并且又需要在父组件中使用自定义参数时,这时我们就无法接受到子组件传出的参数了。
找到了两种方法可以同时添加自定义参数的方法。

子组件传出单个参数时:

// 子组件
this.$emit('test',this.param)
// 父组件
@test='test($event,userDefined)'

子组件传出多个参数时:

// 子组件
this.$emit('test',this.param1,this.param2, this.param3)
// 父组件 arguments 是以数组的形式传入
@test='test(arguments,userDefined)'

自定义事件传参问题 #5735


Vue 给组件绑定自定义事件无效怎么解决

将原生事件绑定到组件

Vue 的属性与方法同名

详解
[Vue warn]: Method "xxx" has already been defined as a data property.
[Vue warn]: Error in mounted hook: "TypeError: this.xxx is not a function"
TypeError: this.xxx is not a function

Vue 如果想扩展某个现有的组件时,怎么做呢

详解
  1. 使用 Vue.extend 直接扩展
  2. 使用 Vue.mixin 全局混入
  3. HOC 封装
  4. 加 slot 扩展

EventBus 全局注册路由切换时重复触发事件

详解

建议在 created 里注册,在 beforeDestory 移出


怎么修改 Vue 打包后生成文件路径

vue.config.js 中设置 outputDir

动态组件 tab 切换

详解

在不同组件之间进行动态切换可以通过 Vue 的 <component> 元素加一个特殊的 is attribute 来实现:

<!-- 组件会在 `currentTabComponent` 改变时改变 -->
<component v-bind:is="currentTabComponent"></component>

动态组件


怎么缓存当前的组件缓存后怎么更新

详解

在动态组件上使用 keep-alive

在一个多标签的界面中使用 is attribute 来切换不同的组件
当在这些组件之间切换的时候,你有时会想保持这些组件的状态,以避免反复渲染导致的性能问题


说说你对 SPA 单页面的理解及优缺点

详解

SPA 应用就是一个 WEB 应用,可理解为:是一种只需要将单个页面加载到服务器之中的 WEB 应用程序。当浏览器向服务器发出第一个请求时,服务器会返回一个 index.html 文件,它所需的其他资源会在显示时统一加载,部分页面需要时加载。

SPA 单页面的实现方式有哪些

  1. 监听地址栏中 hash 变化驱动界面变化

  2. 用 pushsate 记录浏览器的历史,驱动界面发送变化

  3. 直接在界面用普通事件驱动界面变化

它们都是遵循同一种原则:div 的显示与隐藏

优点:

  1. 良好的交互式体验。意思是:用户无需刷新页面,获取数据通过异步 ajax 获取,页面显示流畅
  2. 良好的前后端分离模式(MVVM)减轻服务端压力。服务器只需要输出数据就可以,不用管逻辑和页面展示,吞吐能力会提高几倍
  3. 共用同一套后端程序代码,不用修改就可用于 web 界面,手机和平板等客户端设备

缺点:

  1. 不利于 SEO 优化
  2. 由于单页应用在一个页面中显示,所以不可以使用浏览器自带的前进后退功能,想要实现页面切换需要自己进行管理
  3. 首屏加载过慢(初次加载耗时多)原因是:为了实现单页 web 应用功能及展示效果,在页面初始化的时候就会将 js,css 等统一加载,部分页面在需要时加载。当然也有解决方法。

解决方法:

  1. 使用路由懒加载
  2. 开启 Gzip 压缩
  3. 使用 webpack 的 externals 属性把不需要的库文件分离出去,减少打包后文件的大小
  4. 使用 vue 的服务端渲染(SSR)

举例 SPA 应用:网易云音乐。QQ 音乐等


组件中写 name 选项有什么作用

详解
  1. 当项目使用 keep-alive 时,可搭配组件 name 进行缓存过滤
  2. DOM 做递归组件时 递归迭代时需要调用自身 name
  3. vue-devtools 调试工具里显示的组见名称是由 vue 中组件 name 决定的

Vue 递归组件


🔥访问根实例

详解

在每个 new Vue 实例的子组件中,其根实例可以通过 $root property 进行访问。例如,在这个根实例中:

// Vue 根实例
new Vue({
  data: {
    foo: 1,
  },
  computed: {
    bar: function () {
      /* ... */
    },
  },
  methods: {
    baz: function () {
      /* ... */
    },
  },
});

所有的子组件都可以将这个实例作为一个全局 store 来访问或使用。

// 获取根组件的数据
this.$root.foo;

// 写入根组件的数据
this.$root.foo = 2;

// 访问根组件的计算属性
this.$root.bar;

// 调用根组件的方法
this.$root.baz();

$root


🔥访问父级组件实例

详解

$root 类似,$parent property 可以用来从一个子组件访问父组件的实例。它提供了一种机会,可以在后期随时触达父级组件,以替代将数据以 prop 的方式传入子组件的方式。


Vue 中子组件调用父组件的方法,这里有三种方法提供参考

  • 直接在子组件中通过 this.$parent.event 来调用父组件的方法
  • 在子组件里用 $emit 向父组件触发一个事件,父组件监听这个事件
  • 父组件把方法传入子组件中,在子组件里直接调用这个方法

$parent 父实例,如果当前实例有的话。


🔥访问子组件实例或子元素

详解

访问子组件实例或子元素

尽管存在 prop 和事件,有的时候你仍可能需要在 JavaScript 里直接访问一个子组件。为了达到这个目的,你可以通过 ref 这个 attribute 为子组件赋予一个 ID 引用。例如:

<base-input ref="usernameInput"></base-input>

现在在你已经定义了这个 ref 的组件里,你可以使用:

this.$refs.usernameInput;

来访问这个 <base-input> 实例,以便不时之需。比如程序化地从一个父级组件聚焦这个输入框。在刚才那个例子中,该 <base-input> 组件也可以使用一个类似的 ref 提供对内部这个指定元素的访问,例如:

<input ref="input" />

甚至可以通过其父级组件定义方法:

methods: {// 用来从父级组件聚焦输入框 focus: function () { this.$refs.input.focus() } }

这样就允许父级组件通过下面的代码聚焦 <base-input> 里的输入框:

this.$refs.usernameInput.focus();

$children 当前组件树的根 Vue 实例。如果当前实例没有父实例,此实例将会是其自己。


Vue 组件里的定时器要怎么销毁

解析

在 beforeDestroy() 生命周期内清除定时器

通过 $once 这个事件侦听器器在定义完定时器之后的位置来清除定时器


Vue 组件会在什么时候下被销毁

解析

页面关闭。路由跳转。v-if 和改变 key 值


使用 Vue 渲染大量数据时应该怎么优化

解析

这时候你就可以使用 Object.freeze 方法了,它可以冻结一个对象。
当你把一个普通的 JavaScript 对象传给 Vue 实例的 data 选项,Vue 将遍历此对象所有的属性,并使用 Object.defineProperty 把这些属性全部转为 getter/setter,它们让 Vue 能进行追踪依赖,在属性被访问和修改时通知变化。
使用了 Object.freeze 之后,不仅可以减少 observer 的开销,还能减少不少内存开销。


你了解什么是函数式组件吗

Vue 怎么改变插入模板的分隔符

说说你对 provide 和 inject 的理解

provide / inject

说说你对 slot 的理解有多少 slot 使用场景有哪些

插槽

?

写出你知道的表单修饰符和事件修饰符

事件修饰符

.stop 阻止单击事件继续传播
.prevent 提交事件不再重载页面
.capture 添加事件监听器时使用事件捕获模式 即内部元素触发的事件先在此处理,然后才交由内部元素进行处理
.self 只当在 event.target 是当前元素自身时触发处理函数 即事件不是从内部元素触发的
.once 点击事件将只会触发一次
.passive 滚动事件的默认行为 (即滚动行为) 将会立即触发 而不会等待 onScroll 完成

表单修饰符

.lazychange 事件之后进行同步
.number 自动将用户的输入值转为数值类型
.trim 自动过滤用户输入的首尾空白字符

有在 Vue 中使用过 echarts 吗踩过哪些坑如何解决的

Vue 性能的优化的方法有哪些

SSR 解决了什么问题有做过 SSR 吗你是怎么做的

说说你觉得认为的 Vue 开发规范有哪些

Vue 部署上线前需要做哪些准备工作

Vue 过渡动画实现的方式有哪些

进入/离开 & 列表过渡


Vue 父子组件双向绑定的方法有哪些

Vue 要做权限管理 按钮级别

详解

菜单与路由分离,菜单由后端返回

这种方式的缺点:

菜单需要与路由做一一对应,前端添加了新功能,需要通过菜单管理功能添加新的菜单,如果菜单配置的不对会导致应用不能正常使用
全局路由守卫里,每次路由跳转都要做判断

菜单和路由都由后端返回

这种方法也会存在缺点:

全局路由守卫里,每次路由跳转都要做判断
前后端的配合要求更高


Vue 项目的目录结构大型项目怎么划分结构和划分组件呢

Vue3.0 新特性

Vue-loader 是什么

详解

Vue Loader 是什么


怎么捕获组件 Vue 的错误信息

写出多种定义组件模板的方法

说说你都用 Vue 做过哪些类型的项目

使用 Vue 手写一个过滤器

你有使用过 render 函数吗有什么好处

render 字符串模板的代替方案,允许你发挥 JavaScript 最大的编程能力。该渲染函数接收一个 createElement 方法作为第一个参数用来创建 VNode.

手写一个自定义指令及写出如何调用

全局自定义指令

局部指令

你有用过事件总线 (EventBus) 吗说说你的理解

组件传值 (兄弟组件)通信

  1. 通过 Bus.$emit('on-message',this.abc) 的方式进行发布消息,他有两个参数,一个是消息声明,第二个是传递的值,key 和 value 的关系
  2. 另一个组件接收通过 Bus.$on('on-message', msg => { })的方式,第一个参数是传递过来的消息声明,第二个参数可以是个函数,msg 就是做为传递过来的参数
  3. 这里有个坑,在发布者进行发布消息的时候,要在 destroyed 生命周期中,进行销毁,并且在接收的时候 $on 要在 created 生命周期中进行获取,mounted 是获取不到的,这样写,在旧组件销毁的时候新的组件拿到旧组件传来的值,然后在挂载的时候更新页面里的数据。否则传过来的值是不更新的
  4. 我们可以在 bus.js 中使用 data,methods 等选项,都是公共信息,bus.js 中的 data 数据可以说类似于 vuex 中 state 中的数据。如果实际项目中需要存值。
  5. 复杂项目建议还是使用 vuex.

说说 Vue 的优缺点分别是什么

DOM 渲染在哪个周期中就已经完成了

第一次加载页面时会触发哪几个钩子

如何引入 scss 引入后如何使用

使用 Vue 开发过程你是怎么做接口管理的

如果将 axios 异步请求同步化处理

你有封装过 axios 吗主要是封装哪方面的

如何中断 axios 的请求

Axios 提供了一个 CancelToken 的函数,这是一个构造函数,该函数的作用就是用来取消接口请求的。

axios 是什么怎样使用它怎么解决跨域的问题

说说你对 Vue 的 template 编译的理解

v-on 可以绑定多个方法吗

v-on

你认为 Vue 的核心是什么

详解

Vue.js 的两大核心: 数据驱动 和 组件系统

  • 数据驱动,也就是数据的双向绑定

Vue 响应式核心就是,getter 的时候会收集依赖,setter 的时候会触发依赖更新

Vue 将遍历 data 中对象的所有 property,并使用 Object.defineProperty 把这些 property 全部转为 getter/setter.

这些 getter/setter 对用户来说是不可见的,但是在内部它们让 Vue 能够追踪依赖,在 property 被访问和修改时通知变更。

每个组件实例都对应一个 watcher 实例,它会在组件渲染的过程中把 “接触” 过的数据 property 记录为依赖。

getter 的时候我们会收集依赖,依赖收集就是订阅数据变化 watcher 的收集,依赖收集的目的是当响应式数据发生变化时,能够通知相应的订阅者去处理相关的逻辑。

setter 的时候会触发依赖更新,之后当依赖项的 setter 触发时,会通知 watcher,从而使它关联的组件重新渲染。

  • 组件系统

组件的核心选项

1 模板(template):模板声明了数据和最终展现给用户的 DOM 之间的映射关系。

2 初始数据(data):一个组件的初始数据状态。对于可复用的组件来说,这通常是私有的状态。

3 接受的外部参数 (props):组件之间通过参数来进行数据的传递和共享。

4 方法(methods):对数据的改动操作一般都在组件的方法内进行。

5 生命周期钩子函数(lifecycle hooks):一个组件会触发多个生命周期钩子函数,最新 2.0 版本对于生命周期函数名称改动很大。

6 私有资源(assets):Vue.js 当中将用户自定义的指令。过滤器。组件等统称为资源。一个组件可以声明自己的私有资源。私有资源只有该组件和它的子组件可以调用


说说你对 Vue 的 mixin 的理解,有什么应用场景

解析

mixin 用于全局混入,会影响到每个组件实例。

mixins 应该是我们最常使用的扩展组件的方式了。如果多个组件中有相同的业务逻辑,就可以将这些逻辑剥离出来,通过 mixins 混入代码,比如上拉下拉加载数据这种逻辑等等。另外需要注意的是 mixins 混入的钩子函数会先于组件内的钩子函数执行,并且在遇到同名选项的时候也会有选择性的进行合并

混入

组件和插件有什么区别

Vue 实例挂载的过程是什么

Vue 在组件中引入插件的方法有哪些

Vue 监听到数组或对象变化的场景

如何追踪变化

怎么在 watch 监听开始之后立即被调用

Vue 如何监听键盘事件

怎么使 CSS 样式只在当前组件中生效

详解

组件分布在多个文件上 (例如 CSS Modules)

单文件组件让你可以可选 scoped attribute 会自动添加一个唯一的 attribute (比如 data-v-21e5b78) 为组件内 CSS 指定作用域

自定义指令的生命周期 (钩子函数) 有哪些

详解

钩子函数

💼Vue CLI

Vue CLI 提供了的哪几种脚手架模板

Vue CLI 工程中常用的 npm 命令有哪些

在使用 Vue CLI 开发 Vue 项目时,自动刷新页面的原理你了解吗

Vue CLI3 插件有写过吗怎么写一个代码生成插件

Vue CLI 生成的项目可以使用 es6. es7 的语法吗为什么

Vue CLI 怎么解决跨域的问题

Vue CLI 中你经常的加载器有哪些

你知道什么是脚手架吗

说下你了解的 Vue CLI 原理你可以自己实现个类 Vue CLI 吗

怎么使用 Vue CLI3 创建一个项目

Vue CLI3 你有使用过吗它和 2.x 版本有什么区别

Vue CLI 默认是单页面的,那要弄成多页面该怎么办呢

不用 Vue CLI, 你自己有搭建过 Vue 的开发环境吗流程是什么

⛑Vue Router

? $route 和 $router 的区别

$route 是 “路由信息对象”, 包括 path,params,hash,query,fullPath,matched,name 等路由信息参数。而 $router 是 “路由实例” 对象包括了路由的跳转方法,钩子函数等。

Route Object Properties

The Route Object

Vue Router 重定向页面

Vue Router 配置 404 页面

切换路由时,需要保存草稿的功能,怎么实现呢


Vue Router 如何响应路由参数的变化

你有看过 Vue Router 的源码吗说说看

切换到新路由时,页面要滚动到顶部或保持原先的滚动位置怎么做呢

在什么场景下会用到嵌套路由

如何获取路由传过来的参数

路由组件传参

说说 active-class 是哪个组件的属性

active-class 是 vue-router 模块的 router-link 组件中的属性,用来设置链接激活时使用的 CSS 类名。

在 Vue 组件中怎么获取到当前的路由信息

怎样动态加载路由

怎么实现路由懒加载呢

滚动行为

解析

Vue Router 钩子函数有哪些都有哪些参数

解析

导航守卫

  1. 导航被触发。
  2. 在失活的组件里调用 beforeRouteLeave 守卫。
  3. 调用全局的 beforeEach 守卫。
  4. 重用的组件里调用 beforeRouteUpdate 守卫 (2.2+).
  5. 在路由配置里调用 beforeEnter.
  6. 解析异步路由组件。
  7. 在被激活的组件里调用 beforeRouteEnter.
  8. 调用全局的 beforeResolve 守卫 (2.5+).
  9. 导航被确认。
  10. 调用全局的 afterEach 钩子。
  11. 触发 DOM 更新。
  12. 调用 beforeRouteEnter 守卫中传给 next 的回调函数,创建好的组件实例会作为回调函数的参数传入。

👜Vuex

你有写过 Vuex 中 store 的插件吗

你有使用过 Vuex 的 module 吗主要是在什么场景下使用

解析

由于使用单一状态树,应用的所有状态会集中到一个比较大的对象。当应用变得非常复杂时,store 对象就有可能变得相当臃肿。

为了解决以上问题,Vuex 允许我们将 store 分割成模块(module). 每个模块拥有自己的 state. mutation. action. getter. 甚至是嵌套子模块——从上至下进行同样方式的分割

Module


Vuex 使用 actions 时不支持多参数传递怎么办

你觉得 Vuex 有什么缺点

你觉得要是不用 Vuex 的话会带来哪些问题

Vuex 怎么知道 state 是通过 mutation 修改还是外部直接修改的

请求数据是写在组件的 methods 中还是在 Vuex 的 action 中

怎么监听 Vuex 数据的变化

⭕️Vuex 的 action 和 mutation 的特性是什么有什么区别

解析

更改 Vuex 的 store 中的状态的唯一方法是提交 mutations.Vuex 中的 mutation 非常类似于事件:每个 mutation 都有一个字符串的 事件类型 (type) 和 一个 回调函数 (handler). 这个回调函数就是我们实际进行状态更改的地方,并且它会接受 state 作为第一个参数 你可以向 store.commit 传入额外的参数,即 mutation 的 载荷 (payload):

actions 类似于 mutation, 不同在于:Action 提交的是 mutation, 而不是直接变更状态。Action 可以包含任意异步操作。Action 通过 store.dispatch 方法触发:

mutation action
mutation 可以直接变更状态 action 提交的是 mutation,而不是直接变更状态。
mutation 只能是同步操作 action 可以包含任意异步操作。
mutation 是用 this.$store.commit('SET_NUMBER',10) 来提交 action 是用 this.store.dispatch('ACTION_NAME',data) 来提交。
mutation 第一个参数是 state 而 action 第一个参数是 context

页面刷新后 Vuex 的 state 数据丢失怎么解决

🔥Vuex 的 state. getter. mutation. action. module 特性分别是什么

Vuex 中有几个核心属性,它们的作用分别是什么

解析

state, 状态初始化,并实施观察
getter, 获取数据用于 view 或 data 中使用
mutation: 内部处理 state 变化
action: 处理外部交互
module: 模块化以上四个

state 唯一数据源,Vue 实例中的 data 遵循相同的规则
getters 可以认为是 store 的计算属性,就像计算属性一样,getter 的返回值会根据它的依赖被缓存起来,且只有当它的依赖值发生了改变才会被重新计算。Getter 会暴露为 store.getters 对象,你可以以属性的形式访问这些值。
mutation 更改 Vuex 的 store 中的状态的唯一方法是提交 mutation, 非常类似于事件,通过 store.commit 方法触发
action Action 类似于 mutation,不同在于 Action 提交的是 mutation,而不是直接变更状态,Action 可以包含任意异步操作
module 由于使用单一状态树,应用的所有状态会集中到一个比较大的对象。当应用变得非常复杂时,store 对象就有可能变得相当臃肿。为了解决以上问题,Vuex 允许我们将 store 分割成模块(module).


Vuex 主要解决的是什么问题推荐在哪些场景用

解析

如果您不打算开发大型单页应用,使用 Vuex 可能是繁琐冗余的。确实是如此——如果您的应用够简单,您最好不要使用 Vuex. 一个简单的 store 模式 (opens new window) 就足够您所需了。


💍Element UI

Element UI 是怎么做表单验证的在循环里对每个 input 验证怎么做呢

你有二次封装过 Element UI 组件吗

Element UI 怎么修改组件的默认样式

Element UI 的穿梭组件如果数据量大会变卡怎么解决不卡的问题呢

Element UI 表格组件如何实现动态表头

Element UI 使用表格组件时有遇到过问题吗

有阅读过 Element UI 的源码吗

项目中有使用过 Element UI 吗有遇到过哪些问题它的使用场景主要是哪些

有用过哪些 Vue 的 ui 说说它们的优缺点


文章作者: 庄引
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 庄引 !
  目录