日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) >

「从源码中学习」面试官都不知道的Vue题目答案

發(fā)布時(shí)間:2025/4/5 67 豆豆
生活随笔 收集整理的這篇文章主要介紹了 「从源码中学习」面试官都不知道的Vue题目答案 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

前言

當(dāng)回答面試官問(wèn)及的Vue問(wèn)題,我們除了照本宣科的回答外,其實(shí)還可以根據(jù)少量的源碼來(lái)秀一把,來(lái)體現(xiàn)出你對(duì)Vue的深度了解。

本文會(huì)陸續(xù)更新,此次涉及以下問(wèn)題:

  • “new Vue()做了什么?”
  • “什么階段才能訪問(wèn)DOM?”
  • “談?wù)勀銓?duì)Vue生命周期的理解。”
  • 擴(kuò)展:新生命周期鉤子serverPrefetch是什么?
  • “vue-router路由模式有幾種?”
  • “談?wù)勀銓?duì)keep-alive的了解?”
  • “了解Vue2.6+新全局API:Vue.observable()嗎?”
  • 1. “new Vue()做了什么?”

    new關(guān)鍵字代表實(shí)例化一個(gè)對(duì)象, 而Vue實(shí)際上是一個(gè)類(lèi), 源碼位置是/src/core/instance/index.js。

    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) } 復(fù)制代碼

    接著我們跳轉(zhuǎn)追蹤至this._init(),即Vue.prototype._init,位于src\core\instance\init.js 在_init()方法的內(nèi)部有一系列 init* 的方法

    Vue.prototype._init = function (options?: Object) {const vm: Component = this// ...忽略,從第45行看起if (process.env.NODE_ENV !== 'production') {initProxy(vm)} else {vm._renderProxy = vm}// expose real selfvm._self = vminitLifecycle(vm)initEvents(vm)initRender(vm)callHook(vm, 'beforeCreate')initInjections(vm) // resolve injections before data/propsinitState(vm)initProvide(vm) // resolve provide after data/propscallHook(vm, 'created')// ...忽略if (vm.$options.el) {vm.$mount(vm.$options.el)}} } 復(fù)制代碼

    1.1 這里我們概述一遍:

  • initProxy,作用域代理,攔截組件內(nèi)訪問(wèn)其它組件的數(shù)據(jù)。
  • initLifecycle, 建立父子組件關(guān)系,在當(dāng)前實(shí)例上添加一些屬性和生命周期標(biāo)識(shí)。如:$children、$refs、_isMounted等。
  • initEvents,用來(lái)存放除@hook:生命周期鉤子名稱(chēng)="綁定的函數(shù)"事件的對(duì)象。如:$on、$emit等。
  • initRender,用于初始化$slots、$attrs、$listeners
  • initInjections,初始化inject,一般用于更深層次的組件通信,相當(dāng)于加強(qiáng)版的props。用于組件庫(kù)開(kāi)發(fā)較多。
  • 只要在上一層級(jí)的聲明的provide,那么下一層級(jí)無(wú)論多深都能夠通過(guò)inject來(lái)訪問(wèn)到provide的數(shù)據(jù)。這么做也是有明顯的缺點(diǎn):在任意層級(jí)都能訪問(wèn),導(dǎo)致數(shù)據(jù)追蹤比較困難,不知道是哪一個(gè)層級(jí)聲明了這個(gè)或者不知道哪一層級(jí)或若干個(gè)層級(jí)使用。

    • initState,是很多選項(xiàng)初始化的匯總,包括:props、methods、data、computed 和 watch 等。
    • initProvide,初始化provide。
    • vm.$mount,掛載實(shí)例。

    2. “什么階段才能訪問(wèn)DOM?”

    這個(gè)回答可以從beforeCreate以及 created 的調(diào)用時(shí)機(jī)談起,我們根據(jù)上面的概述,來(lái)簡(jiǎn)化下代碼:

    callHook(vm, 'beforeCreate') // 初始化 inject // 初始化 props、methods、data、computed 和 watch // 初始化 provide callHook(vm, 'created') // 掛載實(shí)例 vm.$mount(vm.$options.el) 復(fù)制代碼

    所以當(dāng)面試官問(wèn)你:

    • beforeCreate以及 created 調(diào)用時(shí),哪些數(shù)據(jù)能用與否?
    • 什么階段才能訪問(wèn)DOM?
    • 為什么created之后才掛載實(shí)例?

    知道怎么回答了吧。

    3. “談?wù)勀銓?duì)Vue的生命周期的理解”

    常規(guī)回答這里就不說(shuō)了,來(lái)稍微深入點(diǎn)的:

  • created/mounted/updated/destroyed,以及對(duì)應(yīng)的before鉤子。分別是創(chuàng)建=>掛載=>更新=>銷(xiāo)毀。
  • Vue源碼中定義了一個(gè)mergeHook函數(shù)來(lái)遍歷一個(gè)常量數(shù)組LIFECYCLE_HOOKS,該數(shù)組實(shí)際上是由與生命周期鉤子同名的字符串組成的數(shù)組。
  • // v2.6.10 最新版 var LIFECYCLE_HOOKS = ['beforeCreate','created','beforeMount','mounted','beforeUpdate','updated','beforeDestroy','destroyed','activated','deactivated','errorCaptured',// v2.6+ 'serverPrefetch' ]; 復(fù)制代碼

    于是,你可以答多activated & deactivated(keep-alive 組件激活/停用)、errorCaptured(v2.5 以上版本有的一個(gè)鉤子,用于處理錯(cuò)誤)這三個(gè)。

    3.1 新生命周期鉤子:serverPrefetch是什么?

    可以看到,serverPrefetch前身是ssrPrefetch。顧名思義,這是用來(lái)處理ssr的。允許我們?cè)阡秩具^(guò)程中“等待”異步數(shù)據(jù)。可在任何組件中使用,而不僅僅是路由組件。

    這里我們貼出一段官方例子:

    <!-- Item.vue --> <template><div v-if="item">{{ item.title }}</div><div v-else>...</div> </template><script> export default {computed: {item () {return this.$store.state.items[this.$route.params.id]}},serverPrefetch () {return this.fetchItem()},mounted () {if (!this.item) {this.fetchItem()}},methods: {fetchItem () {// return the Promise from the actionreturn this.$store.dispatch('fetchItem', this.$route.params.id)}} } </script> 復(fù)制代碼
    • 絕大多數(shù)的面試官都不會(huì)去關(guān)注v2.6+ 以后的代碼記錄和變更。這里如果你說(shuō)出這個(gè)v2.6.10的變化,嘖嘖...面試官肯定更加欣賞你。

    3.2 生命周期鉤子的合并策略

    拿callHook(vm, 'created')講,先判斷組件的選項(xiàng)中有無(wú)對(duì)應(yīng)名字的生命周期鉤子,再判斷是否有 parentVal(vm)。若存在parentVal(vm)且都有對(duì)應(yīng)的生命周期鉤子,則會(huì)將兩者concat為一個(gè)數(shù)組(parentVal.concat(childVal))。所以,生命周期鉤子其實(shí)是可以寫(xiě)成數(shù)組。如:

    created: [ function () {console.log('first') }, function () {console.log('second') }, function () {console.log('third') }] 復(fù)制代碼

    鉤子函數(shù)將按順序執(zhí)行。

    4. “Vue-router 路由模式有幾種?”

    三種 "hash" | "history" | "abstract",一般人只知道兩種"hash" | "history"。

    這里貼出源碼:

    switch (mode) {case 'history':this.history = new HTML5History(this, options.base)breakcase 'hash':this.history = new HashHistory(this, options.base, this.fallback)breakcase 'abstract':this.history = new AbstractHistory(this, options.base)breakdefault:if (process.env.NODE_ENV !== 'production') {assert(false, `invalid mode: ${mode}`)} } 復(fù)制代碼

    # mode

    類(lèi)型: string

    默認(rèn)值: "hash" (瀏覽器環(huán)境) | "abstract" (Node.js 環(huán)境)

    可選值: "hash" | "history" | "abstract" 配置路由模式:

    • hash: 使用 URL hash 值來(lái)作路由。支持所有瀏覽器,包括不支持 HTML5 History Api 的瀏覽器。
    • history: 依賴(lài) HTML5 History API 和服務(wù)器配置。查看 HTML5 History 模式。
    • abstract: 支持所有 JavaScript 運(yùn)行環(huán)境,如 Node.js 服務(wù)器端。如果發(fā)現(xiàn)沒(méi)有瀏覽器的 API,路由會(huì)自動(dòng)強(qiáng)制進(jìn)入這個(gè)模式.

    5. “談?wù)勀銓?duì)keep-alive的了解?”

    先貼一個(gè)常規(guī)回答:

    keep-alive是 Vue 內(nèi)置的一個(gè)組件,可以使被包含的組件保留狀態(tài),或避免重新渲染。 在vue 2.1.0 版本之后,keep-alive新加入了兩個(gè)屬性: include(包含的組件緩存) 與 exclude(排除的組件不緩存,優(yōu)先級(jí)大于include) 。

    然后你可以開(kāi)始騷了:

  • <keep-alive>是 Vue 源碼中實(shí)現(xiàn)的一個(gè)全局抽象組件,通過(guò)自定義 render 函數(shù)并且利用了插槽來(lái)實(shí)現(xiàn)數(shù)據(jù)緩存和更新。它的定義在src/core/components/keep-alive.js 中:
  • export default {name: 'keep-alive',abstract: true,... } 復(fù)制代碼
  • 所有的抽象組件是通過(guò)定義abstract選項(xiàng)來(lái)聲明的。抽象組件不渲染真實(shí)DOM,且不會(huì)出現(xiàn)在父子關(guān)系的路徑上(initLifecycle會(huì)忽略抽象組件),相關(guān)代碼片段:
  • if (parent && !options.abstract) {// abstract 即 `ptions.abstract`// while 循環(huán)查找第一個(gè)非抽象的父組件while (parent.$options.abstract && parent.$parent) {parent = parent.$parent}parent.$children.push(vm) } 復(fù)制代碼

    6. “了解Vue2.6+新全局API:Vue.observable()嗎?”

    Vue2.6+新的全局API是Vue.observable(),它的使用方式:

    import vue from vue; const state = Vue.observable ({counter: 0, }); export default {render () {return (<div>{state.counter}<button v-on:click={() => {state.counter ++; }}>Increment counter</ button></ div>);}, }; 復(fù)制代碼

    而它定義在/src/core/global-api/index.js第48行:

    import { observe } from 'core/observer/index' // ... // 2.6 explicit observable API Vue.observable = <T>(obj: T): T => { observe(obj) return obj } 復(fù)制代碼

    再看看它import的observe,最近一次提交在12/1/2018,唔。。。。

    核心就是暴露出observe(obj)觀測(cè)后的數(shù)據(jù),代碼啥都沒(méi)改。懂了吧?

    求一份深圳的內(nèi)推

    目前本人在準(zhǔn)備跳槽,希望各位大佬和HR小姐姐可以?xún)?nèi)推一份靠譜的深圳前端崗位!

    • 微信:huab119
    • 郵箱:454274033@qq.com

    作者掘金文章總集

    • 為何你始終理解不了JavaScript作用域鏈?
    • 「Vue實(shí)踐」項(xiàng)目升級(jí)vue-cli3的正確姿勢(shì)
    • 「從源碼中學(xué)習(xí)」徹底理解Vue選項(xiàng)Props
    • 「從源碼中學(xué)習(xí)」Vue源碼中的JS騷操作
    • 「從源碼中學(xué)習(xí)」面試官都不知道的Vue題目答案

    公眾號(hào):

    轉(zhuǎn)載于:https://juejin.im/post/5c959f74f265da610c068fa8

    總結(jié)

    以上是生活随笔為你收集整理的「从源码中学习」面试官都不知道的Vue题目答案的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

    如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。