年底了,有的盆友可能會考慮跳槽,從今天起,每天更新一些面試題,也是考察自己是否對這些知識點熟練于心。
糖糖會堅持更新,若有遺漏知識點,后續會補充。如果有不對的地方,歡迎朋友們指出。
“形象走在能力前面”
無論你今年幾歲,只要你邁入職場,建議去準備一套正裝。在外形上要職業化、專業化。
女生,化淡妝,保證自己的氣色要活力滿滿。男生,要干凈整潔,有精神。
“態度決定一切”
前端知識點多如牛毛,如果真的是面試,題海深深,你怎么知道問你什么?如果你跟背書一樣,十分機械地回答,也無法得到面試官的認可。
如果問到不會的,也不會害怕,畢竟知識點那么多,卡殼很正常,但你要妥善解決。
始終呈現一個自信的、積極的態度,百分之八十的公司或者企業更看重的是你的工作態度和忠誠度。
“知己知彼百戰百勝”
一般面試會問什么?關心什么?
人事關心你的生活狀態是否符合工作要求。
項目經理關心你的技術是否達標。
面試提問會涉及模塊:
個人介紹(含離職原因)、項目案例、主流框架、基礎知識點。
建議對自己擅長的模塊展開回答,把一個面試題回答透,比你沒有目標的背題有用。
面試干貨——能力和技術十分重要:
Vue 的優缺點
優點:
創建單頁面應用的輕量級Web應用框架
簡單易用
雙向數據綁定
組件化的思想
虛擬DOM
數據驅動視圖
缺點:
不支持IE8
談談對SPA 的理解
SPA是Single-Page-Application的縮寫,翻譯過來就是單頁應用。在WEB頁面初始化時一同加載Html、Javascript、Css。一旦頁面加載完成,SPA不會因為用戶操作而進行頁面重新加載或跳轉,取而代之的是利用路由機制實現Html內容的變換。
優點
1.良好的用戶體驗,內容更改無需重載頁面。
2.基于上面一點,SPA相對服務端壓力更小。
3.前后端職責分離,架構清晰。
缺點
1.由于單頁WEB應用,需在加載渲染頁面時請求JavaScript、Css文件,所以耗時更多。
2.由于前端渲染,搜索引擎不會解析JS,只能抓取首頁未渲染的模板,不利于SEO。
3.由于單頁應用需在一個頁面顯示所有的內容,默認不支持瀏覽器的前進后退。
缺點3的補充:
前端路由機制解決了單頁應用無法前進后退的問題。Hash模式中Hash變化會被瀏覽器記錄(onhashchange事件),History模式利用 H5 新增的pushState和replaceState方法可改變瀏覽器歷史記錄棧。
MVVM 的理解
MVVM是Model-View-ViewModel的縮寫。Model 代表數據層,可定義修改數據、編寫業務邏輯。View 代表視圖層,負責將數據渲染成頁面。ViewModel 負責監聽數據層數據變化,控制視圖層行為交互,簡單講,就是同步數據層和視圖層的對象。ViewModel 通過雙向綁定把 View 和 Model 層連接起來,且同步工作無需人為干涉,使開發人員只關注業務邏輯,無需頻繁操作DOM,不需關注數據狀態的同步問題。
這張圖建議保存,十分直觀,方便理解與記憶。
如何實現 v-model
v-model指令用于實現input、select等表單元素的雙向綁定,是個語法糖。
原生 input 元素若是text/textarea類型,使用 value 屬性和 input 事件。
原生 input 元素若是radio/checkbox類型,使用 checked屬性和 change 事件。
原生 select 元素,使用 value 屬性和 change 事件。
input 元素上使用 v-model 等價于
<input :value="message" @input="message = $event.target.value" />
復制代碼
實現自定義組件的 v-model
自定義組件的v-model使用prop值為value和input事件。若是radio/checkbox類型,需要使用model來解決原生 DOM 使用的是 checked 屬性 和 change 事件,如下所示。
// 父組件
<template>
<base-checkbox v-model="baseCheck" />
</template>
復制代碼
// 子組件
<template>
<input type="checkbox" :checked="checked" @change="$emit('change', $event.target.checked)" />
</template>
<script>
export default {
model: {
prop: 'checked',
event: 'change'
},
prop: {
checked: Boolean
}
}
</script>
復制代碼
Vue 響應式原理
核心源碼位置:vue/src/core/observer/index.js
響應式原理3個步驟:數據劫持、依賴收集、派發更新。
數據分為兩類:對象、數組。
對象
遍歷對象,通過Object.defineProperty為每個屬性添加 getter 和 setter,進行數據劫持。getter 函數用于在數據讀取時進行依賴收集,在對應的 dep 中存儲所有的 watcher;setter 則是數據更新后通知所有的 watcher 進行更新。
核心源碼
function defineReactive(obj, key, val, shallow) {
// 實例化一個 dep, 一個 key 對應一個 dep
const dep = new Dep()
// 獲取屬性描述符
const getter = property && property.get
const setter = property && property.set
if ((!getter || setter) && arguments.length === 2) {
val = obj[key]
}
// 通過遞歸的方式處理 val 為對象的情況,即處理嵌套對象
let childOb = !shallow && observe(val)
Object.defineProperty(obj, key, {
enumerable: true,
configurable: true,
// 攔截obj.key,進行依賴收集
get: function reactiveGetter () {
const value = getter ? getter.call(obj) : val
// Dep.target 是當前組件渲染的 watcher
if (Dep.target) {
// 將 dep 添加到 watcher 中
dep.depend()
if (childOb) {
// 嵌套對象依賴收集
childOb.dep.depend()
// 響應式處理 value 值為數組的情況
if (Array.isArray(value)) {
dependArray(value)
}
}
}
return value
},
set: function reactiveSetter (newVal) {
// 獲取舊值
const value = getter ? getter.call(obj) : val
// 判斷新舊值是否一致
if (newVal === value || (newVal !== newVal && value !== value)) {
return
}
if (process.env.NODE_ENV !== 'production' && customSetter) {
customSetter()
}
if (getter && !setter) return
// 如果是新值,用新值替換舊值
if (setter) {
setter.call(obj, newVal)
} else {
val = newVal
}
// 新值做響應式處理
childOb = !shallow && observe(newVal)
// 當響應式數據更新,依賴通知更新
dep.notify()
}
})
}
復制代碼
數組
用數組增強的方式,覆蓋原屬性上默認的數組方法,保證在新增或刪除數據時,通過 dep 通知所有的 watcher 進行更新。
核心源碼
const arrayProto = Array.prototype
// 基于數組原型對象創建一個新的對象
export const arrayMethods = Object.create(arrayProto)
const methodsToPatch = [
'push',
'pop',
'shift',
'unshift',
'splice',
'sort',
'reverse'
]
methodsToPatch.forEach(function (method) {
const original = arrayProto[method]
// 分別在 arrayMethods 對象上定義7個方法
def(arrayMethods, method, function mutator (...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.dep.notify()
return result
})
})
復制代碼
Vuex 的理解及使用
Vuex 是一個專為 Vue.js 應用程序開發的狀態管理模式,采用集中式存儲管理應用的所有組件的狀態。
主要解決如下 兩個 問題
- 多個視圖依賴同一狀態。
- 來自不同視圖的行為需要變更同一個狀態。
其包含如下模塊,搬官網圖
State:定義并初始化全局狀態。
Getter: 依賴 State 中的狀態,進行二次包裝,不會影響 State 源數據。
Mutation: 更改 State 狀態的函數,必須是同步。
Action:用于提交 Mutation,可包含任意異步操作。
Module:若應用復雜,Store 會集中一個比較大的對象而顯得臃腫,Module允許我們將 Store模塊化管理。
當然,若應用比較簡單,共享狀態也比較少,可以用 Vue.observe 去替代 Vuex,省去安裝一個庫也挺好。
Vue 路由傳參方式
Vue 路由有 三種 方式進行傳參
方案一
// 路由配置
{
path: '/detail/:id',
name: 'Detail',
component: () => import('./Detail.vue')
}
// 路由跳轉
let id = 1
this.{id}'})
// 獲取參數
this.$route.params.id
復制代碼
方案二
方案二,URL 雖然不顯示我們的傳參,但是是可以在子組件獲取參數的。當然也有問題:會存在刷新丟失參數。
若想不丟失,需和方案一路由配置一樣。原因是第二種方式傳參是上一個頁面 push 函數中攜帶的,刷新沒有 push 的動作。
// 路由配置
{
path: '/detail',
name: 'Detail',
component: () => import('./Detail.vue')
}
// 路由跳轉
let id = 1
this.route.params.id
復制代碼
方案三
// 路由配置
{
path: '/detail',
name: 'Detail',
component: () => import('./Detail.vue')
}
// 路由跳轉
let id = 1
this.route.query.id
復制代碼