使用lodash防抖_什么,lodash 的防抖失效了?
? ?戳藍(lán)字「前端技術(shù)優(yōu)選」關(guān)注我們哦!
作者:yeyan1996
https://juejin.im/post/6892577964458770445
應(yīng)某人的要求被迫營(yíng)業(yè),望各位看官不要吝嗇手中的贊-。-
背景
在使用 uni-app 開(kāi)發(fā)小程序時(shí),有個(gè)填寫(xiě)表單的需求,包含兩個(gè)輸入框,看起來(lái)像這樣
image-20201107143814796兩個(gè)在普通不過(guò)的輸入框
因?yàn)樾枰獜?fù)用一些樣式和邏輯,所以將輸入框抽象成了組件,代碼簡(jiǎn)化后如下
子組件代碼
由于在父組件中需要依賴(lài)輸入的值請(qǐng)求接口,為避免接口頻繁調(diào)用,這邊引入 lodash?debounce?用于防抖
這個(gè)需求在 yeyan1996 眼中沒(méi)有任何難度,但在幾天后卻收到了部分用戶(hù)反饋,說(shuō)在兩個(gè)輸入框分別填寫(xiě)了值,但最終只有一個(gè)輸入框有效
這時(shí)才回頭想起代碼中的 debounce ....
問(wèn)題原因
收到用戶(hù)反饋后,yeyan1996 嘗試多次點(diǎn)擊輸入框,發(fā)現(xiàn)問(wèn)題并不是必現(xiàn),最終總結(jié)出了規(guī)律
填寫(xiě)第一個(gè)輸入框后,快速對(duì)第二個(gè)輸入框進(jìn)行輸入,才會(huì)造成最終的表單數(shù)據(jù)中只有一個(gè)值的問(wèn)題
通過(guò)下圖子組件的 log 可以看到,雖然 ui 界面顯示兩個(gè)輸入框都有值,但實(shí)際只觸發(fā)了第二個(gè)輸入框的 log
Kapture 2020-11-07 at 14.58.57之所以 ui 界面顯示兩個(gè)輸入框都有值,是因?yàn)槭怯脩?hù)直接和 textarea 控件交互,實(shí)際并沒(méi)有更新控件綁定的 value 值
最終結(jié)論:第一個(gè)輸入框中被 debounce 包裹的函數(shù)并沒(méi)有執(zhí)行
是防抖問(wèn)題么?
嘗試將 debounce 去掉后,果然 bug 解決了
Kapture 2020-11-07 at 15.06.41那么,是防抖的問(wèn)題么?
不妨先思考下 Vue 組件的實(shí)現(xiàn)原理,我在?[Vue.js進(jìn)階]從源碼角度剖析Vue的生命周期?中提到過(guò),每個(gè) .vue 文件可以理解為一個(gè)構(gòu)造函數(shù),或者一個(gè) Class,而在父組件中引用組件就等于對(duì)其的實(shí)例化
上述代碼即創(chuàng)建了 2 個(gè) CustomTextarea 組件的實(shí)例
熟悉面向?qū)ο蟮耐瑢W(xué)應(yīng)該知道,構(gòu)造函數(shù)實(shí)例化時(shí),同時(shí)會(huì)創(chuàng)建實(shí)例的屬性和方法,一般每個(gè)實(shí)例的屬性都不相同,而方法因?yàn)槭呛瘮?shù),所以會(huì)復(fù)用,已達(dá)到節(jié)省內(nèi)存的效果
class?Person?{??constructor(name)?{
????this.name?=?name
??}
??eat()?{}
}
const?person1?=?new?Person('張三')
const?person2?=?new?Person('李四')
console.log(person1.name?===?person2.name)?//?false
console.log(person1.eat?===?person2.eat)?//?true
Vue2 ?的組件借鑒了面向?qū)ο蟮脑?#xff0c;雖然內(nèi)部的實(shí)現(xiàn)方式不同,但最終的行為一致,即組件的每個(gè)實(shí)例都擁有不同的 data,但會(huì)復(fù)用相同的 methods
源碼地址:https://github.com/vuejs/vue/blob/dev/src/core/instance/state.js#L286
image-20201107155528333286 行中 methods 對(duì)象是每個(gè)組件實(shí)例共用的,每實(shí)例化一個(gè)組件,會(huì)創(chuàng)建相同的引用,指向 methods 中的函數(shù)
未命名上圖案例中, 所有 custom-textarea 中的 handleInput 都指向同一個(gè)函數(shù),而作為 props 的 value 字段是通過(guò)父組件傳入的,并不會(huì)共享(分別為 text1/text2)
解決方案
經(jīng)過(guò)上述的分析,答案顯而易見(jiàn),兩個(gè)組件實(shí)例都指向了同一個(gè)被 debounce 包裹的 handleInput 函數(shù)
所以在輸入第一個(gè)值后, 1000 毫秒內(nèi)快速切換到第二個(gè)輸入框進(jìn)行輸入,此時(shí)由于防抖效果仍存在,導(dǎo)致第一次的輸入并沒(méi)有計(jì)算在內(nèi)
而第二次輸入完畢后,經(jīng)過(guò) 1000 毫秒,最終只會(huì)執(zhí)行第二個(gè) custom-textarea 的 handleInput
只要使得每個(gè)組件實(shí)例的 handleInput 互相獨(dú)立,即可解決問(wèn)題
將 handleInput 從 methods 放到 data 中,每次初始化時(shí)創(chuàng)建防抖函數(shù),此時(shí)每個(gè)組件實(shí)例的 handleInput 就不會(huì)互相干擾
Kapture 2020-11-07 at 16.44.41大功告成???
題外話(huà)
Vue 組件中通過(guò)將 data 定義為一個(gè)函數(shù),函數(shù)的返回值作為組件的數(shù)據(jù)來(lái)源,使得每個(gè)組件實(shí)例的數(shù)據(jù)都不相同
而 Vue 組件中 methods 是所有實(shí)例共用的,那么對(duì)于 watch/computed/生命周期,它們是否會(huì)共用的呢?
和 methods 對(duì)象相同,computed 對(duì)象的屬性名是一個(gè)響應(yīng)式變量,而值是一個(gè)函數(shù),所以所有實(shí)例也會(huì)指向同一個(gè)函數(shù),但由于這個(gè)函數(shù)需要有返回值,所以不會(huì)用防抖函數(shù)進(jìn)行包裹,很少遇到函數(shù)公用導(dǎo)致的問(wèn)題
而 watch 也和 methods 對(duì)象相同,所有組件實(shí)例共用,所以也會(huì)存在防抖的問(wèn)題
至于生命周期本身就是一個(gè)函數(shù),如果對(duì)生命周期設(shè)置了防抖,多個(gè)組件實(shí)例同時(shí)初始化時(shí)也會(huì)造成只執(zhí)行一次的情況
參考資料
[Vue.js進(jìn)階]從源碼角度剖析Vue的生命周期
【Vue原理】Methods - 源碼版](https://segmentfault.com/a/1190000019605909)
在看點(diǎn)這里總結(jié)
以上是生活随笔為你收集整理的使用lodash防抖_什么,lodash 的防抖失效了?的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 绘制三维散点图_SPSS统计作图教程:三
- 下一篇: 路由销毁上一页_路由器原理(数据通信)