设计初衷
编写代码过程中最讨厌的就是重复的事情做的多过 3
次,所以在做项目当中自己不多不少都会有一种写复用代码的冲动。
思路
自己看过最多的论坛就是 Laravel
的,里面也有教程这个功能,自己很大一种程度就是想模仿这个功能。
教程有两点:
- 菜单栏
- 内容跟着菜单联动

所以这里面我们就明白知道,菜单栏与教程内容是关联关系的。然后看见大部分网上的教程都是采用不同的 url
来对每个菜单进行跳转的。
实践
需求分析明白后,在生成菜单这里就遇到坑。如果是采用不同的 url
的话就会要在生成菜单的时候要填写 url
, 而这个 url
明显是要英文字母的。这个有打算使用拼音来解决,不过因为时间成本有点高最后就放弃了。要做这个需求那么我就要将这个组件封装的非常复杂,要动态添加路由进去,这个明显是不符合的。
最后决定使用一开始将所有数据全部查询出来,然后点击不同的菜单,然后赋值到 mavon-editor
这个组件中去。
组件目录结构:
1 2 3 4 5
| │ Index.vue │ └─Menu Menu.vue SubMenu.vue
|
Index.vue
文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| <template> <el-row> <el-col :span="4"> <dMenu :menus="menus" v-on:info="changeInfo"></dMenu> </el-col> <el-col :span="20"> <el-row> <h4 style="text-align: center;">{{ item.title }}</h4> <mavon-editor ref="md" v-model="item.mdCode" style="padding: 5px 10px;" :subfield="false" :defaultOpen="'preview'" :toolbarsFlag="false" :editable="false" :scrollStyle="true" :ishljs="true" ></mavon-editor> </el-row> </el-col> </el-row> </template>
|
这里面就是实现菜单与 markdown
文本展示的代码。
Menu.vue
文件
1 2 3 4 5
| <template> <el-menu :default-active="$route.path" :default-openeds="menusVuex" @open="open" @close="close"> <SubMenu :menus="menus" parent="/" v-bind="$attrs" v-on="$listeners"></SubMenu> </el-menu> </template>
|
这里面可以看见这个 Menu
组件嵌套了一个 SubMenu
子组件,这里面就会涉及一个问题。因为这里要在 Index.vue
点击菜单实现数据变换展示,这里变成了 爷->父->子的三层关系,子要如何调用爷的方法呢?
其实就是使用上面的方法
1
| <dMenu :menus="menus" v-on:info="changeInfo"></dMenu>
|
采用 v-on:info
监听 info
变量的方法,然后父组件将所有的监听和绑定属性传递到子组件中去。
1
| <SubMenu :menus="menus" parent="/" v-bind="$attrs" v-on="$listeners"></SubMenu>
|
采用 v-bin="$attrs" v-on="$listeners"
方法,所以在子组件中我们就可以使用 $emit('info', menu)
进行调用了。
取巧
因为上面的实现方式是采取点击事件切换文本的,所以会存在怎么去保持点击的目录在刷新之后继续展开?
直接在 url
里面拼上菜单的 index
。
1 2 3 4 5 6 7 8 9 10
| open(index) { let newQuery = JSON.parse(JSON.stringify(this.$route.query)); let _index = []; if ("tutirialIndex" in newQuery) { _index = newQuery.tutorialIndex.split(","); } _index.push(index); newQuery.tutorialIndex = _index.join(","); this.$router.replace({ query: newQuery }); },
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| close(index) { let newQuery = JSON.parse(JSON.stringify(this.$route.query)); let _index = []; if ("tutirialIndex" in newQuery) { _index = newQuery.tutorialIndex.split(","); } let idx = _index.indexOf(index); if (idx > -1) { _index.splice(idx, 1); } newQuery.tutorialIndex = _index.join(","); if (newQuery.tutorialIndex == "") { delete newQuery.tutorialIndex; } this.$router.replace({ query: newQuery }); }
|
然后在 Menu.vue
组件中的 created
函数写入以下代码:
1 2 3 4 5 6
| created: function () { let newQuery = JSON.parse(JSON.stringify(this.$route.query)); if ("tutorialIndex" in newQuery) { this.openMenus = newQuery.tutorialIndex.split(","); } },
|
这样子我们刷新页面也不怕丢失打开菜单栏了