如何用vue实现树形菜单?
在公司培训了2周,布置的作业是从树形,grid分页以及echarts中选一个。由于都不是很熟,就挑了第一个。本来想在网上找找参考,然后模仿着做一个,但是网上的代码多少参差不齐,写到一半没了,所以只要自己写篇博客,记录下实现过程。
一、准备工作:
1.此次树形是用vue实现的,电脑需提前配置好node.js和vue.js,具体怎么配置,这里不作说明。
1)如果不记得自己有没有安装,可以win+R调出运行窗口,输入cmd,按enter
2)输入node -v和vue -V(注意vue中的-V是大写的)
node -v
vue -V
如果显示了版本号,则意为已安装。
2.引用奥森图标,进入官网下载包
3.需要对vue和webpack有基本的了解
一切准备就绪后,那么我们就开始吧
二、安装
1.首先在本地创建一个文件夹,命名为vue-tree,进入命令行窗口,然后进入到vue-tree文件夹所在位置
2.安装vue-cli,用cnpm更快
npm i -g vue-cli
然后创建一个webpack项目并且下载依赖
vue init webpack vue-tutorial
进入到vue-tutorial文件夹里,cd vue-tutorial
npm i
然后
npm run dev
这时我们就可以在localhost:8080中查看我们的应用了。
三、代码展示
下面进入重点啦~
1.打开你的main.js文件
然后在src/components文件夹下新建2个vue文件,同时新建一个common文件夹,在里面新增一个vue文件,具体看图(这里的font-aswesome是我下载的一个压缩包),layout负责布局展示,index负责树形展示,treeMenu负责渲染。
我们先配置好main.js
import Vue from 'vue' import VueRouter from 'vue-router' import Layout from './components/layout.vue' import IndexPages from './common/index.vue' import myTree from './components/treeMenu.vue' Vue.use(VueRouter) let router = new VueRouter({ mode: 'history', routes: [ { path: '/', component: IndexPages } ] }) /* eslint-disable no-new */ new Vue({ el: '#app', router, template: '<Layout/>', components: { Layout } })
2.打开layout.vue文件,开始编写(这段样式用的慕课一位讲师的)。其他的组件将在<router-view></router-view>中被渲染出来。
/** * 页面的入口,负责页面的布局 */ <template> <div> <div class="app-head"> <div class="app-head-inner"> <img src="../assets/logo.png"> <div class="head-nav"> <ul class="nav-list"> <li>登录</li> <li class="nav-pile">|</li> <li>注册</li> <li class="nav-pile">|</li> <li>关于</li> </ul> </div> </div> </div> <div class="container"> <router-view></router-view> </div> <div class="app-foot"> <p>© 2017 cindy</p> </div> </div> </template> <script> </script> <!-- Add "scoped" attribute to limit CSS to this component only --> <style> html, body, div, span, applet, object, iframe, h1, h2, h3, h4, h5, h6, p, blockquote, pre, a, abbr, acronym, address, big, cite, code, del, dfn, em, img, ins, kbd, q, s, samp, small, strike, strong, sub, sup, tt, var, b, u, i, center, dl, dt, dd, ol, ul, li, fieldset, form, label, legend, table, caption, tbody, tfoot, thead, tr, th, td, article, aside, canvas, details, embed, figure, figcaption, footer, header, hgroup, menu, nav, output, ruby, section, summary, time, mark, audio, video { margin: 0; padding: 0; border: 0; font-size: 100%; font: inherit; vertical-align: baseline; } /* HTML5 display-role reset for older browsers */ article, aside, details, figcaption, figure, footer, header, hgroup, menu, nav, section { display: block; } body { line-height: 1; } ol, ul { list-style: none; } a { color: inherit; text-decoration: none; } body { background: #f0f2f5; font-family: "Helvetica Neue",Helvetica,Arial,"Hiragino Sans GB","Hiragino Sans GB W3","Microsoft YaHei UI","Microsoft YaHei","WenQuanYi Micro Hei",sans-serif; font-size: 14px; color: #444; } .app-head { background: #363636; color: #b2b2b2; height: 90px; line-height: 90px; width: 100%; } .app-head-inner { width: 1200px; margin: 0 auto; } .app-head-inner img { width: 50px; margin-top: 20px; } .head-nav { float: right; } .head-nav ul { overflow: hidden; } .head-nav li { cursor: pointer; float: left; } .nav-pile { padding: 0 10px; } .app-foot { text-align: center; height: 80px; width: 100%; line-height: 80px; background: #e3e4e8; clear: both; margin-top: 30px; } .container { width: 1200px; height: 470px; margin: 0 auto; } ul li { padding-left: 10px; } </style>
3.打开index.vue文件,代码如下,树形主要在<ul v-for="menuItem in theModel"> <myTree class="item" :model="menuItem"></myTree> </ul>实现。
/** * 树形和echarts的展示 */ <template> <div class="index-wrap"> <div class="index-left"> <div class="index-left-block"> <h2>树形侧边导航栏</h2> <ul v-for="menuItem in theModel"> <myTree class="item" :model="menuItem"></myTree> </ul> </div> </div> <div class="index-right"> <div class="index-right-block"> </div> </div> </div> </template> <script> import myTree from '../components/treeMenu.vue'var myData =[{ 'id': '1', 'menuName': 'echarts', 'menuCode': '10', 'children': [ { 'menuName': '地图', 'menuCode': '11', }, { 'menuName': '柱状图', 'menuCode': '12', 'children': [ { 'menuName': '交错正负轴标签', 'menuCode': '121' }, { 'menuName': '柱状图框选 ', 'menuCode': '122' }, { 'menuName': '堆叠柱状图', 'menuCode': '124' }] }, { 'menuName': '条形图', 'menuCode': '13' }] }, { 'id': '2', 'menuName': '树形结构', 'menuCode': '21' }, { 'id': '3', 'menuName': 'gird分页', 'menuCode': '30' }] export default { name: 'items', props: ['model'], components: { myTree }, data () { return { theModel: myData } } } </script> <style scoped> .index-wrap { width: 1200px; margin: 0 auto; overflow: hidden; } .index-left { float: left; width: 300px; text-align: left; } .index-right { float: left; width: 900px; } .index-left-block, .index-right-block{ height: 450px; margin: 15px; background: #fff; box-shadow: 0 0 1px #ddd; } .index-left-block h2,.index-right-block h2 { background: #4fc08d; color: #fff; padding: 20px 20px; font-size: 1.5em; } .item { cursor: pointer; } ul{ line-height: 40px; list-style-type: dot; } li div:active,li div:hover { background: #9FDABE; color: #eee; } ul li:hover { background: #A6C2B0; } </style>
4.最重要的一个文件:treeMenu.vue。这个文件里有用到font-awesome,需要大家自行去官网下载。然后将压缩包解压后,放到src的下面。我将文件夹重名为“font-awesome”,然后在<script></script>标签里引用import '../font-awesome/css/font-awesome.min.css'。
/** * 树的组件,主要功能在这里实现 * */ <template> <li> <div @click="toggle" @dblclick="changeType"> <!-- isFolder判断是否存在子级改变图标 --> <i v-if="isFolder"uk-animation-="" class="fa " :class="[open?'fa-folder-open':'fa-folder']"></i> <i v-if="!isFolder" class="fa fa-file-image-o"></i> {{ model.menuName }} <i v-if="isFolder" class="fa " :class="[open ? 'fa-chevron-down' : 'fa-chevron-right']" style="display: inline-block;float: right;padding:13px 20px 0 0;"></i> </div> <ul v-show="open" v-if="isFolder"> <tree-menu v-for="item in model.children" :model="item"></tree-menu> <li class="add" @click="addChild"> <i class="fa fa-plus-square-o" style="padding-left: 20px;"> <i style="display: inline-block;padding-left: 20px;">add</i> </i> </li> </ul> </li> </template> <script> import '../font-awesome/css/font-awesome.min.css' import Vue from 'vue' export default { name: 'treeMenu', props: ['model'], data() { return { open: false, } }, computed: { isFolder:function() { return this.model.children && this.model.children.length } }, methods: { toggle: function() { if(this.isFolder) { this.open = !this.open } }, changeType: function() { if(!this.isFolder) { Vue.set(this.model,'children',[]) this.addChild() this.open = true } }, addChild: function() { this.model.children.push({ name:'new stuff' }) } } } </script> <style scoped> ul { line-height: 40px; list-style-type: dot; } li div:active,li div:hover { background: #9FDABE; color: #eee; } ul li:hover { background: #A6C2B0; } .fa-folder-open, .fa-folder, .fa-file-image-o { padding:0 20px; } </style>
所以处理完之后,就是这样子的啦(echarts是后面加上去的,可以不用管)
我把代码放到github上了,大家可以下载看看(github上的代码包含了echarts,大家注意搭配我的博客看)
https://github.com/yuegreen/vueTree
官网中也有关于树组件的实现,大家可以去参考参考
https://cn.vuejs.org/v2/examples/tree-view.html
如果对本文章有什么问题和建议,欢迎在评论区讨论~
本文来自博客园,作者:沐木琴,转载请注明原文链接:https://www.cnblogs.com/cindy79/p/7229196.html
以小白的视角记录问题,如果你也有什么不懂的问题,欢迎来评论区讨论。