<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ??碼云GVP開源項目 12k star Uniapp+ElementUI 功能強大 支持多語言、二開方便! 廣告
                [TOC] >[success] # 遞歸組件的使用 **遞歸組件** 有什么 **用處** 呢,一般用于 **樹形結構的收縮展開菜單功能**, **層級** 是 **不固定** 的, **根據后端返回的數據進行動態渲染** 的,所以需要用 **遞歸組件** 來 **從 根節點 循環一直到 葉子節點** 為止。 接下來我們先 **封裝一個簡單的Menu組件** ,然后 **循循漸進的再封裝一個遞歸組件**。 >[success] ## 封裝Menu組件 封裝一個 **簡單的菜單** ,效果如下圖 ![](https://img.kancloud.cn/0e/cc/0ecc76c7c45c9619866907768c19e1ea_300x147.gif) 1. **父組件** 首先在 **路由列表** 的 **路由對象** 中添加新創建的 **menu-page** 頁面配置路由 **src/router/router.js** ~~~ export default [ { path: '/menu_page', name: '/menu_page', component: () => import('@/views/menu-page') } ] ~~~ 然后在 **src/views/menu-page.vue** 頁面 **引入menuComponents**, **menuComponents** 中包含了 **3個** 組件,**AMenu、 AMenuItem、 ASubmenu** ,可以使用 **擴展運算符的方式引入** ,也可以使用 **解構的方式引入** 。 **src/views/menu-page.vue** ~~~ <template> <div class="menu-box"> <a-menu> <a-menu-item>111</a-menu-item> <a-menu-item>222</a-menu-item> <a-submenu> <div slot="title">333</div> <a-menu-item>333-11</a-menu-item> <a-submenu> <div slot="title">333-22</div> <a-menu-item>333-22-11</a-menu-item> <a-menu-item>333-22-22</a-menu-item> </a-submenu> </a-submenu> </a-menu> </div> </template> <script> import menuComponents from '_c/menu' // 雖然說下面的擴展運算符很方便,但不清楚哪些組件可用,用解構賦值引入就很方便 const { AMenu, AMenuItem, ASubmenu } = menuComponents export default { name: 'menu_page', components: { AMenu, AMenuItem, ASubmenu // ...menuComponents // 廢棄:擴展運算符展開引入的3個組件,看起來比較簡潔 } } </script> <style lang="scss"> .menu-box{ width: 300px; height: 400px; } </style> ~~~ 2. **子組件** **src/components/menu/a-menu.vue** ~~~ <template> <div class="a-menu"> <slot></slot> </div> </template> <script> export default { } </script> <style lang="scss"> // .a-menu 里的所有都設置為list-style: none .a-menu{ & *{ list-style: none; }; ul{ padding: 0; margin: 0; } } </style> ~~~ **src/components/menu/a-ment-item.vue** ~~~ <template> <li class="a-menu-item"> <slot></slot> </li> </template> <script> export default { name: 'AMentItem' } </script> <style lang="scss"> .a-menu-item{ background: rgb(90, 92, 104); color: white; } </style> ~~~ **src/components/menu/a-submenu.vue** ~~~ <template> <ul class="a-submenu"> <div class="a-submenu-title" @click="handleClick"> <slot name="title"></slot> <span class="shrink-icon" :style="{ transform: `rotate(${ showChild ? 0 : 180 }deg)` }">^</span> </div> <div v-show="showChild" class="a-submenu-child-box"> <slot></slot> </div> </ul> </template> <script> export default { name: 'ASubmenu', data(){ return{ showChild: false } }, methods: { handleClick(){ this.showChild = !this.showChild } } } </script> <style lang="scss"> .a-submenu{ background: rgb(33, 35, 39); &-title{ color: white; position: relative; .shrink-icon{ position: absolute; top: 0; right: 10px; } } &-child-box{ overflow: hidden; padding-left: 20px; } li{ background: rgb(33, 35, 39); } } </style> ~~~ 定義一個 **index.js 方便父組件引用** **src/components/menu/index.js** ~~~ import AMenu from './a-menu.vue' import AMenuItem from './a-ment-item.vue' import ASubmenu from './a-submenu.vue' export default { // 導出3個組件 AMenu, AMenuItem, ASubmenu } ~~~ >[success] ## 封裝遞歸組件 **遞歸組件是根據數據層級** 來渲染的,如下圖層級可以達到很深層,甚至 **無限層** 。 ![](https://img.kancloud.cn/d7/fc/d7fc2d3eee8eb6488c4ae69b8e2f16e4_300x210.gif) 下面 **組件** 中 **AMenu, AMenuItem, ASubmenu** 組件在上面的 **封裝Menu組件** 的都有寫過,這里就不再寫了。 1. **父組件** **src/views/menu-page.vue** ~~~ <template> <div class="menu-box"> <!-- 普通菜單結構 --> <!-- <a-menu> <a-menu-item>111</a-menu-item> <a-menu-item>222</a-menu-item> <a-submenu> <div slot="title">333</div> <a-menu-item>333-11</a-menu-item> <a-submenu> <div slot="title">333-22</div> <a-menu-item>333-22-11</a-menu-item> <a-menu-item>333-22-22</a-menu-item> </a-submenu> </a-submenu> </a-menu> --> <!-- 遞歸組件的結構 --> <a-menu> <!-- template上是不可以寫key的,所以需要寫在里面 --> <template v-for="(item, index) in list"> <a-menu-item v-if="!item.children" :key="`menu_item${ index }`">{{ item.title }}</a-menu-item> <re-submenu v-else :key="`menu_item${ index }`" :parent="item" :index="index"></re-submenu> </template> </a-menu> </div> </template> <script> import menuComponents from '_c/menu' import ReSubmenu from '_c/re-submenu' const { AMenu, AMenuItem, ASubmenu } = menuComponents export default { name: 'menu_page', components: { AMenu, AMenuItem, ASubmenu, ReSubmenu }, data(){ return{ list: [ // 樹形數據結構 { title: '1111' }, { title: '2222' }, { title: '3333', children: [ { title: '3333-1' }, { title: '3333-2', children: [ { title: '3333-2-1', }, { title: '3333-2-2', }, { title: '3333-2-3', children: [ { title: '3333-2-3-1', }, { title: '3333-2-3-2', } ] } ] } ] } ] } } } </script> <style lang="scss"> .menu-box{ width: 300px; height: 400px; } </style> ~~~ 2. **子組件** **src/components/re-submenu/re-submenu.vue** ~~~ <!-- 組件自己調用自己設一個條件,不然就會像遞歸一樣一直調用組件自己,陷入死循環 --> <template> <a-submenu> <div slot="title">{{ parent.title }}</div> <template v-for="(item, i) in parent.children"> <!-- 如果無children,證明是葉子節點(最后一級),只需要顯示title即可 --> <a-menu-item v-if="!item.children" :key="`menu_item${ index }_${ i }`">{{ item.title }}</a-menu-item> <!-- 如果有children繼續循環 --> <re-submenu v-else :key="`menu_item${ index }_${ i }`" :parent="item"></re-submenu> </template> </a-submenu> </template> <script> import menuComponents from "_c/menu"; const { AMenuItem, ASubmenu } = menuComponents; export default { name: "ReSubmenu", components: { AMenuItem, ASubmenu, }, props: { parent: { type: Object, default: () => ({}) }, index: Number } }; </script> ~~~ 定義一個 **index.js 方便父組件引用** **src/components/re-submenu/re-submenu.vue** ~~~ import ReSubmenu from './re-submenu.vue' export default ReSubmenu ~~~ 3. **遞歸組件注意項** 3.1. 一定要有 **終止條件的判斷** ,不然會陷入 **死循環** 。 3.2. **遞歸組件** 一定要給 **組件定義name值** ,它才能 **引用當前自身的組件** 。
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看