Vue的面试题库

一. Vue核心小知识点

1、vue中 key 值的作用

key的特殊性主要用在Vue的虚拟DOM算法,再新旧nodes对比时辨别VNodes。如果不使用key,Vue会使用一种最大限度减少动态元素并且尽可能的尝试修复/再利用相同类型元素的算法。使用key,它会基于key的变化重新排列元素顺序,并且会移除key不存在的元素。

有相同父元素的子元素必须有独特的key。重复的key会造成渲染错误。

最常见的用例是结合 v-for:

 
1 <ul>  
2      <li v-for="item in items" :key="item.id">...
3      </li>
4  </ul>

 

它也可以用于强制替换元素/组件而不是重复使用它。当你遇到如下场景时它可能会很有用:

完整地触发组件的生命周期钩子 触发过渡

1  <transition> 
2      <span :key="text">{{ text }}</span>
3  </transition>

 

当 text 发生改变时,<span> 会随时被更新,因此会触发过渡。

2.vue中子组件调用父组件的方法

子组件调用父组件的方法可以使用this.$emit()

第一种方法是在子组件里用$emit向父组件触发一个事件,父组件监听这个事件就行了。

$emit
父组件

 1 <template>
 2   <div>
 3     <child @fatherMethod="fatherMethodOther"></child>
 4   </div>
 5 </template>
 6 <script>
 7   import child from './child';
 8   export default {
 9     components: {
10       child
11     },
12     methods: {
13       fatherMethodOther(str) {
14         console.log(str);
15       }
16     }
17   };
18 </script>

子组件

 1 <template>
 2   <div>
 3     <button @click="childMethod">点击</button>
 4   </div>
 5 </template>
 6 <script>
 7   export default {
 8     methods: {
 9       childMethod() {
10         this.$emit('fatherMethod', 'hello');
11       }
12     }
13   };
14 </script>

第二种方法是直接在子组件中通过this.$parent.event来调用父组件的方法

$parent
父组件

 1 <template>
 2   <div>
 3     <child></child>
 4   </div>
 5 </template>
 6 <script>
 7   import child from './child';
 8   export default {
 9     components: {
10       child
11     },
12     methods: {
13       fatherMethod(str) {
14         console.log(str);
15       }
16     }
17   };
18 </script>

子组件

 1 <template>
 2   <div>
 3     <button @click="childMethod">点击</button>
 4   </div>
 5 </template>
 6 <script>
 7   export default {
 8     methods: {
 9       childMethod() {
10         this.$parent.fatherMethod('hello');
11       }
12     }
13   };
14 </script>
  1. vue等单页面应用及其优点

    优点:

         1.具有桌面应用的及时性,网站的可移植性和可访问性。
      2.用户体验好,块,内容改变不需要重新加载整个页面
      3.基于上面一点,SPA相对对服务器压力小。
      4.良好的前后端分离。SPA和RESTful架构一起使用,后端不再负责模板渲染、
      输出页面工作,web前端和各种移动终端地位对等,后端API通用化。
      5.同一套后端程序代码,不用修改就可以用于Web界面、手机、平板等多种客户端;

    缺点:

     1、不利于SEO。(如果你看中SEO,那就不应该在页面上使用JavaScript,
     你应该使用网站而不是Web应用)
     2、初次加载耗时相对增多。
     3、导航不可用,如果一定要导航需要自行实现前进、后退。

    4.vue.js的两个核心是什么?

    数据驱动和组件化。

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

    vue数据双向绑定是通过数据劫持结合发布者-订阅者模式的方式来实现的。具体实现过程:

    我们已经知道实现数据的双向绑定,首先要对数据进行劫持监听,所以我们需要设置一个监听器Observer,用来监听所有属性。如果属性发上变化了,就需要告诉订阅者Watcher看是否需要更新。因为订阅者是有很多个,所以我们需要有一个消息订阅器Dep来专门收集这些订阅者,然后在监听器Observer和订阅者Watcher之间进行统一管理的。接着,我们还需要有一个指令解析器Compile,对每个节点元素进行扫描和解析,将相关指令对应初始化成一个订阅者Watcher,并替换模板数据或者绑定相应的函数,此时当订阅者Watcher接收到相应属性的变化,就会执行对应的更新函数,从而更新视图。因此接下去我们执行以下3个步骤,实现数据的双向绑定:

    1.实现一个监听器Observer,用来劫持并监听所有属性,如果有变动的,就通知订阅者。

    2.实现一个订阅者Watcher,可以收到属性的变化通知并执行相应的函数,从而更新视图。

    3.实现一个解析器Compile,可以扫描和解析每个节点的相关指令,并根据初始化模板数据以及初始化相应的订阅器。

    流程图如下:

二. v-show和v-if指令的共同点和不同点?

  1. v-show指令是通过修改元素的display的css属性达到让其显示或者隐藏

  2. v-if指令是直接销毁和重建DOM达到让元素显示和隐藏的效果

  3. (注意:v-if 可以实现组件的重新渲染)

     

三. 如何让CSS只在当前组件中起作用?

将当前组件<style>修改为<style scoped>

四. <keep-alive></keep-alive>的作用是什么?

<keep-alive></keep-alive> 包裹动态组件时,会缓存不活动的组件实例,主要用于保留组件状态或避免重新渲染。

对列表组件使用<keep-alive></keep-alive>进行缓存, 这样用户每次返回列表的时候,都能从缓存中快速渲染,而不是重新渲染

五. Vue中引入组件的步骤?

六.请列举出3个Vue中常用的生命周期钩子函数?

vue的生命周期分为8个阶段,创建前/后,载入前/后,更新前/后,销毁前/后。

第一次页面加载需要beforeCreate,created,beforeMount,mounted四个钩子函数。

1) beforeCreate---创建前

组件实例被创建,组件属性计算之前,数据对象data都为undefined,未初始化。

2)created---创建后

组件实例创建完成,属性已经绑定数据对象data已存在,但DOM未生成,$el未存在。

3)beforeMount---挂载前

vue实例的$el和data都已初始化,挂载之前为虚拟的dom节点,data.message未替换。

4)mounted---挂载后

vue实例挂载完成,data.message替换,ajax请求等一系列操作。

5)beforeUpdate---更新前

当data发生变化,会触发此方法。

6)updated---更新后l

当data发生变化,会触发此方法。

7)beforeDestory--销毁前

组件销毁前调用。

8)destoryed---销毁后

组件销毁后调用,对data的改变不会再触发周期函数,vue实例已解除事件监听和dom绑定,但dom结构依然存在。

七.请简述下Vuex的原理和使用方法

 数据单向流动
 
 一个应用可以看作是由上面三部分组成: View, Actions,State,
 数据的流动也是从View => Actions => State =>View 以此达到数据的单向流动.
 
 但是项目较大的, 组件嵌套过多的时候, 多组件共享同一个State会在数据传递时出现很多问题
 .Vuex就是为了解决这些问题而产生的.
 
 Vuex可以被看作项目中所有组件的数据中心,我们将所有组件中共享的State抽离出来,
 任何组件都可以访问和操作我们的数据中心
 
 Vuex的组成:一个实例化的Vuex.Store由state, mutations和actions三个属性组成:
  1. state中保存着共有数据
  2. 改变state中的数据有且只有通过mutations中的方法,且mutations中的方法必须是同步的
  3. 如果要写异步的方法,需要些在actions中, 并通过commit到mutations中进行state中数据的更改.

八.为什么v-if和v-for不能连用?

  • v-for优先级高于v-if,如果连在一起使用的话会把v-if给每一个元素都添加上,

    重复运行于每一个v-for循环中,会造成性能浪费

  • 可以将v-if写在v-for的外层


九.定义vue-router的动态路由?怎么获取传过来的动态参数?

设置:在router目录下的index.js文件中,对path属性加上/:id

获取:使用router对象的params.id

十.v-for中为什么要用key

因为vue组件高度复用,增加Key可以标识组件的唯一性,key的作用主要是为了高效的更新虚拟DOM,

  1. 无key时,会存在“就地复用”的问题。(同一组件标签相同,key相同就会复用)

  2. 有key时,只需移动无需重新创建dom。

十一.Vue中v-html会导致那些问题?

  1. V-html更新的是元素的 innerHTML 。内容按普通 HTML 插入, 不会作为 Vue 模板进行编译 。

  2. 但是有的时候我们需要渲染的html片段中有插值表达式,或者按照Vue模板语法给dom元素绑定了事件。

  3. 在单文件组件里,scoped 的样式不会应用在 v-html 内部,因为那部分 HTML 没有被 Vue 的模板编译器处理。如果你希望针对 v-html 的内容设置带作用域的 CSS,你可以替换为 CSS Modules 或用一个额外的全局 <style>元素手动设置类似 BEM 的作用域策略。

  4. 后台返回的html片段,以及css样式和js,但是返回的js是不执行的,因为浏览器在渲染的时候并没有将js渲染,这时要在$nextTick中动态创建script标签并插入

十二.Vue组件如何通信?

https://www.cnblogs.com/fundebug/p/10884896.html


十三.什么是作用域插槽?

插槽可以控制html模板的显示与不显示。作用域插槽其实就是带数据的插槽。

原来父组件可以通过绑定数据传递给子组件。作用域插槽就可以通过子组件绑定数据传递给父组件。

十四.vue-router有哪几种路由守卫?

路由守卫为: 全局守卫:beforeEach 后置守卫:afterEach 全局解析守卫:beforeResolve 路由独享守卫:beforeEnter

十五.组件中的data为什么是一个函数?

new Vue() 中,data 是可以作为一个对象进行操作的,然而在 component 中,data 只能以函数的形式存在,不能直接将对象赋值给它。

当data选项是一个函数的时候,每个实例可以维护一份被返回对象的独立的拷贝,这样各个实例中的data不会相互影响,是独立的。


vue核心知识——vuex

十六.不用Vuex会带来什么问题?

一、可维护性会下降,你要想修改数据,你得维护三个地方

二、可读性会下降,因为一个组件里的数据,你根本就看不出来是从哪来的

三、增加耦合,大量的上传派发,会让耦合性大大的增加,本来Vue用Component就是为了减少耦合,

现在这么用,和组件化的初衷相背。

1.vuex有哪几种属性?

有五种,分别是 State、 Getter、Mutation 、Action、 Module。

2、vuex的State特性是?

一、Vuex就是一个仓库,仓库里面放了很多对象。其中state就是数据源存放地,对应于与一般Vue对象里面的data 二、state里面存放的数据是响应式的,Vue组件从store中读取数据,若是store中的数据发生改变,依赖这个数据的组件也会发生更新 三、它通过mapState把全局的 state 和 getters 映射到当前组件的 computed 计算属性中

3、vuex的Getter特性是?

一、getters 可以对State进行计算操作,它就是Store的计算属性 二、 虽然在组件内也可以做计算属性,但是getters 可以在多组件之间复用 三、 如果一个状态只在一个组件内使用,是可以不用getters

4、vuex的Mutation特性是?

一、Action 类似于 mutation,不同在于: 二、Action 提交的是 mutation,而不是直接变更状态。 三、Action 可以包含任意异步操作

5、Vue.js中ajax请求代码写在组件的methods中还是vuex的actions中?

一、如果请求来的数据是不是要被其他组件公用,仅仅在请求的组件内使用,就不需要放入vuex 的state里。 二、如果被其他地方复用,这个很大几率上是需要的,如果需要,请将请求放入action里,方便复用,并包装成promise返回,在调用处用async await处理返回的数据。如果不要复用这个请求,那么直接写在vue文件里很方便。


十七.Ajax请求放在那个生命周期中?

答案:mounted

vue本身不支持发送AJAX请求,需要使用vue-resource、axios等插件实现

等到异步渲染开启的时候,created 就可能被中途打断,中断之后渲染又要重做一遍,想一想,在 created 中做ajax调用,代码里看到只有调用一次,但是实际上可能调用 N 多次,这明显不合适。 相反,若把发ajax 放在 mounted,因为 mounted 在第二阶段,所以绝对不会多次重复调用,这才是ajax合适的位置.

十八.v-model中的实现原理级如何自定义v-model?

VUE中的v-model可以实现双向绑定,但是原理是什么呢?往下看看吧

根据官方文档的解释,v-model其实是一个语法糖,它会自动的在元素或者组件上面解析为 :value="" 和 @input="", 就像下面这样

1 // 标准写法
2 <input v-model="name">
3 
4 // 等价于
5 <input :value="name" @input="name = $event.target.value">
6 
7 // 在组件上面时
8 <div :value="name" @input="name = $event"></div>

1.当在input输入框输入内容时,会自动的触发input事件,更新绑定的name值。

2.当name的值通过JavaScript改变时,会更新input的value值

根据上面的原理,vue就通过v-model实现双向数据绑定

 

看了前面的解释,对于v-model有了一定的理解。下面我们就来实现自己组件上面的v-model吧

需求:实现一个简单的点击按钮,每次点击都自动的给绑定值price加100。 组件名为 AddPrice.vue

 1 // AddPrice.vue
 2 // 通过props接受绑定的value参数
 3 <template>
 4   <div @click="$emit('input',value + 100 )">点击加钱<div>
 5 </template>
 6 
 7 <script>
 8   export default {
 9     props: ['value']
10   }
11     
12 </script>
13 
14 // 在父组件中调用
15 <add-price v-model="price"></add-price>

组件中使用props接受传入的参数值value, 组件点击事件触发并 使用$emit调用父组件上的input事件,实现了自定义的双向绑定

十九.响应式数据的原理是什么?

1、声明式

  只需要声明在哪里where,做什么what,而无需关系如何实现how

1  //此map方法就是,声明式的,只告诉map要实现获取2倍,然后map具体怎么实现不关心
2  var  arr = [1,2,3,4];
3  var newArr = arr.map((item,index)=>{
4      return item*2;
5  })

 

2、命令式

  需要以具体的代码表达在哪里where,做什么what,以及如何实现how

1  //forEach就是命令式,会具体操作数组,还有如何得到结果push
2  var  arr = [1,2,3,4];
3  var newArr = [];
4  arr.forEach((item,index)=>{
5      newArr.push(item*2);
6  })

 

声明式的理解:

  1)DOM状态只是数据状态的一种映射

  2)所有的逻辑尽可能在状态的层面去进行

  3)当状态变化了,View会被框架自动更新到合理的状态

 

3、响应式数据原理

vue响应式的核心就是Object.defindProperty

作用:直接在一个对象上定义一个新的属性,或者修改一个对象的现有属性

语法:Object.definProperty(obj,prop,descriptor)

参数:obj要在其上定义属性的对象,prop要定义的或要修改的属性的名称,descriptor将被定义或修改的属性描述符

    数据描述

      configurable:是否可以删除属性,默认false

      enumberable:此属性是否可以被枚举,默认false

      value:   该属性对应的值,默认undefined

      writable:  属性的值是否可以被重写,默认false

    访问器描述

      getter:是一种获得属性值的方法

      setter:是一种设置属性值的方法

 1  //数据劫持,转成getter和setter
 2  function observer(obj){
 3      Object.keys(obj).forEach((item)=>{
 4            defineReactive(obj,item,obj[item])
 5      })
 6  }
 7  8  function defineReactive(obj,key,value){
 9      Object.defineProperty(obj,key,{
10          enumerable:true,
11          configurable:true,
12          get(){
13               return value;
14          },
15          set(newValue){
16               if(value == newValue){return}       
17              //value相当于是一个公用的存储空间,把最新的值存进去;访问也是访问这里面的最新的值
18               value=newValue;       
19              //此处还会放一些其他复杂的操作,收集依赖,通知变化等
20          }
21      })
22  }

 

vue响应式原理理解:

  1、把一个普通的js对象传给Vue实例的data选项对象

  2、Vue将遍历此对象的所有的属性,并使用Object.defineProperty把这些属性全部转换为getter/setter

  3、Vue内部会对数据进行劫持操作,进而追踪依赖,在属性被访问和修改时通知变化


二十.Vue中是如何检查数组变化?

1.使用函数劫持的方式,重写了数组的方法 2.vue 将 data 中的数据,进行了原型链重写,指向了自己定义的数组原型方法,这样当调用数组 api 的时候,可以通知依赖更新,如果数组中包含着引用类型,则会对数组中的引用类型再次进行监控。

二十一.Vue中Computed的特点?

在computed中,可以定义一些属性,这些属性,叫做计算属性。计算属性的本质就是一个方法,只不过,我们在使用这些计算属性的时候,是把它们的名称,直接当做属性来使用,并不会把计算属性当做方法来使用。

三个注意事项:

一、计算属性在引用的时候,一定不要加()去调用,直接把它当作普通的属性去使用就好了;

二、只要计算属性这个function内部所用到的data中的数据发生了变化,就会立即重新计算这个计算属性的值;

三、计算属性的求值结果,会被缓存起来,方便下次继续使用;如果计算属性方法中,所依赖的任何数据,都没有发生过变化,则不会重新对计算属性求值。

 

posted @ 2020-08-15 11:09  肥龙啃锅盔  阅读(708)  评论(0编辑  收藏  举报