使用lodash防抖_什么,lodash 的防抖失效了?

d35ab7b06ec1648860f47ab3e403aa78.gif? ?戳藍字「前端技術優選」關注我們哦!

作者:yeyan1996

https://juejin.im/post/6892577964458770445

應某人的要求被迫營業,望各位看官不要吝嗇手中的贊-。-

背景

在使用 uni-app 開發小程序時,有個填寫表單的需求,包含兩個輸入框,看起來像這樣

855327c6d09a1fbb079e4495f0279281.png
image-20201107143814796

兩個在普通不過的輸入框

因為需要復用一些樣式和邏輯,所以將輸入框抽象成了組件,代碼簡化后如下




子組件代碼






由于在父組件中需要依賴輸入的值請求接口,為避免接口頻繁調用,這邊引入 lodash?debounce?用于防抖

這個需求在 yeyan1996 眼中沒有任何難度,但在幾天后卻收到了部分用戶反饋,說在兩個輸入框分別填寫了值,但最終只有一個輸入框有效

這時才回頭想起代碼中的 debounce ....

問題原因

收到用戶反饋后,yeyan1996 嘗試多次點擊輸入框,發現問題并不是必現,最終總結出了規律

填寫第一個輸入框后,快速對第二個輸入框進行輸入,才會造成最終的表單數據中只有一個值的問題

通過下圖子組件的 log 可以看到,雖然 ui 界面顯示兩個輸入框都有值,但實際只觸發了第二個輸入框的 log

c983b604252e091198af08422cb75fa6.gif
Kapture 2020-11-07 at 14.58.57

之所以 ui 界面顯示兩個輸入框都有值,是因為是用戶直接和 textarea 控件交互,實際并沒有更新控件綁定的 value 值

最終結論:第一個輸入框中被 debounce 包裹的函數并沒有執行

是防抖問題么?

嘗試將 debounce 去掉后,果然 bug 解決了

99836957fa7ec10ab6ded97c2ce60116.gif
Kapture 2020-11-07 at 15.06.41

那么,是防抖的問題么?

不妨先思考下 Vue 組件的實現原理,我在?[Vue.js進階]從源碼角度剖析Vue的生命周期?中提到過,每個 .vue 文件可以理解為一個構造函數,或者一個 Class,而在父組件中引用組件就等于對其的實例化

  

上述代碼即創建了 2 個 CustomTextarea 組件的實例

熟悉面向對象的同學應該知道,構造函數實例化時,同時會創建實例的屬性和方法,一般每個實例的屬性都不相同,而方法因為是函數,所以會復用,已達到節省內存的效果

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 ?的組件借鑒了面向對象的原理,雖然內部的實現方式不同,但最終的行為一致,即組件的每個實例都擁有不同的 data,但會復用相同的 methods

源碼地址:https://github.com/vuejs/vue/blob/dev/src/core/instance/state.js#L286

0468621571a122f5b0a3c8e78b927288.png
image-20201107155528333

286 行中 methods 對象是每個組件實例共用的,每實例化一個組件,會創建相同的引用,指向 methods 中的函數

6725f0954d6040d29fece4ecb112c07f.png
未命名

上圖案例中, 所有 custom-textarea 中的 handleInput 都指向同一個函數,而作為 props 的 value 字段是通過父組件傳入的,并不會共享(分別為 text1/text2)

解決方案

經過上述的分析,答案顯而易見,兩個組件實例都指向了同一個被 debounce 包裹的 handleInput 函數

所以在輸入第一個值后, 1000 毫秒內快速切換到第二個輸入框進行輸入,此時由于防抖效果仍存在,導致第一次的輸入并沒有計算在內

而第二次輸入完畢后,經過 1000 毫秒,最終只會執行第二個 custom-textarea 的 handleInput

只要使得每個組件實例的 handleInput 互相獨立,即可解決問題






將 handleInput 從 methods 放到 data 中,每次初始化時創建防抖函數,此時每個組件實例的 handleInput 就不會互相干擾

fdb5a4a3928c2825d2dc574d96aeaa7c.gif
Kapture 2020-11-07 at 16.44.41

大功告成???

題外話

Vue 組件中通過將 data 定義為一個函數,函數的返回值作為組件的數據來源,使得每個組件實例的數據都不相同

而 Vue 組件中 methods 是所有實例共用的,那么對于 watch/computed/生命周期,它們是否會共用的呢?




和 methods 對象相同,computed 對象的屬性名是一個響應式變量,而值是一個函數,所以所有實例也會指向同一個函數,但由于這個函數需要有返回值,所以不會用防抖函數進行包裹,很少遇到函數公用導致的問題

而 watch 也和 methods 對象相同,所有組件實例共用,所以也會存在防抖的問題

至于生命周期本身就是一個函數,如果對生命周期設置了防抖,多個組件實例同時初始化時也會造成只執行一次的情況

參考資料

[Vue.js進階]從源碼角度剖析Vue的生命周期

【Vue原理】Methods - 源碼版](https://segmentfault.com/a/1190000019605909)

a8e91c1a28d4f5a1192fe83fa2526be5.gif

1b8bc32c237f7ebde3bc693feb825fac.pngafcfcf63af2a65377fa70e382eb75c50.png在看點這里8fb8e76c89a4b3a2e2a50bda355ff669.gif

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/279264.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/279264.shtml
英文地址,請注明出處:http://en.pswp.cn/news/279264.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Ubuntu 12.10中的8個新功能,Quantal Quetzal

Ubuntu 12.10 has been released and you can download it now. From better integration with web apps and online services to improvements in Unity, there are quite a few changes – although none of them are huge or groundbreaking. Ubuntu 12.10已發布&#xff0c…

背單詞APP調研分析

前言:隨著我國網絡經濟重心向移動端的轉移,移動教育領域獲得的關注度在持續放大。互聯網的發展和移動設備的普及,我們開始在移動設備上學習,各種學習教育軟件如雨后春筍,越來越多,就背單詞軟件來說&#xf…

linux 提取cpio_Linux提取RPM包文件(cpio命令)詳解

在講解如何從 RPM 包中提取文件之前,先來系統學習一下 cpio 命令。cpio 命令用于從歸檔包中存入和讀取文件,換句話說,cpio 命令可以從歸檔包中提取文件(或目錄),也可以將文件(或目錄)復制到歸檔包中。歸檔包,也可稱為文…

cdh中使用hue使用教程_我可以在戶外使用Philips Hue燈泡嗎?

cdh中使用hue使用教程Philips Hue lights are great to have in your house, and they can add a lot of convenience to your living space. However, what if you want to use these smart bulbs outdoors in porch lights or flood lights? Will Philips Hue bulbs work pr…

django (三) admin后臺系統

admin后臺系統 1. 安裝MySQL 1,安裝mysql: sudo apt install mysql-server (安裝過程中輸入密碼并牢記) 2,安裝后進入mysql: mysql -u用戶名 -p密碼 mysql -uroot -proot ? 3,在Django中配置和使用mysql數據庫 使用mysql數據庫,settings中配置如下: DAT…

python博客訪問量_史詩級干貨-python爬蟲之增加CSDN訪問量

AI人工智能史詩級干貨-python爬蟲之增加CSDN訪問量史詩級干貨-python爬蟲之增加CSDN訪問量搜索微信公眾號:‘AI-ming3526’或者’計算機視覺這件小事’ 獲取更多算法、機器學習干貨csdn:https://blog.csdn.net/baidu_31657889/github:https://github.com…

弄斷過河電纜_你說的是:剪斷電纜線

弄斷過河電纜Earlier this week we asked you if you’d cut the cable and switched to alternate media sources to get your movie and TV fix. You responded and we’re back with a What You Said roundup. 本周早些時候,我們問您是否要切斷電纜并切換到其他媒…

復制粘貼的句子

Today you do things people will not do,tomorrow you will do things people can not do. 你今天做別人不愿做的事,明天就能做別人做不到的事。轉載于:https://www.cnblogs.com/wensens/p/9723998.html

路由銷毀上一頁_路由器原理(數據通信)

路由:對數據包選擇路徑的過程路由器(也叫網關)智能選擇數據傳輸路由的設備,其端口數量較少!功能:連接網絡1.連接異構網絡以太網、ATM網絡、FDDI網絡2.連接遠程網絡局域網、廣域網隔離廣播將廣播隔離在局域網內路由選擇網絡安全地址…

您可能沒有使用的最佳三星Galaxy功能

Samsung packs its flagship phones with a slew of features—some are even better than stock Android. Either way, there are a lot of things on these phones that you may not be using. Here are some of the best. 包三星旗艦手機用的特性-擺有的甚至比普通的Android…

win7更新錯誤0x800b0109_win7更新漏洞后產生0x0000006B藍屏的解決方法圖解

這幾天不少網友在使用win7更新補丁后就藍屏了,代碼為0x0000006b。發生這一藍屏問題的都是安裝了2016年四月份推出的安全更新補丁,安裝后就出現藍屏,有的網友表示沒問題,有的直接藍了。這個藍屏重啟后依舊,安全模式進不…

獲取構造器的信息

獲取類構造器的用法與上述獲取方法的用法類似,如: import java.lang.reflect.*;public class constructor1 {public constructor1() {}protected constructor1(int i, double d) { } public static void main(String args[]) { try { Class cls Class.f…

如何使用facebook_如果每個人都已經開始使用Facebook,Facebook能否繼續發展?

如何使用facebookThere are only so many people on earth, and so many hours in the day. Is that starting to limit the growth of social media? 地球上只有那么多人,一天中有很多小時。 這是否開始限制社交媒體的增長? Think about how much time…

2018-10-03-Python全棧開發-day60-django序列化-part3

聯合唯一 clean_字段方法只能對某個字段進行檢查,當clean方法執行完之后,最后還會執行clean方法,在clean方法中,可以通過獲取數據字典中的值然后進行驗證 from django.shortcuts import render,HttpResponsefrom django import fo…

mysql時間字段條件查詢_mysql 查詢 時間作為查詢條件

今天select * from 表名 where to_days(時間字段名) to_days(now());昨天SELECT * FROM 表名 WHERE TO_DAYS( NOW( ) ) - TO_DAYS( 時間字段名) < 1近7天SELECT * FROM 表名 where DATE_SUB(CURDATE(), INTERVAL 7 DAY) < date(時間字段名)近30天SELECT * FROM 表名 whe…

mac按文件名查找文件_如何在Mac上查找和刪除大文件

mac按文件名查找文件Freeing up disk space on a full hard drive can be difficult, especially when it’s full of small files. However, there are some excellent tools for macOS that let you find the files taking up the most space and delete the ones you don’t…

Swift5.1 語言參考(十) 語法匯總

★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★?微信公眾號&#xff1a;山青詠芝&#xff08;shanqingyongzhi&#xff09;?博客園地址&#xff1a;山青詠芝&#xff08;https://www.cnblogs.com/strengthen/&#xff09;?GitHub地址&a…

timestamp mysql php_PHP和Mysql的Timestamp互換

在mysql中有三種時間字段類型&#xff1a;DATETIME&#xff0c;DATE和TIMESTAMP。DATETIME以YYYY-MM-DD HH:MM:SS格式的字符串來保存數據&#xff1b;DATE則是只有年月日以YYYY-MM-DD形式的字串&#xff1b;TIMESTAMP類型和PHP中的TIMESTAMP類型名字一樣&#xff0c;但是兩者基…

dmg是什么文件格式_什么是DMG文件(以及我該如何使用)?

dmg是什么文件格式DMG files are containers for apps in macOS. You open them, drag the app to your Applications folder, and then eject them, saving you the hassle of the dreaded “Install Wizard” of most Windows apps. So if all they are is a folder for an a…

mysql索引三個字段查詢兩個字段_mysql中關于關聯索引的問題——對a,b,c三個字段建立聯合索引,那么查詢時使用其中的2個作為查詢條件,是否還會走索引?...

情況描述&#xff1a;在MySQL的user表中&#xff0c;對a,b,c三個字段建立聯合索引&#xff0c;那么查詢時使用其中的2個作為查詢條件&#xff0c;是否還會走索引&#xff1f;根據查詢字段的位置不同來決定&#xff0c;如查詢a, a,b a,b,c a,c 都可以走索引的&#…