Vue Web开发(二)

1. 项目搭建

1.1. 首页架子搭建

  使用Element ui中的Container布局容器,选择倒数第二个样式,将代码复制到Home.vue。
在这里插入图片描述

1.1.1.下载less

  (1)下载less样式
npm i less
在这里插入图片描述
  (2)下载less编辑解析器
npm i less-loader@5.0.0
在这里插入图片描述
  在项目package.文件中可以看到下载包
在这里插入图片描述

1.1.2. 界面开发

  界面
在这里插入图片描述
(1)按需引入组件

//main.js
import Vue from 'vue'
import App from './App.vue'
import 'element-ui/lib/theme-chalk/index.css';
//ElementUI全局引入
// import ElementUI from 'element-ui';
// Vue.use(ElementUI)
//ElementUI按需引入
import {Button,Container,Aside,Header,Main} from 'element-ui';
Vue.use(Button)
Vue.use(Container)
Vue.use(Aside)
Vue.use(Header)
Vue.use(Main)
import router from '../router/router.js';
Vue.config.productionTip = false
new Vue({
	router,
    render: h => h(App),
}).$mount('#app')

在这里插入图片描述
(2)界面搭建

//view/home.vue
<template>
	<el-container style="height: 100%;">
		<el-aside width="auto">Aside</el-aside>
		<el-container>
			<el-header>Header</el-header>
			<el-main>Main</el-main>
		</el-container>
	</el-container>
</template>
<script>
	export default {
		name: 'Home',
		data() {
			return {}
		}
	}
</script>
<style lang="less">
	.el-header {
		background-color: black;
	}
	.el-main {
		padding-top: 0px;
	}
</style>

在这里插入图片描述

1.2. 左侧导航栏实现

  本质上这个模块应该是在Home.vue的Aside标签内,这个模块每个页面都会用到,所以我们把它新建成一个公共模块,所以我们在components文件下新建CommonAside.vue文件,components会存放所有组件。
  左侧导航栏逻辑如图所示,有一级菜单、二级菜单。这里我们使用Element ui的NavMenu导航菜单组件的折叠组件。
在这里插入图片描述
在这里插入图片描述
  (1)新建components/CommonAside.vue文件,引入现成组件,复制代码至CommonAside.vue文件,还有style、script代码。

//components/CommonAside.vue
<template>
<el-menu default-active="1-4-1" class="el-menu-vertical-demo" @open="handleOpen" @close="handleClose" :collapse="isCollapse">
  <el-submenu index="1">
    <template slot="title">
      <i class="el-icon-location"></i>
      <span slot="title">导航一</span>
    </template>
    <el-menu-item-group>
      <span slot="title">分组一</span>
      <el-menu-item index="1-1">选项1</el-menu-item>
      <el-menu-item index="1-2">选项2</el-menu-item>
    </el-menu-item-group>
    <el-menu-item-group title="分组2">
      <el-menu-item index="1-3">选项3</el-menu-item>
    </el-menu-item-group>
    <el-submenu index="1-4">
      <span slot="title">选项4</span>
      <el-menu-item index="1-4-1">选项1</el-menu-item>
    </el-submenu>
  </el-submenu>
  <el-menu-item index="2">
    <i class="el-icon-menu"></i>
    <span slot="title">导航二</span>
  </el-menu-item>
  <el-menu-item index="3" disabled>
    <i class="el-icon-document"></i>
    <span slot="title">导航三</span>
  </el-menu-item>
  <el-menu-item index="4">
    <i class="el-icon-setting"></i>
    <span slot="title">导航四</span>
  </el-menu-item>
</el-menu>
</template>
<script>
	export default {
	  data() {
	    return {
	      isCollapse: true
	    };
	  },
	  methods: {
	    handleOpen(key, keyPath) {
	      console.log(key, keyPath);
	    },
	    handleClose(key, keyPath) {
	      console.log(key, keyPath);
	    }
	  }
	}
</script>
<style>
	.el-menu-vertical-demo:not(.el-menu--collapse) {
	  width: 200px;
	  min-height: 400px;
	}
</style>

在这里插入图片描述
在这里插入图片描述
  (2)在CommonAside.vue文件中新建template标签,将元素标签放入,style、script代码在template标签外面。根据外面的逻辑图删除一些不必要的元素。

//components/CommonAside.vue
<template>
    <el-menu default-active="1-4-1" class="el-menu-vertical-demo" @open="handleOpen" @close="handleClose"
             :collapse="isCollapse">
        <el-menu-item index="2">
            <i class="el-icon-menu"></i>
            <span slot="title">导航二</span>
        </el-menu-item>
        <el-submenu index="1">
            <template slot="title">
                <i class="el-icon-location"></i>
                <span slot="title">导航一</span>
            </template>
            <el-menu-item-group>
                <span slot="title">分组一</span>
                <el-menu-item index="1-1">选项1</el-menu-item>
            </el-menu-item-group>
        </el-submenu>
        <el-menu-item index="3" disabled>
            <i class="el-icon-document"></i>
            <span slot="title">导航三</span>
        </el-menu-item>
    </el-menu>
</template>

<script>
    export default {
        data() {
            return {
                isCollapse: false
            };
        },
        methods: {
            handleOpen(key, keyPath) {
                console.log(key, keyPath);
            },
            handleClose(key, keyPath) {
                console.log(key, keyPath);
            }
        }
    }
</script>
<style>
    .el-menu-vertical-demo:not(.el-menu--collapse) {
        width: 200px;
        min-height: 400px;
    }
</style>

在这里插入图片描述
  (3)menu数据:在data()return中定义menu,将数据放入menu,并且将isCollapse属性设置为false!!!,表示图标展开。

[
        {
          path: "/",
          name: "home",
          label: "首页",
          icon: "s-home",
          url: "Home/Home",
        },
        {
          path: "/mail",
          name: "mail",
          label: "商品管理",
          icon: "video-play",
          url: "MailManage/MailManage",
        },
        {
          path: "/user",
          name: "user",
          label: "用户管理",
          icon: "user",
          url: "UserManage/UserManage",
        },
        {
          label: "其他",
          icon: "location",
          children: [
            {
              path: "/page1",
              name: "page1",
              label: "页面1",
              icon: "setting",
              url: "Other/PageOne",
            },
            {
              path: "/page2",
              name: "page2",
              label: "页面2",
              icon: "setting",
              url: "Other/PageTwo",
            }
          ],
        },
      ]
//components/CommonAside.vue
<template>
	<el-menu default-active="1-4-1" class="el-menu-vertical-demo" @open="handleOpen" @close="handleClose"
		:collapse="isCollapse">
		<el-menu-item index="2">
			<i class="el-icon-menu"></i>
			<span slot="title">导航二</span>
		</el-menu-item>
		<el-submenu index="1">
			<template slot="title">
				<i class="el-icon-location"></i>
				<span slot="title">导航一</span>
			</template>
			<el-menu-item-group>
				<span slot="title">分组一</span>
				<el-menu-item index="1-1">选项1</el-menu-item>
			</el-menu-item-group>
		</el-submenu>
		<el-menu-item index="3" disabled>
			<i class="el-icon-document"></i>
			<span slot="title">导航三</span>
		</el-menu-item>
	</el-menu>
</template>

<script>
	export default {
		data() {
			return {
				isCollapse: false,
				menu: [{
						path: "/",
						name: "home",
						label: "首页",
						icon: "s-home",
						url: "Home/Home",
					},
					{
						path: "/mail",
						name: "mail",
						label: "商品管理",
						icon: "video-play",
						url: "MailManage/MailManage",
					},
					{
						path: "/user",
						name: "user",
						label: "用户管理",
						icon: "user",
						url: "UserManage/UserManage",
					},
					{
						label: "其他",
						icon: "location",
						children: [{
								path: "/page1",
								name: "page1",
								label: "页面1",
								icon: "setting",
								url: "Other/PageOne",
							},
							{
								path: "/page2",
								name: "page2",
								label: "页面2",
								icon: "setting",
								url: "Other/PageTwo",
							}
						],
					},
				]
			};
		},
		methods: {
			handleOpen(key, keyPath) {
				console.log(key, keyPath);
			},
			handleClose(key, keyPath) {
				console.log(key, keyPath);
			}
		}
	}
</script>

<style>
	.el-menu-vertical-demo:not(.el-menu--collapse) {
		width: 200px;
		min-height: 400px;
	}
</style>

  在CommonAside.vue中,这里主要是处理数据,使用computed计算属性,两个属性,noChildren和hasChildren,需要对数据源进行过滤。过滤使用filter方法,filter里面有一个函数,判断是否有子项目,这样可以拿到noChildren和hasChildren两个数组。主要是为了区分一二级菜单的渲染。

//计算属性
computed:{
      noChildren(){
          return this.menu.filter(item => !item.children)
      },
      hasChildren(){
          return this.menu.filter(item => item.children)
      }
  }

1.2.1. 一级菜单渲染

  一级菜单,进行页面渲染,更改前面的代码。遍历有v-for,使用遍历需要加上key,使用路径作为唯一标识。图标原本是,这里我们用字符串拼接,因为数据中有icon对象,双花括号渲染数据,数据有多少条就渲染多少条,一级菜单一个有四个,分别是首页、商品管理、用户管其他。

<!-- 一级菜单,:=v-bind: -->
    <el-menu-item v-for="item in noChildren" :index="item.path" :key="item.path">
      <i :class="'el-icon-'+item.icon"></i>
      <span slot="title">{{item.label}}</span>
    </el-menu-item>
//components/CommonAside.vue
<template>
	<el-menu default-active="1-4-1" class="el-menu-vertical-demo" @open="handleOpen" @close="handleClose"
		:collapse="isCollapse">
		<!-- 一级菜单,:=v-bind: -->
		<el-menu-item v-for="item in noChildren" :index="item.path" :key="item.path">
			<i :class="'el-icon-'+item.icon"></i>
			<span slot="title">{{item.label}}</span>
		</el-menu-item>
		<el-submenu index="1">
			<template slot="title">
				<i class="el-icon-location"></i>
				<span slot="title">导航一</span>
			</template>
			<el-menu-item-group>
				<span slot="title">分组一</span>
				<el-menu-item index="1-1">选项1</el-menu-item>
			</el-menu-item-group>
		</el-submenu>
		<el-menu-item index="3" disabled>
			<i class="el-icon-document"></i>
			<span slot="title">导航三</span>
		</el-menu-item>
	</el-menu>
</template>

<script>
	export default {
		data() {
			return {
				isCollapse: false,
				menu: [{
						path: "/",
						name: "home",
						label: "首页",
						icon: "s-home",
						url: "Home/Home",
					},
					{
						path: "/mail",
						name: "mail",
						label: "商品管理",
						icon: "video-play",
						url: "MailManage/MailManage",
					},
					{
						path: "/user",
						name: "user",
						label: "用户管理",
						icon: "user",
						url: "UserManage/UserManage",
					},
					{
						label: "其他",
						icon: "location",
						children: [{
								path: "/page1",
								name: "page1",
								label: "页面1",
								icon: "setting",
								url: "Other/PageOne",
							},
							{
								path: "/page2",
								name: "page2",
								label: "页面2",
								icon: "setting",
								url: "Other/PageTwo",
							}
						],
					},
				]
			};
		},
		methods: {
			handleOpen(key, keyPath) {
				console.log(key, keyPath);
			},
			handleClose(key, keyPath) {
				console.log(key, keyPath);
			}
		},
		//计算属性
		computed: {
			//没有子菜单
			noChildren() {
				return this.menu.filter(item => !item.children)
			},
			//有子菜单
			hasChildren() {
				return this.menu.filter(item => item.children)
			}
		}
	}
</script>
<style>
	.el-menu-vertical-demo:not(.el-menu--collapse) {
		width: 200px;
		min-height: 400px;
	}
</style>

在这里插入图片描述

1.2.2. 二级菜单渲染

   更改CommonAside.vue文件,item可以拿到数据。
   添加

通用后台管理系统

标签

<!-- 二级菜单 -->
    <el-submenu v-for="item in hasChildren" :index="item.path" :key="item.path">
      <template slot="title">
        <i :class="'el-icon'+item.icon"></i>
        <span slot="title">{{item.label}}</span>
      </template>
      <!-- 这里subItem和subIndex并没有实际意义,只是用来指代item.children的多个数组,两者甚至可以互换,只新定义一个也可以的,:index后面有没有.path都可以运行成功 -->
      <el-menu-item-group v-for="(subItem,subIndex) in item.children" :key="subItem.path">
        <el-menu-item :index="subIndex.path">{{subItem.label}}</el-menu-item>
      </el-menu-item-group>
    </el-submenu>
//components/CommonAside.vue
<template>
	<el-menu default-active="1-4-1" class="el-menu-vertical-demo" @open="handleOpen" @close="handleClose"
		:collapse="isCollapse">
		<h3>通用后台管理系统</h3>
		<!-- 一级菜单,:=v-bind: -->
		<el-menu-item v-for="item in noChildren" :index="item.path" :key="item.path">
			<i :class="'el-icon-'+item.icon"></i>
			<span slot="title">{{item.label}}</span>
		</el-menu-item>
		<!-- 二级菜单 -->
		<el-submenu v-for="item in hasChildren" :index="item.path" :key="item.path">
			<template slot="title">
				<i :class="'el-icon'+item.icon"></i>
				<span slot="title">{{item.label}}</span>
			</template>
			<!-- 这里subItem和subIndex并没有实际意义,只是用来指代item.children的多个数组,两者甚至可以互换,只新定义一个也可以的,:index后面有没有.path都可以运行成功 -->
			<el-menu-item-group v-for="(subItem,subIndex) in item.children" :key="subItem.path">
				<el-menu-item :index="subIndex.path">{{subItem.label}}</el-menu-item>
			</el-menu-item-group>
		</el-submenu>
		<el-menu-item index="3" disabled>
			<i class="el-icon-document"></i>
			<span slot="title">导航三</span>
		</el-menu-item>
	</el-menu>
</template>

<script>
	export default {
		data() {
			return {
				isCollapse: false,
				menu: [{
						path: "/",
						name: "home",
						label: "首页",
						icon: "s-home",
						url: "Home/Home",
					},
					{
						path: "/mail",
						name: "mail",
						label: "商品管理",
						icon: "video-play",
						url: "MailManage/MailManage",
					},
					{
						path: "/user",
						name: "user",
						label: "用户管理",
						icon: "user",
						url: "UserManage/UserManage",
					},
					{
						label: "其他",
						icon: "location",
						children: [{
								path: "/page1",
								name: "page1",
								label: "页面1",
								icon: "setting",
								url: "Other/PageOne",
							},
							{
								path: "/page2",
								name: "page2",
								label: "页面2",
								icon: "setting",
								url: "Other/PageTwo",
							}
						],
					},
				]
			};
		},
		methods: {
			handleOpen(key, keyPath) {
				console.log(key, keyPath);
			},
			handleClose(key, keyPath) {
				console.log(key, keyPath);
			}
		},
		//计算属性
		computed: {
			//没有子菜单
			noChildren() {
				return this.menu.filter(item => !item.children)
			},
			//有子菜单
			hasChildren() {
				return this.menu.filter(item => item.children)
			}
		}
	}
</script>
<style>
	.el-menu-vertical-demo:not(.el-menu--collapse) {
		width: 200px;
		min-height: 400px;
	}
</style>

在这里插入图片描述
  源码下载