vue 面试题积累(含答案)

1、什么是MVVM

MVVM是Model-View-ViewModel的简写。

模型-视图-视图模型

  模型:组件中的data属性

  视图:组件中的template

  视图模型:new Vue() 出来的对象,它是连接view和model的桥梁。

    一是将【模型】转化成【视图】,即将后端传递的数据转化成所看到的页面。实现的方式是:数据绑定。

    二是将【视图】转化成【模型】,即将所看到的页面转化成后端的数据。实现的方式是:DOM 事件监听。

在MVVM的框架下视图和模型是不能直接通信的。它们通过ViewModel来通信。

数据流向如下:

 

2、MVC和MVVM的区别

MVC是Model-View- Controller的简写。即模型-视图-控制器。M和V指的意思和MVVM中的M和V意思一样。C即Controller指的是页面业务逻辑

使用MVC的目的就是将M和V的代码分离。‘MVC是单向通信。也就是View跟Model,必须通过Controller来承上启下。

两者的区别:

  MVVM其实是MVC的改进版,两者没有很大的区别,只是MVVM实现了双向数据绑定,MVC是单向通信的。

  mvc是比较早的偏后端开发的模式,而且各做各的事,互不干扰,想做双向绑定就只能dom模拟,但是mvvm是实现了响应式的双向数据绑定的,而且还是基于mvc模式演变出来的,你能做的我也能做,你没实现的我却能实现,所以mvvm模式更受前端市场的欢迎

3、vue、react、jquery的区别

vue和jquery的区别:

  jquery是使用选择器($)选取DOM对象,对其进行赋值、取值、事件绑定等操作,其实和原生的HTML的区别只在于可以更方便的选取和操作DOM对象,而数据和界面是在一起的。比如需要获取label标签的内容:$("lable").val(),它还是依赖DOM元素的值。

  Vue则是通过Vue对象将数据和View完全分离开来了。对数据进行操作不再需要引用相应的DOM对象,可以说数据和View是分离的,他们通过Vue对象这个vm实现相互的绑定。这就是传说中的MVVM。

vue和react的区别:

相似点:

  • 都使用虚拟dom
  • 各自都提供了响应式的实现,数据驱动视图
  • 这两个都是用来开发SPA的框架,所以组件化、状态管理、路由这些功具备了
  • 组件间通信也都用到了 props

不同点:

  • 数据绑定:vue实现了数据的双向绑定,react数据流动是单向
  • 组件写法不一样,:React推荐的做法是 JSX,也就是把HTML和CSS全都写进JavaScript。Vue推荐的做法是webpack+vue-loader的单文件组件格式,即html,css,jd写在同一个文件;
  • 数据和视图更新方式不一样:state对象在react应用中不可变的,需要使用setState方法更新状态;在vue中,state对象不是必须的,数据由data属性在vue对象中管理
  • react没有实现双向数据绑定,只有响应式。如果想要响应式需要自己去书写
  • 虚拟dom实现方式上的不一样:vue会跟踪每一个组件的依赖关系,不需要重新渲染整个组件树.而对于React而言,每当应用的状态被改变时,该组件以及以下的所有子组件都会重新渲染,所以react中会需要shouldComponentUpdate这个生命周期函数方法来进行控制。
  • diff算法实现不一样

4、组件之间的通信

父子之间的通信:

  1.父组件向子组件通信:props。在子组件中定义props属性

  2.子组件向父组件通信:emit。在子组件中使用emit发射事件,然后在父组件中定义方法实现这个事件

  3.$emit和$on也可以实现任何组件之间的通信。包括父子、兄弟、跨级。不过它得有个中间桥梁来传输数据。这个桥梁一般是个空对象 new Vue()

var Event = new Vue()
Event.$emit(事件名,参数)
Event.$on(事件名,data => {})

  4.vuex

    Vuex 的状态存储是响应式的,单向数据流。必须通过vuex提供的方式 Mutations 去 commit 提交修改state数据

    vuex的几个重要属性。store、state、getters、action、mutations

  5.$children、ref、$parent

    ref、children可以实现父组件直接获取子组件的实例,通过实例可以直接使用子组件中的方法活或者属性。两者的不同点:children 是个按子组件位置存放子组件实例,ref 可以通过定义属性直接去获取指定的实例

    parent 相反是提供给子组件访问父组件实例的方法

   6.provide 和 inject:可以实现跨级获取数据

   父组件通过 provide 传递数据出去,子组件通过 inject 获取数据

 5、vuex相关的面试题

(1)vuex是什么?怎么使用?哪种功能场景使用它?

vue框架中状态管理。在main.js引入store,注入。新建一个目录store,…… export 。场景有:单页应用中,组件之间的状态。音乐播放、登录状态、加入购物车

(2)vuex有哪几种属性?

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

vuex的State特性

  A、Vuex就是一个仓库,仓库里面放了很多对象。其中state就是数据源存放地,对应于一般Vue对象里面的data

  B、state里面存放的数据是响应式的,Vue组件从store中读取数据,若是store中的数据发生改变,依赖这个数据的组件也会发生更新

  C、它通过mapState把全局的 state 和 getters 映射到当前组件的 computed 计算属性中

vuex的Getter特性

  A、getters 可以对State进行计算操作,它就是Store的计算属性

  B、 虽然在组件内也可以做计算属性,但是getters 可以在多组件之间复用

  C、 如果一个状态只在一个组件内使用,是可以不用getters

vuex的Mutation特性:修改state的唯一途径,必须使用 commit 去提交修改state

Action 类似于 mutation,不同在于:Action 提交的是 mutation,而不是直接变更状态;Action 可以包含任意异步操作。使用的是 store.dispatch('increment')去触发

6、v-if 和 v-show 的 相同点和不同点

  两者都是用来对元素做显示隐藏的

  v-if 是直接通过销毁和重建dom来实现的。

  v-show 是通过元素的css属性来通知显示和隐藏的

  性能上来讲的话 v-show或更高效。如果是要频繁切换的话建议使用 v-show

7、vue 如何让css只在自己的文件上生效

  只需要在组件的 style 标签加上 scoped属性就可以

8、keep-alive组件的作用

  <keep-alive> 包裹动态组件时,会缓存不活动的组件实例,而不是销毁它们。

  把需要缓存的组件包裹在这个组件中。主要用于保留组件状态或避免重新渲染。

  加上这个组件后进行切换会有 activated 和 deactivated 两个生命周期函数执行

9、脚手架自定义组件的过程

  第一步:在components目录新建你的组件文件(indexPage.vue),script一定要export default {}

  第二步:在需要用的页面(组件)中导入:import indexPage from ‘@/components/indexPage.vue’

  第三步:注入到vue的子组件的components属性上面,components:{indexPage}

  第四步:在template视图view中使用,

  例如有indexPage命名,使用的时候则index-page

10、路由组件的懒加载

  使用es6提供的 import 关键字

import Vue from 'vue'
import Router from 'vue-router'

Vue.use(Router)

const HelloWorld = ()=>import("@/components/HelloWorld")
export default new Router({
  routes: [
    {
      path: '/',
      name: 'HelloWorld',
      component:HelloWorld
    }
  ]
})

11、vue 计算属性的理解和 watch 的区别

  computed 通过计算结果得到的属性,其本身就是个属性,只是这个属性是经过计算得到的,用法和属性的用法是一模一样的,只是定义的位置不同。

<div id="app">
    <p>计算属性fullName:{{fullName}}</p>
</div>

<script>
    var vm = new Vue({  
        el: '#app',  
        data: {  
            firstName: 'Foo',  
            lastName: 'Bar',  
        },  
        computed: {  
            fullName: function () {  
                return this.firstName + ' ' + this.lastName  
            }  
        }  
    })
</script>

  watch 做数据监听,只要监听的属性发生变化,定义的方法就会执行

var vm = new Vue({
  data: {
    a: 1,
  },
  watch: {
    a: function (val, oldVal) {
      console.log('new: %s, old: %s', val, oldVal)
    }
  }
})

12、计算属性和methods的区别

  计算属性具有缓存机制。如果某个值重复的调用而且没有改变,methods的话会重复的执行使用,计算属性是会把缓存中的数据直接取出来使用。只有计算属性中依赖的属性发生变化的时候,值才会重新计算

13、v-if的使用注意事项

  1、v-if和v-else或v-else-if之间不能添加其他元素。

错误示例
<span v-if="type==1">错误示范</span>
<span>哈哈哈</span>
<p v-else>嘿嘿嘿</p>
正确示例
<span v-if="type==1">正确示范</span>
<p v-else>嘿嘿嘿</p>
<span>哈哈哈</span>

  2、为同一类的组件做显示隐藏的时候,最好加上 key 属性来做标识,被标识的组件就会重新渲染了

<template v-if="type=== 'username'" key="1">  
  <label>用户名</label>  
  <input placeholder="输入用户名">  
</template>  
<template v-else  key="2">  
  <label>邮箱</label>  
  <input placeholder="输入邮箱">  
</template>

14、vue 生命周期函数相关面试题

 

 

 1、什么是vue生命周期

  组件实例从创建到销毁的过程,叫做生命周期。开始创建、初始化数据、编译模板、挂载Dom→渲染、更新→渲染、卸载等一系列过程,我们称这是 Vue 的生命周期

2、vue生命周期的作用是什么

  生命周期中有多个函数(钩子函数),这些钩子函数可以让我们在特定的时刻执行特殊的事件,形成更好的逻辑。

3、第一次页面加载会触发的函数

  beforeCreate, created, beforeMount, mounted

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

  DOM 渲染在 mounted 中就已经完成了。

5、生命周期函数和使用场景

beforeCreadted vue实例的挂载元素$el和数据对象data都为undefined,还未初始化。el 和 data 并未初始化 加loading事件
created 完成了 data 数据的初始化,el没有 结束loading、请求数据为mounted渲染做准备
beforeMount vue实例的$el和data都初始化了,但还是虚拟的dom节点,就是说还没有挂载  
mounted vue实例挂载完成 配合路由钩子使用,可以在这里发送异步事件请求
beforeUpdate data更新时触发  
updated data更新时触发 数据更新时,做一些处理(此处也可以用watch进行观测)
beforeDestroy 组件销毁时触发  
destroyed
组件销毁时触发,vue实例解除了事件监听以及和dom的绑定(无响应了),但DOM节点依旧存在 组件销毁时进行提示

15、同级元素为什么要使用key

  同级相同标签名的元素切换时,需要通过 key 特性设置唯一的值来标记以让 Vue 区分它们,高效更新虚拟dom,否则 Vue 为了效率只会替换相同标签内部的内容。

16、后期添加属性的方法

  vue只有在初始化定义的数据才具有响应式,后期如果要添加属性,必须使用 Vue.set 来添加属性,不然数据是不会具有响应式的  Vue.set(object, key, value)

17、vue响应式原理

2.x版本

  1、Observer 通过Object.definePropty进行数据劫持

  4、Dep 发布订阅者,添加观察者者以及在数据发生改变的时候通知观察者

  3、Watcher 观察者,对数据进行观察以及保存数据修改需要触发的回调

  2、Compiler 模板编译器,对HTML模板进行编译,提取其中的变量并转化为数据。

  当把一个普通的 JavaScript 对象传入 Vue 实例作为 data 选项,Vue 将遍历此对象所有的 property,并使用 Object.defineProperty() 进行数据劫持把这些 property 全部转为 getter和setter。

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

  对模板进行编译的时候,收集跟变量有关的数据。

  在使用getter方法时,总会通知wather实例对view层渲染页面。.
  同样的,在使用setter方法时,总会在变更值的同时,通知wather实例对view层进行更新。

  vue是结合数据劫持和发布订阅者模式来实现双向数据绑定的,当要读取数据的时候会自动触发方法,并且会被赋值

  由于 Object.defineProperty() 方法只部分支持IE9,所以Vue兼容IE版本最低为IE9,这也就是 Vue 不支持 IE8 以及更低版本浏览器的原因。

3.0版本

  使用了ES6中的proxy对数据进行代理。

18、vue组件的data为什么要return一个对象

  对象为引用类型,当重用组件时,由于数据对象都指向同一个data对象,当在一个组件中修改data时,其他重用的组件中的data会同时被修改。
  而使用返回对象的函数,由于每次返回的都是一个新对(Object的实例),引用地址不同,则不会出现这个问题。
19、vue路由的几种模式
  两种:hash(默认)、history   可以用model属性切换路由模式
  hash模式下路径有个 # 号
  history模式使用的是 HTML5 中 history API
20、v-if和v-for一起使用的弊端以及解决办法
  由于v-for的优先级比v-if高,所以导致每循环一次就会去v-if一次,而v-if是通过创建和销毁dom元素来控制元素的显示与隐藏,所以就会不停的去创建和销毁元素,造成页面卡顿,性能下降。
  解决方案:在v-for的外层或内层包裹一个元素来使用v-if
21、vue父组件和子组件生命周期的顺序
1.渲染过程顺序:

  父组件beforeCreate() -> 父组件created() -> 父组件beforeMount() -> 子组件beforeCreate() ->子组件created() -> 子组件beforeMount() -> 子组件mounted() -> 父组件mounted()
2.更新过程顺序:
  父组件更新过程:
    父组件beforeUpdate() -> 父组件updated()
  子组件更新过程:
    父组件beforeUpdate() -> 子组件beforeUpdate() -> 子组件updated() -> 父组件updated()
3.销毁过程
  父组件beforeDestroy() -> 子组件beforeDestroy() -> 子组件destroyed() -> 父组件destroyed()

22、vue中事件修饰符有哪些

  .stop: 阻止事件冒泡
  .native: 绑定原生事件
  .once: 事件只执行一次
  .self:将事件绑定在自身身上,相当于阻止事件冒泡
  .prevent: 阻止默认事件
  .caption: 用于事件捕获

23、vue中如何解决页面不重新渲染问题

  this(Vue).$forceUpdate() 这个方法可以迫使Vue 实例重新渲染。它仅仅影响实例本身和插入插槽内容的子组件,而不是所有子组件。

24、vue-router有哪些导航钩子(导航守卫)

  全局前置守卫:可以一次定义多个守卫,当一个导航触发时,全局前置守卫按照创建顺序执行。守卫是异步解析执行,此时导航在所有守卫 resolve 完之前一直处于 等待中

router.beforeEach((to, from, next) => {
   to: Route: 即将要进入的目标 路由对象

    from: Route: 当前导航正要离开的路由

    next: Function:  必须手动调用一下这个函数,不然路由不能解析没法进行跳转
})

  全局解析守卫:router.beforeResolve 注册一个全局解析守卫。在导航被确认之前,同时在所有组件内守卫和异步路由组件被解析之后,解析守卫就被调用。

  全局后置守卫:这个守卫没有 next 方法

router.afterEach((to, from) => {
  // ...
})

  路由独享守卫:beforeEnter直接定义在路由里面去

const router = new VueRouter({
  routes: [
    {
      path: '/foo',
      component: Foo,
      beforeEnter: (to, from, next) => {
        // ...
      }
    }
  ]
})

  组件内的守卫:

    路由组件内直接定义以下路由导航守卫:(直接定义在组件内部,定义在跟data同级) 

    beforeRouteEnter

    beforeRouteUpdate (2.2 新增)

    beforeRouteLeave

const Foo = {
  template: `...`,
  beforeRouteEnter (to, from, next) {
    // 在渲染该组件的对应路由被 confirm 前调用
    // 不!能!获取组件实例 `this`
    // 因为当守卫执行前,组件实例还没被创建
  },
  beforeRouteUpdate (to, from, next) {
    // 在当前路由改变,但是该组件被复用时调用
    // 举例来说,对于一个带有动态参数的路径 /foo/:id,在 /foo/1 和 /foo/2 之间跳转的时候,
    // 由于会渲染同样的 Foo 组件,因此组件实例会被复用。而这个钩子就会在这个情况下被调用。
    // 可以访问组件实例 `this`
  },
  beforeRouteLeave (to, from, next) {
    // 导航离开该组件的对应路由时调用
    // 可以访问组件实例 `this`
  }
}

beforeRouteEnter 守卫 不能 访问 this,因为守卫在导航确认前被调用,因此即将登场的新组件还没被创建。

不过,你可以通过传一个回调给 next来访问组件实例。在导航被确认的时候执行回调,并且把组件实例作为回调方法的参数。

  完整的导航调用顺序:

  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 的回调函数,创建好的组件实例会作为回调函数的参数传入。

25、vue-router里面主要有哪些组件

  主要这三个:<router-link><router-view><keep-alive>

26、路由传参

  动态路由使用 path 传参。动态路由path参数变化的时候,组件不会重新渲染而是会复用,所以生命周期函数不会再次执行,不过可以使用 watch 进行监听

{
  path: '/details/:id'
  name: 'Details'
  components: Details
}
获取方式:
console.log(this.$route.params.id)

// 监听当前路由发生变化的时候执行
watch: {
  $route(to, from){
    console.log(to.path)
    // 对路由变化做出响应
  }
}
组件内导航钩子函数
beforeRouteUpdate(to, from, next){
  // to do somethings
}

  Params

  参数不会显示在路径上

  浏览器强制刷新参数会被清空

 // 传递参数
  this.$router.push({
    name: Home,
    params: {
        number: 1 ,
        code: '999'
    }
  })
  // 接收参数
  const p = this.$route.params

  Query

  参数会显示在路径上,刷新不会被清空

  name 可以使用path路径

// 传递参数
this.$router.push({
  name: Home,
  query: {
  number: 1 ,
  code: '999'
}
})
// 接收参数
const q = this.$route.query

 

posted on 2020-09-06 18:43  棋士牧生  阅读(468)  评论(0编辑  收藏  举报

导航