美文网首页
vue面试题

vue面试题

作者: 吾名刘斩仙 | 来源:发表于2020-03-15 14:10 被阅读0次

Vue面试题

未经允许 禁止转载

1. v-if和v-show的区别

v-show是通过CSS的display来控制显示隐藏

v-if是真正的渲染和销毁,不是显示和隐藏

频繁切换用v-show,否则V-if

2. 为何在v-for中使用key

必须用key,且尽量不能是index或random

在diff算法中通过tag和key来判断是不是sameVnode,所以key是必要的

减少渲染次数,提高渲染性能

3. 描述vue组件生命周期(父子组件)

单组件:

BeforeCreate,created,BeforeMount,mounted,BeforeUpdate,updated,BeforeDestroy,destroyed

父子组件:

父beforeCreate -> 子beforeCreate

子created -> 父created

父beforeMount -> 子beforeMount

子mounted -> 父mounted

父beforeUpdate -> 子beforeUpdate

子updated -> 父updated

父beforeDestroy -> 子beforeDestroy

子destroyed -> 父destroyed

4. 常用的组件通讯

父子组件props和this.$emit

自定义事件event.on/event.off/event.$emit

vuex

5. vue的渲染流程

三个知识点:响应式、虚拟DOM、模板渲染

流程:rander函数触发data的getter、使data被监听起来,data变化之后会触发setter,通知watcher,然后re-rander生成vnode

6. 双向数据绑定 v-modle的实现原理

input元素的动态value变量和绑定事件的$event.target.value是同一个变量,data更新会触发re-render

7. 对MVVM的理解

M(Model)V(View)VM(ViewModel)数据驱动视图

M可以理解为DOMTree,V可以理解为data对象,VM可以理解为vue动态指令、监听等。
MVVM架构可以理解为用vue的监听和动态指令等对data对象进行修改,然后渲染到DOM

8. computed有什么特点

缓存,data不变则不会重新计算

合理使用computed会提高性能

9. 为何组件data必须是一个函数

每个vue实际上是一个类,在使用的时候会把这个类实例化,只有当data是一个函数的时候形成闭包,才不会影响到其他实例化的类的data。

10. ajax应该放在哪个生命周期

mounted。因为JS是单线程,ajax是异步获取数据。放在mounted之前没有实际意义,只会让逻辑更加混乱。

11. 如何将所有props传递给子组件

<User :props='$props' />

12. 如何自己实现v-model

<input type='text' :value='val' @input='$emit('change',$event.target.value' />

model: {
    prop: val,
    event: change
},
props:{
    val: {
        type: String,
        default: ''
    }
}

13. 多个组件有相同的逻辑,如何抽离

mixin

import 'myMixin' from './myMixin.js'
export default{
    mixins: [myMixin],
}

在myMixin.js里抽离公共逻辑,在需要使用的组件里引用该mixin

mixin存在的问题

  1. 变量来源不明确,不利于阅读

  2. 多mixin可能会造成命名冲突

  3. mixin和组件可能出现多对多的关系,复杂度较高

14. 何时要使用异步组件

加载大组件、路由异步加载

15. 何时使用keep-alive

缓存组件,不需要重复渲染

多个静态tab页的切换

16. 何时需要使用beforeDestory

解绑自定义事件event.$off

清除定时器

解绑自定义的DOM事件,如window scroll等

17. 什么是作用域插槽

组件的slot有自己的data,传到父组件中

18. vuex中action和mutation有何区别

action处理异步,mutation不可以

mutation做原子操作(一次处理)

action可以整合多个mutation(提交Mutation的集合)

19. vue-router常用的路由模式

hash(默认)

h5 history(需要服务端支持)

20. 如何配置vue-router异步加载

const router = new VueRouter({
    path: '/',
    component:=>import('./../components/xxx')
})

21. 用vnode描述一个DOM结构

<!-- DOM -->
<div class='container' id='div1'>
    <p>vdom</p>
    <ul style='font-size: 14px;'>
        <li>a</li>
    </ul>
</div>



//用JS模拟DOM
{
    tag: 'div',
    props:{
        id: 'div1',
        className: 'container'
    },
    children: [
        {
            tag: 'p',
            children: 'vdom'
        },
        {
            tag: 'ul',
            props: {
                style: 'font-size: 14px'
            },
            children: [
                {
                    tag: 'li',
                    children: 'a'
                }
            ]
        }
    ]
}

22. 监听data变化的核心API是什么

Object.defineProperty

深度监听、监听数组

缺点:

  1. 深度监听需要递归到底,一次性计算量大。
  2. 无法监听新增/删除属性。(需要用Vue.set/Vue.delete)
  3. 无法监听数组

23. vue如何监听数组变化

Object.definedProperty不能监听数组变化

重新定义原型 重写pop push等方法 实现监听

vue3.0 proxy可以原生支持监听数组变化

24. 描述响应式原理

监听data变化 组件渲染和更新流程

25. diff算法的时间复杂度

O(n)

在O(n^3)的基础上通过以下方法达到O(n):

  1. 只比较同一层级,不跨级比较
  2. 如果tag不相同则直接销毁重建
  3. 如果tag和key相同,则认为是相同节点,不深入比较

26. 简述diff算法过程

  1. patch(elem,vnode)、patch(vnode,newVnode)

  2. patchVnode、addVnode、removeVnode

  3. updateChildren(key的重要性)

27. vue为何是异步渲染,$nextTick有何用

异步渲染能提高渲染性能

data多出修改合并,一次提交。所以正常情况拿不到最新的DOM,需要通过$nextTick拿到最新DOM

28. vue常见性能优化

  1. 合理使用v-if v-show

  2. 合理使用computed

  3. v-for中加key

  4. v-for避免和v-if同时使用(因为v-for的优先级高,每次v-for都需要处理v-if)

  5. 自定义事件、DOM事件要及时销毁

  6. 合理使用异步组件

  7. 合理使用keep-alive

  8. data层级不要太深(深度监听需要遍历到底,一次性计算量大)

  9. 使用vue-loader做预编译

29. vue3.0升级内容

全部使用TS重写

性能提升,代码量减少

调整部分API

30. vue3.0使用proxy重写响应式

Object.defineProperty的缺点:

  1. 深度监听需要递归到底,一次性计算量大。
  2. 无法监听新增/删除属性。(需要用Vue.set/Vue.delete)
  3. 无法监听数组

Proxy:

get、set、delete

Reflect作用:

和Proxy能力一一对应、规范化、标准化、函数式、代替Object上的工具函数(如: Reflect.ownKeys()替代Object.getOwnPropertyNames())

Proxy实现响应式原理:

const data = {
    name: 'liu',
    age: 25
}

const proxyData = reactive(data)

function reactive(target = {}){
    //判断target是否是对象
    if(target !== 'object' || target == null){
        return target
    }
    //代理配置
    const proxyConf = {
        get(target,key,reciver){
            const result = Reflect.get(target,key,reciver)
            return result
        },
        set(target,key,value,reciver){
            const result = Reflect.set(target,key,value,reciver)
            return result
        },
        delete(target,key){
            const result = Reflect.delete(target,key)
            return result
        }
    }
    //生成代理对象
    const observer = new Proxy(target,proxyConf)
    return observer
}

console.log(proxyData.name) //get  liu
proxyData.name = 'zhangsan' //set zhangsan
delete proxyData.name       //删除name

相关文章

网友评论

      本文标题:vue面试题

      本文链接:https://www.haomeiwen.com/subject/dwfrehtx.html