后端人员开发前端vue。
git地址:https://github.com/1065744299/vue-elment-ui
演示地址:https://1065744299.github.io/
csdn下载源码地址:https://download.csdn.net/download/qq_25451199/11256228
这个demo主要用到vue、vueRouter、vueX、element UI、echarts等技术。主要以展示怎么使用为主。主要的功能有登录、路由、store、报表、导出等。
这里用vue的多页面功能,为了组件的重复使用。
开始介绍代码:
为了打包的时候直打包一个页面,这里对vue.config.js做了修改;代码如下:
var projectname = process.argv[5]
var glob = require('glob')
function getEntry () {
var entries = {}
if (process.env.NODE_ENV === 'production') {
entries = {
index: {
// page的入口
entry: 'src/modules/' + projectname + '/main.js',
// 模板来源
template: 'public/index.html',
// 在 dist/index.html 的输出
filename: 'index.html',
title: projectname,
chunks: ['chunk-vendors', 'chunk-common', 'index']
}
}
} else {
var items = glob.sync('./src/modules/*/*.js')
for (var i in items) {
var filepath = items[i]
var fileList = filepath.split('/')
var fileName = fileList[fileList.length - 2]
entries[fileName] = {
entry: `src/modules/${fileName}/main.js`,
// 模板来源
template: `public/index.html`,
// 在 dist/index.html 的输出
filename: `${fileName}.html`,
// 提取出来的通用 chunk 和 vendor chunk。
chunks: ['chunk-vendors', 'chunk-common', fileName]
}
}
}
return entries
}
var pages = getEntry()
// vue.config.js
module.exports = {
// 基本路径
publicPath: '/',
// 输出文件目录
// outputDir: 'dist',
// webpack-dev-server 相关配置
devServer: {
port: 8888
},
// 生产禁止显示源代码
productionSourceMap: false,
// 输出文件目录
outputDir: 'dist/' + projectname,
pages: pages
}
下面开始搭建一个简单的demo。
主要有几个基础的组件。
先了解下项目结构:


这里主要说组件的内容。
- Home.vue
主页组件
<template>
<el-container>
<el-header>
<Head :isCollapse='isCollapse' @changeCollapse="changeCollapsed" :sysName='sysName' :userInfo='homeUserInfo' @logoutHandle='logoutHandle'></Head>
</el-header>
<el-container>
<el-aside :class="isCollapse?'menu-collapsed':'menu-expanded'">
<Menu :isCollapse='isCollapse' :defaultActive="defaultActive" :menuJson='menuJson' @selectedTab="selectedTab(arguments)"/>
</el-aside>
<el-main>
<div class="my-main">
<Main :editableTabsValue="editableTabsValue" ref="myMain" @selectedTab="mainSelectedTab(arguments)"/>
</div>
</el-main>
</el-container>
</el-container>
</template>
<script>
import Menu from '@/components/Menu.vue'
import Head from '@/components/Head.vue'
import Main from '@/components/Main.vue'
export default {
name: 'app',
props: ['sysName', 'userInfo', 'menuJson'],
components: {
Menu,
Head,
Main
},
data () {
return {
// 菜单是否折叠
'isCollapse': false,
// 主展示区默认选项卡
'editableTabsValue': '首页',
// 菜单默认选中
'defaultActive': '/main/home'
}
},
computed: {
'homeUserInfo': function () {
return this.userInfo
}
},
methods: {
changeCollapsed: function () {
this.isCollapse = !this.isCollapse
},
selectedTab: function (args) {
this.editableTabsValue = args[0]
this.defaultActive = args[1]
this.$refs.myMain.addTab(this.editableTabsValue, this.defaultActive)
},
mainSelectedTab: function (args) {
this.editableTabsValue = args[0]
this.defaultActive = args[1]
},
myRoute: function (index) {
this.$router.push({ 'path': index })
},
logoutHandle: function () {
this.$emit('logoutHandle')
}
},
created: function () {
this.myRoute(this.defaultActive)
}
}
</script>
<style>
html,body,#app,.el-container {
height: 100%;
}
.el-header {
color: #333;
line-height: 60px;
padding: 0 0px;
}
.el-aside {
background-color: #eef1f6;
color: #333;
line-height: 200px;
}
.el-main {
color: #333;
padding: 0 0 0 0px;
width: 100%;
}
.menu-collapsed{
flex:0 0 65px;
width: 65px;
}
.menu-expanded{
flex:0 0 201px;
width: 201px;
}
body{
margin: 0px;
}
main {
height: 100%;
overflow-y: auto;
}
</style>
- Head.vue
头部组件
<template>
<el-col :span="24" class="header">
<el-col :span="10" class="logo " :class="isCollapse?'logo-collapse-width':'logo-width'">
{
{isCollapse?'':sysName}}
<img src="../assets/w.jpg" width="66px" height="100%" v-show="isCollapse"/>
</el-col>
<el-col :span="10">
<div class="tools">
<i :class="isCollapse?'el-icon-s-unfold':'el-icon-s-fold'" @click="pchangeCollapse"></i>
</div>
</el-col>
<el-col :span="4" class="userinfo">
<el-dropdown trigger="hover">
<span class="el-dropdown-link userinfo-inner"><img :src="img"/>{
{name}}</span>
<el-dropdown-menu slot="dropdown">
<el-dropdown-item>我的消息</el-dropdown-item>
<el-dropdown-item>设置</el-dropdown-item>
<el-dropdown-item @click.native="logoutHandle">退出登录</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
</el-col>
</el-col>
</template>
<script>
let userInfo = {
name: '苏三杰',
img: 'https://raw.githubusercontent.com/taylorchen709/markdown-images/master/vueadmin/user.png'
}
export default {
props: {
'isCollapse': {
type: Boolean,
default: true
},
'userInfo': {
type: Object,
default: () => userInfo
},
'sysName': {
type: String,
default: 'WEBDEMO'
}
},
data () {
return {}
},
computed: {
'name': function () {
return this.userInfo.name
},
'img': function () {
return this.userInfo.img
}
},
methods: {
pchangeCollapse: function () {
this.$emit('changeCollapse')
},
logoutHandle: function () {
this.$confirm('确定要退出吗?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
// this.$message({
// type: 'success',
// message: '删除成功!'
// })
this.$emit('logoutHandle')
}).catch(() => {
this.$message({
type: 'info',
message: '已取消退出'
})
})
}
}
}
</script>
<style scoped>
.header {
height: 60px;
line-height: 60px;
background: #67C23A;
color:#fff
}
.userinfo {
height: 60px;
line-height: 60px;
text-align: right;
padding-right: 35px;
float: right;
}
.userinfo-inner {
height: 60px;
line-height: 60px;
cursor: pointer;
color:#fff;
}
.userinfo-inner>img {
cursor: pointer;
color:#fff;
width: 40px;
height: 40px;
border-radius: 20px;
margin: 10px 0px 10px 10px;
float: right;
}
.logo {
height:60px;
font-size: 22px;
border-color: rgba(238,241,146,0.3);
border-right-width: 1px;
border-right-style: solid;
}
.txt {
color:#fff;
}
.logo-width{
width:202px;
padding-left:20px;
padding-right:20px;
}
.logo-collapse-width{
width:65px;
padding-left:0px;
padding-right:0px;
}
.tools{
padding: 0px 23px;
width:14px;
height: 60px;
line-height: 60px;
cursor: pointer;
}
</style>
- Main.vue
主展示区组件
<template>
<el-tabs v-model="myEditableTabsValue" type="card" closable @tab-remove="removeTab" @tab-click="goRoute">
<el-tab-pane
v-for="(item) in editableTabs"
:key="item.name"
:label="item.title"
:name="item.name"
:myindex="item.index"
>
<div class="mymain">
<router-view/>
</div>
</el-tab-pane>
</el-tabs>
</template>
<script>
export default {
props: ['editableTabsValue'],
data () {
return {
editableTabs: [{
title: '首页',
name: '首页',
index: '/main/home'
}],
myEditableTabsValue: this.editableTabsValue
}
},
methods: {
addTab (name, index) {
for (var t in this.editableTabs) {
if (this.editableTabs[t].name === name) {
this.myEditableTabsValue = name
return
}
}
this.editableTabs.push({
title: name,
name: name,
index: index
})
this.myEditableTabsValue = name
},
removeTab (targetName) {
let tabs = this.editableTabs
let activeName = this.myEditableTabsValue
// let activeName = ''
let _index = ''
if (activeName === targetName) {
tabs.forEach((tab, index) => {
if (tab.name === targetName) {
let nextTab = tabs[index + 1] || tabs[index - 1]
if (nextTab) {
activeName = nextTab.name
_index = nextTab.index
}
}
})
}
this.$router.push({ 'path': _index })
this.$emit('selectedTab', activeName, _index)
this.myEditableTabsValue = activeName
this.editableTabs = tabs.filter(tab => tab.name !== targetName)
},
goRoute (args) {
let tabs = this.editableTabs
let _thisTab = tabs.filter(tab => tab.name === args.name)[0]
this.$router.push({ 'path': _thisTab.index })
this.$emit('selectedTab', _thisTab.name, _thisTab.index)
// this.$emit('myRoute', _thisTab.index)
}
}
}
</script>
<style scoped>
.mymain {
padding: 0 5px
}
</style>
- Menu.vue
菜单组件
<template>
<div>
<el-menu
:default-active="defaultActive"
class="el-menu-vertical-demo"
@open="handleOpen"
@close="handleClose"
:collapse="isCollapse"
background-color="#eef1f6"
active-text-color="#20a0ff"
:collapse-transition="false"
text-color="#48576a"
:router="true"
>
<template v-for="m in menus">
<el-submenu v-if="m.type=='subMenu'" :index="m.id" :key="m.id">
<template slot="title">
<i :class="m.icon"></i>
<span slot="title">{
{m.name}}</span>
</template>
<el-menu-item v-for="mi in m.submenus" :key="mi.id" :index="mi.url" :route="{path: mi.url}" @click.native="selected(mi.name, mi.url)">
{
{mi.name}}
</el-menu-item>
</el-submenu>
<el-menu-item v-if="m.type=='menu-item'" :index="m.url" :key="m.id" :route="{path: m.url}" @click.native="selected(m.name, m.url)">
<i :class="m.icon"></i>
<span slot="title">
{
{m.name}}
</span>
</el-menu-item>
</template>
</el-menu>
</div>
</template>
<script>
let menuJson = [
{
id: '1',
name: '首页',
type: 'menu-item',
url: '/',
icon: 'el-icon-star-off',
submenus: []
},
{
id: '2',
name: 'TableS',
type: 'subMenu',
url: '',
icon: 'el-icon-s-grid',
submenus: [
{
id: '3',
name: '动态table',
type: 'subMenu',
url: '/about',
icon: ''
},
{
id: '4',
name: '拖拽table',
type: 'subMenu',
url: '/about1',
icon: ''
},
{
id: '5',
name: '综合table',
type: 'subMenu',
url: '/about2',
icon: ''
}
]
},
{
id: '6',
name: '列表demo',
type: 'subMenu',
url: '',
icon: 'el-icon-user',
submenus: [
{
id: '7',
name: '用户列表',
type: 'subMenu',
url: '/user',
icon: ''
}
]
}
]
export default {
// props: ['isCollapse', 'defaultActive', 'menuJson'],
props: {
'isCollapse': {
type: Boolean,
default: true
},
'defaultActive': {
type: String,
default: '首页'
},
'menuJson': {
type: Array,
default: () => menuJson
}
},
data () {
return {
menus: this.menuJson
}
},
methods: {
handleOpen (key, keyPath) {
console.log(key, keyPath)
},
handleClose (key, keyPath) {
console.log(key, keyPath)
},
selected (name, index) {
本文档展示了后端人员如何使用vue2、vueRouter、vueX和element UI构建一个包含登录、路由、状态管理、报表和导出功能的后台管理框架。提供了项目结构、关键组件介绍及代码修改说明,包括Home、Head、Main、Menu、Table等组件的使用。源码可在GitHub和CSDN下载。
最低0.47元/天 解锁文章
3032

被折叠的 条评论
为什么被折叠?



