Vue2 面试题总结1(笔记自用)

目录

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

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

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

3.1 单个组件 

3.2 父子组件

4. Vue组件如何通讯(常见)

5. 描述组件渲染和更新的过程 

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

7.  对 MVVM 的理解

扫描二维码关注公众号,回复: 14887633 查看本文章

8. computed 有何特点 

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

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

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

12.  如何自定义实现 v-model

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

14. 何时要使用异步组件?

15. 何时需要使用 keep-alive ?  

16. 何时需要使用 beforeDestory ?

17. 什么是作用域插槽?

18. Vuex 中 action 和 mutation 有何区别?

19. Vue-router 常用的路由模式?

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

21. 请用 vnode 描述一个 DOM 结构

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

23. Vue 如何监听数组变化?

24. 请描述响应式原理 

25. diff 算法的时间复杂度 

26. 简述 diff 算法过程

27. Vue为何是异步渲染,$nextTick 何用?

28. Vue常见性能优化 


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

  • v-show 通过 CSS display 控制显示和隐藏
  • v-if 组件真正的渲染和销毁,而不是显示和隐藏
  • 频繁切换显示状态用 v-show,否则用 v-if

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

  •  必须用 key,且不能是 index 和 random
  • diff 算法中通过 tag 和 key 来判断,是否是 sameNode
  • 减少渲染次数,提高渲染性能

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

  • 挂载
  • 更新
  • 销毁

3.1 单个组件 

3.2 父子组件

  • 挂载过程

        父- beforeCreate -> 父-created -> 父- beforeMount -> 子-beforeCreate -> 子- created -> 子-beforeMount -> 子-mounted -> 父-mounted

  • 更新过程

        父-beforeUpdate -> 子-beforeUpdate -> 子-updated -> 父-updated

  • 销毁过程

        父-beforeDestory -> 子-beforeDestory -> 子-destoryed -> 父destoryed

简易版:父-created -> 子- created -> 子-mounted -> 父-mounted

初始化:由外到内

渲染:从内到外(子组件渲染完,父组件才算完)

更新:先触发父组件数据的变化,然后更新子组件,(子组件更新完,父组件才算完)

销毁:先触发父组件的销毁,然后销毁子组件,(子组件销毁完,父组件才算完)

4. Vue组件如何通讯(常见)

  • 父子组件 props 和 this.$emit
  • 自定义事件 event.$on  event.$off  event.$emit
  • vuex(所有组件共享)

5. 描述组件渲染和更新的过程 

 Vue 原理三大模块:

  • 响应式(紫色 Data 监听属性变化)
  • 模板渲染(黄色部分)
  • 虚拟 DOM(绿色部分)

 过程:渲染时执行 render 函数会触发 Touch 的 getter ,之后收集依赖到 Watcher 里面,在触发 Data 更改时,会通知 Watcher,看之前是不是收集过这个 data 数据,如果收集过,就触发 setter 函数,然后触发 render 函数,重新渲染,如果之前没有收集过(即在页面模板没有用到)则不会触发 setter ,也不会重新渲染

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

  • input 元素的 value = this.name
  • 绑定 input 事件,@input=“name = $event.target.value”
  • data 更新触发 re-render

7.  对 MVVM 的理解

  • Model:后端传递的数据
  • View:所看到的页面
  • ViewModel:MVVM模式的核心,它是连接 Model和View的模型

ViewModel有两个方向(实现双向数据绑定)

  • 将Model转换成View,将后端传递的数据转换成所看到的页面,实现的方式是数据绑定(Data Bindings)
  • 将View转换成Model,将所看到的页面转换成后端数据,实现的方式是DOM监听事件(DOM Listeners)

8. computed 有何特点 

  • 缓存,data 不变不会重新计算
  • 提高性能 

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

<script>
export default {
  name: 'app',
  data() {
      return {
        name: 'vue',
        list: ['a', 'b', 'c']
      }
  },
  methods: {
    changeName() {
        this.name = '双越'
    },
    addItem() {
        this.list.push(`${Date.now()}`)
    }
  }
}
</script>
  •  因为 .vue 组件编译出来以后,是一个 class(一个类),
  • 在每个地方使用这个 class 的时候,实际上是对 class 进行实例化,
  • 在实例化的时候去执行 data,
  • 如果 data 不是函数的话,那每个组件的数据 data 都一样了,就共享了,
  • 如果 data 是一个函数,那么两个 data 就在闭包之中,不会相互影响

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

  • mounted(DOM 加载完成之后)
  • JS 是单线程的,ajax 异步获取数据(DOM 渲染完成之后,再触发 ajax 请求,请求完之后再把数据渲染到页面,合理)
  • 放在 mounted 之前没用,只会让逻辑更加混乱(DOM 没渲染完,也不会执行,在排队之中)

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

  • $props
  • <User v-bind="$props" />

12.  如何自定义实现 v-model

// 父组件
<CustomVModel v-model="name"/>
 
// 子组件
<template>
    <!-- 例如:vue 颜色选择 -->
    <input type="text"
        :value="text1"
        @input="$emit('change1', $event.target.value)"
    >
    <!--
        1. 上面的 input 使用了 :value 而不是 v-model
        2. 上面的 change1 和 model.event1 要对应起来
        3. text1 属性对应起来
    -->
</template>
 
<script>
export default {
    model: {
        prop: 'text1', // 对应 props text1
        event: 'change1'
    },
    props: {
        text1: String,
        default() {
            return ''
        }
    }
}

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

  • mixin
  • 变量来源不明确
  • 多mixin可能会造成命名冲突
  • mixin和组件可能出现多对多的关系,复杂度较高
  • Vue3 提出的Composition API旨在解决这些问题

14. 何时要使用异步组件?

  • 加载大组件(编辑器,图表)
  • 路由异步加载
  • 优化性能

15. 何时需要使用 keep-alive ?  

  • 缓存组件,不需要重复渲染
  • 如多个静态 tab 切换
  • 优化性能

16. 何时需要使用 beforeDestory ?

  •  解绑自定义事件 event.$off
  • 清除定时器
  • 解绑自定义 DOM 事件(addEventListener),如 window scroll 等
  • 以上不解绑容易内存泄露

17. 什么是作用域插槽?

// 父组件
<ScopedSlotDemo :url="website.url">
    <template v-slot="slotProps">
        {
   
   {slotProps.slotData.title}}
    </template>
</ScopedSlotDemo>
 
// 子组件
<template>
    <a :href="url">
        <slot :slotData="website">
            {
   
   {website.subTitle}} <!-- 默认值显示 subTitle ,即父组件不传内容时 -->
        </slot>
    </a>
</template>
 
<script>
export default {
    props: ['url'],
    data() {
        return {
            website: {
                url: 'http://wangEditor.com/',
                title: 'wangEditor',
                subTitle: '轻量级富文本编辑器'
            }
        }
    }
}
</script>

18. Vuex 中 action 和 mutation 有何区别?

  • action 中处理异步,mutation 不可以
  • mutation 做原子操作(每次操作一个)
  • action 可以整合多个 mutation

19. Vue-router 常用的路由模式?

  • to B 的系统推荐使用 hash,简单易用,对 url 规则不敏感
  • to C 的系统,可以考虑选择 H5 history(SEO,性能优化),但需要服务端支持
  • 能选择简单的,就别用复杂的,要考虑成本和收益
  •  hash (默认) window.onhashchange
  • 特点:
  • hash 变化会触发网页跳转,即浏览器的前进,后退
  • hash 变化不会刷新页面,SPA 必需的特点
  • hash 永远不会提交到 server 端(前端自生自灭)
  •  H5 history (需要服务端支出)history.pushState 和 window.onpopstate
  • 特点:
  • 用 url 规范的路由,但跳转时不刷新页面

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

 通过 import 加载异步组件的方式配置

21. 请用 vnode 描述一个 DOM 结构

<!-- 页面dom结构 -->
<div id="div1" class="container">
  <p>vdom</p>
  <ul style="font-size: 20px;">
    <li>a</li>
  </ul>
</div>
 
<script>
  /* js模拟dom结构 */
  const vdom = {
    tag: 'div',
    props: {
      className: 'container',
      id: 'div1'
    },
    children: [
      {
        tag: 'p',
        children: 'vdom'
      },
      {
        tag: 'ul',
        props: {
          style: 'font-size: 20px'
        },
        children: [
          {
            tag: 'li',
            children: 'a'
          }
        ]
      }
    ]
  }
</script>

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

  • Object.defineProperty
  • 以及深度监听,监听数组
  • 有何缺点

23. Vue 如何监听数组变化?

  •  Object.defineProperty 不能监听数组变化
  • 重新定义原型,重写 push pop 等方法,实现监听
  • Vue3 Proxy 可以原生支持监听数组变化

24. 请描述响应式原理 

  • 监听 data 变化(Object.defineProperty)
  •  组件渲染和更新的流程

25. diff 算法的时间复杂度 

  • O(n)

  • 在 O(n ^3) 基础上做了一些调整
  • 只比较同一层级,不跨级比较
  • tag 不相同,则直接删掉重建,不再深度比较
  • tag 和 key,两者都相同,则认为是相同节点,不再深度比较

26. 简述 diff 算法过程

  •  patch(elem,vnode)和 patch(vnode,newVnode)
  • pathchVnode 和 addVnodes 和 removeVnodes
  • updateChildren (key 的重要性)

27. Vue为何是异步渲染,$nextTick 何用?

  •  异步渲染(以及合并 data 修改),以提高渲染性能
  • $nextTick 在DOM 更新完成之后,触发回调

28. Vue常见性能优化 

  •  合理使用 v-show 和 v-if
  • 合理使用 computed
  • v-for 时加 key,以及避免和 v-if 同时使用,(v-for 优先级高,每层都要判断 v-if,造成性能浪费)
  • 自定义事件,DOM 事件及时销毁(beforeDestory)
  • 合理使用异步组件
  • 合理使用 keep-live
  • data 层级不要太深
  • 使用 vue-loader 在开发环境做模板编译(预编译)
  • webpack 层面优化
  • 前端通用的性能优化,如图片懒加载
  • 使用 SSR

猜你喜欢

转载自blog.csdn.net/weixin_39763711/article/details/126429376