解決 vue-element-admin 中 側邊欄 Sidebar 的詭異錯位 BUG 但不報錯的事件


程序報錯不可怕,可怕的是出錯了不報錯,令人絕望。

今天一天思考和修復這個問題,比較尷尬的是,解決了后仍然不知道發生了什么,可能是運行環境的差異導致的現象吧。

現象如下圖:

可以看到在 vue-element-admin 和 electron-vue-serialport 中的表現不一樣,electron-vue-serialport 中側邊欄已經錯位了。

起初按經驗來說,我是先思考,應該是 css 樣式布局出了問題,但簡單的檢查一下發現,electron 中不能使用審查元素,這就棘手了。

因為這是 vue 框架出來的代碼,不像傳統的 html + css 可以查閱相關性,很多隱性的 style 的 class 修改難以預料。

但 vue-element-admin 的部分是沒問題的,那么我就手動展開開發者調試工具,去手動調整 HTML 的內容試圖修復,第一次測試對比發現它掉標簽了,所以有一個 Tooltip 的標簽丟失了(經由 vue-element-admin 的對比發現),那么就看看代碼的關聯性。

vue 框架的代碼關聯性很難找,如果不是正向寫出代碼的人,在面對龐大的 vue 項目一般是會看懵的,甚至無從下手直接迷茫,但稍微理解幾個點有利於去逆向理解整個項目代碼,必須清楚知道 vue 組件 components 和視圖 views 的區別與關系,了解 views 是如何調用和包含 components 的。

我在閱讀和理解后,明白了自定義標簽的由來,這個是一個難以搜索的函數鏈,因為 views 包含的 components 名稱和使用時的標簽並非統一,而是大寫(AppLink)對小寫(<app-link></app-link>)的關系,所以在搜索代碼的時候要稍微留意這層命名的區別,如果不知道這個事實就容易找不到要深入的代碼。

在比對兩者的代碼后,發現應該是 views 的部分出了問題。


<template>
  <div v-if="!item.hidden" class="menu-wrapper">
    <!-- <div> {{ !item.hidden }} </div> -->
    <template v-if="hasOneShowingChild(item.children,item) && (!onlyOneChild.children||onlyOneChild.noShowingChildren)&&!item.alwaysShow">
      <app-link v-if="onlyOneChild.meta" :to="resolvePath(onlyOneChild.path)">
        <el-menu-item :index="resolvePath(onlyOneChild.path)" :class="{'submenu-title-noDropdown':!isNest}">
          <item :icon="onlyOneChild.meta.icon||(item.meta&&item.meta.icon)" :title="onlyOneChild.meta.title" />
        </el-menu-item>
      </app-link>
    </template>

    <el-submenu v-else ref="subMenu" :index="resolvePath(item.path)" popper-append-to-body>
      <template slot="title">
        <item v-if="item.meta" :icon="item.meta && item.meta.icon" :title="item.meta.title" />
      </template>
      <sidebar-item
        v-for="child in item.children"
        :key="child.path"
        :is-nest="true"
        :item="child"
        :base-path="resolvePath(child.path)"
        class="nest-menu"
      />
    </el-submenu>
  </div>
</template>

在不了解的情況下,我一般會先解決問題為主,最后再來思考為什么。

既然知道是側邊欄(Sidebar)出問題,根據原型 vue-element-admin 對照,先是試圖 build:web 產生 electron 下的 web ,然后用 pm2 啟動去判斷,but 意料內的失敗了,編譯出現太多依賴問題,感覺去修復的話就會走偏,沒有定位問題反而產生更多問題。

那么怎么做呢,先是對拷兩邊的 HTML 內容發現,確認了確實是缺少標簽導致的,但是為什么會缺少呢?這個原因也不了解,那就試試舊代碼,因為 electron-vue-admin 來的,也同樣使用了 element-ui 且樣式正常。

所以上述代碼改成如下:


<template>
  <div v-if="!item.hidden" class="menu-wrapper">
    <!-- <div> {{ !item.hidden }} </div> -->
    <template v-if="hasOneShowingChild(item.children,item) && (!onlyOneChild.children||onlyOneChild.noShowingChildren)&&!item.alwaysShow">
      <app-link v-if="onlyOneChild.meta" :to="resolvePath(onlyOneChild.path)">
        <el-menu-item :index="resolvePath(onlyOneChild.path)" :class="{'submenu-title-noDropdown':!isNest}">
          <svg-icon v-if="onlyOneChild.meta&&onlyOneChild.meta.icon" :icon-class="onlyOneChild.meta.icon"></svg-icon>
          <span v-if="onlyOneChild.meta&&onlyOneChild.meta.title" slot="title">{{onlyOneChild.meta.title}}</span>
          
          <!-- <item :icon="onlyOneChild.meta.icon||(item.meta&&item.meta.icon)" :title="onlyOneChild.meta.title" /> -->
        </el-menu-item>
      </app-link>
    </template>

    <el-submenu v-else ref="subMenu" :index="resolvePath(item.path)" popper-append-to-body>
      <template slot="title">
        <item v-if="item.meta" :icon="item.meta && item.meta.icon" :title="item.meta.title" />
      </template>
      <sidebar-item
        v-for="child in item.children"
        :key="child.path"
        :is-nest="true"
        :item="child"
        :base-path="resolvePath(child.path)"
        class="nest-menu"
      />
    </el-submenu>
  </div>
</template>

既然在調試器中測試通過,評估兩者不同的地方就在於引用 vue 的 item 組件,那么就試圖按以下步驟處理它。

  • 復制舊代碼到新框架,成功,但引出了其他問題,丟失了二級菜單列。
  • 檢查代碼,將舊代碼的變量替換,符合預期。
  • 最后把這個封裝退出來,還原回未封裝的狀態。
  • 然后,就結束......了。

其實我也只是比較巧妙的解決了問題,因為我並沒有在新代碼上解決問題,因為我也不知道新代碼上要如何解決問題,我只能根據一個既成事實去確認修復方案后解決問題。

那么本次事件到此結束,不管遇到什么困難!我們都要奧力給 XD。

  • 解決問題不是學習,不需要以理解原理和正面對着干才是唯一的方法
  • 曲線救國不一定好,但一定可以解決問題。

在解決了問題后再去思考為什么就好了,所以最后的個人分析是認為,兩者的編譯環境並不統一,而且也沒有牛逼到所有組件的關系我都清清楚楚,這個項目已經不小了,沒辦法保證所有部件沒有沖突,樣式表沖突的可能性比較大,舉個例子,現在版本中 item 標簽已經存在了,如果不注意去使用這個標簽,那么順着更新的過程中,這個標簽將會存在問題,而這個問題是前者組件先引入留下來的,所以后來載入的組件覆蓋后,其他樣式表 css 之間的關系就會沖突,想來這個項目有機會還是要退回 template 的方式后去解構,否則許多不清楚的組件沖突了只會讓事情變得復雜和麻煩,如果不是特別熟悉這個項目的碼農(例如我 XD),那就會破壞這個項目的架構穩定性了。

但個人的感覺來看,應該是環境差異,支持的部分沒有統一,因為一個兩年前的框架去兼容現在的項目,或多或少都會有一些編譯鏈的問題,附帶該項目 electron-vue-serialport 喔。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM