vue3 避坑指南:解決 dev 和 prod 壞境下邏輯不一致問題

背景

最近在開發 element3 的時候,遇到了一個問題,打包後的代碼會報錯,和在 dev 壞境下的代碼行爲不一致。前端

調研後發現這個問題可能小夥伴們都會遇到 !! 因此趕忙寫了篇文章記錄下來,讓你們少掉一點頭髮vue

發現問題

element3 社區羣有小夥伴反饋了一個問題:git

組件 Tab 在 dev 壞境下邏輯一切正常,可是在 prod 壞境下就報錯了github

潛意識裏面發現這個問題沒那麼簡單,由於以前也有小夥伴說在 prod 壞境下某些組件報錯api

定位問題

趕忙要到 demo,先跑了 dev 環境。嗯,沒啥問題markdown

而後又跑了 prod 壞境。 嗯,果真出現問題了數據結構

ok, 出現問題就好辦了,接着查看了一下報錯信息ide

發如今 prod 壞境下 ctx 這個對象的數據結構發生改變了oop

這是在 dev 壞境下:spa

這是在 prod 壞境下:

好,問題咱們已經定位好了,其實問題就已經解決了一半了

那咱們剩下的其實只須要弄明白兩個點

  • 咱們怎麼能繞過這個問題
  • vue3 源碼裏面是如何處理這個 ctx 的

解決問題

咱們先來看看如何繞過這個問題

先找到問題代碼,在 element3/Tabs.vue 這個組件內

這裏的邏輯就是經過 provide 給全部子組件提供當前組件的實例對象

可是問題就發生在這裏,咱們經過上面的案例已經知道,組件實例對象在 dev 和 prod 壞境下 ctx 對象的數據結構是不一致的。

而後看一下在哪裏使用的,找到 element3/TabPane.vue 這個組件內

這個代碼寫的真的是醜呀,這也正是我要重寫全部組件的緣由所在!

那咱們怎麼繞過這個問題呢? 咱們已知組件實例對象的 ctx 是會變的,那麼咱們能不能在 Tab 組件中只提供 TabPane 中用到的數據呢?咱們只要不用到 ctx 是否是就 ok 了

來 咱們先來試一試

稍微統計了一下會涉及到如下幾個數據

  • tabList
  • props.modelValue
  • state.activeName
  • state.activeIndex

那咱們回到 Tab 組件中只提供 TabPane 用到的數據吧

回來 TabPane 改下使用方式

這樣咱們就繞過了 ctx 的使用

好,問題修完了 咱們打個包 驗證一下 有沒有問題吧

打包成功,接着把生成的文件放到報錯的 demo 裏面執行一下

先驗證 dev 壞境

控制檯安安靜靜 ,不錯不錯

在看看 prod 壞境

歐耶,完美解決

深刻問題

好 問題雖然解決了,可是還不能停,咱們還要深刻探索一下 vue3 的源碼,搞懂兩個問題

  • 源碼是怎麼基於環境處理的 ctx
  • 爲何它要這麼處理 ctx

源碼是怎麼基於環境處理的 ctx

要想知道這個問題,其實只要找到生成 ctx 的代碼邏輯就能夠了

很簡單的邏輯,就是判斷是否爲 dev 壞境,而後作邏輯處理

爲何它要這麼處理 ctx

基於源碼裏面的註釋咱們也已經瞭解到了

這個 ctx 就是爲了便於在開發模式下經過控制檯檢查

而到了 prod 模式下,它就會變成一個空對象了

而在 vue 中定義 ctx 的註釋中瞭解到,這個是公共實例的代理 target,而且還包含了一些經過 options 注入的屬性以及用戶自定義的屬性

那咱們就驗證一下用 options api 寫的時候它是什麼樣子的

dev 環境下的輸出結果

prod 壞境下的輸出結果

果真 vue 把咱們在 methods 中聲明好的方法掛載到了 ctx 上,因此咱們訪問起來仍是沒有問題的

可是沒有看到 count,盲猜的話應該是在對應的 proxy handler 內處理的

其實到這裏我又產生了一個問題,就是 vue 裏面是怎麼處理的這個邏輯。

這個問題就留着下回在講吧~ 怕大家太長不看

so,咱們如今就已經得出了一個結論:

在之後的開發中千萬不要在 setup 中調用 getCurrentInstance().ctx 來獲取組件內部數據

總結

最後來總結一下,咱們從問題出發,發現問題,定位問題,解決問題,最後深刻問題。

而且最終獲得告終論:在 setup 中不能夠調用 getCurrentInstance().ctx 來獲取組件內部數據,由於在 prod 會被幹掉

你學到了嗎?

若是這篇文章你有所獲的話,請幫我點個贊


相關文章
相關標籤/搜索