vue面试题

v-show 和 v-if 的区别

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

为何 v-for 中要用key

  • diff算法中通过tag和key来判断,是否是sameNode(相同节点)
  • 减少渲染次数,提升渲染性能

不只是vue,react中在执行列表渲染时也会要求给每个组件添加上key这个属性。
要解释key的作用,需要先介绍一下虚拟DOM的Diff算法了。
我们知道,vue和react都实现了一套虚拟DOM,使我们可以不直接操作DOM元素,只操作数据便可以重新渲染页面。而隐藏在背后的原理便是其高效的Diff算法。
vue和react的虚拟DOM的Diff算法大致相同,其核心是基于两个简单的假设:
两个相同的组件产生类似的DOM结构,不同的组件产生不同的DOM结构。
同一层级的一组节点,他们可以通过唯一的id进行区分。
基于以上这两点假设,使得虚拟DOM的Diff算法的复杂度从O(n^3)降到了O(n)。
在这里插入图片描述
当页面的数据发生变化时,Diff算法只会比较同一层级的节点:
如果节点类型不同,直接干掉前面的节点,再创建并插入新的节点,不会再比较这个节点以后的子节点了。
如果节点类型相同,则会重新设置该节点的属性,从而实现节点的更新。
当某一层有很多相同的节点时,也就是列表节点时,Diff算法的更新过程默认情况下也是遵循以上原则。
所以key的作用主要是为了高效的更新虚拟DOM
详细分析

描述Vue组件生命周期(有父子组件的情况)

vue组件生命周期图示

在这里插入图片描述

  • beforeCreate:Vue 实例的挂载元素 $el 和数据对象 data 都为未定义,还未初始化。
  • created:vue 实例的数据对象 data 有值了,$el 没有。
  • beforeMount:vue 实例的 $el 和 data 都初始化了,但还是虚拟的dom 节点,具体的 data.filter 还未替换掉。
  • mounted:vue 实例挂载完成,data.filter 成功渲染
  • beforeUpdate:data 更新时触发。
  • updated:data 更新时触发。
  • beforeDestroy:组件销毁时触发。
  • destroyed:组件销毁时触发,vue 实例解除了事件监听以及 dom 的绑定(无响应了),但 DOM 节点依旧存在。
Created和mount区别

Created实例初始化 也没并没有渲染 mounted 页面渲染完成
vue是异步渲染,data改变后,Dom不会立刻渲染
$nextTick会在Dom渲染之后被触发,获取最新Dom节点

vue父子组件生命周期
  • 初始化父组件先于子组件,挂载时子组件先于父组件
  • 更新前父组件先于子组件,更新时子组件先于父组件
  • 销毁前父组件先于子组件,销毁时子组件先于父组件

Vue组件如何通讯

  • 父子组件通讯props和this.$ emit (父组件通过props向下传递数据给子组件,子组件传递数据给父组件是通过$emit触发事件)
  • 兄弟间组件通讯event. o n e v e n t . on event. onevent.emit(通过自定义事件通讯)
  • vuex
    Vue实例本身具有了$on $emit自定义事件的能力

vue高级特性

  • 自定义v-model

  • $nextTick

  • slot

  • 动态、异步组件

  • keep-alive

  • minxin

    自定义v-model

父组件

<template>
    <div>
        <!-- 自定义v-model -->
        <p>{{name}}</p>
        <custom v-model="name" />
    </div>
</template>
<script>
import custom from './Custom'
export default {
  components: {
    custom
  },
  data () {
    return {
      name: '张三'
    }
  }
}
</script>

子组件:

<template>
    <input type="text"
    :value="text"
    @input="$emit('change',$event.target.value)">
</template>
<script>
export default {
  model: {
    prop: 'text',
    event: 'change'
  },
  props: {
    text: String,
    default () {
      return ''
    }
  }
}
</script>
$nextTick

在下次 DOM 更新循环结束之后执行延迟回调。在修改数据之后立即使用这个方法,获取更新后的 DOM。
简单理解:当数据更新了,在dom中渲染后,自动执行$nextTick函数,

slot (插槽)

slot详细分析

动态组件

有的时候,在不同组件进行动态切换是非常有用的
可以通过Vue种的元素加一个特殊的is属性来实现:

<!-- 组件会在 `组件名` 改变时改变 -->
<component v-bind:is="组件名"></component>

根据 v-bind:is=“组件名” 中的组件名去自动匹配组件,如果匹配不到则不显示。

异步组件

面试常见性能优化之一:异步组件
当组件体积非常大,通过异步组件
异步组件就是定义的时候什么都不用做,只在组件组要渲染的时候进行加载渲染并缓存
Vue实现按需加载,官方推荐使用结合webpack的代码分割功能进行。定义为异步加载的组件,在打包的时候,会打包成单独的js文件存储在static/js文件夹里面,在调用时使用ajax请求回来插入到html中。
同步组件和异步组件引入的区别

  • 同步组件
<script>
import helloWord from './helloWord '
export default {
   components: {
        FormDemo: () => import('./helloWord ')
     }
}
</script>
  • 异步组件:
<script>
export default {
   components: {
        helloword
     }
}
</script>

动态组件和异步组件

keep-alive(缓存组件)

vue如何缓存组件
面试常见性能优化之一:keep-alive
当在组件之间切换的时候,你有时会想保持这些组件的状态,以避免反复重渲染导致的性能问题,为了解决这个问题,我们可以使用元素将其动态组件包裹起来

<!-- 失活的组件将会被缓存!-->
<keep-alive>
  <component v-bind:is="组件名"></component>
</keep-alive>

vue组件如何抽离公共逻辑 (mixin)

多个组件有相同的逻辑,抽离出来
创建一个js文件myMixin.js

export default {
 data() {
  return {
   name: 'mixin'
  }
 },
 created() {
  console.log('mixin...', this.name);
 },
 mounted() {},
 methods: {}
}

在组件中引入

<script>
 import myMixin from './myMixin'
 export default {
   minxins: [myMixin],//可以添加多个,会自动合并起来
}
</script>

minxin并不是完美的解决方案,会有一些问题
minxin存在的问题:

  • 变量来源不明确,不利于阅读
  • 多mixin可能会造成命名冲突
  • mixin和组件可能会出现多对多的关系,复杂度较高

vuex

vuex
Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。

  • vuex中的state用于存放数据,而且只存放各个组件都要使用的数据
  • mutations和actions中的方法核心作用就是操作state中的数据,。因为vuex反对在组件中直接操作store中的state中的数据,推荐的方式是在组件中调用store中的mutations或者actions中的方法,让这些方法再去操作state中的数据

vuex图示
在这里插入图片描述

vue-router 使用

路由模式(hash、H5 history)

  • hash模式(默认),如http://abc.com/#/user/10 H5
  • hiistory模式,如http://abc.com/user/2

后者需要serve端支持,因此无特殊需求可选择前者
路由配置(动态路由、懒加载)

Computed

特点:Computed 有缓存,data不变则不会重新计算

Watch 如何深度监听

Deep:true 实现深度监听
在这里插入图片描述
Watch 监听引用类型,拿不到oldVal
Event.proto_.constructor 原生的event对象
Event.target 事件挂载位置
Vue 中的event是原生的 事件被挂载到当前元素

数据驱动视图

传统组件,只是静态渲染,更新还要依赖于操作DOM
数据驱动试图-Vue MVVM 更多的是操作数据

MVVM模型

Model-View-ViewModel的缩写
Model: 模型 View: 视图 ViewModel: 作为视图的模型,为视图服务
在这里插入图片描述

Vue响应式

核心: API Object.defineProperty
Object.defineProperty 缺点

  • 深度监听,需要递归到底,一次性计算量大
  • 无法监听新增属性和删除属性(Vue.set Vue.delete)
  • 无法监听数组,需要特殊处理

Vue3.0使用proxy实现响应式
Peoxy兼容性不好
通过Object.defineProperty 中的get 和set可以实现监听

如何深度监听data变化

在这里插入图片描述

监听数组

API Object.defineProperty 不具备监听数组能力,需要自己实现
重新定义数组原型,创建新对象,原型指向原型,在扩展新的方法不会影响原型
在这里插入图片描述

Vue和React是数据驱动视图,如何有效控制DOM操作

DOM操作耗时耗费性能,js执行比较快
解决方案:把计算转移为js计算,因为js执行速度很快
vdom - 用js模拟DOM结构,计算出最小的变更,操作DOM
在这里插入图片描述
遵循规律:tag:标签 props: 属性 children:子元素

编译模板

编译模板为render模板,执行render函数返回vnode
基于vnode再执行 patch 和 diff
使用webpack vue-loader,会在开发环境下编译模板

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

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

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

定义的vue组件是一个类,每个组件使用的时候相当于对类的实例化

ajax请求放在哪个生命周期

  • 放在 mounted里面
  • js是单线程,ajax是异步获取数据

何时使用异步组件

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

何时使用beforeDestory

  • 解绑自定义事件event.$off
  • 清除定时器
  • 解绑自定义的DOM事件,如window scroll等

Vue常见性能优化

  • 合理使用v-show 和v-if
  • 合理使用computed
  • v-for时加key,以及避免和v-if同时使用
  • 自定义事件、dom事件及时销毁(避免内存泄漏)
  • 合理使用异步组件
  • 合理使用keep-alive
  • data层级不要太深
  • webpack层面的优化
  • 图片懒加载
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值