模擬面試、簡歷指導、入職指導、計畫指導、答疑解惑 可私信找我~已幫助100+名同學完成改造!
前言
大家好,我是林三心,用最通俗易懂的話講最難的知識點是我的座右銘,基礎是進階的前提是我的初心~
背景
這幾天看到好多文章標題都是類似於:
不用 ref 的 xx 個理由
不用 reactive 的 xx 個理由
歷數 ref 的 xx 宗罪
我就很不解,到底是什麽原因導致有這兩批人:
抵觸 ref 的人
抵觸 reactive 的人
看了這些文章,我可以總結出他們的想法
抵觸 reactive 的人
抵觸 reactive 的人,他們的想法大概就是:
1、 Vue 官方推薦 ref
2、 reactive 有型別限制,ref 沒有
3、 reactive 使用不當會遺失響應式,比如解構
4、 reactive 無法修改整個物件的值
抵觸 ref 的人
抵觸 ref 的人,他們的想法大概就是:
1、 ref 的底層其實就是 reactive,用 ref 相當於多了一層,耗費效能
2、 ref 的 .value 用起來很麻煩,增加使用者心裏負擔
3、 ref 到樣版的時候會解掉 value 這一層,這時候也會耗費效能
把我整笑了~
說實話,看到這些文章,有點把我整笑了,其實你要用 ref 或者 reactive 都沒錯,但是沒比必要那麽抵觸,編程很多時候並不是非黑即白啊。。。
既然 Vue3 推出了 ref 和 reactive,那就說明他們都有存在的必要,在計畫中不同的場景去運用他們,我覺得才是最好的,而不是用一個不用另一個,不止這兩個,還有很多其他好用的 Vue3 API
我想針對這兩批人的想法做一個回應:
回應 -> 抵觸 reactive 的人
1、官方是推薦,不是抵觸
2、reactive 既然有型別限制,那就在特定時候用 reactive 就行
3、使用不當會遺失響應式?那就是開發者對於 Vue3 API 的使用還不熟
4、用 Object.assign 就可以修改整個物件的值
回應 -> 抵觸 ref 的人
1、耗費效能的話,這麽久了,也沒人貼出到底耗費了多少效能?
2、.value 不麻煩,我覺得 .value 可以起到辨別響應式和非響應式數據的效果,而且現在編輯器都有外掛程式提供的程式碼補全了,多個 .value 也花不了多少時間吧?
靈活使用 Vue3 API 才是王道
其實在平時開發中,我覺得基本數據型別和陣列,都可以用 ref 來管理,而物件的話可以使用 reactive 來管理,比如表單物件、狀態物件
其實 Vue3 不止有這兩個 API ,還有很多其他 API ,也很好用,大家只要去靈活使用它們,能讓你的Vue3 計畫上一個層次
readonly
顧名思義,就是唯讀的意思,如果你的數據被這個 API 包裹住的話,那麽修改之後並不會觸發響應式,並且會提示警告
readonly 的用途一般用於一些 hooks 暴露出來的變量,不想外界去修改,比如我封裝一個 hooks,這樣去做的話,那麽外界只能用變量,但是不能修改變量,這樣大大保護了 hooks 內部的邏輯~
shallowRef
shallowRef 用來包住一個基礎型別或者參照型別,如果是基礎型別那麽跟 ref 基本沒區別,如果是參照型別的話,那麽直接改深層內容是不能觸發響應式的,除非直接修改參照地址,如下:
註意:改深層屬效能改數據,只是沒觸發響應式,所以當下一次響應式觸發的時候,你修改的深層數據會渲染到頁面上~
shallowRef 的用處主要用於一些比較大的但又變化不大的數據,比如我有一個表格數據,透過介面直接獲取,並且主要用在前端展示,需要修改一些深層的內容,但是這些內容並不需要立即表現在頁面上,比如以下例子,我只需要展示 name、age 欄位,至於 isOld 欄位並不需要展示,我想要計算 isOld 但是又不想觸發響應式更新,所以可以用 shallowRef 包起來,進而減少響應式更新,最佳化效能
shallowReactive
shallowReactive 用來包住一個參照型別,被包住後,修改第一層才會觸發響應式更新,也就是淺層的內容,修改深層的內容並不會觸發響應式更新
註意:改深層屬效能改數據,只是沒觸發響應式,所以當下一次響應式觸發的時候,你修改的深層數據會渲染到頁面上~
shallowReactive 用的比較少,shallowReactive 的用處跟 shallowRef 比較像,都是為了讓一些比較大的數據能減少響應式更新,進而最佳化效能
toRef & toRefs
先說說 toRef 吧,我們平時在使用 reactive 的時候會有一個苦惱,那就是解構,比如看以下例子,我們為了少些一些程式碼,解構出來了 name 並放到樣版裏渲染,但是當我們想改原數據的時候,發現 name 並不會更新,這就是解構出來基礎型別的苦惱
這時我們可以使用 toRef,這個時候我們直接修改 name 也會觸發原數據的修改,修改原數據也會觸發 name 的修改
但是如果是內容太多了,我們想一個一個去用 toRef 的話會寫很多程式碼
所以我們可以使用 toRefs 一次性解構
toRaw & markRaw & unref
toRaw 可以把一個響應式 reactive 轉成普通物件,也就是把響應式物件轉成非響應式物件
toRaw 主要用在回呼傳參中,比如我封裝一個 hooks,我想要把 hooks 內維護的響應式變量轉成普通數據,當做參數傳給回呼函式,可以用 toRaw
markRaw 可以用來標記響應式物件裏的某個內容不被追蹤,如果你的響應式物件裏有某個內容數據量比較大,但又不想被追蹤,你可以使用 markRaw
unref 相當於返回 ref 的 value
effectScope & onScopeDispose
effectScope 可以有兩個作用:
收集副作用
全域狀態管理
收集副作用
比如我們封裝一個共用的 hooks,為了減少頁面隱患,肯定會統一收集副作用,並且在元件銷毀的時候去統一消除,比如以下程式碼:
但是這麽收集很麻煩, effectScope 能幫我們做到統一收集,並且透過 stop 方法來進行清除,且 stop 執行的時候會觸發 effectScope 內部的 onScopeDispose
我們可以利用 effectScope & onScopeDispose 來做一些效能最佳化,比如下面這個例子,我們封裝一個滑鼠監聽的 hooks
但是如果在頁面裏呼叫多次的話,那麽勢必會往 window 身上監聽很多多余的事件,造成效能負擔,所以解決方案就是,無論頁面裏呼叫再多次 useMouse,我們只往 window 身上加一個滑鼠監聽事件
全域狀態管理
現在 Vue3 最火的全域狀態管理工具肯定是 Pinia 了,那麽你們知道 Pinia 的原理是什麽嗎?原理就是依賴了 effectScope
所以我們完全可以自己使用 effectScope 來實作自己的局部狀態管理,比如我們封裝一個通用元件,這個元件層級比較多,並且需要共享一些數據,那麽這個時候肯定不會用 Pinia 這種全域狀態管理,而是會自己寫一個局部的狀態管理,這個時候 effectScope 就可以排上用場了
vueuse 中的 createGlobalState 就是為了這個而生
provide & inject
Vue3 用來提供註入的 API,主要是用在元件的封裝,比如那種層級較多的元件,且子元件需要依賴父元件甚至爺爺元件的數據,那麽可以使用 provide & inject,最典型的例子就是 Form 表單元件,可以去看看各個元件庫的源碼,表單元件大部份都是用 provide & inject 來實作的,比如 Form、Form-Item、Input這三個需要互相依賴對方的規則、欄位名、欄位值,所以用 provide & inject 會更好。具體用法看文件吧~https://cn.vuejs.org/guide/components/provide-inject.html
結語
我是林三心
一個待過 小型toG型外包公司、大型外包公司、小公司、潛力型創業公司、大公司 的作死型前端選手;
一個偏前端的全幹工程師;
一個不正經的金塊作者;
逗比的B站up主;
不帥的小紅書博主;
喜歡打鐵的籃球菜鳥;
喜歡歷史的乏味少年;
喜歡rap的五音不全弱雞如果你想一起學習前端,一起摸魚,一起研究簡歷最佳化,一起研究面試進步,一起交流歷史音樂籃球rap,可以來俺的摸魚學習群哈哈,點這個,有7000多名前端小夥伴在等著一起學習哦 -->
廣州的兄弟可以約飯哦,或者約球~我負責打鐵,你負責進球,謝謝~