「从源码中学习」面试官都不知道的Vue题目答案
前言
當回答面試官問及的Vue問題,我們除了照本宣科的回答外,其實還可以根據少量的源碼來秀一把,來體現出你對Vue的深度了解。
本文會陸續更新,此次涉及以下問題:
1. “new Vue()做了什么?”
new關鍵字代表實例化一個對象, 而Vue實際上是一個類, 源碼位置是/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) } 復制代碼接著我們跳轉追蹤至this._init(),即Vue.prototype._init,位于src\core\instance\init.js 在_init()方法的內部有一系列 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)}} } 復制代碼1.1 這里我們概述一遍:
只要在上一層級的聲明的provide,那么下一層級無論多深都能夠通過inject來訪問到provide的數據。這么做也是有明顯的缺點:在任意層級都能訪問,導致數據追蹤比較困難,不知道是哪一個層級聲明了這個或者不知道哪一層級或若干個層級使用。
- initState,是很多選項初始化的匯總,包括:props、methods、data、computed 和 watch 等。
- initProvide,初始化provide。
- vm.$mount,掛載實例。
2. “什么階段才能訪問DOM?”
這個回答可以從beforeCreate以及 created 的調用時機談起,我們根據上面的概述,來簡化下代碼:
callHook(vm, 'beforeCreate') // 初始化 inject // 初始化 props、methods、data、computed 和 watch // 初始化 provide callHook(vm, 'created') // 掛載實例 vm.$mount(vm.$options.el) 復制代碼所以當面試官問你:
- beforeCreate以及 created 調用時,哪些數據能用與否?
- 什么階段才能訪問DOM?
- 為什么created之后才掛載實例?
知道怎么回答了吧。
3. “談談你對Vue的生命周期的理解”
常規回答這里就不說了,來稍微深入點的:
于是,你可以答多activated & deactivated(keep-alive 組件激活/停用)、errorCaptured(v2.5 以上版本有的一個鉤子,用于處理錯誤)這三個。
3.1 新生命周期鉤子:serverPrefetch是什么?
可以看到,serverPrefetch前身是ssrPrefetch。顧名思義,這是用來處理ssr的。允許我們在渲染過程中“等待”異步數據??稍谌魏谓M件中使用,而不僅僅是路由組件。
這里我們貼出一段官方例子: <!-- 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> 復制代碼- 絕大多數的面試官都不會去關注v2.6+ 以后的代碼記錄和變更。這里如果你說出這個v2.6.10的變化,嘖嘖...面試官肯定更加欣賞你。
3.2 生命周期鉤子的合并策略
拿callHook(vm, 'created')講,先判斷組件的選項中有無對應名字的生命周期鉤子,再判斷是否有 parentVal(vm)。若存在parentVal(vm)且都有對應的生命周期鉤子,則會將兩者concat為一個數組(parentVal.concat(childVal))。所以,生命周期鉤子其實是可以寫成數組。如:
created: [ function () {console.log('first') }, function () {console.log('second') }, function () {console.log('third') }] 復制代碼鉤子函數將按順序執行。
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}`)} } 復制代碼# mode
類型: string
默認值: "hash" (瀏覽器環境) | "abstract" (Node.js 環境)
可選值: "hash" | "history" | "abstract" 配置路由模式:
- hash: 使用 URL hash 值來作路由。支持所有瀏覽器,包括不支持 HTML5 History Api 的瀏覽器。
- history: 依賴 HTML5 History API 和服務器配置。查看 HTML5 History 模式。
- abstract: 支持所有 JavaScript 運行環境,如 Node.js 服務器端。如果發現沒有瀏覽器的 API,路由會自動強制進入這個模式.
5. “談談你對keep-alive的了解?”
先貼一個常規回答:
keep-alive是 Vue 內置的一個組件,可以使被包含的組件保留狀態,或避免重新渲染。 在vue 2.1.0 版本之后,keep-alive新加入了兩個屬性: include(包含的組件緩存) 與 exclude(排除的組件不緩存,優先級大于include) 。
然后你可以開始騷了:
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>);}, }; 復制代碼而它定義在/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 } 復制代碼再看看它import的observe,最近一次提交在12/1/2018,唔。。。。
核心就是暴露出observe(obj)觀測后的數據,代碼啥都沒改。懂了吧?求一份深圳的內推
目前本人在準備跳槽,希望各位大佬和HR小姐姐可以內推一份靠譜的深圳前端崗位!
- 微信:huab119
- 郵箱:454274033@qq.com
作者掘金文章總集
- 為何你始終理解不了JavaScript作用域鏈?
- 「Vue實踐」項目升級vue-cli3的正確姿勢
- 「從源碼中學習」徹底理解Vue選項Props
- 「從源碼中學習」Vue源碼中的JS騷操作
- 「從源碼中學習」面試官都不知道的Vue題目答案
公眾號:
轉載于:https://juejin.im/post/5c959f74f265da610c068fa8
總結
以上是生活随笔為你收集整理的「从源码中学习」面试官都不知道的Vue题目答案的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 大三下学期第四周总结
- 下一篇: 聊聊技术路线的选择