這里給大家分享我在網上總結出來的一些知識,希望對大家有所幫助

一.typescript 高階型別 Exclude 和 Extract
Exclude<T, U>
TypeScript 2.8 中增加了 Exclude 型別,該如何理解這個高級型別的定義呢?
type Exclude<T, U> = T extends U ? never : T;
從 Exclude 的定義來看,就是判斷 T 是否繼承于 U,如果是,則回傳 never,否則回傳 T,
1. T, U 之間的關系,是否是基于結構相似呢?
interface IPerson {
name: string,
age: number,
sex: 0 | 1,
}
interface IMan {
name: string,
age: number,
}
type Man = Exclude<IPerson, IMan> // 等效于 type Man = never
結論:只需要兩者型別能夠保持一致,同時 T 的型別能夠兼容 U 的型別即可,
2. 對于聯合型別,是如何進行類比的?
type Fruits = "apple" | "banana" | 'peach' | 'orange';
type DislikeFruits = "apple" | "banana";
type FloveFruits = Exclude<Fruits, DislikeFruits> // 等效于 type FloveFruits = "peach" | "orange"
// 實際上 Exclude 進行的比較
type FloveFruits =
| ("apple" extends "apple" | "banana" ? never : "apple")
| ("banana" extends "apple" | "banana" ? never : "banana")
| ("peach" extends "apple" | "banana" ? never : "peach")
| ("orange" extends "apple" | "banana" ? never : "orange")
// 所以最后的結果
type FloveFruits = "peach" | "orange"
當入參是聯合型別時,它會以分布式的形式去進行比較,
Extract<T, U>
Extract 的功能,與 Exclude 相反,它是 提取 T 中可以賦值給 U 的型別,
type Extract<T, U> = T extends U ? T : never
1. T, U 之間的關系,是否是基于結構相似呢?
interface IPerson {
name: string,
age: number,
sex: 0 | 1,
}
interface IMan {
name: string,
age: number,
}
type Man = Extract<IPerson, IMan> // 等效于 type Man = IPerson
與 Exclude 相同,均是保持相同的結構即可,只不過他們的取值邏輯相反,
2. 對于聯合型別,是如何進行類比的?
type Fruits = "apple" | "banana" | 'peach' | 'orange'; type DislikeFruits = "apple" | "banana"; type FloveFruits = Extract<Fruits, DislikeFruits> // 等效于 type FloveFruits = "apple" | "banana"
原理與 Exclude 類似,僅僅是取值的邏輯不同而已,
二.vue事件方法之$off方法的實作原理
vue中事件方法一共就四個,掛載在vue實體上的$off移除事件中心里面某個事件的回呼函式,通常會用到,那么$off的內部實作原理是什么呢?下面我們來詳細說下$off:
vm.$off( [event, callback] )
引數:
{string | Array<string>} event (只在 2.2.2+ 支持陣列)
{Function} [callback]
作用:
移除自定義事件監聽器,
如果沒有提供引數,則移除所有的事件監聽器;
如果只提供了事件,則移除該事件所有的監聽器;
如果同時提供了事件與回呼,則只移除這個回呼的監聽器,
原理:
該方法用來移除事件中心里面某個事件的回呼函式,根據所傳入引數的不同,作出不同的處理,
Vue.prototype.$off = function (event, fn) {
const vm: Component = this
// all
if (!arguments.length) {
vm._events = Object.create(null)
return vm
}
// array of events
if (Array.isArray(event)) {
for (let i = 0, l = event.length; i < l; i++) {
this.$off(event[i], fn)
}
return vm
}
// specific event
const cbs = vm._events[event]
if (!cbs) {
return vm
}
if (!fn) {
vm._events[event] = null
return vm
}
if (fn) {
// specific handler
let cb
let i = cbs.length
while (i--) {
cb = cbs[i]
if (cb === fn || cb.fn === fn) {
cbs.splice(i, 1)
break
}
}
}
return vm
}
該方法內部就是通過不斷判斷所傳引數的情況進而進行不同的邏輯處理,
首先,判斷如果沒有傳入任何引數(即arguments.length為0),這就是第一種情況:如果沒有提供引數,則移除所有的事件監聽器,我們知道,當前實體上的所有事件都存盤在事件中心_events屬性中,要想移除所有的事件,那么只需把_events屬性重新置為空物件即可,
接著,判斷如果傳入的需要移除的事件名是一個陣列,就表示需要一次性移除多個事件,那么我們只需同訂閱多個事件一樣,遍歷該陣列,然后將陣列中的每一個事件都遞回呼叫$off方法進行移除即可,
接著,獲取到需要移除的事件名在事件中心中對應的回呼函式cbs,
接著,判斷如果cbs不存在,那表明在事件中心從來沒有訂閱過該事件,那就談不上移除該事件,直接回傳,退出程式即可,
接著,如果cbs存在,但是沒有傳入回呼函式fn,這就是第二種情況:如果只提供了事件,則移除該事件所有的監聽器,這個也不難,我們知道,在事件中心里面,一個事件名對應的回呼函式是一個陣列,要想移除所有的回呼函式我們只需把它對應的陣列設定為null即可,
接著,如果既傳入了事件名,又傳入了回呼函式,cbs也存在,那這就是第三種情況:如果同時提供了事件與回呼,則只移除這個回呼的監聽器,那么我們只需遍歷所有回呼函式陣列cbs,如果cbs中某一項與fn相同,或者某一項的fn屬性與fn相同,那么就將其從陣列中洗掉即可,
就這么簡單,
本文轉載于:
https://blog.csdn.net/leelxp/article/details/107212699
如果對您有所幫助,歡迎您點個關注,我會定時更新技術檔案,大家一起討論學習,一起進步,

轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/509705.html
標籤:其他
