產(chǎn)品經(jīng)理開(kāi)需求會(huì) ---> 拿到文檔扮念,下載項(xiàng)目,排期 ---> 開(kāi)發(fā) ---> 聯(lián)調(diào) ---> 測(cè)試 ---> 發(fā)布到流水線
MVVM
MVVM 模式不需要操作 dom 元素,將數(shù)據(jù)綁定到 viewModel 層上碧库,會(huì)自動(dòng)將數(shù)據(jù)渲染到頁(yè)面中視圖變化會(huì)通知 viewModel層 更新數(shù)據(jù)柜与。ViewModel 是 MVVM 模式中的橋梁.
響應(yīng)式數(shù)據(jù)的原理
核心: Object.defineProperty Vue 在初始化數(shù)據(jù)時(shí),會(huì)給 data 中的屬性使用 Object.defineProperty 重新定義所有屬性,當(dāng)頁(yè)面取到對(duì)應(yīng)屬性時(shí)嵌灰。會(huì)進(jìn)行依賴收集(收集當(dāng)前組件的watcher) 如果屬性發(fā)生變化會(huì)通
知相關(guān)依賴進(jìn)行更新操作弄匕。
雙向數(shù)據(jù)綁定
雙向數(shù)據(jù)綁定是由數(shù)據(jù)劫持結(jié)合發(fā)布者訂閱者實(shí)現(xiàn)的。數(shù)據(jù)劫持是通過(guò)Object.defineProperty()來(lái)劫持對(duì)象數(shù)據(jù)的setter和getter操作沽瞭。在數(shù)據(jù)變動(dòng)時(shí)做你想做的事迁匠。
通過(guò)Observer來(lái)監(jiān)聽(tīng)自己的model數(shù)據(jù)變化,通過(guò)Compile來(lái)解析編譯模板指令驹溃,最終利用Watcher搭起Observer和Compile之間的通信橋梁城丧,達(dá)到數(shù)據(jù)變化視圖更新,在初始化Vue實(shí)例時(shí)豌鹤,遍歷data這個(gè)對(duì)象亡哄,給每一個(gè)鍵值對(duì)利用Object.definedProperty對(duì)data的鍵值對(duì)新增get和set方法,利用了事件監(jiān)聽(tīng)DOM的機(jī)制傍药,讓視圖去改變數(shù)據(jù)
Vue-router
字符串寫(xiě)法:
$router.push('地址/參數(shù)')--->params的方式(需要占位)
$router.push('地址?參數(shù)')--->query的方式(不需要占位)
對(duì)象的寫(xiě)法:
$router.push({name:'名字',params:{鍵:值}})--->params的方式(需要占位,設(shè)置name屬性) $router.push({path:'地址',query:{鍵:值}})--->query的方式(不需要占位)
原理:
Hash路由:利用URL上的hash磺平,當(dāng)hash改變不會(huì)引起頁(yè)面刷新魂仍,所以可以利用 hash 值來(lái)做單頁(yè)面應(yīng)用的路由拐辽,并且當(dāng) url 的 hash 發(fā)生變化的時(shí)候拣挪,可以觸發(fā)相應(yīng) hashchange 回調(diào)函數(shù)。
History路由:History 路由是基于 HTML5 規(guī)范俱诸,在 HTML5 規(guī)范中提供了 history.pushState || history.replaceState 來(lái)進(jìn)行路由控制
概念:?jiǎn)雾?yè)應(yīng)用(single page web application菠劝,SPA),是在一個(gè)頁(yè)面完成所有的業(yè)務(wù)功能睁搭,瀏覽器一開(kāi)始會(huì)加載必需的HTML赶诊、CSS和JavaScript,之后所有的操作都在這張頁(yè)面完成园骆,這一切都由JavaScript來(lái)控制舔痪。
優(yōu)點(diǎn):操作體驗(yàn)流暢 - 減少服務(wù)器壓力
缺點(diǎn):首次加載大量資源(按需加載) - 對(duì)搜索引擎SEO不友好(vue-meta-info配合prerender-spa-plugin)
路由守衛(wèi)分類
全局前置守衛(wèi)
router.beforeEach((to, from, next) => {
// ...
})
全局解析守衛(wèi)
router.beforeResolve
全局后置鉤子
router.afterEach((to, from) => {
// ...
})
路由獨(dú)享的守衛(wèi)
在路由配置上直接定義 beforeEnter
{
path: '/foo',
component: Foo,
beforeEnter: (to, from, next) => {
// ...
}
}
組件內(nèi)的守衛(wèi)
在路由組件內(nèi)直接定義以下路由導(dǎo)航守衛(wèi):
beforeRouteEnter
beforeRouteUpdate (2.2 新增)
beforeRouteLeave
每個(gè)守衛(wèi)方法接收三個(gè)參數(shù):
to :到哪去(準(zhǔn)備進(jìn)入的路由)
from: 從哪來(lái)(準(zhǔn)備離開(kāi)的路由)
next:function
next() 進(jìn)入下一個(gè)鉤子
next(false) 中斷當(dāng)前的導(dǎo)航
next(‘/’) 中斷當(dāng)前導(dǎo)航,進(jìn)入新的導(dǎo)航
next(error) 導(dǎo)航終止
完整的導(dǎo)航解析流程:
1. 導(dǎo)航被觸發(fā)锌唾。
2. 在失活的組件里調(diào)用 beforeRouteLeave 守衛(wèi)锄码。
3. 調(diào)用全局的 beforeEach 守衛(wèi)。
4. 在重用的組件里調(diào)用 beforeRouteUpdate 守衛(wèi) (2.2+)晌涕。
5. 在路由配置里調(diào)用 beforeEnter滋捶。
6. 解析異步路由組件。
7. 在被激活的組件里調(diào)用 beforeRouteEnter余黎。
8. 調(diào)用全局的 beforeResolve 守衛(wèi) (2.5+)重窟。
9. 導(dǎo)航被確認(rèn)。
10. 調(diào)用全局的 afterEach 鉤子惧财。
11. 觸發(fā) DOM 更新巡扇。
12. 用創(chuàng)建好的實(shí)例調(diào)用 beforeRouteEnter 守衛(wèi)中傳給 next 的回調(diào)函數(shù)。
keep-alive的使用
用來(lái)包裹動(dòng)態(tài)組件垮衷,實(shí)現(xiàn)組件的緩存厅翔,當(dāng)組件切換時(shí)不會(huì)對(duì)當(dāng)前組件進(jìn)行卸載,常用的2個(gè)屬性
include / exclude ,2個(gè)生命周期 activated , deactivated
include - 字符串或正則表達(dá)式。只有名稱匹配的組件會(huì)被緩存帘靡。
exclude - 字符串或正則表達(dá)式知给。任何名稱匹配的組件都不會(huì)被緩存。
max - 數(shù)字描姚。最多可以緩存多少組件實(shí)例涩赢。
require.context自定義引入全局組件
require.context()
const contexts = require.context('全局組件文件夾路徑', true/false, /.vue$/)
contexts.keys().forEach(filename => {
const coms = contexts(filename).default
Vue.component(coms.name, coms)
})
Vue的render函數(shù)
在入口文件中 render: h => h(App) 引入App父組件文件并傳入調(diào)用,就會(huì)構(gòu)建DOM
簡(jiǎn)單的說(shuō)轩勘,在vue中我們使用模板HTML語(yǔ)法組建頁(yè)面的筒扒,使用render函數(shù)我們可以用js語(yǔ)言來(lái)構(gòu)建DOM
因?yàn)関ue是虛擬DOM,所以在拿到template模板時(shí)也要轉(zhuǎn)譯成VNode的函數(shù)绊寻,而用render函數(shù)構(gòu)建DOM花墩,vue就免去了轉(zhuǎn)譯的過(guò)程悬秉。
當(dāng)使用render函數(shù)描述虛擬DOM時(shí),vue提供一個(gè)函數(shù)冰蘑,這個(gè)函數(shù)是就構(gòu)建虛擬DOM所需要的工具和泌。官網(wǎng)上給他起了個(gè)名字叫createElement。還有約定的簡(jiǎn)寫(xiě)叫h,
linsters
$attr: 包含了父作用域中不作為 prop 被識(shí)別 (且獲取) 的 attribute 綁定 (class 和 style 除外)祠肥。當(dāng)一個(gè)組件沒(méi)有聲明任何 prop 時(shí)武氓,這里會(huì)包含所有父作用域的綁定 (class 和 style 除外),并且可以通過(guò) v-bind="$attrs" 傳入內(nèi)部組件——在創(chuàng)建高級(jí)別的組件時(shí)非常有用仇箱。
$listeners:包含了父作用域中的 (不含 .native 修飾器的) v-on 事件監(jiān)聽(tīng)器县恕。它可以通過(guò) v-on="$listeners" 傳入內(nèi)部組件——在創(chuàng)建更高層次的組件時(shí)非常有用。
options
props:當(dāng)前組件接收到的 props 對(duì)象剂桥。Vue 實(shí)例代理了對(duì)其 props 對(duì)象忠烛,就可以直接this.使用了
$options:用于當(dāng)前 Vue 實(shí)例的初始化選項(xiàng)。需要在選項(xiàng)中包含自定義 property 時(shí)會(huì)有用處:
new Vue({
customOption: 'foo',
created: function () {
console.log(this.$options.customOption) // => 'foo'
}
})
provide $inject
項(xiàng)目的權(quán)限控制
1. 創(chuàng)建vue實(shí)例的時(shí)候?qū)ue-router掛載权逗,但這個(gè)時(shí)候vue-router掛載一些登錄或者不用權(quán)限的公用的頁(yè)面美尸。
2. 當(dāng)用戶登錄后,獲取用role旬迹,將role和路由表每個(gè)頁(yè)面的需要的權(quán)限作比較火惊,生成最終用戶可訪問(wèn)的路由表。
3. 調(diào)用router.addRoutes(store.getters.addRouters)添加用戶可訪問(wèn)的路由奔垦。
4. 使用vuex管理路由表屹耐,根據(jù)vuex中可訪問(wèn)的路由渲染側(cè)邊欄組件
Vue中是如何檢測(cè)數(shù)組變化
使用函數(shù)劫持的方式,重寫(xiě)了數(shù)組的方法
Vue 將 data 中的數(shù)組椿猎,進(jìn)行了原型鏈重寫(xiě)惶岭。指向了自己定義的數(shù)組原型方法,這樣當(dāng)調(diào)用數(shù)組api 時(shí)犯眠,可以通知依賴更新.如果數(shù)組中包含著引用類型按灶。會(huì)對(duì)數(shù)組中的引用類型再次進(jìn)行監(jiān)控。
為何Vue采用異步渲染
因?yàn)槿绻徊捎卯惒礁驴疬郑敲疵看胃聰?shù)據(jù)都會(huì)對(duì)當(dāng)前組件進(jìn)行重新渲染.所以為了性能考慮鸯旁。 Vue
會(huì)在本輪數(shù)據(jù)更新后,再去異步更新視圖!
Vue $nextTick作用
nextTick 方法主要是使用了宏任務(wù)和微任務(wù),定義了一個(gè)異步方法.多次調(diào)用 nextTick 會(huì)將方法存入隊(duì)列中量蕊,通過(guò)這個(gè)異步方法清空當(dāng)前隊(duì)列铺罢。 所以這個(gè) nextTick 方法就是異步方法
作用:將回調(diào)延遲到下次 DOM 更新循環(huán)之后執(zhí)行。在修改數(shù)據(jù)之后立即使用它残炮,然后等待 DOM 更新韭赘。
diff
Diff算法有三大策略:
Tree Diff :對(duì)DOM樹(shù)每一層進(jìn)行遍歷,找出不同
Component Diff : 組件的差異比較势就,如果是同一類型組件泉瞻,就按原策略繼續(xù)比較虛擬DOM即可脉漏,如果不是同一類型組件就替換組件下所有子節(jié)點(diǎn)
Element Diff : 真實(shí)DOM渲染,結(jié)構(gòu)差異的比較袖牙,將不同的地方渲染到DOM樹(shù)上
1.先同級(jí)比較侧巨,在比較子節(jié)點(diǎn)
2.先判斷一方有兒子一方?jīng)]兒子的情況
3.比較都有兒子的情況
4.遞歸比較子節(jié)點(diǎn)
具名插槽和作用域插槽的區(qū)別
具名插槽可以出現(xiàn)在不同的地方,不限制出現(xiàn)次數(shù)贼陶,只要name匹配上刃泡,那么這些內(nèi)容就會(huì)插入到這個(gè)name的插槽中巧娱。
作用域插槽其實(shí)就是帶數(shù)據(jù)的插槽碉怔,即帶參數(shù)的插槽,簡(jiǎn)單的來(lái)說(shuō)就是子組件提供給父組件的參數(shù)禁添,該參數(shù)僅限于插槽中使用撮胧,父組件可根據(jù)子組件傳過(guò)來(lái)的插槽數(shù)據(jù)來(lái)進(jìn)行不同的方式展現(xiàn)和填充插槽內(nèi)容。
區(qū)別:
普通插槽
在父組件初始化期間會(huì)編譯成文本子節(jié)點(diǎn)存起來(lái)老翘,在子組件渲染的時(shí)候直接將插槽替換成父組件里渲染的節(jié)點(diǎn)
作用域插槽
在父組件初始化期間會(huì)編譯成一個(gè)函數(shù)芹啥,在子組件初始化的時(shí)候執(zhí)行這個(gè)函數(shù)生成vnode再進(jìn)行渲染
computed和watch
computed:計(jì)算屬性:某個(gè)數(shù)據(jù)的值改變,相關(guān)聯(lián)的數(shù)據(jù)會(huì)自動(dòng)的發(fā)生變化 (get set方法)
默認(rèn) computed 也是一個(gè) watcher 是具備緩存的,只要當(dāng)依賴的屬性發(fā)生變化時(shí)才會(huì)更新視圖
watch:某個(gè)數(shù)據(jù)變化了,想要做相關(guān)的事情 (newVal, oldValue)
Watch中的deep:true 是如何實(shí)現(xiàn)的:當(dāng)用戶指定了 watch 中的deep屬性為 true 時(shí)铺峭,如果當(dāng)前監(jiān)控的值是數(shù)組類型墓怀。會(huì)對(duì)對(duì)象中的每一項(xiàng)進(jìn)行求值,此時(shí)會(huì)將當(dāng)前 watcher 存入到對(duì)應(yīng)屬性的依賴中卫键,這樣數(shù)組中對(duì)象發(fā)生變化時(shí)也會(huì)通知數(shù)據(jù)更新
組件之間傳值怎么做
父子間通信 父->子通過(guò) props 傀履、子-> 父 $on、$emit (發(fā)布訂閱)
獲取父子組件實(shí)例的方式 $parent莉炉、$children
在父組件中提供數(shù)據(jù)子組件進(jìn)行消費(fèi) Provide钓账、inject 插件
Ref 獲取實(shí)例的方式調(diào)用組件的屬性或者方法
Event Bus 實(shí)現(xiàn)跨組件通信 Vue.prototype.$bus = new Vue()
Vuex 狀態(tài)管理實(shí)現(xiàn)通信 $attrs $listeners
描述組件渲染和更新過(guò)程
vue.observable
vue2.6新增在Vue實(shí)例外部創(chuàng)建響應(yīng)式對(duì)象
v-model是干什么的 怎么用
雙向數(shù)據(jù)綁定,如果數(shù)據(jù)更新絮宁,視圖就會(huì)更新梆暮,如果視圖更新數(shù)據(jù)也會(huì)更新
input radio checkbox select
為當(dāng)前的節(jié)點(diǎn)標(biāo)簽綁定input事件
* 如果標(biāo)簽中的數(shù)據(jù)發(fā)生變化,此時(shí)觸發(fā)input事件,判斷表達(dá)式之前的數(shù)據(jù)和現(xiàn)在輸入的數(shù)據(jù)是否不同,之后會(huì)進(jìn)入到MVVM的set方法內(nèi)部再進(jìn)入到observer.js的set方法內(nèi)部,根據(jù)當(dāng)前的這個(gè)屬性的dep對(duì)象通知當(dāng)前dep對(duì)象中subs數(shù)組中的watcher進(jìn)行數(shù)據(jù)的更新操作
vue中的key
1. 虛擬DOM的key的作用?
1). 簡(jiǎn)單的說(shuō): key是虛擬DOM對(duì)象的標(biāo)識(shí), 在更新顯示時(shí)key起著極其重要的作用
2). 詳細(xì)的說(shuō): 當(dāng)列表數(shù)組中的數(shù)據(jù)發(fā)生變化生成新的虛擬DOM后, React進(jìn)行新舊虛擬DOM的diff比較
a. key沒(méi)有變
item數(shù)據(jù)沒(méi)變, 直接使用原來(lái)的真實(shí)DOM
item數(shù)據(jù)變了, 對(duì)原來(lái)的真實(shí)DOM進(jìn)行數(shù)據(jù)更新
b. key變了
銷(xiāo)毀原來(lái)的真實(shí)DOM, 根據(jù)item數(shù)據(jù)創(chuàng)建新的真實(shí)DOM顯示(即使item數(shù)據(jù)沒(méi)有變)
2. key為index的問(wèn)題
1). 添加/刪除/排序 => 產(chǎn)生沒(méi)有必要的真實(shí)DOM更新 ==> 界面效果沒(méi)問(wèn)題, 但效率低
2). 如果item界面還有輸入框 => 產(chǎn)生錯(cuò)誤的真實(shí)DOM更新 ==> 界面有問(wèn)題
注意: 如果不存在添加/刪除/排序操作, 用index沒(méi)有問(wèn)題
3. 解決:
使用item數(shù)據(jù)的標(biāo)識(shí)數(shù)據(jù)作為key, 比如id屬性值
Vuex
state:包含了多個(gè)狀態(tài)數(shù)據(jù)的對(duì)象
mutations:包含多個(gè)直接修改狀態(tài)數(shù)據(jù)的方法的對(duì)象
actions:包含多個(gè)間接修改狀態(tài)數(shù)據(jù)的方法的對(duì)象
getters:包含多個(gè)狀態(tài)數(shù)據(jù)的計(jì)算屬性的get的方法的對(duì)象
modules:用來(lái)做Vuex的模塊
生命周期
數(shù)據(jù)初始化之前、數(shù)據(jù)初始化之后绍昂、頁(yè)面渲染之前啦粹、頁(yè)面渲染之后、頁(yè)面更新之前窘游、頁(yè)面更新之后唠椭、銷(xiāo)毀實(shí)例之前、銷(xiāo)毀實(shí)例之后
組件加載先后順序
常用指令和組件
MVVM源碼分析
Vue的理解,數(shù)據(jù)代理,模版解析,劫持,雙向數(shù)據(jù)綁定?
* 數(shù)據(jù)代理--->劫持--->模版解析
*
*
* Vue中是有數(shù)據(jù)代理的
* 創(chuàng)建Vue的實(shí)例對(duì)象的時(shí)候,把data對(duì)象中所有數(shù)據(jù)通過(guò)Object.keys()進(jìn)行遍歷,內(nèi)部調(diào)用Object.defineProperty()把data對(duì)象中所有的數(shù)據(jù)一個(gè)一個(gè)添加到vm實(shí)例對(duì)象上,vm對(duì)象可以直接訪問(wèn)data對(duì)象中的數(shù)據(jù)了,vm代理了data,data是被代理者
* Vue中是有數(shù)據(jù)劫持的
* 當(dāng)Vue中數(shù)據(jù)代理結(jié)束后,就開(kāi)始數(shù)據(jù)劫持,通過(guò)observe()方法開(kāi)始進(jìn)行數(shù)據(jù)的劫持,判斷data是一個(gè)對(duì)象后,創(chuàng)建劫持的實(shí)例對(duì)象,內(nèi)部遍歷vm的data對(duì)象,然后把vm的data對(duì)象中所有的數(shù)據(jù)一個(gè)一個(gè)添加到劫持對(duì)象的data對(duì)象上,當(dāng)前在正式添加之前,創(chuàng)建dep對(duì)象(id,subs數(shù)組),只要vm中的data對(duì)象有多少個(gè)屬性就會(huì)創(chuàng)建多少個(gè)dep對(duì)象(將來(lái)和watcher建立關(guān)系)
* Vue中是有模版解析的
* 當(dāng)數(shù)據(jù)劫持后,開(kāi)始模版解析,獲取html中的容器對(duì)象,然后在內(nèi)存中創(chuàng)建文檔碎片對(duì)象,把容器中的所有的節(jié)點(diǎn)全部的添加到文檔碎片對(duì)象中,然后遍歷所有的節(jié)點(diǎn),判斷節(jié)點(diǎn)是標(biāo)簽還是文本?
* 如果是標(biāo)簽,獲取該標(biāo)簽內(nèi)部的所有的屬性,判斷當(dāng)前的屬性是不是指令
* 如果是事件指令,通過(guò)addEventLister()方法綁定事件
* 如果是普通指令,調(diào)用compileUtil中相關(guān)方法,進(jìn)入到updater對(duì)象中調(diào)用方法進(jìn)行操作
*
* 如果是文本,還要判斷當(dāng)前的文本節(jié)點(diǎn)是不是插值,如果是插值則調(diào)用updater對(duì)象中相關(guān)的方法,進(jìn)行替換數(shù)據(jù)操作
*
* 最終很多方法都會(huì)調(diào)用compileUtil中的方法,會(huì)進(jìn)入到bind方法內(nèi)部,開(kāi)始創(chuàng)建watcher對(duì)象,會(huì)獲取當(dāng)前使用的表達(dá)式的值,會(huì)調(diào)用get方法,內(nèi)部就開(kāi)始建立dep和watcher的關(guān)系(調(diào)用了get方法,獲取表達(dá)式的值,進(jìn)入mvvm的get,會(huì)進(jìn)入observer中的get方法,調(diào)用watcher對(duì)象中的addDep方法)
* dep和watcher的關(guān)系
* 1對(duì)1
* 1對(duì)多
* 多對(duì)1
* 多對(duì)多
* 把watcher添加到dep的subs數(shù)組,把dep連同id添加到watcher的depIds對(duì)象中
*
* 此時(shí),在內(nèi)存中的文檔碎片對(duì)象中模版解析已經(jīng)全部搞定,最后全部的渲染到html容器中,顯示到界面中
* 如果頁(yè)面中更新數(shù)據(jù),會(huì)直接進(jìn)入mvvm的set方法,進(jìn)入obserber的set方法,找到當(dāng)前修改數(shù)據(jù)的這個(gè)屬性對(duì)應(yīng)的dep對(duì)象,調(diào)用當(dāng)前dep.notify()通知對(duì)應(yīng)的這個(gè)dep的subs數(shù)組中的watcher對(duì)象,調(diào)用內(nèi)部的update方法,判斷數(shù)據(jù)是否需要進(jìn)行修改,如果需要修改最后調(diào)用updater對(duì)象中的相關(guān)方法,進(jìn)行模版的再次解析數(shù)據(jù)操作,界面變化了
*
*
*
* Vue中是有雙向數(shù)據(jù)綁的张峰,同上
創(chuàng)建Vue的實(shí)例的時(shí)候,除了數(shù)據(jù)綁定和數(shù)據(jù)劫持以外,會(huì)進(jìn)入到compile模版解析中,在內(nèi)存中創(chuàng)建文檔碎片對(duì)象,把html容器中所有的子級(jí)節(jié)點(diǎn)全部的存放在文檔碎片對(duì)象中,遍歷所有的節(jié)點(diǎn)判斷當(dāng)前的節(jié)點(diǎn)是不是標(biāo)簽,然后獲取當(dāng)前節(jié)點(diǎn)標(biāo)簽中所有的屬性,判斷當(dāng)前的屬性是不是指令,然后再判斷當(dāng)前的指令是不是普通指令v-model,再然后為當(dāng)前的節(jié)點(diǎn)標(biāo)簽綁定input事件
* 如果標(biāo)簽中的數(shù)據(jù)發(fā)生變化,此時(shí)觸發(fā)input事件,判斷表達(dá)式之前的數(shù)據(jù)和現(xiàn)在輸入的數(shù)據(jù)是否不同,之后會(huì)進(jìn)入到MVVM的set方法內(nèi)部再進(jìn)入到observer.js的set方法內(nèi)部,根據(jù)當(dāng)前的這個(gè)屬性的dep對(duì)象通知當(dāng)前dep對(duì)象中subs數(shù)組中的watcher進(jìn)行數(shù)據(jù)的更新操作
JS繼承
1. 原型鏈繼承:
讓新實(shí)例的原型等于父類的實(shí)例泪蔫。
特點(diǎn):1、實(shí)例可繼承的屬性有:實(shí)例的構(gòu)造函數(shù)的屬性喘批,父類構(gòu)造函數(shù)屬性撩荣,父類原型的屬性铣揉。(新實(shí)例不會(huì)繼承父類實(shí)例的屬性!)
缺點(diǎn):1餐曹、新實(shí)例無(wú)法向父類構(gòu)造函數(shù)傳參逛拱。
2、繼承單一台猴。
3侦锯、所有新實(shí)例都會(huì)共享父類實(shí)例的屬性。(原型上的屬性是共享的舞骆,一個(gè)實(shí)例修改了原型屬性朝氓,另一個(gè)實(shí)例的原型屬性也會(huì)被修改!)
2. 借用構(gòu)造函數(shù)繼承:
重點(diǎn):用.call()和.apply()將父類構(gòu)造函數(shù)引入子類函數(shù)(在子類函數(shù)中做了父類函數(shù)的自執(zhí)行(復(fù)制))
特點(diǎn):1休讳、只繼承了父類構(gòu)造函數(shù)的屬性讲婚,沒(méi)有繼承父類原型的屬性。
2俊柔、解決了原型鏈繼承缺點(diǎn)1筹麸、2、3雏婶。
3物赶、可以繼承多個(gè)構(gòu)造函數(shù)屬性(call多個(gè))。
4留晚、在子實(shí)例中可向父實(shí)例傳參酵紫。
缺點(diǎn):1、只能繼承父類構(gòu)造函數(shù)的屬性倔丈。
2憨闰、無(wú)法實(shí)現(xiàn)構(gòu)造函數(shù)的復(fù)用。(每次用每次都要重新調(diào)用)
3需五、每個(gè)新實(shí)例都有父類構(gòu)造函數(shù)的副本鹉动,臃腫。
3. 組合繼承(組合原型鏈繼承和借用構(gòu)造函數(shù)繼承)(常用)
重點(diǎn):結(jié)合了兩種模式的優(yōu)點(diǎn)宏邮,傳參和復(fù)用
特點(diǎn):1泽示、可以繼承父類原型上的屬性,可以傳參蜜氨,可復(fù)用械筛。
2、每個(gè)新實(shí)例引入的構(gòu)造函數(shù)屬性是私有的飒炎。
缺點(diǎn):調(diào)用了兩次父類構(gòu)造函數(shù)(耗內(nèi)存)埋哟,子類的構(gòu)造函數(shù)會(huì)代替原型上的那個(gè)父類構(gòu)造函數(shù)。
4. 原型式繼承
重點(diǎn):用一個(gè)函數(shù)包裝一個(gè)對(duì)象,然后返回這個(gè)函數(shù)的調(diào)用赤赊,這個(gè)函數(shù)就變成了個(gè)可以隨意增添屬性的實(shí)例或?qū)ο蟠秤bject.create()就是這個(gè)原理。
特點(diǎn):類似于復(fù)制一個(gè)對(duì)象抛计,用函數(shù)來(lái)包裝哄孤。
缺點(diǎn):1、所有實(shí)例都會(huì)繼承原型上的屬性吹截。
2瘦陈、無(wú)法實(shí)現(xiàn)復(fù)用。(新實(shí)例屬性都是后面添加的)
字符串方法
數(shù)組方法
forEach filter reduce map every some
拷貝
盒模型
forEach map reduce
防抖和節(jié)流
函數(shù)節(jié)流:首先執(zhí)行一次,然后在間隔時(shí)間再執(zhí)行
在函數(shù)需要頻繁觸發(fā)的時(shí)候,函數(shù)執(zhí)行一次后,只有大于設(shè)定的執(zhí)行周期后才會(huì)執(zhí)行下一次,適合多次事件按照時(shí)間分配來(lái)觸發(fā)
應(yīng)用的場(chǎng)景:
窗口的調(diào)用,頁(yè)面的滾動(dòng),DOM的元素的拖拽(mounsemove),瘋狂的搶購(gòu)(mounsedown)
function throttle(callback, time) {
let start = 0 // 保證第一次事件必然是調(diào)用的
return function (...args) {
console.log('throttle事件觸發(fā)')
const current = Date.now() // 當(dāng)前時(shí)間
// 判斷條件是否滿足
if (current - start > time) {
start = current
callback.apply(this, args)
}
}
}
函數(shù)防抖:無(wú)論多少次的調(diào)用,只是最后一次執(zhí)行
在函數(shù)需要頻繁觸發(fā)的時(shí)候,在規(guī)定的時(shí)間內(nèi),只能讓最后一次是生效的,之前都不觸發(fā)
應(yīng)用的場(chǎng)景:
實(shí)時(shí)的搜索聯(lián)想:keyup
文本框輸入驗(yàn)證(輸入內(nèi)容,需要發(fā)送ajax請(qǐng)求)
function debounce(callback, time) {
return function (...args) {
console.log('debounce事件觸發(fā)')
// 清理定時(shí)器的操作
if (callback.timeId) {
clearTimeout(callback.timeId)
}
callback.timeId = setTimeout(() => {
// 刪除保存的定時(shí)器id
delete callback.timeId
callback.apply(this, args)
}, time);
}
}
無(wú)論是節(jié)流還是防抖,最后都會(huì)返回一個(gè)回調(diào)