欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

vue相关面试题1

程序员文章站 2022-04-19 07:50:35
...

1、库和框架的区别

答: 库 本质上是一个函数的集合,每一次调用函数,实现一个特定的功能,使用库的时候,把库当成工具使用,需要自己控制代码的执行逻辑。
    框架 是一套完整的解决方案,使用框架的时候,框架实现了大部分的功能,我们只需要按照框架的规则书写代码即可,使用框架开发比库开发效率更高,更容易维护。

2、MVC 和 MVVM 的区别

答: MVVM
    M Model 模型 指的是数据层
    V View  视图 指的是用户页面
    VM ViewModel 视图模型
    视图模型是MVVM模式的核心,它是连接view和model的桥梁,MVVM实现了view和model的自动同步,当model的属性改变时,我们不用自己手动操作DOM元素,来改变view的显示,反之亦然,我们称之为数据的双向绑定。

    MVC
    M Model 模型 指的是数据层
    V View  视图 指的是用户页面
    C controller 控制器 指的是页面业务逻辑
    view传送指令到controller,controller完成业务逻辑后,要求model改变状态,model将新的数据发送给view,用户得到反馈。所有通信都是单向的。

3、v-if 和 v-show 的区别,适合场景

答: v-if是通过创建和删除DOM元素来控制元素的显示和隐藏,适用于不需要频繁切换元素显示和隐藏的情况
    v-show是通过操作css的display:block和display:none来控制元素的显示和隐藏,适用于需要频繁切换元素的显示和隐藏的场景。

4、v-for 和 v-if 的优先级那个更高

答: v-for优先级高于v-if
    如果同时出现v-for和v-if,无论判断条件是否成立,都会执行一遍v-for循环,这样浪费性能,所以要尽可能的避免两者一起使用。

5、vue 中的事件修饰符有哪些,分别作用是什么

答: .prevent  阻止事件默认行为
    .stop     阻止事件冒泡
    .capture  设置事件捕获机制
    .self     只有点击元素自身才能触发事件
    .once     事件只触发一次

6、v-model 的修饰符有哪些,分别作用是什么

答: .trim   去除首尾空格
    .lazy   只在输入框失去焦点或按回车键时更新内容,不是实时更新
    .number 将数据转换成number类型(原本是字符串类型)

7、vue 中的按键修饰符有哪些

答: .tab
    .enter
    .esc
    .space
    .delete(捕获"删除"和"空格"键)
    .up
    .down
    .left
    .right

8、v-for 中为什么要加 key,原理是什么

答: 原理:
      1.vue实现了一套虚拟DOM,使我们可以不直接操作DOM元素只操作数据,就可以重新渲染页面,而隐藏在背后的原理是高效的Diff算法
      2.当页面数据发生变化时,Diff算法只会比较同一层级的节点;
      3.如果节点类型不同,直接干掉前面的节点,再创建并插入新的节点,不会再比较这个节点后面的子节点;
        如果节点类型相同,则会重新设置该节点属性,从而实现节点更新
      4.使用key给每个节点做一个唯一标识,Diff算法就可以正确失败此节点,"就地更新"找到正确的位置插入新的节点。
    作用:
      1.key的作用主要是为了高效的更新虚拟DOM,提高渲染性能。
      2.key属性可以避免数据混乱的情况出现。

9、computed 和 watch 的区别

答: 1.概念
      computed是计算属性,它会根据所依赖的数据动态显示新的计算结果,通过计算出来的属性不需要调用,可以直接在DOM中使用。
      watch是监视对象,键是data对应的数据,值是对应的回调函数,值也可以是包含选项的对象,当data数据发生变化时,就会发生一个回调,它有两个参数,val(修改后的data数据),oldval(原来的data数据),vue实例会在实例化的时候调用$watch(),变量watch对象的每个属性,deep属性可以实现深度监听。
    2.缓存
      computed具有缓存属性,只有依赖的数据发生改变,才会重新进行计算,如果所依赖的数据没有发送改变,就调用缓存。
    3.使用场景
      当一个属性受多个属性影响的时候使用computed,比如:购物车商品结算;
      当一条数据影响多条数据的时候,使用watch,比如:贷款金额的判断

10、自己实现一个 v-model 的效果

答:
    <input type="text">
    <script>
    
     // vue2.0
    let data = {
      msg: 'hello vue'
    }
    let input = document.querySelector('input')
    input.value = data.msg
    input.addEventListener('input', function () {
      data.msg = this.value
    })
    let temp = data.msg
    Object.defineProperty(data, 'msg', {
      get() {
        return temp
      },
      set(value) {
        input.value = value
        return (temp = value)
      }
    })

    // vue3.0
    let data = {
      msg: 'hello vue'
    }
    let input = document.querySelector('input')
    input.value = data.msg
    input.addEventListener('input', function () {
      obj.msg = this.value
    })
    const obj = new Proxy(data, {
      get(target, key) {
        return target[key]
      },
      set(target, key, value) {
        target[key] = value
        input.value = value
      }
    })
   </script>
   

11、 Object.defineProperty和proxy的区别

1、Object.defineProperty  用于监听对象的数据变化
缺点:
    1)无法监听数组变化
    2)只能劫持对象的属性,属性值也是对象那么需要深度遍历
2、proxy  可以理解为 在被劫持的对象之前 加了一层拦截
   proxy返回的是一个新对象, 可以通过操作返回的新的对象达到目的
总结:
当使用 defineProperty 时,我们修改原来的 obj 对象就可以触发拦截
而使用 proxy,就必须修改代理对象,即 Proxy 的实例才可以触发拦截

12、怎么理解 vue 的生命周期

答: vue的生命周期:vue实例从创建到销毁的全过程,这个过程可以分为3个阶段
    第一阶段:初始化阶段   创建vue实例,准备数据,准备模板,渲染视图
    第二阶段:数据更新阶段 当数据变化时,会进行新旧DOM的对比,对比出差异的部分,进行差异化更新。
    第三阶段:实例销毁阶段 当vm.$destroy()被调用,vue实例就会被销毁,释放相关资源,此时再更新数据,视图不会再变化。

13、vue 钩子函数有哪些,有哪些使用的场景

答: beforeCreate  在data数据注入到vm实例之前,此时vm身上没有数据
    created       在data数据注入到vm实例之前,此时vm身上有数据

    beforeMount   生成的结构替换视图之前,此时DOM还没更新
    mounted       生成的结构替换视图之前,此时DOM已经更新完成

    beforeUpdate  数据变化了,dom更新之前
    updated       数据变化了,dom更新之后

    beforeDestroy 实例销毁,是否资源之前
    destroyed     实例销毁,是否资源之后

    这些钩子函数会在vue的生命周期的不同阶段,自动被vue调用

    常用的钩子函数使用场景
    beforeCreate  做loading的一些渲染
    created       结束loading, 发送数据的请求,拿数据
    mounted       可以对dom进行操作
    updated       监视数据的更新
    beforeDestroy 销毁非vue资源,防止内存泄漏,例如清除定时器

14、vue 中怎么给 data 动态添加数据,为什么要这样写

答: 1.官方文档定义:如果在vue实例创建之后添加新的属性到实例上,她不会触发视图更新。
    2.原因:受现代JavaScript的限制,vue不能检测到对象属性的添加或删除。由于vue会在初始化实例是对属性执行getter/setter转换过程(使用Object.defineProperty进行数据的劫持)。所以属性必须在data对象上存在才能让vue转换它,这样才能让它是响应的。
    方法:1.this.$set(对象名,属性,值)或 Vue.set(对象名,属性,值)
          2.Object.assign(target,source)添加多个属性
          例如:
            const target = {a:1, b:2}
            const source = {b:4, d:5}
            const returnedTarget = Object.assign(target,source)
            console.log(returnedTarget); //{ a: 1, b: 4, c: 5 }

15、$nextTick 的原理和使用的场景

答: 1.使用原理
      1) vue是异步执行dom更新的,一旦观察到数据变化,vue就会开启一个队列,然后把在同一事件循环当中观察到数据变化的watcher推送进这个队列,如果这个watcher被触发多次,只会被推送到队列一次,这种缓冲行为可以有效的去掉重复数据造成的不必要的计算和dom操作,这样可以提高渲染效率。
      2) 如果要获取更新后的dom元素,可以使用vue内置的$nextTick方法,参数是一个函数。它的作用类似setTimeout,进行执行异步的操作。
    2.应用:vue中的nextTick主要用于处理数据动态变化后,DOM还未及时更新的问题,用nextTick可以获取数据更新后最新dom的变化。
    3.场景:
      1)第三方插件,在vue生成的某些dom动态发生变化时重新应用该插件。
      2)视图更新之后,基于新的视图进行操作。
      
      
  /* 
        1. vue中实现了双向的数据绑定,,所以,vue会自动监测数据的变化,当数据发生了改变,vue会自动更新DOM结构。
        2. vue为了性能的提升,DOM更新是异步的。
        3. 问题:我们修改了数据后,无法立即获取到更新后的DOM结构
      */
      const vm = new Vue({
        el: '#app',
        data: {
          count: 0
        },
        methods: {
          async add() {
            this.count++
            this.count++
            this.count++
            this.count++
            this.count++
            this.count++
            this.count++
            this.count++
            this.count++
            // nextTick的回调函数会在DOM更新后立即执行
            await this.$nextTick()
            console.log(this.$refs.a.innerText)
          }
        }
      })

16、vue 中组件如何进行通信

答: 1.父传子
      1) 给子组件以添加属性的方式传值(属性名全小写)
      2)在子组件中通过props接收传递的参数
    2.子传父
      1) 在子组件中,通过触发事件的同时传值
         this.$emit(事件名,参数1,参数2...)
      2) 在父组件中,给子组件注册相应的事件,接收参数
         @事件名 = "fatherFn"
    3.非父子
      1) 创建一个都能访问到的事件总线(bus),本质上是一个空的vue实例
         const bus = new Vue()
      2) 在A组件中,触发bus事件,触发的同时传值
         bus.$emit(事件名,参数1,参数2...)
      3) 在B组件中给bus注册对应的事件,接收参数
         bus.$on(事件名,事件处理函数)

17、vue 组件中 data 为什么必须是一个函数

答: vue组件是可复用的vue实例,组件中的data写成一个函数,并且以函数返回值的显示定义,函数形成局部作用域,这样每次复用组件,就会返回一个新的data,确保data数据的独立性,各个组件之间修改不会相互影响,如果data使用对象,对象是引用类型,会导致复用组件中的data都指向同一块内存,那么各组件的数据就会相互响应,不能保持独立性了。

18、组件化和模块化的区别

答: 组件化:主要是从界面上进行划分,是对于结构、样式、行为的整体拆分,方便调用和复用。
    模块化:主要是从代码逻辑的焦点进行划分,是对js功能的拆分和封装,方便代码分层开发,保证每个功能模块职责单一。
    组件化和模块化的优点:开发调试效率高,可维护性强、避免阻塞、版本管理更容易。

19、怎么理解 vue 中的虚拟 DOM

答: 虚拟DOM其实就是一颗以JavaScript对象(VNode)作为基础的树,用对象属性来描述阶段,实际上它只是一层对真实DOM的抽象,最终可以通过一系列操作使这棵树映射到真实环境上。简单理解可以把虚拟DOM理解为一个简单的JS对象,并且最少包含标签名(tag)、属性(attrs)和子元素对象(children)三个属性。不同的框架对这三个属性的命名会有点差别。vue的虚拟DOM是将多次DOM操作保存在一个js对象(虚拟DOM对象)中,然后用这个js对象一次性的去更新dom操作,这样就避免了很多无效的计算。

20、vue-loader 是做什么的

答: 概念:vue-loader是基于webpack的一个loader,解析和转换.vue文件。提取出其中的逻辑代码script,样式代码style,以及HTML模板template,再分别把他们交给对应的loader去处理。
    用途:js可以写es6、style样式可以是less或scss等

21、vue 中怎么操作 dom

答: 要在mounted中使用,在执行mounted的时候,vue已经渲染了dom节点,可以获取dom节点。
    方法:
      1)在标签中添加ref="name"
      2)在方法中用this.$refs.name拿到这个元素,

22、router 和 route 的区别

答: router是VueRouter的实例,是一个全局的路由对象,它包含了所有的路由和许多关键的对象和属性。
    route是当前正在跳转的路由对象,是一个局部路由对象。里面包含当前路由的信息,比如:name,path,params,query等

23、路由传参的方式和区别

答: 方式:params 和 query
    区别:params用的是name,传递的参数在地址栏不会显示,类似于post
          query用的是path,传递的参数会在地址栏显示出来,类似于get
          
     举例:
     1、params 传参
    传: this.$router.push({
          name: 'particulars',
          params: {
            id: id
          }
        })
     接:this.$route.params.id
     
     2、query传参
     传:this.$router.push({
          path: '/particulars',
          query: {
            id: id
          }
        })
      接:this.$route.query.id

24、导航钩子有几种(导航守卫)具体怎么用的

: 分类:
    1、全局守卫: router.beforeEach
    2、全局解析守卫: router.beforeResolve
    3、全局后置钩子: router.afterEach
    4、路由独享的守卫: beforeEnter
    5、组件内的守卫: beforeRouteEnter、beforeRouteUpdate (2.2 新增)、beforeRouteLeave
    使用:
    1、全局守卫: router.beforeEach
       const router = new VueRouter({ ... })
          router.beforeEach((to, from, next) => {
          // ...
        })
    2、全局解析守卫: router.beforeResolve
       可以用 router.beforeResolve 注册一个全局守卫。这和 router.beforeEach 类似,区别是:在导航被确认之前,同时在所有组件内守卫和异步路由组件被解析之后,解析守卫就被调用。
    3、全局后置钩子: router.afterEach
       router.afterEach((to, from) => {
          // ...
        })
    4、路由独享的守卫: beforeEnter
       const router = new VueRouter({
          routes: [
            {
              path: '/foo',
              component: Foo,
              beforeEnter: (to, from, next) => {
                // ...
              }
            }
          ]
        })
    5、组件内的守卫: 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`
          }
        }

25、keep-alive的理解

1、keep-alive是Vue.js的一个内置组件。vuevue2.0提供了一个keep-alive组件用来缓存组件,避免多次加载相应的组件,减少性能消耗。
2、它有两个生命周期:
activated: keep-alive组件**时调用
deactivated: keep-alive组件停用时调用
它提供了include与exclude两个属性,允许组件有条件地进行缓存
3、示例:
<!-- keep-alive代码可以结合v-if进行包裹,如果meta中的keepAlive为true进行缓存,否侧不进行缓存,这样可以更灵活一些 -->
  <keep-alive>
      <router-view v-if="$route.meta.keepAlive" />
    </keep-alive>
    <router-view v-if="!$route.meta.keepAlive" />

<template>
  <div id="app">
  	// 1. 将缓存 name 为 test 的组件
  	<keep-alive include='test'>
      <router-view/>
    </keep-alive>
	
	// 2. 将缓存 name 为 a 或者 b 的组件,结合动态组件使用
	<keep-alive include='a,b'>
  	  <router-view/>
	</keep-alive>
	
	// 3. 使用正则表达式,需使用 v-bind
	<keep-alive :include='/a|b/'>
  	  <router-view/>
	</keep-alive>	
	
	// 5.动态判断
	<keep-alive :include='includedComponents'>
  	  <router-view/>
	</keep-alive>
	
	// 5. 将不缓存 name 为 test 的组件
	<keep-alive exclude='test'>
  	  <router-view/>
	</keep-alive>
  </div>
</template>

<script>
export default {
  name: 'App'
}
</script>
4、原理:
	首先,你要知道Vue.js内部将DOM节点抽象成了一个个的VNode(虚拟DOM)节点。所以,keep-alive的缓存也是基于VNode节点的而不是直接存储DOM结构。
	其实就是将需要缓存的VNode节点保存在this.cache中,在render时,如果VNode的name符合在缓存条件(可以用include以及exclude控制),则会从this.cache中取出之前缓存的VNode实例进行渲染。
相关标签: vue