不去面试看了千遍距离太久也宛如一遍,面试前看一遍宛如千遍,临阵磨枪不快也光,赶忙冲,保藏+重视每天睡前看一遍催眠又深刻,梦里梦外面试不迷路

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组件的生命周期(父子组件)

  • 挂载
    • beforeCreate
    • created
    • beforeMount
    • mounted
  • 更新
    • beforeUpdate
    • updated
  • 毁掉
    • beforeDestroy
    • Destroyed
钩子函数 进程
beforeCreate 在实例初始化之后, 数据观测和作业装备之前被调用此刻data和methods以及页面的DOM结构都没有初始化什么都做不了
created 在实例创立完结后被当即调用此刻data 和 methods现已可以运用可是页面还没有烘托出来
beforeMount 在挂载开端之前被调用此刻页面上还看不到实在数据仅仅一个模板页面罢了
mouted el被新创立的vm.$el替换, 并挂载到实例上去之后调用该钩子。数据现已实在烘托到页面上在这个钩子函数里边咱们可以运用一些第三方的插件
beforeUpdate 数据更新时调用,发生在虚拟DOM打补丁之前。 页面上数据仍是旧的
update 由于数据更改导致的虚拟DOM从头烘托和打补丁, 在这之后会调用该钩子。页面上数据现已替换成最新的
beforeDestroy 实例毁掉之前调用
destroyed 实例毁掉后调用

4.vue组件怎么通讯(常见)

5.描绘组件烘托和更新的进程

  • 初度烘托的进程
    • 解析模板为render函数
    • 触发呼应式,监听data特色getter setter
    • 履行render函数,生成vnode,patch(elem,vnode)
    • 履行render会触发getter
  • 更新进程
    • 修正data,触发setter
    • 从头履行render函数,生成newVnode
    • patch(vnode,newVnode),diff算法会算差异

Vue面试真题演练

Vue面试真题演练

Vue面试真题演练

Vue面试真题演练

6.双向数据绑定v-model的完结原理

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

3个步骤,完结数据的双向绑定:

vue的双向绑定完结原理juejin.cn/post/684490…

vue 双向数据绑定完结原理juejin.cn/post/684490…

1.完结一个监听器Observer,用来绑架并监听一切特色,假如有改动的,就告诉订阅者。

2.完结一个订阅者Watcher,可以收到特色的改动告诉并履行相应的函数,然后更新视图。

3.完结一个解析器Compile,可以扫描和解析每个节点的相关指令,并依据初始化模板数据以及初始化相应的订阅器。

Vue面试真题演练

vue是选用数据绑架结合发布者-订阅者形式的办法,经过**Object.defineProperty()**来绑架各个特色的setter,getter,在数据改动时发布音讯给订阅者,触发呼应的监听回调。

v-model原理其实便是给input作业绑定oninput作业 就会立刻调用底层方针对应的setter办法 改动data里的特色的值 然后完结双向数据绑定

vue单项数据绑定原理

单项绑定进程:变量变了,由set发告诉给watcher,watcher告知虚拟DOM树,叫它该比较了,我这有值变了,所以生成新的dom树进行一个比较,然后逐级分类比较,比较出哪个元素发生改动就把这个元素更新到页面,这便是单项数据绑定原理。

Vue面试真题演练

vue双向数据绑定原理

Vue面试真题演练

7.对MVVM的了解

Vue面试真题演练

Vue面试真题演练

8.computed有什么特色

  • computed有缓存,data不变则不会从头核算

  • 进步功用

  • 核算特色呈现的目的是处理模板中放入过多的逻辑会让模板过重且难以保护的问题

  • 核算特色是基于它们的呼应式依靠进行缓存的

  • 在某些情况,咱们或许需求对数据进行一些转化后再显现,或许需求将多个数据结合起来进行显现

    • 比如咱们有firstNamelastName两个变量,咱们需求显现完好的称号。
    • 可是假如多个当地都需求显现完好的称号,咱们就需求写多个{{firstName}} {{lastName}}

methods和computed差异

  • methods里边的数据不管发没发生改动, 只需调用了都会履行函数(有的时分数据没发生改动咱们不希望调用函数)
  • computed核算特色会进行缓存, 假如数据没发生改动,函数只会被调用一次(数据发生改动才会调用函数)

总结:

  • methods不管数据发没发生改动都会调用函数
  • computed只需在依靠数据发生改动时才回调函数

2.侦听器 watch

侦听器的运用场景:数据改动时履行异步开销较大的操作 (eg:咱们可以运用watch来进行路由的监听)

留意: watch 中的特色,一定是data 中 现已存在的数据

watch比如codesandbox.io/s/vuebaseus…

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

咱们需求先复习下原型链的知识,其实这个问题取决于 js ,而并非是 vue 。

由于根本上.vue文件被编译出来是个class是一个类,每个当地运用组价的时分相当于对class实例化,实例化时分履行这个data()

基于此,咱们来看看这个问题:

function Component(){
}
Component.prototype.data = {
    name:'jack',
    age:22,
}
var componentA = new Component();
var componentB = new Component();
componentA.data.age=55;
console.log(componentA,componentB)
仿制代码

此刻,componentA 和 componentB data之间指向了同一个内存地址,age 都变成了 55, 导致了问题!

接下来很好解释为什么 vue 组件需求 function 了:

function Component(){
 this.data = this.data()
}
Component.prototype.data = function (){
    return {
    name:'jack',
    age:22,
}
}
var componentA = new Component();
var componentB = new Component();
componentA.data.age=55;
console.log(componentA,componentB)
仿制代码

此刻,componentA 和 componentB data之间彼此独立, age 分别是 55 和 22 ,没有问题!

这样每一个实例的data特色都是独立的,不会彼此影响了。所以,你现在知道为什么vue组件的data必须是函数了吧。这都是由于js自身的特性带来的,跟vue自身设计无关。其实vue不应该把这个办法名取为data(),应该叫setData或其他更简略当即的办法名。

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

  • mounted
  • js是单线程,ajax异步获取数据
  • 放在mounted之前没有用,只会让逻辑更加混乱

11.怎么将组件一切props传递给子组件

  • $props

12.怎么自己完结v-model

<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 ''
        }
    }
}
</script>

13.多个组件有相同的逻辑,怎么抽离?mixin

mixin

mixin缺陷:变量来历不明确(隐式传入),不利于阅览,使代码变得难以保护;多个mixins的生命周期会融合到一起运转,可是同名特色、同名办法无法融合,或许会导致冲突;mixins和组件或许呈现多对多的联系,复杂度较高(即一个组件可以引证多个mixins,一个mixins也可以被多个组件引证)。

Vue2/Vue3中的代码逻辑复用比照(mixins、自界说hook)juejin.cn/post/694978…

eg:

<div v-if="editAuthJudge(pageDetails)" class="canvas-config-item" @click="showDebugModal">
  <span class="item-label"><i class="mtdicon-monitor"></i>本地调试</span>      
</div>
<div v-if="actionsMap['revoke'] && editAuthJudge(pageDetails)" @click="handleRevokeConfig">
  <mtd-tooltip content="撤销修正" placement="top">
    <span class="item-label"><i class="mtdicon-undo-o"></i>撤销</span>
  </mtd-tooltip>
</div>
<div v-if="actionsMap['revoke'] && editAuthJudge(pageDetails)" :class="['canvas-config-item', sdk.activeVersionIndex === 0 ? 'disabled' : '']" @click="handleRecoveryConfig">
  <mtd-tooltip content="康复修正" placement="top">
    <span class="item-label"><i class="mtdicon-redo"></i>康复</span>
  </mtd-tooltip>
</div>
import editAuthJudge from "../components/mixins/editAuthJudge";
export default {
  name: 'CanvasConfigPanel',
  mixins: [editAuthJudge],
  inject: {
    zero: {
      default: () => ({})
    }
  },
  props: {
    pageDetails: {
        type: Object,
        default: () => {}
    },
    actions: {
      type: Array,
      default: () => {
        return ['device', 'scale', 'code', 'revoke', 'preview', 'clear', 'import', 'export', 'showLine', 'hideLine']
      }
    }
  },

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

  • 道理和webpack的按需加载是相同的
  • 加载大组件
  • 路由异步加载

15.何时需求是用keep-alive?

  • 缓存组件,不需求重复烘托
  • 如多个静态tab页的切换
  • 优化功用

16.何时需求是用beforeDestory?

  • 免除自界说作业event.$off,不然简略形成内存走漏
  • 铲除定时器
  • 解绑自界说的DOM作业(addEventLisenner),如window scroll等

17.什么是效果域插槽

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>
<ScopedSlotDemo :url="website.url">
  <template v-slot="slotProps">
  	{{slotProps.slotData.title}}
  </template>
</ScopedSlotDemo>
import ScopedSlotDemo from './ScopedSlotDemo'

18.Vuex中action和mutation有何差异

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

19.Vue-router常用的路由形式

  • hash
  • H5 history(需求服务端支撑)
  • 原理
  • 两者比较

20.怎么装备Vue-router异步加载

const Foo = () => import('./Foo.vue')
const router = new VueRouter({
  routes: [{ path: '/foo', component: Foo }]
})

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

Vue面试真题演练

22.监听data改动的中心API是什么?

中心API——Object.defineProperty(obj, prop, descriptor)

  • 监听方针、监听数组
  • 复杂方针、深度监听

Object.defineProperty缺陷:

  • 深度监听,需求递归究竟,一次性核算量大
  • 无法监听新增特色/删去特色(Vue.set Vue.delete)
  • 无法原生监听数组,需求特别处理

23.Vue怎么监听数组改动?

  • Object.defineProperty不能监听数组改动
  • 从头界说原型,重写push pop等办法,完结监听
  • Proxy可以原生支撑数组改动

24.请描绘呼应式原理

监听data改动

组件烘托和更新的进程

25.diff算法的时刻复杂度

  • O(n)
  • 在O(n^3)基础上做了一些调整

26.简述diff算法的进程

运用开端vdom

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

27.vue为何是异步烘托,$nextTick何用?

  • 异步烘托(以及兼并data()修正),以进步烘托功用
  • $nextTick 在DOM更新哇之后,触发回调
  • 页面烘托时会将 data 的修正做整合,屡次 data 修正只会烘托一次
<template>
  <div id="app">
    <ul ref="ul1">
        <li v-for="(item, index) in list" :key="index">
            {{item}}
        </li>
    </ul>
    <button @click="addItem">增加一项</button>
  </div>
</template>
<script>
export default {
  name: 'app',
  data() {
      return {
        list: ['a', 'b', 'c']
      }
  },
  methods: {
    addItem() {
        this.list.push(`${Date.now()}`)
        this.list.push(`${Date.now()}`)
        this.list.push(`${Date.now()}`)
        // 1. 异步烘托,$nextTick 待 DOM 烘托完再回调
        // 3. 页面烘托时会将 data 的修正做整合,屡次 data 修正只会烘托一次
        this.$nextTick(() => {
          // 获取 DOM 元素
          const ulElem = this.$refs.ul1
          // eslint-disable-next-line
          console.log( ulElem.childNodes.length )
        })
    }
  }
}
</script>

28.Vue常见功用优化

  • 合理运用v-show 和 v-if
  • 合理运用 computed 有缓存 进步功用
  • v-for 中运用 key,以及防止和v-if一起运用
  • 自界说作业、DOM作业及时毁掉,防止内存走漏,页面越用越卡
  • 合理运用异步组件,大的第三方组价
  • 合理运用keep-alive,不要重复烘托时分缓存下来
  • data 层级不要太深,由于呼应式监听,深度监听核算深度多,页面会卡
  • 运用vue-loader在开发环境做模板编译(预编译)
  • webpack层面的优化
  • 前端通用的功用优化,如图片懒加载
  • 运用SSR

29.vue父子组件生命周期履行顺序,请完好表述

单一组件中:

beforeCreate→created→beforeMounted→mounted→beforeUpdate→update→beforeDestroy→destroyed

父子组件中:

常用钩子简易版:父create→子created→子mounted→父mounted

①加载烘托进程:

父beforeCreate→父created→父beforeMounted→子beforeCreate→子created→子beforeMounted→子mounted→父mounted

②更新进程:

父beforeUpdate→子beforeUpdate→子update→父update

③毁掉进程:

父beforeDestroy→子beforeDestroy→子destroyed→父destroyed

留意问题:

在父组件调用接口数据,经过props传递给子组件,接口呼应是异步的,子组件不管在哪个钩子都取不到数据。由于子组件的mounted都履行完之后,父组件的恳求才回来数据。会导致,从父组件传递给子组件的数据是undefined。

处理:

①在烘托子组件时分加上一个条件,dataList是父组件调用接口回来的数据。当有数据的时分在去烘托子组件。这样就会形成天然的堵塞。在父组件的created中的恳求回来数据后,才会履行子组件的created,mounted。最后履行父组件的mounted。

<div class="test">
    <children v-if="dataList" :data="dataList" ></children>
</div>

②在子组件中watch监听,父组件获取到的值改动,子组件就可以监听到

watch:{
    data:{
      deep:true,
      handler:function(newVal,oldVal) {
        this.$nextTick(() => {
          this.data = newVal
        })
      }
    },
}

每个生命周期详细适用哪些场景

钩子函数 进程
beforeCreate 创立前,在实例初始化之后, 数据观测和作业装备之前被调用此刻data和methods以及页面的DOM结构都没有初始化什么都做不了。data,computed,watch,methods 上的办法和数据均不能访问。可以在这儿加个loading作业
created 创立后,在实例创立完结后被当即调用,此刻data、props、computed 和 methods现已可以运用可是页面还没有烘托出来。①可访问data computed watch methods上的办法数据②初始化完结时的作业写在这儿,异步恳求也适宜在这儿调用(恳求不宜过多,防止白屏时刻太长)③可以在这儿完毕loading作业,还做一些初始化,完结函数自履行。④未挂载DOM,若在此阶段进行DOM操作一定要放在Vue.nextTick()的回调函数中
beforeMount **挂载前,**在挂载开端之前被调用此刻页面上还看不到实在数据仅仅一个模板页面罢了。但vue挂载的根节点现已创立,下面vue对DOM的操作将围绕这个根元素继续进行。beforeMount这个阶段是过渡性的,一般一个项目只能用到一两次。
mouted **挂载,**完结创立vm.el,和双向绑定。el被新创立的vm.el,和双向绑定。el被新创立的vm.el替换, 并挂载到实例上去之后调用该钩子。①数据现已实在烘托到页面上在这个钩子函数里边咱们可以运用一些第三方的插件。②完结挂载DOM和烘托,可在mounted钩子函数中对挂载的DOM进行操作。③可在这建议后端恳求,拿回数据,配合路由钩子做一些作业。
beforeUpdate **数据更新前,数据驱动DOM。**数据更新时调用,发生在虚拟DOM打补丁之前。 页面上数据仍是旧的。①可在更新前访问现有的DOM,如手动移出增加的作业监听器。
update 数据更新后,完结虚拟DOM的从头烘托和打补丁。由于数据更改导致的虚拟DOM从头烘托和打补丁, 在这之后会调用该钩子。页面上数据现已替换成最新的。①组件DOM已完结更新,可履行依靠的DOM操作。②留意:不要在此函数中操作数据(修正特色),会陷入死循环。
activated 在运用vue-router时有时需求运用**<keep-alive></keep-alive>**来缓存组件状况,这个时分created钩子就不会被重复调用了。
deactivated <keep-alive></keep-alive>组件被移除时运用
beforeDestroy 实例毁掉之前调用①可做一些删去提示,如:您确定删去xx吗?
destroyed 实例毁掉后调用。前组件已被删去,毁掉监听作业,组件、作业、子实例也被毁掉。

juejin.cn/post/684490…

juejin.cn/post/684490…

juejin.cn/post/684490…

30.vue slot和slot-scope的了解

让用户可以扩展组件,去更好的复用组件和对其做定制化处理。eg:布局组件、表格列、卡片

  • 默许插槽|单个插槽|匿名插槽:子: 父:内容直接在子组件的标签内写入内容即可

  • 签字插槽:子:<slot name=”up”> 父:

    内容
    是在默许插槽的基础上加上slot特色,值为子组件插槽name特色值
  • 效果域插槽|带数据的插槽:子:<slot name=”up” :data=”data”> 父:;经过slot-scope获取子组件的信息,在内容中运用。这儿可以用解构语法去直接获取想要的特色。

    • **原理:**slot实质上是回来VNode的函数,一般情况下,Vue中的组件要烘托到页面上需求经过template→render function→VNode→DOM的进程。组件挂载的实质便是履行烘托函数得到VNode,至于data/props/computed这些特色都是给VNode供给数据来历
    • 效果域插槽合适的场景是至少包括三级以上的组件层级,是一种优异的组件化计划!

    Vue面试真题演练

juejin.cn/post/684490…

juejin.cn/post/684490…

juejin.cn/post/684490…

31.vue3和vue2优缺陷(开发、打包、上线等环节)

①生命周期的改动

Vue2.X Vue3
beforeCreate 运用setup()
created 运用setup()
beforeMounted onBeforeMount
mounted onMounted
beforeUpdate onBeforeUpdate
updated onUpdated
beforeDestroy onBeforeUnmount
destroyed onUnmounted
errorCaptured onErrorCaptured

②运用proxy代替defineProperty

Vue2.X-defineProperty Vue3-proxy
vue为什么对数组方针的深层监听无法完结,由于组件每次烘托都是将data里的数据经过defineProperty进行呼应式或许双向绑定上,之前没有后加的特色是不会被绑定上,也就不会触发更新烘托 defineProperty只能呼应初次烘托时分的特色,Proxy需求的是整体,不需求关心里边有什么特色,而且Proxy的装备项有13种,可以做更详尽的作业,这是之前的defineProperty无法达到的
vue2.x之所以只能兼容到IE8便是由于defineProperty无法兼容IE8,其他浏览器也会存在细微兼容问题 proxy的话除了IE,其他浏览器都兼容,这次vue3仍是运用了它,说明vue3直接抛弃了IE的兼容考虑,个人感觉现已没人用IE
Object.defineProperty( Obj, ‘name’, {
enumerable: true, //可枚举
configurable: true, //可装备
// writable:true, //跟可装备不能一起存在
// value:’name’, //可写死直
get: function () {
return def
},
set: function ( val ) {
def = val
}
} )
//两个参数,方针,13个装备项
const handler = {
get: function(obj, prop) {
return prop in obj ? obj[prop] : 37;
},
set:function(){ },
…13个装备项
};
const p = new Proxy({}, handler);
p.a = 1;
p.b = undefined;
console.log(p.a, p.b); // 1, undefined
console.log(‘c’ in p, p.c); // false, 37

③diff算法的提升

Vue2.X-diff Vue3-diff
vue2.x供给相似于HTML的模板语法,可是,它是将模板编译成烘托函数来回来虚拟DOM树Vue结构经过递归遍历两个虚拟DOM树,并比较每个节点上的每个特色,来确定实际DOM的哪些部分需求更新。由于现代JavaScript引擎履行的高级优化,这种有点暴力的算法一般非常快速,可是**DOM的更新依然涉及许多不必要的CPU作业** DOM树等级:在没有动态改动节点结构的模板指令(例如v-if和v-for)的情况下,节点结构坚持彻底静态。假如咱们将一个模板分成由这些结构指令分隔的嵌套“块”,则每个块中的节点结构将再次彻底静态。当咱们更新块中的节点时,咱们不再需求递归遍历DOM树 – 该块内的动态绑定可以在一个平面数组中跟踪。这种优化经过将需求履行的树遍历量削减一个数量级来规避虚拟DOM的大部分开销。②编译器:活跃检测模版中的静态节点、子树、数据方针,并在生成的代码中将他们提升到烘托函数之外。这样可以防止每次烘托时从头创立这些方针,然后打打进步内存运用率并削减垃圾收回的频率。③元素等级:编译器还依据需求履行的更新类型,为每个具有动态绑定的元素生成一个优化标志。例如,具有动态类绑定和许多静态特色的元素将收到一个标志,提示只需求进行类查看。运转时将获取这些提示并选用专用的快速路径。Vue 3有时占用的CPU时刻不到Vue 2的十分之一

④typeScript的支撑

Vue2.X-js Vue3-ts

⑤打包的体积改动

Vue2.X-23kb Vue3-10kb
vue2官方说的运转时打包师23k,但这仅仅没安装依靠的时分,随着依靠包和结构特性的增多,有时分不必要的,未运用的代码文件都被打包了进去,所以后期项目大了,打包文件会特别多还很大。 Vue 3中,咱们经过将大多数全局API和内部帮助程序移动到Javascriptmodule.exports特色上完结这一点。这允许现代形式下的module bundler可以静态地剖析模块依靠联系,并删去与未运用的module.exports特色相关的代码。模板编译器还生成了对树颤动友爱的代码,只需在模板中实际运用某个特性时,该代码才导入该特性的帮助程序。

vue3组件根本结构剖析

//dom 里的东西根本上都是没有变的
<template>
  <h1>{{ msg }}</h1>
  <button @click="increment">
    count: {{ state.count }}, double: {{ state.double }},three:{{ three }},refnum:{{refnum}}
  </button>
</template>
<script>
//这儿便是Vue3的组合Api了,这儿跟react的 import { useState ,useEffect } from 'react' 有些相似,需求用啥引啥
import {ref, reactive, computed ,watchEffect,watch} from "vue";
export default {
  name: "HelloWorld",
  props: {
    msg: String,
  },
  //上面比照的时分说过,setup相当于beforeCreate 和created,简略了解便是初始化
  setup() { 
  	//这儿经过reactive使state成为相应状况(后面会详细介绍)
    const state = reactive({
      count: 0,
      //核算特色computed的运用更灵活了
      double: computed(() => state.count * 2),
    });
    //computed也可以独自拿出来运用
    const three = computed(() => state.count * 3)
    //ref跟reactive效果相同都是用来数据相应的,ref的颗粒度更小(后面详细比照)
	const refnum = ref()
   //这儿的watchEffect只需里边的变量发生了改动就会履行,并且第一次烘托会当即履行,没有改动前后回来参数,无法监听整个reactive
    watchEffect(() => {
      refnum.value = state.count;
      console.log(state, "watchEffect");
    });
    //watch里第一个参数是监听需求的变量,第二个是履行的回调函数,
    watch(refnum,(a,b)=>{
      console.log(a,b,'watch,a,b')
    })
    //一切的办法里再也不需求用this了,这是很爽的
    function increment() {
      state.count++;
    }
   	//组中模板中需求的变量,都要经过return给露出出去,就像当初data({return { } }) 是相同的
    return {
      state,
      increment,
      three,
      refnum
    };
  },
};
</script>

vue3生命周期的运用

<script>
import {
  reactive,
  computed,
  onMounted,
  onBeforeMount,
  onBeforeUpdate,
  onUpdated,
  onUnmounted,
  onBeforeUnmount,
} from "vue";
export default {
  setup() {
    const state = reactive({
      count: 0,
      double: computed(() => state.count * 2),
    });
    function increment() {
      state.count++;
    }
    onUpdated(() => {
      console.log("onUpdated");
    });
    onUnmounted(() => {
      console.log("onUnmounted");
    });
    onBeforeUnmount(() => {
      console.log("onBeforeUnmount");
    });
    onBeforeUpdate(() => {
      console.log("onBeforeUpdate1");
    });
    onMounted(() => {
      console.log("onMounted");
    });
    onBeforeMount(() => {
      console.log("onBeforeMount");
    });
    console.log("setup");
    return {
      state,
      increment,
    };
  },
};
</script>
履行顺序
1.setup
2.onBeforeMount
3.onMounted
4.onBeforeUpdate
5.onUpdated

Vue3组件API的运用

①setup

<template><br/> <img alt="Vue logo" src="" /><br/> <HelloWorld msg="Baby张 Vue3 RC" /><br/> //这儿传参给子组件<br/></template><br/><script><br/>import HelloWorld from "./components/HelloWorld.vue";<br/>import { provide } from "vue";<br/>export default {<br/> name: "App",<br/> components: {<br/> HelloWorld,<br/> }<br/>};<br/></script> //props 接纳的父组件传的参数,这就有点像react的props了
//ctx 这个参数表示的当时方针实例,也就个是变相的this
setup(props,ctx){
console.log(props.msg, ctx, “app-setup”);
}
假如你还想要更多当时组件相关的特色,还可以从组合Api 里引证 getCurrentInstance
import {getCurrentInstance } from “vue”;
const all = getCurrentInstance()
console.log(all, “app-setup”);

Vue面试真题演练

Vue面试真题演练

②ref、toRef、toRefs

ref:生成值类型的呼应式数据;用于模版和reactive;经过.value修正值

<template>
  <p>ref demo {{ageRef}}{{state.name}}</p>
</template>
import { ref , toRef , toRefs } from 'vue'
export default {
setup(){
  const ageRef = ref(20) // 值类型 呼应式
  const nameRef = ref('小圆脸儿')
  const state= reactive({
  	name:nameRef
  })
	setTimeout(()=>{
		console.log('ageRef',ageRef.value)
		ageRef.value = 25 //.value 修正值
		nameRef.value = '晓雪'
  },1000)
  return {
    ageRef,
    state
  }
 }
}
<template>
  <p ref="elemRef">我是一行文字</p>
</template>
import { ref , toRef , toRefs,onMounted } from 'vue'
export default {
  name : 'RefTemplate',
  setup(){
  const elemRef = ref(null)
  onMounted(()=>{
    console.log('ref template',elemRef.value.innerHTML)
  })
   return {
   	 elemRef
   }
}

toRef:针对一个呼应式(reactive封装)方针的prop;创立一个ref,具有呼应式;两者坚持引证联系

<template>
  <p>toRef demo {{ageRef}}-{{state.name}}{{state.age}}</p>
</template>
import { ref , toRef , toRefs,onMounted } from 'vue'
export default {
  name : 'ToRef',
  setup(){
  	const state = reactive({ //针对一个呼应式(reactive封装)方针的prop
      age:20,
      name:'小圆脸儿'
    })
		const ageRef = toRef(state,'age') //创立一个ref,具有呼应式
		setTimeout(()=>{
      state.age = 25 //.value 修正值
    },1000)
  	setTimeout(()=>{
      state.age = 30 //.value 修正值
    },2000)
    return {
      state,
      ageRef
    }
	}
}

toRefs:将呼应式方针(reactive封装)转化为一般方针;方针的每个prop都对应的ref;两者坚持引证联系

笼统组成函数时分

<template>
  <p>toRef demo {{name}}{{age}}</p>
</template>
import { ref , toRef , toRefs,onMounted } from 'vue'
export default {
  name : 'ToRef',
  setup(){
  	const state = reactive({ //针对一个呼应式(reactive封装)方针
      age:20,
      name:'小圆脸儿'
    })
		const stateAsRefs = toRefs(state) //将呼应式方针(reactive封装)转化为一般方针
		// const {age:ageRef,name:nameRef} = stateAsRefs // 每个特色,都是ref方针
    //return {
    // ...stateAsRefs
    //}
    //return {
   //  ageRef,
   //  nameRef
   // }
    return stateAsRefs
	}
}

ref 就当作简略的呼应式变量 toRef 便是把不是呼应式的方针转化成呼应式 toRefs 便是把呼应式的reactive方针,分解成无数的呼应式 ref

1.ref呼应式的数据,在函数里读取的时分需求 .value获取

  1. dom里不需求咱们+value 结构替咱们主动解构了
  2. 组件return的时分将 reactive的方针 toRefs ,可以使代码更简洁,又不会丢掉数据的呼应式

③reactive

上面的 demo 中多多少少都用到了,用法也很简略,就说下留意点:

  • reactive 内部是可以运用核算特色等各种办法,它仅仅把数据完结呼应式罢了
  • reactivereturn 的数据最好是用toRefs 转化一下,优点谁用谁知道
  • ref 混合运用时分可以用isRef 判别类型

④watch、watchEffect

watch 需求详细监听参数,watchEffect 不需求传入监听参数

watch 的回调函数跟以前相同有前后比照的参数,watchEffect 啥都没有

watch 只需监听特色改动才履行,watchEffect 第一次会当即履行

watchwatchEffect都无法监听未被绑定的特色

watch 可以直接监听 refreactive 绑定的方针,watchEffect 不可以(ref的值要.value,reactive的值要详细到内部特色),只会履行第一次

⑤函数组件

import { ref, computed, watch, onMounted } from 'vue'
const App = {
  template: `
    <div>
      <span>count is {{ count }}</span>
      <span>plusOne is {{ plusOne }}</span>
      <button @click="increment">count++</button>
    </div>
  `,
  setup() {
    // reactive state
    const count = ref(0)
    // computed state
    const plusOne = computed(() => count.value + 1)
    // method
    const increment = () => { count.value++ }
    // watch
    watch(() => count.value * 2, val => {
      console.log(`count * 2 is ${val}`)
    })
    // lifecycle
    onMounted(() => {
      console.log(`mounted`)
    })
    // expose bindings on render context
    return {
      count,
      plusOne,
      increment
    }
  }
}

⑥Other

juejin.cn/post/689229…

juejin.cn/post/684490…

juejin.cn/post/711112…

juejin.cn/post/709857…

juejin.cn/post/711112…

juejin.cn/post/713325…

juejin.cn/post/698906…

juejin.cn/post/698906…

juejin.cn/post/712435…

juejin.cn/post/711568…

juejin.cn/post/694638…

juejin.cn/post/719929…

juejin.cn/post/722142…

juejin.cn/post/706522…

juejin.cn/post/716827…

juejin.cn/post/726074…

32.vue3为什么选择vite?

①vite比webpack更快

在webpack开发时构建时,默许会抓取并构建你的整个运用,然后才干供给服务,这就导致了你的项目中存在任何一个错误(即便当时错误不是首页引证的模块),他依然会影响到你的整个项目构建。所以你的项目越大,构建时刻越长,项目启动速度也就越慢。

vite不会在一开端就构建你的整个项目,而是会将引证中的模块区别为依靠和源码(项目代码)两部分,对于源码部分,他会依据路由来拆分代码模块,只会去构建一开端就必须要构建的内容。

一起vite以原生 ESM的办法为浏览器供给源码,让浏览器接管了打包的部分作业。

Vue面试真题演练

②简略

Vite 的用法很简略, 履行初始化命令:

yarn create @vitejs/app my-vue-app --template vue

就得到了一个预设好的开发环境,可以开端愉快地写 demo 了,Vite 开箱就给你一堆功用,包括 css 预处理器、html 预处理器、hash 命名、异步加载、分包、紧缩、HMR 等:

这些功用,作者都按行业最佳实践预设好了,一般不需求用户介入做变更。

Vite 定位便是傻瓜式但强大的构建东西,你专注写好事务代码,早点下班,不用再为了东西费神吃力了。

③生态

除了极致的运转功用与简易的运用办法外,Vite 对已有生态的兼容性也不容忽略,首要体现在两个点:

  • 与 Vue 解耦,兼容支撑 React、Svelte、Preact、Vanilla 等,这意味着 Vite 可以被运用在大多数现代技术栈中
  • 与 Rollup 极端接近的插件接口,这意味着可以复用 Rollup 生态中大部分现已被反复锤炼的东西

③vite快可是也有缺陷

当源码中有commonjs模块加载,那么将会呈现模块加载失利的问题。经过依靠预构建的办法处理该问题。

当你初次启动 vite 时,Vite 在本地加载你的站点之前预构建了项目依靠。默许情况下,它是主动且透明地完结的。

这便是 Vite 履行时所做的“依靠预构建”。这个进程有两个目的:

  1. CommonJS 和 UMD 兼容性: 在开发阶段中,Vite 的开发服务器将一切代码视为原生 ES 模块。因此,Vite 必须先将以 CommonJS 或 UMD 形式供给的依靠项转化为 ES 模块。

    在转化 CommonJS 依靠项时,Vite 会进行智能导入剖析,这样即便模块的导出是动态分配的(例如 React),签字导入(named imports)也能正常作业:

    js

    // 契合预期
    import React, { useState } from 'react'
    
  2. 功用: 为了进步后续页面的加载功用,Vite将那些具有许多内部模块的 ESM 依靠项转化为单个模块。

    有些包将它们的 ES 模块构建为许多独自的文件,彼此导入。例如,lodash-es 有超越 600 个内置模块!当咱们履行 import { debounce } from 'lodash-es' 时,浏览器一起发出 600 多个 HTTP 恳求!即便服务器可以轻松处理它们,但大量恳求会导致浏览器端的网络拥塞,使页面加载变得明显缓慢。

    经过将 lodash-es 预构建成单个模块,现在咱们只需求一个HTTP恳求!

留意

依靠预构建仅适用于开发形式,并运用 esbuild 将依靠项转化为 ES 模块。在生产构建中,将运用 @rollup/plugin-commonjs

require加载同步,nodejs服务端一般运用require加载模块,一般是一个文件,只需求从本地硬盘中读取,速度比较快。可是在浏览器端就不相同了,文件一般存放在服务器或CDN上,假如运用同步的办法加载一个模块还需求由网络的快慢来决定,或许时刻会很长,这样浏览器很简略进去假死状况。所以才有了后面说的AMD和CMD模块化计划,他们都是异步加载的,比较合适浏览器端运用。

CommonJS和ES6模块的差异

  • 由于CommonJSrequire语法是同步的,所以就导致了CommonJS模块标准只合适用在服务端,而ES6模块不管是在浏览器端仍是服务端都是可以运用的,可是在服务端中,还需求遵从一些特别的规矩才干运用 ;

  • CommonJS 模块输出的是一个值的拷贝,而ES6 模块输出的是值的引证;

  • CommonJS 模块是运转时加载,而ES6 模块是编译时输出接口,使得对JS的模块进行静态剖析成为了或许;

  • 由于两个模块加载机制的不同,所以在对待循环加载的时分,它们会有不同的表现。CommonJS遇到循环依靠的时分,只会输呈现已履行的部分,后续的输出或许改动,是不会影响现已输出的变量。而ES6模块相反,运用import加载一个变量,变量不会被缓存,实在取值的时分就能取到终究的值;

  • 关于模块顶层的this指向问题,在CommonJS顶层,this指向当时模块;而在ES6模块中,this指向undefined

  • 关于两个模块互相引证的问题,在ES6模块傍边,是支撑加载CommonJS模块的。可是反过来,CommonJS并不能requireES6模块,在NodeJS中,两种模块计划是分开处理的。

    juejin.cn/post/684490…

33.Vue组件传值办法以及运用场景

父传子:props

子传父:子emit、父emit、父on、v-on

兄弟之间:event bus、refs、refs、root、

父取子:ref:父this.ref :父 this.refs.child1.msg 、this.$refs.child1.childConsole(“hello”)

子取父:parent:子1发送:this.parent:子1发送:this.parent.emit(“send”,”我是子组件1″);子2接纳:this.emit(“send”, “我是子组件1”); 子2接纳:this.parent.$on(‘send’,(value)=>{ console.log(‘child2 received value is :>> ‘, value); })

父取/调子:children父:this.children 父:this.children[0]

跨层级:provide/inject

父传子孙后代:attrs子:attrs 子:attrs.value v-bind=”$attrs” 孙子:props:value

孙传父爷:listeners子:this.listeners 子:this.listeners.event(‘hello vue’) 父:@event=”message” message(value) { console.log(‘value :>> ‘, value); };孙:this.emit(“event”,”hellovue”);子:v−on=”emit(“event”, “hello vue”); 子:v-on=”listeners” 父:@event=”message”

任意组件通信:vuex

slot-scope v-slot

juejin.cn/post/728710…

34.vue的nextTick和nextTick 和set原理及运用场景

①set

①-①运用场景

由于JavaScript的约束,Vue无法检测到data中数组和方针的改动,因此也不会触发视图更新

当咱们对data中的数组或方针进行修正时,有些操作办法是非呼应式的,Vue检测不到数据更新,因此也不会触发视图更新。此刻需求运用Vue.set()进行呼应式的数据更新

eg:

data () {
  return {
    student: {
      name: '',
      sex: ''
    }
  }
}
mounted () { // ——钩子函数,实例挂载之后
  this.student.age = 18
}
mounted () {
  this.$set(this.student,"age", 24)
  // Vue.set
	Vue.set(this.student, "age", 24)
}

受 ES5 的约束,Vue.js 不能检测到方针特色的增加或删去。由于 Vue.js 在初始化实例时对property将特色转为 getter/setter,所以特色property必须在 data 方针上才干让 Vue.js 转化它,才干让它是呼应的。

正确写法:this.$set(this.data,”key”,value’)

Vue.set(target,key,value)

Vue 不允许动态增加根级呼应式特色。

只可以运用 Vue.set(object, propertyName, value) 办法向嵌套方针增加呼应式特色,例如

var vm=new Vue({
    el:'#test',
    data:{
        //data中现已存在info根特色
        info:{
            name:'小圆脸儿';
        }
    }
});
//给info增加一个年纪特色
// this.user.age = 28 这样是不起效果, 不会被Observeryua
Vue.set(vm.info,'age','28');

①-②Vue.set()和this.$set()完结原理

vue中$set办法对数组和方针的处理实质上的相同的,对新增的值增加呼应然后手动触发派发更新。

vm.$set()在new Vue()时分就被注入到Vue的原型上。

源码方位: vue/src/core/instance/index.js

仿制代码import { initMixin } from './init'
import { stateMixin } from './state'
import { renderMixin } from './render'
import { eventsMixin } from './events'
import { lifecycleMixin } from './lifecycle'
import { warn } from '../util/index'
function Vue (options) {
  if (process.env.NODE_ENV !== 'production' &&
    !(this instanceof Vue)
  ) {
    warn('Vue is a constructor and should be called with the `new` keyword')
  }
  this._init(options)
}
initMixin(Vue)
// 给原型绑定署理特色$props, $data
// 给Vue原型绑定三个实例办法: vm.$watch,vm.$set,vm.$delete
stateMixin(Vue)
// 给Vue原型绑定作业相关的实例办法: vm.$on, vm.$once ,vm.$off , vm.$emit
eventsMixin(Vue)
// 给Vue原型绑定生命周期相关的实例办法: vm.$forceUpdate, vm.destroy, 以及私有办法_update
lifecycleMixin(Vue)
// 给Vue原型绑定生命周期相关的实例办法: vm.$nextTick, 以及私有办法_render, 以及一堆东西办法
renderMixin(Vue)
export default Vue

stateMixin()

仿制代码...
 Vue.prototype.$set = set
 Vue.prototype.$delete = del
 ...

set()

源码方位: vue/src/core/observer/index.js

$set在Vue中的界说:

function set(target: Array<any> | Object, key: any, val: any): any {
  // ①先判别set的方针是否是undefined 或 null或 根本类型 (由于用户不应该往undefined和根本类型中set东西)
  if (
    process.env.NODE_ENV !== "production" &&
    (isUndef(target) || isPrimitive(target))
  ) {
    // ①result 假如是undefined或根本类型就报错
    warn(
      `Cannot set reactive property on undefined, null, or primitive value: ${(target: any)}`
    );
  }
  // ②判别了方针是否是数组与key是不是合法的index,合法的index是指值为大于等于0的整数
  if (Array.isArray(target) && isValidArrayIndex(key)) {
     // 修正数组的长度, 防止索引>数组长度导致splcie()履行有误
    target.length = Math.max(target.length, key);
    // ②result假如两个条件都建立就对方针数组调用splice办法刺进或许修正数组
    target.splice(key, 1, val); //这个splice不是一般的splice,是被vue署理重写过的splice
    return val;
  }
  //方针完结呼应
  // ③判别了特色假如在方针方针中直接return完毕逻辑 (由于vue只需增加方针方针中本来没有的特色时才会失掉呼应)
  if (key in target && !(key in Object.prototype)) {
    target[key] = val;
    return val;
  }
  // 以上都不建立, 即开端给target创立一个全新的特色
  // 获取Observer实例
  // vue在初始化的时分会将data里的一切特色都变成呼应式,假如的值是方针或许数组则会new一个Observer实例储存在__ob__
  const ob = (target: any).__ob__;
   // Vue 实例方针拥有 _isVue 特色, 即不允许给Vue 实例方针增加特色
  // 也不允许Vue.set/$set 函数为根数据方针(vm.$data)增加特色
  // 拿到这个方针的_ob_进行判别,假如不存在就说明是未经过vue初始化的一般方针而不是呼应式方针
  if (target._isVue || (ob && ob.vmCount)) {
    process.env.NODE_ENV !== "production" &&
      warn(
        "Avoid adding reactive properties to a Vue instance or its root $data " +
          "at runtime - declare it upfront in the data option."
      );
    return val;
  }
   // target自身就不是呼应式数据, 直接赋值
  if (!ob) {
    target[key] = val;
    return val;
  }
  // 进行呼应式处理
  // 手动经过defineReactive为特色增加get办法与set办法完结呼应
  defineReactive(ob.value, key, val);
  // 然后手动调用dep里的notify()发布更新
  ob.dep.notify();
  return val;
}

数组完结呼应

$set完结数组修正呼应的办法是署理重写的数组的一部分办法,接下来咱们看一下详细完结

vue中署理重写的不仅仅splice,有push、pop、shift、unshift、splice、sort、reverse这七个办法

const arrayProto = Array.prototype
export const arrayMethods = Object.create(arrayProto)
// vue中署理重写 有push、pop、shift、unshift、splice、sort、reverse
const methodsToPatch = [
  'push',
  'pop',
  'shift',
  'unshift',
  'splice',
  'sort',
  'reverse'
]
function def(obj, key, val, enumerable) {
    Object.defineProperty(obj, key, {
        value: val,
        enumerable: !!enumerable,
        writable: true,
        configurable: true
    });
}
methodsToPatch.forEach(function (method) {
  const original = arrayProto[method]
  def(arrayMethods, method, function mutator (...args) {
   // 首先履行了const result = original.apply(this, args)履行本来数组的办法并获取它的值
    const result = original.apply(this, args)
    const ob = this.__ob__
    let inserted
    // 判别假如是往数组中增加值
    switch (method) {
      case 'push':
      case 'unshift':
        inserted = args
        break
      case 'splice':
        inserted = args.slice(2)
        break
    }
    // 就将新增加的值也完结呼应式
    if (inserted) ob.observeArray(inserted)
    // 最后一步拿到这个数组的_ob_方针对_ob_里的dep进行派发更新
    ob.dep.notify()
    return result
  })
})

东西函数:

// 判别给定变量是否是未界说,当变量值为 null时,也会以为其是未界说
export function isUndef (v: any): boolean %checks {
  return v === undefined || v === null
}
// 判别给定变量是否是原始类型值
export function isPrimitive (value: any): boolean %checks {
  return (
    typeof value === 'string' ||
    typeof value === 'number' ||
    // $flow-disable-line
    typeof value === 'symbol' ||
    typeof value === 'boolean'
  )
}
// 判别给定变量的值是否是有用的数组索引
export function isValidArrayIndex (val: any): boolean {
  const n = parseFloat(String(val))
  return n >= 0 && Math.floor(n) === n && isFinite(val)
}

关于(ob && ob.vmCount)

export function observe (value: any, asRootData: ?boolean): Observer | void {
  // 省掉...
  if (asRootData && ob) {
    // vue现已被Observer了,并且是根数据方针, vmCount才会++
    ob.vmCount++
  }
  return ob
}

在初始化Vue的进程中有

export function initState (vm: Component) {
  vm._watchers = []
  const opts = vm.$options
  if (opts.props) initProps(vm, opts.props)
  if (opts.methods) initMethods(vm, opts.methods)
  if (opts.data) {
    //opts.data为方针特色
    initData(vm)
  } else {
    observe(vm._data = {}, true /* asRootData */)
  }
  if (opts.computed) initComputed(vm, opts.computed)
  if (opts.watch && opts.watch !== nativeWatch) {
    initWatch(vm, opts.watch)
  }
}

initData(vm)

function initData (vm: Component) {
  let data = vm.$options.data
  data = vm._data = typeof data === 'function'
    ? getData(data, vm)
    : data || {}
  // 省掉...
  // observe data
  observe(data, true /* asRootData */)
}

nextTick

②-①运用场景:

nextTick 办法是在 Vue.js 中常见的一种异步更新 DOM 的机制。它的原理是运用 JavaScript 的作业循环机制以及浏览器的烘托流程来完结推迟履行 DOM 更新操作。

它的呈现首要是为了处理 Vue 的异步更新导致的 DOM 更新后的操作问题。

在 Vue 中,数据的改动会触发从头烘托 DOM,但实际上,Vue 的数据更新是异步的。也便是说,当咱们修正了 Vue 实例的数据后,并不会当即进行 DOM 更新,而是鄙人一个作业循环中才会进行。

这个异步更新机制的设计是为了优化功用。Vue 会对进行屡次数据改动进行兼并,然后鄙人一个作业循环中进行一次性的 DOM 更新,然后削减不必要的 DOM 操作,进步功用。

然而,由于异步更新的机制,有时分或许在修正数据后需求当即履行一些 DOM 操作,例如获取到更新后的 DOM 元素、更新后的款式核算、触发一些特定作业等。这时分就需求运用 nextTick 办法了。

nextTick 办法是 Vue 供给的一个实用东西,它可以将回调函数推迟到下一个 DOM 更新循环之后履行。也便是说,经过 nextTick 办法,咱们可以保证在 DOM 更新完结后履行某些操作。

运用 nextTick 办法常常用来处理以下问题:

  • 获取更新后的 DOM 元素
  • 更新后的款式核算
  • 触发一些特定作业

综上所述,nextTick 的呈现处理了 Vue 的异步更新机制导致的 DOM 更新后的操作问题,使咱们可以在正确的机遇履行对应的操作,进步开发功率和灵活性。

②-②完结原理:

  • 将传递的回调函数放入 callbacks 全局数组中
  • 调用 timerFunc 函数,在浏览器的异步行列中放入改写callbacks(flashcallbacks ) 函数 ,推迟履行 (依据运转环境判别将flashcallbacks() 放入宏使命或许是微使命行列, 使得 flashcallbacks 被推迟调用)
  • 作业循环到了微使命或许宏使命,依次遍历履行 callbacks 数组中的一切函数

推迟调用优先级如下:

Promise.then > MutationObserver > setImmediate > setTimeout

MutationObserver 是H5 新加的一个功用,其功用是监听 DOM 节点的改动,在一切 DOM 改动完结后,履行回调函数。

Vue是异步履行dom更新的,一旦观察到数据改动,Vue就会开启一个行列,然后把在同一个作业循环 (event loop) 傍边观察到数据改动的 watcher 推送进这个行列。假如这个watcher被触发屡次,只会被推送到行列一次。这种缓冲行为可以有用的去掉重复数据形成的不必要的核算和Dom操作。而鄙人一个作业循环时,Vue会清空行列,并进行必要的DOM更新。

当你设置 vm.someData = ‘new value’,DOM 并不会马上更新,而是在异步行列被铲除,也便是下一个作业循环开端时履行更新时才会进行必要的DOM更新。假如此刻你想要依据更新的 DOM 状况去做某些作业,就会呈现问题。为了在数据改动之后等候 Vue 完结更新 DOM ,可以在数据改动之后当即运用 Vue.nextTick(callback) 。这样回调函数在 DOM 更新完结后就会调用。

nextTick完结原理概况:juejin.cn/post/725617…

juejin.cn/post/684490…

juejin.cn/post/684490…

juejin.cn/post/717618…

35.vue更新策略及diff算法

更新进程

  • 修正data,触发setter
  • 从头履行render函数,生成newVnode
  • patch(vnode,newVnode),diff算法会算差异

diff算法

运用开端vdom 虚拟DOM 。虚拟DOM算法 = 虚拟DOM + Diff算法

diff算法:新旧虚拟DOM比照,找出更改的虚拟节点,并更新虚拟节点所对应的实在节点,完结精准的更新实在DOM,进而进步功率。

运用虚拟DOM算法耗费核算:总耗费=虚拟DOM增修改+实在DOM差异增修改(diff算法功率)+重绘与重排(较少)

直接操作DOM的耗费核算:总耗费=实在DOM彻底增修改+重绘与重排(较多)

  • 同层比照:深度优先算法 patch(elem,vnode) 和 patch(vnode,newVnode)
  • 比照流程:patchVode 和 addVnodes 和 removeVnodes
  • 比照子节点,并更新:updateChildren(key的重要性)

juejin.cn/post/699495…

juejin.cn/post/691937…

juejin.cn/post/699058…

36.mixins和vuex的优缺陷

Mixins 是咱们可以重用的代码块

vuex源码便是调用了Vue.mixin,Vuex的双向绑定经过调用 new Vue完结,然后经过 Vue.mixin 注入到Vue组件的生命周期中,再经过绑架state.get将数据放入组件中

37.Vue动态加载异步组件原理及运用场景

中心原理便是 nextTick 完结异步行列 条件是需求了解 js 作业循环机制

juejin.cn/post/696122…

38.你都做过哪些 Vue 的功用优化

这儿只罗列针对 Vue 的功用优化 整个项目的功用优化是一个大工程 可以另写一篇功用优化的文章 哈哈

  • 方针层级不要过深,不然功用就会差
  • 不需求呼应式的数据不要放到 data 中(可以用 Object.freeze() 冻住数据)
  • v-if 和 v-show 区别运用场景
  • computed 和 watch 区别运用场景
  • v-for 遍历必须加 key,key 最好是 id 值,且防止一起运用 v-if
  • 大数据列表和表格功用优化-虚拟列表/虚拟表格
  • 防止内部走漏,组件毁掉后把全局变量和作业毁掉
  • 图片懒加载
  • 路由懒加载
  • 第三方插件的按需引入
  • 恰当选用 keep-alive 缓存组件
  • 防抖、节省运用
  • 服务端烘托 SSR or 预烘托

其他Vue真题:juejin.cn/post/696122…

其他Vue详解合集如下:

  1. Vue根本运用1
  2. vue2.x的10种组件间通信办法2
  3. Vue2.X的运用 3
  4. Vue面试真题演练 4 当时文档
  5. Vue3 5 更新中

感谢阅览

「❤️重视+点赞+保藏+评论+转发❤️」,创造不易,鼓舞笔者创造更好的文章