iview 酸爽debug: subMenu預設選中無效的解決方法

Aibot發表於2022-06-02

一. 在iview中寫一個submenu

        <Col span="3" type="flex" v-if="showCids">
          <Menu
            ref="menus"
            theme="light"
            active-name="0"
            @on-select="selectMenu"
            width="auto"
          >
            <MenuGroup title="cid">
              <MenuItem v-for="(cid, index) in cids" :key="index" :name="index">
                {{ cid }}
              </MenuItem>
            </MenuGroup>
          </Menu>
        </Col>

因為這個subMenu是動態生成的, 他的name我設定為動態生成過程中的index, 所以第一個subMenu的name是0.
根據上述設定, 參考官網的說明,使用activeName="0"來表示啟用的name, 還特別注意力name是string而不是int基本資料型別. 所以就通過這種方式讓subMenu0呈現啟用態. 很好, 並不work下面是高能的踩坑過程, 如果不想看可以直接跳轉 "三. 解決方法"

二. 踩坑全過程

根據網上的資料, 我迅速的發現瞭解決問題的路徑. "因為subMenu是動態展開的"--->所以需要呼叫updateActiveName()方法, 在subMenu的資料填充之後進行呼叫. 然後我就根據網上的教程和iview官網的描述吭呲吭呲學了半個多小時. 因為在呼叫這個函式的時候我碰到了很多問題. 最重要的問題就是我根本找不到這個函式的呼叫入口, 說人話就是誰來呼叫這個函式. 教程上說是this.$refs.menu.updateActiveName(). 這行話含義就深了, 作為前端菜鳥根本把握不住. 首先refs是社麼? 其次menu又是什麼? 最後this.$nextTick() 為社麼在這個函式裡沒有出現? 當然更新的新手會問this.$nextTick()是什麼, 他為什麼要在這裡出現.
所以這個問題遞迴的層數真的夠多的, 有多多呢? 看圖吧.?

所以首先需要解決的就是找到找到$refs的問題, 怎麼找呢?
找個傻得得兒, 根本就不可能找到好嘛. 因為這是自己定義的,而恰好官網的示例中沒有定義這個屬性. 就是這行程式碼了

<Menu ref="menu">
  <MenuGroup>
    //...
  </MenuGroup>
</Menu>

其中ref的值可以任意修改. 只要this.$refs.menuref=menu對應就可以.
然後就要集中經歷解決this.nextTick()在哪裡呼叫的問題. 好吧這其實不成為問題. 只不過因為當時錯誤的歸因, 所以在這條路上走的深入了一些.
那麼view渲染的過程會有create, before mount, mount這些步驟. 於是我又簡單學習了一下他們的區別. 主要的區別就是資料是否已經append到變數中. 只有mount成功才能確保資料mount成功.

後來發現時機不是問題. 只要在呼叫資料的函式後面呼叫. 但是一定一定要在之前讓v-if的判斷條件為真. 畢竟我之前給自己埋了個坑. 為了讓介面美觀, 在subMenu 沒有資料的時候我是隱藏它的. 所以...總之, 埋坑這件事我一直可以的.如果不做程式設計師改行作家, 我應該能順便賣刀片. 哈哈哈發家致富新途徑說不定央視致富經都得找我做節目的那種.
所以this.$refs.menu一直是undefined就很合理了, 畢竟都沒有visible啊, 當然不會渲染啊, 不渲染怎麼會被拿到$refs.啊啊啊, 坑王竟是我自己.
然後就順理成章在拿到資料之後, 呼叫?

menuChange(_index) {
  this.activeName = _index.toString();
  this.$nextTick(() => {
      console.log("menuChange ", this.activeName, this.$refs.menus.currentActiveName, this.$refs.menus)
      this.$refs.menus.updateActiveName()
            })

非常完美的發現還得用this.activeName?????既然如此, 為什麼不直接動態資料繫結呢? 我這一圈子圖啥呢? 圖樣圖森破吧.
當然上述程式碼去掉 this.activeName = _index.toString();也是能執行良好的. 但是那樣每次呼叫menuChange就標識預設值. 函式名最好換成defaultSubMenu

三. 解決方法

法一

defaultSubMenu() {
  this.$nextTick(() => {
      this.$refs.menus.updateActiveName()
            })

獲取完資料之後呼叫, 指向預設subMenu-->name='0'

法二

        <Col span="3" type="flex" v-if="showCids">
          <Menu
            ref="menus"
            theme="light"
            :active-name=dynamicAcName
            @on-select="selectMenu"
            width="auto"
          >
            <MenuGroup title="cid">
              <MenuItem v-for="(cid, index) in cids" :key="index" :name="index">
                {{ cid }}
              </MenuItem>
            </MenuGroup>
          </Menu>
        </Col>

動態修改一下acitve-name屬性. 接收完資料之後, 為this.dynamicAcName賦值.

相關文章