详细Vue面试题

1. 虚拟DOM

虚拟DOM( VDOM )是利用了js的Object对象模型来模拟真实DOM,它的结构是一个树形结构,操作虚拟DOM比真实DOM更高效

2. diff算法

diff算法的思维来自于后端,用来比较两个或多个文件,返回值是文件的不同点,diff算法进行的是同级比较

diff算法的比较思维(Vue中),会出现以下四种情况:

    1. 此节点是否被移除  --->  添加新的节点
   
    2. 属性是否被更改 --->  旧属性改为新属性
   
    3. 文本内容被改变  --->  旧内容改为新内容
   
    4. 结构完全不同  --->  节点将被整个移除替换

3. 自己封装过什么组件,描述一下

4. v-if和v-show有什么区别

v-if用于操作Dom是否渲染,而v-if操作的则是display属性,v-if的有更高的切换开销,v-show有更大的初始渲染开销,所以,如果需要频繁切换,使用v-show比较好,而如果渲染条件改变次数少,则v-if更好

5. Vue的双向绑定原理是什么

v-model默认绑定了对象的value,checked等属性,当它初次绑定的时候,就会触发getter,watcher就会触发, watcher通知Vue生成新的VDOM树,再通过render函数进行渲染,生成真实DOM当视图修改时,意味着DOM的value属性值改变,就会触发setter,watcher监听机制就会执行,watcher通知Vue生成新的VDOM树,再通过render函数进行渲染,生成真实DOM

6. 如何在Vue组件之间传递价值通信 【本人理解为如何在组件内通信】

  • 父子通信

    1. 绑定简单数据类型
      • 父组件中定义数据, 通过单向数据绑定的形式, 将数据绑定在子组件的属性身上, 属性是自定义属性
      • 子组件通过配置项中的props接收数据, props可以是一个数组,数组中放的是自定义属性的名称
      • 接受完后,则这个自定义属性可以向data中的数据一样直接在子组件模板中使用
      • 父组件中的数据一旦修改, 子组件数据就会修改,但是子组件无法修改数据, 那么这也就是单项数据流
  • 子父通信

    1. 绑定复杂数据类型
      • 父组件中的数据是复杂数据类型的数据,那么父组件再给子组件绑定数据时,给子组件的是一个引用地址
      • 所以,子组件可以通过这个引用地址,修改这个数据
    2. 父组件传递一个方法给子组件,达到操作子组件,间接操作父组件数据的效果
      • 父组件定义方法, 然后将这个方法通过单向数据绑定的形式传递给子组件,即通过自定义属性
      • 子组件通过props属性接收, 然后通过 事件调用:例:@click=“自定义属性自定义属性名”
    3. 通过自定义事件来实现通信
      • 父组件中定义 数据 和 方法(方法时用来操作数据的)
      • 在子组件身上绑定自定义事件
      • 子组件定义方法, 在这个方法中通过 this.$emit(eventType,实际参数) 来调用自定义事件的事件处理程序
  • 非父子组件通信

    1. 使用ref来绑定组件, 【ref链】

      • 在父组件的模板中, 使用ref = refName 绑定在两个兄弟组件身上
      • 在任意一个子组件中, 就可以通过 this. p a r e n t . parent. parent.refs.refName 就可以获得另一个子组件了, 同时这个自组件身上的数据和方法同样也得到了
    2. 通过事件总线(bus)

      • 它是通过事件的发布(声明), 以及事件的订阅(触发)来做的

      • 首先在js中 创建一个bus对象(vm)

        var bus = new Vue()
        
      • 在Count组件中定义数据, 和修改数据的方法

      • 在Count组件中 通过 created 钩子 , 进行bus事件的发布

        created: {
            bus.$on('add',this.addCount)
        }
        
      • 在MyButton组件的方法中通过 bus进行事件的订阅

        increment () {
            bus.$emit( 'add' )
        }
        

7. Vue 生命周期的理解

  1. Vue 实例有一个完整的生命周期,生命周期也就是指一个实例从开始创建到销毁的这个过程。

    • beforeCreated():在实例创建之前执行,数据未加载状态。

    • created():在实例创建、数据加载后,能初始化数据,DOM 渲染之前执行。

    • beforeMount():虚拟 DOM 已创建完成,在数据渲染前最后一次更改数据。

    • mounted():页面、数据渲染完成,真实 DOM 挂载完成。

    • mounted():页面、数据渲染完成,真实 DOM 挂载完成。

    • beforeUpadate():重新渲染之前触发。

    • updated():数据已经更改完成,DOM 也重新 render 完成,更改数据会陷入死循环。

    • beforeDestory()

      和 destoryed():前者是销毁前执行(实例仍然完全可用),后者则是销毁后执

8. vue对数组的方法,做了哪些封装

9. 路由的种类及路由实现的底层原理

  1. 种类
    • hash: 使用 URL hash 值来作路由。支持所有浏览器,包括不支持 HTML5 History Api 的浏览器。
    • history: 依赖 HTML5 History API 和服务器配置。【需要后端支持】
    • abstract: 支持所有 JavaScript 运行环境,如 Node.js 服务器端。如果发现没有浏览器的 API,路由会自动强制进入这个模式。
  2. 底层原理

10. slot用什么可以代替

11. 2.6版本对slot有哪些改变,及如何使用

- 改变:

  vue 在 2.6.0 中,具名插槽和作用域插槽引入了一个新的统一的语法 (即 `v-slot` 指令)。它取代了 `slot` 和 `slot-scope` 这两个目前已被废弃但未被移除且仍有用的特性。但是将会在vue 3 中,被废弃的这两个,不会被支持即无效。

- 使用

  1. 具名插槽的变化

     ```javascript
         
         
     
     
         
         
     ```

  2. 具名插槽的缩写

     跟 v-on 和 v-bind 一样,v-slot 也有缩写,即把参数之前的所有内容 (v-slot:) 替换为字符 #。例如 v-slot:header 可以被重写为 #header:

     ```html
     
       	
     
       	

A paragraph for the main content.

And another one.

``` 3. 作用域插槽的变化 ```html
说了:{{thing.said}}
``` 4. 动态插槽名:态指令参数也可以用在 v-slot 上,来定义动态的插槽名: ```html ```

12. V-modle可以用什么替代

v-model其实是v-bind和v-on的语法糖

``其实是

``的语法糖

v-on,它其实就是一个事件绑定器。我们仔细阅读一下

``,

发现它由两部分组成:v-bind:value和v-on:input,必须是value属性和input事件,否则也不会等价于v-model,而且input事件里面,正好是something等于当前输入值。

13. Vuex的理解

vuex是一个集中式的存储仓库【状态】,类似于 本地存储、数据库,vuex是vue的状态管理工具,它的功能主要是实现多组件间的状态【数据】共享

vuex的组成部分(其中state,action和mutation是它的核心组成)

- **state: 状态**

- **action: 动作(业务交互)**

- **mutation: 修改state**

- getter: 获取数据的

- store: state的存储者

应用场景

相对比较大型的应用(状态较多)

### 14. 如何封装插件

1. 创建插件目录,使用npm init -y 初始化目录。

2. 定义插件组件内容,并在入口文件index.js中引入插件组件,并使用install方法,并导出

   ```JavaScript
   import Vue from 'vue'
   import Loading from './components/Loading.vue'
   
   export default {
       install () {
           Vue.component('Loading',Loading)
       }
   }
   ```

3. 在Vue的入口文件中引入index.js文件并使用Vue.use()使用该组件,则可以在项目中任意位置使用

   ```JavaScript
   import Loading from './zyl_plugins'
   
   Vue.use(Loading)
   ```

15. 是否研究过源码

16. Vue不能检测哪些变动的数组,官方是怎么解决的?你是怎么解决的?

1. 当你利用索引设置一个项时, 例如: vm.items[indexOfItem] = newValue;

   **解决方法**: 使用   Vue.set  || this.$set 或splice(indexOfItem, 1, newValue);

2. 当你修改数组的长度时,例如: vm.items.length = newLength;

   **解决方法**:使用splice(newLength)

17. 问的是vue中 新增 对数组api的响应 源码大概是怎么个流程

18. 问你在Vue是用Ajax吗

Vue数据请求用的是原生的fetch和封装的第三方库axios

19. vue兼容ie?

vue.js是不兼容ie8及其以下浏览器,因为用到了ES5中的`Object.defineProperty`

20. vue做PC?react做移动?

不区分平台,都可以使用

21. vue做pc端会做IE的兼容

第一步、安装 babel-polyfill 
`npm install --save babel-polyfill`
第二步、在VUE项目的src目录下找到main.js,添加代码`import 'babel-polyfill'`
第三步、在webpack.base.conf.js中配置:
`entry: {
app: ['babel-polyfill','./src/main.js']
},`

22. histroy路由如何去掉#

可以用路由的 history 模式,添加 mode: 'history' 之后将使用 HTML5 history 模式,该模式下没有 # 前缀

23. Vue中如何使用防抖节流,

1. 在公共方法中(如 public.js 中),加入函数防抖和节流方法
   
	- 防抖
	
	  ```JavaScript
	  export function _debounce(fn, delay) {
	      var delay = delay || 200;
	      var timer;
	      return function () {
	          var th = this;
	          var args = arguments;
	          if (timer) {
	              clearTimeout(timer);
	          }
	          timer = setTimeout(function () {
	              timer = null;
	              fn.apply(th, args);
	          }, delay);
	      };
	      }
	  ```
	
	- 节流
	
	  ```JavaScript
	  export function _throttle(fn, interval) {
	  var last;
	  var timer;
	  var interval = interval || 200;
	  return function () {
	      var th = this;
	      var args = arguments;
	      var now = +new Date();
	      if (last && now - last < interval) {
	          clearTimeout(timer);
	          timer = setTimeout(function () {
	              last = now;
	              fn.apply(th, args);
	          }, interval);
	      } else {
	          last = now;
	          fn.apply(th, args);
	      }
	  }
	  }
	  ```
	
	  
	
2. 在需要使用的组件引用
   `import { _debounce } from "@/utils/public";`

3. 在 methods 中使用

   ```JavaScript
   methods: {
       // 改变场数
       changefield: _debounce(function(_type, index, item) {
           // do something ...
       }, 200)
     }
   ```

24. 保持活动组件在Vue中的作用

25. vue项目的技术栈?

(技术栈:某项工作或某个职位需要掌握的一系列技能组合的统称)

1. vue
   组件的生命周期、组件的通信、计算属性(computed)、数据更新检测,对象更新、事件处理器(修饰符)、表单控件绑定、异步更新队列、过渡效果、插件、混合(mixins)....
2. vue-router
   两种导航方式(router-link声明式导航,编程式导航)、导航(路由)守卫、路由的激活,动画、数据获取,预载,懒加载,缓存、路由的传接参、动态路由...
3. vuex
   state、actions、mutations、getters、modules、热重载

26. vue cli 搭建项目?

vue-cli  用于快速创建vue项目,底层配置使用的就是webpack

1. 安装cli
   npm install @vue/cli -g  cli3的版本
   npm install vue-cli  -g  cli2的版本
   (npm install @vue/cli-init -g  装了这个工具,可以随意安装cli2又能随意安装cli3)
2. 创建项目
   vue  create  peoject(项目名)   --->cli3
   vue  init  webpack/webpack-simple(简易版本)   peoject(项目名)  ---->cli2
3. 目录结构说明
   * node_modules   项目的依赖包
   * public    静态资源文件夹
   * src       源代码开发目录
     1. assets           当前项目开发的静态资源
     2. compomemts  项目的组件
     3. main.js       webpack中配置的主入口文件
        .......
   * .browserslistrc   项目不支持  ie8及以下
   * .gitignore           git上传时,不上传的文件
   * package.json    当前项目的依赖包配置文件
   * pastcss.cofig.js   给css添加引擎头前缀
   * readme.md        当前项目的说明文件
   * yarn.lock           当前项目的依赖包的第三方库的详细信息记录
4. 下载依赖包
   下载所需要的包,npm/cnpm/yarn
5. 运行项目
   npm run dev

27. dev pro test 环境的配置:相对应的如何配置。script配置,mode环境

28. dev-server 开发如何跑起来的,大概加载了那些东西?加载了那些中间件

29. vue 中的observer

(vue.$data.__ob__)是保存Observer对象的,用来记录是否已经做过数据的“响应式化”,也就是是否已经被Observer处理过,最终是为了用Object.defineProperty进行数据的双向绑定。

30. vue数据响应式,data变成响应式。让其他数据变成响应式,

31. 刷新之后vuex状态之后,重置的问题,如何解决

利用sessionStorage/localStorage,做一个暂时的储存store的模块化结构
主要是针对mutations 和 getters 做一个简单的赋值和取值封装
mutations.js改变state的同时在本地做一个备份
getters.js 取值时默认从state里面取,没有就从本地拿
在页面vue文件直接用mapGetters获取状态值
这样一来就算state被清空了,还可以在本地储存里面获取状态值

32. vue深度监听的方法

watch所监听的对象里添加deep: true

33. vue一面如何实现一个倒计时定时器,回来的时候时间继续

34. hashRouter,history的原理

-  hash 模式 —— 使用 URL 的 hash值 来模拟一个完整的 URL,于是当 URL 改变时,页面不会重新加载。支持所有浏览器,包括不支持 HTML5 History Api 的浏览器。

- history 模式——这种模式充分利用 h5 history.pushState API 来完成 URL 跳转而无须重新加载页面。history需要后台配置支持

35. 路由拦截

登录路由拦截, 

```javascript
router.beforeEach((to, from, next) => {

  if (to.name !== 'login') {

    if (!window.sessionStorage.tokenId) {

      router.push({name: 'login'})

    }

  }

  next()
```

36. vue的生命周期,以及每个周期的作用

- beforeCreate:表示组件创建前的准备工作, 为事件的发布订阅 和 生命周期的开始做初始化,无法获取data数据和真实dom

- created: 在实例创建、数据加载后,能初始化数据,DOM 渲染之前执行。数据、属性、方法已经初始化完成,还没挂载。在这个钩子中可以进行数据请求,然后可以进行默认数据的修改

- beforMount: 挂载之前,已完成模板的渲染,生成了虚拟dom, 但真实dom依然无法获取,在这个钩子中数据请求, 它也可以进行一次数据修改

- mounted:页面、数据渲染完成,真实 DOM 挂载完成。在这个钩子中DOM操作就可以进行了, 也可以进行第三方库的实例化(dom不改变)

- beforeUpdate: 数据更新后被动执行,发生在虚拟DOM重新渲染前,因为这个钩子主要做的事情是内部进行的, 所以对我们而言没有太多的操作意义

- updated: 在数据更改导致的虚拟DOM重新渲染和打补丁之后调用。调用时,组件DOM已经更新,所以可以执行依赖于DOM的操作,如进行第三方库的实例化( DOM是改变的 )。然而在大多数情况下,应该避免在此期间更改状态,通常最好使用计算属性或 watcher 取而代之。

- beforeDestory: 销毁前执行(实例仍然完全可用),

- beforeDestory: 组件连同数据和方法一起被销毁,在这个钩子中做善后工作 , 手动清除一些计时器, 和一些方法, 还有第三方实例化出来的对象

37. vue数据获取在那个生命周期钩子?为什么不在mounted中

看实际情况,一般在created(或beforeRouteEnter)里面就可以,如果涉及到需要页面加载完成之后的话用mounted。

在created的时候,视图中的html并没有渲染出来,所以此时如果直接去操作html的dom节点,一定找不到相关的元素

而在mounted中,由于此时html已经渲染出来了,所以可以直接操作dom节点,(此时document.getelementById 即可生效了)。

38. 是否进行过组件封装?举例下自己如何进行组件封装的

首先,组件可以提升整个项目的开发效率。能够把页面抽象成多个相对独立的模块,解决了我们传统项目开发:效率低、难维护、复用性等问题。

然后,使用Vue.extend方法创建一个组件,然后使用Vue.component方法注册组件。子组件需要数据,可以在props中接受定义。而子组件修改好数据后,想把数据传递给父组件。可以采用emit方法。

39. 组件通信的各种方法

父子 props/event $parent/$children ref provide/inject

兄弟 bus vuex

跨级 bus vuex provide.inject

40. 如何实现秒杀功能(结合vue的生命周期)

```javascript
HTML:
{{countDownList}}
script: export default {   data() {     return {       countDownList: '00天00时00分00秒',       actEndTime: '2018-11-19 18:50:00'     };   },   created() {     this.countDown();   },   methods: {     timeFormat(param) {       return param < 10 ? '0' + param : param;     },     countDown(it) {       var interval = setInterval(() => {         // 获取当前时间,同时得到活动结束时间数组         let newTime = new Date().getTime();         // 对结束时间进行处理渲染到页面         let endTime = new Date(this.actEndTime).getTime();         let obj = null;         // 如果活动未结束,对时间进行处理         if (endTime - newTime > 0) {           let time = (endTime - newTime) / 1000;           // 获取天、时、分、秒           let day = parseInt(time / (60 * 60 * 24));           let hou = parseInt(time % (60 * 60 * 24) / 3600);           let min = parseInt(time % (60 * 60 * 24) % 3600 / 60);           let sec = parseInt(time % (60 * 60 * 24) % 3600 % 60);           obj = {             day: this.timeFormat(day),             hou: this.timeFormat(hou),             min: this.timeFormat(min),             sec: this.timeFormat(sec)           };         } else { // 活动已结束,全部设置为'00'           obj = {             day: '00',             hou: '00',             min: '00',             sec: '00'           };           clearInterval(interval);         }         this.countDownList = obj.day + '天' + obj.hou + '时' + obj.min + '分' + obj.sec + '秒';       }, 1000);     }   } } ```

你可能感兴趣的:(详细Vue面试题)