2021最新Vue 面試題

Vue面試題

  1. v-html 會有XSS風(fēng)險(xiǎn),會覆蓋子組件

  2. computed 有緩存,data不變則不會重新計(jì)算

  3. watch 默認(rèn)不會深度監(jiān)聽,要deep:true開啟

  4. watch 監(jiān)聽引用類型,拿不到oldVal,因?yàn)橹羔樝嗤藭r(shí)已經(jīng)指向了新的val

  5. style指令需要駝峰式命名方式寫,例如{fontSize: '10px'}

  6. v-if v-else 可使用變量,也可使用===表達(dá)式

  7. v-if 和 v-show 的區(qū)別

    v-if false不渲染,適合更新不頻繁的,節(jié)省性能

    v-show false也渲染

  8. v-for 和 v-if 不能一起使用,v-for 比 v-if 優(yōu)先級高,影響性能

  9. 事件的event是原生的event,沒有裝飾過,事件是掛載到當(dāng)前元素

  10. v-for 的 key 因?yàn)?VDOM 的 diff 算法,通過判斷新vnode和舊vnode的key是否相等,從而復(fù)用與新節(jié)點(diǎn)對應(yīng)的老節(jié)點(diǎn),節(jié)約性能開銷

  11. 用index做key在diff算法中不起作用,用index拼接其他值會導(dǎo)致節(jié)點(diǎn)不能復(fù)用,所以用唯一值做key,比如數(shù)據(jù)id

  12. props 和 $emit

    props父組件通過子組件屬性給子組件傳值

    $emit子組件綁定父組件方法,在子組件內(nèi)使用$emit觸發(fā)父組件的方法

  13. Vue組件如何通訊

    父子組件事件props $emit

    自定義事件 $emit $on

    通過vuex

  14. 組件間通訊-自定義事件(常用兄弟組件通訊)

    Vue自有實(shí)現(xiàn),使用EventBus方式(bus總線機(jī)制/發(fā)布訂閱者模式/觀察者模式)

    import Vue from 'vue'
    var event = new Vue()
    export default event
    

    在A組件內(nèi)使用

    event.$emit('onHandle', params)
    

    在B組件內(nèi)的mounted中綁定自定義事件

    event.$on('onHandle', this.handle)
    

    在B組局內(nèi)beforeDestroy中及時(shí)銷毀監(jiān)聽事件,否則可能造成內(nèi)存泄露

    event.$off('onHandle', this.handle)
    
  15. 組件生命周期 <font color="red">* 必須背會</font>

    掛載

    beforeCreate->create->beforeMount->mounted
    

    beforeCreate里沒有this,實(shí)例還未初始化,在數(shù)據(jù)觀測(data observer)和event/watcher事件配置前

    create 初始化示例,沒有渲染,取不到dom,沒有$el,通常初始化某些屬性值

    beforeMount 掛載開始之前,相關(guān)渲染首次被調(diào)用

    mounted 是渲染完了,通常是初始化頁面完成后,再對html的dom節(jié)點(diǎn)進(jìn)行一些需要的操作

    先父組件create->子組件create->子組件mounted->父組件mounted


    更新

    beforeUpdate->updated
    

    beforeUpdate 重新渲染和打補(bǔ)丁之前,在這里更改狀態(tài)不會觸發(fā)重新渲染

    updated 由于數(shù)據(jù)更改導(dǎo)致的重新渲染和打補(bǔ)丁觸發(fā)

    先父組件beforeUpdate-->子組件beforeUpdate->updated->父組件->updated


    銷毀

    beforeDestroy->Destroyed
    

    beforeDestroy 實(shí)例銷毀之前,里面可以用this

    Destroyed 實(shí)例銷毀之后,所以東西解綁,移除所以監(jiān)聽,銷毀所以子實(shí)例,在服務(wù)端渲染不會被調(diào)用

    先父組件beforeDestroy-->子組件beforeDestroy->Destroyed->父組件->Destroyed

  16. 高級特性

    • <font color="red">可以不深入,但必須知道</font>
    • <font color="red">熟練基本用法,了解使用場景</font>
    • <font color="red">最好能和自己的項(xiàng)目經(jīng)驗(yàn)結(jié)合</font>
    1. 自定義v-model

      v-model會默認(rèn)利用名為value的prop和名為input的事件,model會避免單選,復(fù)選將value特性用于不同目的的沖突

      v-model等于

      <input type="text" 
            :value="val" 
            @input="val=$event.target.value">
      

      demo:

      //父組件
      <CustomVModel v-model="name"/>
      <script>
      import CustomVModel from './CustomVModel'
      export default {
          components: {
              CustomVModel
          },
          data() {
              return {
                  name: ''
              }
          }
      }
      </script>
      // 子組件內(nèi)
      <template>
         <!--
         1. input使用了 :value 而不是 v-model
         2. change 和 model.even 要對應(yīng)
         3. text 屬性要對應(yīng) model.prop 和 props.text
         -->
         <input type="text" 
                 :value="text" 
                 @input="$emit('change', $event.target.value)"
          />
      </template>
      <script>
      export default {
          // 改變默認(rèn)v-model的綁定屬性和拋出事件
          model: {
              prop: 'text' // 對應(yīng)props text,
              event: 'change'
          },
          props: {
              text: String,
              default() {
                  return ''
              }
          }
      }
      </script>
      
    2. $nextTick、$refs

      $nextTick

      Vue是異步渲染,$nextTick會在DOM渲染之后被觸發(fā)

      頁面渲染會將 data 的修改做整合,多次 data 修改只會渲染一次


      $refs 在節(jié)點(diǎn)內(nèi)寫ref="dom" 使用this.$refs.dom拿到節(jié)點(diǎn)的dom元素

    3. slot

      基本使用

      父組件在子組件內(nèi)插入節(jié)點(diǎn)內(nèi)容

      // 父組件
      <SlotDemo>
         {{user.name}}
      </SlotDemo>
      // 子組件 SlotDemo
      <div>
          <slot>默認(rèn)顯示</slot>
      </div>
      

      作用域插槽

      父組件在子組件內(nèi)插入節(jié)點(diǎn)內(nèi)容,使用子組件的數(shù)據(jù)

      // 父組件
      <ScopedSlotDemo>
         <template v-slot="slotProps">
             {{slotProps.slotData.name}}
          </template>
      </ScopedSlotDemo>
      // 子組件 ScopedSlotDemo
      <div>
          <slot :slotData="user"></slot>
      </div>
      

      具名插槽

      用于定義多個(gè)插槽

      // 父組件
      <NameSlot>
          <template v-slot:header>
             <h1>插入 header slot中</h1>
          </template>
         <p>插入 main slot中,即未命名的 slot</p>
         <template v-slot:footer>
             <p>插入 footer slot中</p>
          </template>
      </NameSlot>
      // 子組件 NameSlot
      <div class="container">
        <header>
          <slot name="header"></slot>
        </header>
        <main>
          <slot></slot>
        </main>
        <footer>
          <slot name="footer"></slot>
        </footer>
      </div>
      
    4. 動(dòng)態(tài)、異步組件

      動(dòng)態(tài)組件

      用法 :is='component-name'

      需要根據(jù)數(shù)據(jù),動(dòng)態(tài)渲染的場景,即組局類型不確定,例如 信息流

      <div v-for="item in components" v-key="id">
         <component :is="item.name" />    
      </div>
      
      <script>
      import TextInfoComponent from './TextInfoComponent'
      import ImageInfoComponent from './TextInfoComponent'
      export default {
          components: {
              TextInfoComponent,
              ImageInfoComponent
          },
          data() {
              return {
                 components: [{
                     id: 1,
                     name: 'TextInfoComponent',
                 },{
                     id: 2,
                     name: 'ImageInfoComponent',
                 }]
              }
          }
      }
      </script>
      

      異步組件

      import() 函數(shù)

      按需加載, 異步加載大組件

      export default {
          conponents: {
              component: () => import('./component')
          }
      }
      
    5. keep-alive

      緩存組件,頻繁切換,不需要重復(fù)渲染 例如 tab切換

      <keep-alive>
       <KeepAliveStage></KeepAliveStage>
      </keep-alive>
      <script>
      import KeepAliveStage from './KeepAliveStage'
      export default {
          conponents: {
              KeepAliveStage
          }
      }
      </script>
      
    6. mixin

      多組件有相同的邏輯,抽離出來,和主組件混合合并代碼

      會出現(xiàn)問題

      • 變量來源不明確,不利于閱讀
      • 多mixin會造成命名沖突
      • mixin和組件可能出現(xiàn)多對多的關(guān)系,復(fù)雜度較高

      Vue 3 提出的Composition API 旨在解決這些問題

      // 定義 ./myMixin.js
      export default {
          data() {
              return {}
          },
          mounted() {},
          methots: {}
      }
      
      // 使用
      import myMixin from './myMixin'
      export default {
          mixins: [myMixin] // 可以多個(gè),自動(dòng)合并
      }
      
  17. Vuex 使用

    可能會考察 state 的數(shù)據(jù)結(jié)構(gòu)設(shè)計(jì)

    vuex.png
+ 基本概念

1. state // 單一狀態(tài)樹
2. getters // 獲取屬性,計(jì)算屬性啥的
3. actions // 類似控制器,commit 多個(gè) mutations,這里可以異步操作,其他的不行
4. mutations // 更改狀態(tài),必須是同步函數(shù)
5. module // 模塊化Store
6. plugins //插件,相當(dāng)mutation的攔截器,提供store.subscribe((mutation, state) => {})

--------------

+ Vue組件內(nèi)

1. dispatch // 用來觸發(fā) actions
2. commit // 用來觸發(fā) mutations
3. mapState // 映射 state 的函數(shù),computed 中 ...mapState()
4. mapGetters  // 映射 getters 的函數(shù),computed 中 ...mapState()
5. mapActions // 映射 actions 的函數(shù),methods 中 ...mapActions()
6. mapMutations // 映射 mutations 的函數(shù),methods 中 ...mapMutations()
  1. Vue-router 使用

    路由模式(hash,H5 history),后者需要server支持

    mode:‘history’

    路由配置(動(dòng)態(tài)路由,懶加載)

    :id那種,在$route.params.id取到

  2. Vue 原理

    • 如何理解MVVM

      mvvm.png

      Model-View-ViewModel 數(shù)據(jù)模型-視圖-視圖數(shù)據(jù)

      數(shù)據(jù)驅(qū)動(dòng)視圖

      View和Model沒有直接關(guān)聯(lián),ViewMode是給他們提供雙向數(shù)據(jù)綁定的聯(lián)系,優(yōu)點(diǎn)是讓開發(fā)者只需關(guān)注業(yè)務(wù),不需要手動(dòng)操作DOM,也不需要關(guān)注數(shù)據(jù)狀態(tài)同步的問題

    • 監(jiān)聽data變化的核心API是什么,怎么深度監(jiān)聽-遞歸

      Vue 2 是通過 Object.defineProperty 的 getter 和 setter,并結(jié)合觀察者模式實(shí)現(xiàn)數(shù)據(jù)綁定的

      能監(jiān)聽屬性的get set方法

      缺點(diǎn)

      用于深度監(jiān)聽要遞歸到底,一次性計(jì)算量大

      無法監(jiān)聽新增屬性/刪除屬性

      無法原生監(jiān)聽數(shù)組,需要特殊處理

      Vue 3 是通過 es6的 proxy

      優(yōu)點(diǎn)是之前操作的是對象的屬性,現(xiàn)在是操作對象,對js引擎比較友好

      缺點(diǎn)是兼容不好,不能用polyfill,不支持低版本瀏覽器

      監(jiān)聽數(shù)組-重新定義數(shù)組原型鏈

      const oldArrayProperty = Array.prototype
      // 創(chuàng)建新對象,原型指向oldArrayProperty,在擴(kuò)展新的方法不會影響原型
      const arrProto = Object.create(oldArrayProperty)
      ['push', 'pop', 'shift', 'unshift', 'splice'].forEach(methodName => {
          arrProto[methodName] = function() {
              updateView() // 更新視圖
              oldArrayProperty[methodName].call(this, ...arguments)
          }
      })
      
    • 虛擬DOM

      vdom (Virtual DOM) 是實(shí)現(xiàn)vue的重要基石

      用JS模擬DOM結(jié)構(gòu),計(jì)算出最小的變更,操作DOM

      數(shù)據(jù)驅(qū)動(dòng)視圖,控制DOM操作

    • diff算法

      diff算法是vdom中的核心,最關(guān)鍵的部分

      vue2 參考snabbdom,雙端比較

      diff01.png

      核心思路

      patch新舊vnode的children

      新的沒有不管舊的有沒有,就移除children

      新舊都有,就去對比新舊vnode的children

      新有舊沒有,就添加children

      對比新舊vnode的children,先用四個(gè)指針指向新舊nodeChildren的頭尾

      然后循環(huán)指針到中間,循環(huán)內(nèi)進(jìn)行對比key和sel是否相等

      1. 舊children的開始 和 新children的開始 對比
      2. 舊children的結(jié)束 和 新children的結(jié)束 對比
      3. 舊children的開始 和 新children的結(jié)束 對比
      4. 舊children的結(jié)束 和 新children的開始 對比
      5. 以上有相同的,就執(zhí)行處理新舊節(jié)點(diǎn)的children,并對應(yīng)移動(dòng)指針
      6. 以上都沒找到相同的,則去用新的key看看舊的里面有沒有,如果沒有則插入,然后移動(dòng)指針,如果有再判斷sel是否相同,不相同就插入,然后移動(dòng)指針,相同就執(zhí)行處理新舊節(jié)點(diǎn)的children,去掉舊節(jié)點(diǎn),插入新節(jié)點(diǎn),然后移動(dòng)指針
      // children 和 text 是不會共存的,要么是節(jié)點(diǎn)要么是文本
      // elm 對應(yīng)的dom元素
      // 所有元素都可以有key
      Vnode = {sel, data, children, text, elm, key}
      
      //先創(chuàng)建Vnode
      h() => Vnode
      
      patch(oldVnode, newVnode) => {
          if 第一個(gè)參數(shù)不是Vnode
              創(chuàng)建一個(gè)空的Vnode,關(guān)聯(lián)到這個(gè)elm元素
          
          if 判斷Vnode是否相同,則去對比(兩個(gè)Vnode的key 和 sel 都相等)
              Vnode對比: patchVnode()
          else 不同的Vnode直接刪掉重建 
      }
      
      patchVnode(oldVnode, newVnode) => {
          執(zhí)行 prepatch hook
          設(shè)置 vnode.elm,把新的 elm 賦值成舊的 elm, 讓新的知道更新到了哪個(gè) elm
          得到 oldChildren 和 newChildren
          if 判斷newVnode 有沒有 children, newVnode.text == undefined (vnode.children 一般有值) 
              if 新舊都有 children
                  更新children: updateChildren()
              else if 新 children 有,舊 children 無 (舊 text 有)
                  if 如果就的 text 有值,則清空 text
                  添加 children
              else if 新 children 無,舊 children 有
                  移除 children
              else 舊 text 有
                  清空 text
              清空 text
          else vnode.children 沒有值,則刪除舊的 children 并設(shè)置清空 text
      }
      
      // 核心方法
      updateChildren(elm, oldChildren, newChildren) => {
          // 用于循環(huán)從四周到中間
          定義指針 oldStartIndex, oldEndIndex, newStartIndex, oldStartIndex
          
          while(指針到中間停止) {
              if 判斷元素是否是空,操作指針移動(dòng)
              else if oldStart == newStart 開始和開始,判斷是否相同(key 和 sel 都相等)
                  patchVnode(), 操作指針移動(dòng)
              else if oldEnd == newEnd 結(jié)束和結(jié)束,判斷是否相同(key 和 sel 都相等)
                  patchVnode(), 操作指針移動(dòng)
              else if oldStart == newEnd 開始和結(jié)束,判斷是否相同(key 和 sel 都相等)
                  patchVnode(), 操作指針移動(dòng)
              else if oldEnd == newStart 結(jié)束和開始,判斷是否相同(key 和 sel 都相等)
                  patchVnode(), 操作指針移動(dòng)
              else 以上四個(gè)都未命中
                  // 用新節(jié)點(diǎn) key,判斷能否對應(yīng) oldChildren 中某個(gè)節(jié)點(diǎn)的 key
                  在oldChildren中,用新節(jié)點(diǎn)的key去拿節(jié)點(diǎn)
                  if 沒拿到?jīng)]對應(yīng)上,則
                      插入新節(jié)點(diǎn), 操作指針移動(dòng)
                  else 對應(yīng)上
                      if sel 是否相等
                          插入新節(jié)點(diǎn), 操作指針移動(dòng)
                      else key 和 sel 都相等
                          patchVnode(),去掉舊節(jié)點(diǎn),插入新節(jié)點(diǎn), 操作指針移動(dòng)
          }
      }
      

      vue3 參考inferno,最長遞增子序列

      兩個(gè)理念。第一個(gè)是相同的前置與后置元素的預(yù)處理;第二個(gè)則是最長遞增子序列

      1. 從頭對比找到相同的節(jié)點(diǎn)patch,發(fā)現(xiàn)不同則跳出

      2. 如果1沒有patch完,則從后往前找相同的節(jié)點(diǎn)patch,發(fā)現(xiàn)不同則跳出

      3. 如果新節(jié)點(diǎn)大于與舊節(jié)點(diǎn),對剩余的都創(chuàng)建新的vnode

      4. 如果舊節(jié)點(diǎn)大于新節(jié)點(diǎn),對于超出的舊節(jié)點(diǎn)全部卸載

      5. 如果3,4都沒有,則是對于不確定的元素(沒有patch到相同的vnode)

        1. 把沒有比較過的新vnode保存在map里

        2. 記錄已經(jīng)patch節(jié)點(diǎn)的熟練patched,沒有經(jīng)過patch的新節(jié)點(diǎn)數(shù)量tuBePatched

        3. 建立一個(gè)數(shù)組newIndexToOldIndexMap,每個(gè)元素都記錄舊節(jié)點(diǎn)的索引,這個(gè)數(shù)組的索引就是新節(jié)點(diǎn)的索引

        4. 遍歷舊節(jié)點(diǎn)

          1. 如果toBePatched為0,那么統(tǒng)一卸載舊節(jié)點(diǎn)
          2. 如果舊節(jié)點(diǎn)key存在,通過key找到對應(yīng)新節(jié)點(diǎn)的index
          3. 如果舊節(jié)點(diǎn)key不存在,遍歷剩下的所有新節(jié)點(diǎn),試圖找到新節(jié)點(diǎn)對應(yīng)的index
          4. 如果沒有找到對應(yīng)的新節(jié)點(diǎn)就卸載舊節(jié)點(diǎn)
          5. 如果找到對應(yīng)的新節(jié)點(diǎn),把舊節(jié)點(diǎn)的索引記錄在新節(jié)點(diǎn)的數(shù)組中,如果節(jié)點(diǎn)發(fā)生移動(dòng)就記錄已經(jīng)移動(dòng)了,最后patch新節(jié)點(diǎn)
        5. 如果發(fā)生移動(dòng),根據(jù)newIndexToOldIndexMap找到最長穩(wěn)定序列,

        6. 如果證明不存在舊節(jié)點(diǎn)就創(chuàng)建新節(jié)點(diǎn),對于發(fā)生移動(dòng)的節(jié)點(diǎn)進(jìn)行移動(dòng)處理

  3. 模版編譯

    模版編譯為 render 函數(shù),執(zhí)行 render 函數(shù)返回 vnode

    基于 vnode 再執(zhí)行 patch 和 diff

    使用webpack vue-loader

    • JS的 with 語法

      改變 {} 內(nèi)自由變量的查找規(guī)則,當(dāng)做 obj 屬性來查找

      如果找不到匹配的 obj 屬性,就會報(bào)錯(cuò)

      with 要慎用,它打破了作用域規(guī)則,易讀性變差

      // with 能改變 {} 內(nèi)自由變量的查找方式,將 {} 內(nèi)自由變量,當(dāng)做 obj 的屬性來查找
      const obj = {a:100, b:200}
      console.log(obj.a)
      console.log(obj.b)
      console.log(obj.c) // undefined
      with(obj) {
          console.log(a)
          console.log(b)
          console.log(c) // 會報(bào)錯(cuò)
      }
      
  4. 組件 渲染/更新 過程

data.png
> 初次渲染的過程
>
> > 解析模版為 render 函數(shù)
> >
> > 觸發(fā)響應(yīng)式,監(jiān)聽 data 屬性的 getter setter
> >
> > 執(zhí)行 render 函數(shù),生成 vnode, 執(zhí)行 patch(elm, vnode)
>
> 更新過程
>
> > 修改 data,觸發(fā) setter
> >
> > 重新執(zhí)行 render 函數(shù),生成 newVnode
> >
> > 執(zhí)行 patch(vnode, newVnode)
>
> 異步渲染 $nextTick
>
> > 匯總 data 的修改,一次性更新視圖
> >
> > 減少 DOM 操作次數(shù),提升性能
  1. 路由原理

    稍微復(fù)制的SPA,都需要路由

    hash-window.onhashchange

    H5 history-history.pushState 和 window.onpopstate

    H5 history 需要后端支持

    兩者選擇

    toB 推薦hash,簡單易用,對 url 規(guī)范不敏感

    toC 可以考慮選擇H5 history,但需要服務(wù)端支持

    能選擇簡單的就別用復(fù)雜的,要考慮成本和收益

    hash 特點(diǎn)

    hash 變化會觸發(fā)網(wǎng)頁跳轉(zhuǎn),即瀏覽器的前期、后退

    hash 變化不會刷新頁面,SPA必需的特點(diǎn)

    hash 永遠(yuǎn)不會提交到server端(前端自生自滅)

    H5 history

    用 url 規(guī)范的路由,但跳轉(zhuǎn)時(shí)不刷新頁面

    history.pushState

    window.onpopstate

  2. 面試題

    v-show 和 v-if 的區(qū)別

    v-show 通過 css display 控制顯示和隱藏

    v-if 是組件真正的渲染和銷毀,而不是顯示和隱藏

    頻繁切換顯示狀態(tài)用 v-show,否則用 v-if

    為什么 v-for 中用 key

    必須用 key,而且不能是 index 和 random

    diff 算法中通過 tag 和 key 來判斷,是否是 sameNode

    減少渲染次數(shù),提升渲染性能

    描述 vue 組件的生命周期

    單組件生命周期圖

    父子組件生命周期關(guān)系比如 mount 和 update

    Vue 組件如何通訊

    父子組件 props 和 this.$emit

    自定義事件 event.on event.off event.$emit

    vuex

    描述組件渲染和更新的過程

    渲染圖

    雙向數(shù)據(jù)綁定 v-model 的實(shí)現(xiàn)原理

    input 元素的 value = this.name

    綁定 input 事件 this.name = $event.target.value

    data 更新觸發(fā) re-render

    對 MVVM 的理解

    computed 有何特點(diǎn)

    緩存,data 不變不會重新計(jì)算

    提高性能

    為何組件 data 必須是一個(gè)函數(shù)

    js 特性導(dǎo)致的,Object 是引用數(shù)據(jù)類型,會導(dǎo)致同一個(gè)屬性改一個(gè)都變了,是函數(shù)的時(shí)候才能實(shí)例獨(dú)立不相互影響

    ajax 應(yīng)該放在哪個(gè)生命周期

    mounted

    js 是單線程,ajax 是異步獲取數(shù)據(jù)

    放在 mounted 之前沒有用,只會讓邏輯更加混亂,除非有特殊需求

    如何將組件所有的 props 傳遞給子組件

    $props

    <Uer v-bind="$props" />

    如何自己實(shí)現(xiàn) v-model

    多個(gè)組件有相同的邏輯,如何抽離

    mixin

    mixin 的缺點(diǎn)

    何時(shí)要使用異步組件

    加載大組件

    路由異步加載

    何時(shí)需要使用 keep-alive

    緩存組件,不需要重復(fù)渲染

    多個(gè)靜態(tài) tab 頁的切換

    優(yōu)化性能

    何時(shí)需要使用beforeDestory

    解綁自定義事件 event.$off

    清楚定時(shí)器

    解綁自定義的 DOM 事件,如 window scroll 等

    什么是作用域插槽

    把子組件的數(shù)據(jù)傳給父組件顯示

    vuex 中 action 和 mutation 有何區(qū)別

    action 中處理異步,mutation 不可以

    mutation 做原子操作

    action 可以整合多個(gè) mutation

    vue-router 常用的路由模式

    hash 默認(rèn)

    H5 history

    vue-router 兩種模式是怎么實(shí)現(xiàn)的

    hash window.onhashchange

    H5 history window.history.pushState window.history.onpopstate

    vue-router 兩種模式的區(qū)別

    hash有#號,能控制瀏覽器前后跳轉(zhuǎn),不會提交到server端

    H5 history 是規(guī)范 url,需要 server 端配合

    如何配置 vue-router 異步加載

    通過 () => import()

    用 vnode 描述一個(gè) DOM 結(jié)構(gòu)

    監(jiān)聽 data 變化的核心 API 是什么

    Object.defineProperty

    有何缺點(diǎn)

    深度監(jiān)聽需要遞歸、監(jiān)聽數(shù)組需要特殊處理,無法監(jiān)聽新增和刪除的屬性,使用vue.set vue.delete

    Vue3 Proxy 兼容問題,而且不能 polyfill

    Vue 如何監(jiān)聽數(shù)組變化

    Object.defineProperty 不能監(jiān)聽數(shù)組變化

    重新定義原型,重新push pop等方法,實(shí)現(xiàn)監(jiān)聽

    Proxy 可以原生支持監(jiān)聽數(shù)組變化

    描述響應(yīng)式原理

    監(jiān)聽 data 變化

    組件渲染和更新的流程

    diff 算法的時(shí)間復(fù)雜度

    O(n) ,在O(n^3)基礎(chǔ)上做的調(diào)整,只比較同一層級,比較tag不相同直接銷毀重建,通過tag和key判斷是不是同一組件,是就不重復(fù)對比

    簡述 diff 算法過程

    patch(elem, vnode) 和 patch(vnode, newVnode)

    patchVnode 和 addVnodes 和 removeVnodes

    updateChildren,通過key判斷是不是同一節(jié)點(diǎn)

    vue為何是異步渲染,$nextTick 何用

    異步渲染,合并 data 修改,提高性能

    $nextTick 在 DOM 更新之后,觸發(fā)回調(diào)

    vue 常見性能優(yōu)化

    合理使用 v-show v-if

    合理使用 computed

    v-for 時(shí)加 key,以及避免和 v-if 同時(shí)使用

    自定義事件,DOM事件及時(shí)銷毀

    合理使用異步組件

    合理使用 keep-alive

    data 層級不要太深

    使用 vue-loader 在開發(fā)環(huán)境做模版編譯(預(yù)編譯)

    webpack 層面的優(yōu)化

    前端通用的性能優(yōu)化,如圖片懶加載

    使用ssr

  3. Vue 3

    Vue3 比 Vue2 有什么優(yōu)勢

    性能更好

    體積更小

    更好的 ts 支持

    更好的代碼組織

    更好的邏輯抽離

    更多新功能

    Vue3 聲明周期

    Options API: beforeDestory 改為 beforeUnmount destoryed 改為 unmouted

    升級內(nèi)容

    全部用 ts 重寫

    性能提升,代碼量減少

    調(diào)整部分API

  4. 持續(xù)更新中...

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容