寫給自己看的木偶元件和智慧元件的啟示

瓜坤發表於2019-02-27

寫給自己看的木偶元件和智慧元件的啟示

背景

今天在重構一個老專案的側邊欄,在不斷重複修改這個側邊欄檔案的時候對一些已經掌握的知識和概念有了重複和深一點的認識。

  1. 這個側邊欄一開始的樣子:
<template>
  <aside>
    <Menu theme="light" width="auto">
      <Menu-Item name="n1" :to="{ name: 'n1' }">
        <svg aria-hidden="true" class="icon">
          <use :xlink:href="`#icon-x`"/>
        </svg>
        menu1
      </Menu-Item>
      <Menu-Item name="n2" :to="{ name: 'n2' }">
        <svg aria-hidden="true" class="icon">
          <use :xlink:href="`#icon-x`"/>
        </svg>
        menu2
      </Menu-Item>
      <Menu-Item name="n3" :to="{ name: 'n3' }">
        <svg aria-hidden="true" class="icon">
          <use :xlink:href="`#icon-x`"/>
        </svg>
        menu3
      </Menu-Item>
      <Submenu name="s1">
        <template slot="title">
          <svg aria-hidden="true" class="icon">
            <use :xlink:href="`#icon-x`"/>
          </svg>
          menu4
        </template>
        <Menu-Item name="sm1" :to="{ name: 'sm1' }" style="padding-left: 24px;">
          <svg aria-hidden="true" class="asset-sidebar-icon">
          </svg>
          sm1
        </Menu-Item>
        <Menu-Item class="submenu" name="sm2" :to="{ name: 'sm2' }">sm2</Menu-Item>
        <Menu-Item class="submenu" name="sm3" :to="{ name: 'sm3' }">sm3</Menu-Item>
      </Submenu>
    </Menu>
  </aside>
</template>

<script>
export default {
}
</script>

複製程式碼

這種寫法乍一看上去沒有什麼問題, 也能滿足需求,但仔細觀察 dom 結構中 Menu 和 SubMenu 都是重複出現的,所以其實可以進行如下優化

  1. 優化一下之後的樣子
<template>
  <aside class="sidebar">
    <Menu theme="light" width="auto">
      <template v-for="menuItem in menus" >
        <!--含有二級選單的 dom 結構-->
        <Submenu v-if="menuItem.children && menuItem.children.length>0" :key="menuItem.name" name="sm">
          <!--標題-->
          <template slot="title">
            <svg aria-hidden="true" class="asset-sidebar-icon">
              <use :xlink:href="`#icon-x`"/>
            </svg>
            {{menuItem.text}}
          </template>
          <!--二級選單-->
          <Menu-Item v-for="(submenuItem, index) in menuItem.children" :key="index"
                     :name="submenuItem.name" :to="{ name: submenuItem.name }" style="padding-left: 24px;">
            <svg aria-hidden="true" class="icon">
            </svg>
            {{submenuItem.text}}
          </Menu-Item>
        </Submenu>
        <!--只有一級選單的 dom 結構-->
        <Menu-Item v-else :key="menuItem.name" :name="menuItem.name" :to="{ name: menuItem.name }">
          <svg aria-hidden="true" class="icon">
            <use :xlink:href="`#icon-${menuItem.icon}`"/>
          </svg>
          {{menuItem.text}}
        </Menu-Item>
      </template>
    </Menu>
  </aside>
</template>

<script>
export default {
  name: 'Gua',
  data () {
    return {
      routerName: this.$route.name,
      // menu 選項
      menus: [
        {
          text: 'm1',
          name: 'm1',
          icon: 'x'
        },
        {
          text: 'm2',
          name: 'm2',
          icon: 'x'
        },
        {
          text: 'm3',
          name: 'm3',
          icon: 'x'
        },
        {
          text: 'm4',
          name: 'm4',
          icon: 'x',
          children: [
            {
              text: 'sm1',
              name: 'sm1'
            },
            {
              text: 'sm2',
              name: 'sm2'
            },
            {
              text: 'sm3',
              name: 'sm3'
            }
          ]
        },
      ]
    }
  },
  created () {}
}
</script>
複製程式碼

優化成這樣之後我們獲得了一個只需要修改資料就可以完成編輯的側邊欄選單,思考, 如果是優化前需要增加一條選單,或者要改變選單的icon需要做什麼樣的操作? 而現在只需要修改data中的資料就可以了。

  1. 更多
  • react 元件中有木偶元件和智慧元件的概念, 在上面的程式碼例子中, 如果將 data 中的 menus 資料抽離為props, 上述程式碼將變為一個木偶元件擁有更強的複用性。

相關文章