写给自己看的木偶组件和智能组件的启示
背景
今天在重构一个老项目的侧边栏,在不断重复修改这个侧边栏文件的时候对一些已经掌握的知识和概念有了重复和深一点的认识。
- 这个侧边栏一开始的样子:
<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 都是重复出现的,所以其实可以进行如下优化
- 优化一下之后的样子
<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中的数据就可以了。
- 更多
- react 组件中有木偶组件和智能组件的概念, 在上面的代码例子中, 如果将 data 中的 menus 数据抽离为props, 上述代码将变为一个木偶组件拥有更强的复用性。