接上一章vue入门 | 使用vue.js2.0 + ElementUI开发后台管理系统详细教程(一)
在线demo
源码
1. 引入路由工具vue-router,切换视图
#安装vue-router
npm install vue-router --save
2. 使用vue-router
|-- main.js
import Vue from 'vue'
import App from './App'
import VueRouter from 'vue-router'
import routeConfig from './router-config' // 引入router-config.js文件
//加载路由中间件
Vue.use(VueRouter)
//定义路由
const router = new VueRouter({
routes: routeConfig
})
new Vue({
router,
store,
el: "#app",
render: h => h(App)
})
3. 配置路由
在src目录下新建router-config.js,在router-cinfig.js中里面配置路由
// 引入组件
import activePublic from './page/activePublic/index.vue'
export default [
{
// 配置路由,当路径为'/activePublic',使用组件activePublic
path:'/activePublic',component:activePublic,
}
]
4. 使用路由
|--app.vue
<template>
<div id="app">
<!-- 头部导航 -->
...
<main>
<!-- 左侧导航 -->
<div class="main-left">
...
</div>
<!-- 右侧主内容区 -->
<div class="main-right" >
<!-- 视图 -->
<router-view class="view"></router-view>
</div>
</main>
</div>
</template>
5. 打开activePublic/index.vue文件,在页面随便写点东西,测试一下,路由是否配置成功
<template>
<div class="activePublic ">
<!-- element步骤组件 -->
<el-steps :space="200" :active="step" class="step">
<el-step title="活动信息" description=""></el-step>
<el-step title="报名签到" description=""></el-step>
<el-step title="分享设置" description=""></el-step>
<el-step title="个性设置" description=""></el-step>
</el-steps>
</template>
6. 启动项目npm run dev
,看到如下页面,说明路由配置成功
step1.png
7. 接下来,在activePublic/index.vue直接调用element-ui组件,完成活动发布的首页,完成好的代码如下
|-- activePublic/index.vue
<template>
<div class="activePublic ">
<!-- 步骤组件 -->
<el-steps :space="200" :active="step" class="step">
<el-step title="活动信息" description=""></el-step>
<el-step title="报名签到" description=""></el-step>
<el-step title="分享设置" description=""></el-step>
<el-step title="个性设置" description=""></el-step>
</el-steps>
<!-- 视图 -->
<router-view class="view"></router-view>
<div class="but-group">
<el-button >预览</el-button>
<el-button >上一步</el-button>
<el-button type="primary">下一步</el-button>
<el-button type="primary">发布活动</el-button>
</div>
</div>
</template>
上面这个页面又出现了一个router-view,为什么要这样放呢?因为step1、step2、step3、step4四个页面都含有顶部的"步骤"组件,所以这里把step1/2/3/4单独提出来放在4个页面中
8. 在router-config.js文件中配置二级路由
|-- router-config.js
import activePublic from './page/activePublic/index.vue'
<!-- 引入子页面 -->
import step1 from './page/activePublic/step1.vue'
import step2 from './page/activePublic/step2.vue'
import step3 from './page/activePublic/step3.vue'
import step4 from './page/activePublic/step4.vue'
export default [
{
path:'/activePublic',component:activePublic,
// 配置子路由
children:[
// 路径为'/activePublic',使用组件step1
{ path: '' , component: step1 },
// 路径为'/activePublic/step1',使用组件step1
{ path: 'step1', component: step1 },
// 路径为'/activePublic/step2',使用组件step2
{ path: 'step2', component: step2 },
{ path: 'step3', component: step3 },
{ path: 'step4', component: step4 }
]
}
]
9. 重新启动项目cnpm run dev
,在浏览器中默认路径为http://localhost:8080/#/activePublic,根据我们设置的路由规则,就会显示step1.vue页面中的内容,接着完成step1.vue,代码如下,参考element表单组件
|-- step1.vue
<template>
// TODO:这个页面有一个不足之处,时间选择器组件,表单验证出错,这是element组件的问题,留给大家自己去完善
<div class="step1">
<!-- element表单组件 -->
<el-form :model="ruleForm" class="demo-ruleForm" :rules="rules" ref="ruleForm" label-position="top">
<!-- 表单项,prop属性表示要进行表单验证,验证规则对应为rules的属性name -->
<el-form-item label="活动名称" prop="name">
<el-input v-model="ruleForm.name" size="large"></el-input>
</el-form-item>
<el-form-item label="" prop="fenLei">
<!-- 改装后的表单项,在标签栏添加了一个按钮 -->
<el-row style="height: 35px;" type="flex" align="middle">
<el-col :span="3" style="width: 90px;">
<div class="el-form-item__label" style="padding-bottom: 0;"> 活动分类</div>
</el-col>
<el-col class="" :span="2">
<el-button type="text" @click.native="dialogFormFenLeiVisible = true" style="margin: 0;padding: 0;">设置</el-button>
</el-col>
</el-row>
<el-radio-group v-model="ruleForm.fenLei" >
<el-radio v-for="item of ruleForm.fenLeis" :label="item.name"></el-radio>
</el-radio-group>
</el-form-item>
<!-- 这里有一个坑,活动标签并不是一个表单元素,无法使用element自带的验证功能 -->
<el-form-item label="活动标签" required>
<el-tag
v-for="tag in ruleForm.tags"
:closable="true"
type="primary"
@close="handleClose(tag)"
>
{{tag.name}}
</el-tag>
<el-button icon="plus" size="large" @click.native="showDialog" style="vertical-align: middle;margin: 10px;"></el-button>
<transition name="fade">
<div class="el-form-item__error" v-show="tagsValid">{{ tagsError }}</div>
</transition>
</el-form-item>
<el-form-item label="活动时间" required style="width: 750px;">
<el-col :span="5">
<!-- 时间选择器,表单验证时也有点坑,报错异常,建议不用element自带表单验证,自己写验证规则 -->
<el-form-item prop="activeStartTimeDate">
<el-date-picker
v-model="ruleForm.activeStartTimeDate"
type="date"
placeholder="活动开始日期">
</el-date-picker>
</el-form-item>
</el-col>
<el-col :span="5">
<el-form-item prop="activeStartTimeTime">
<el-time-select
placeholder="请选择时间点"
v-model="ruleForm.activeStartTimeTime"
:picker-options="{start: '00:00',step: '00:15',end: '23:45'}">
</el-time-select>
</el-form-item>
</el-col>
<el-col :span="1" style="text-align: center;">—</el-col>
<el-col :span="5">
<el-form-item prop="activeEndTimeDate">
<el-date-picker
v-model="ruleForm.activeEndTimeDate"
type="date"
placeholder="活动结束日期">
</el-date-picker>
</el-form-item>
</el-col>
<el-col :span="5">
<el-form-item prop="activeEndTimeTime">
<el-time-select
placeholder="请选择时间点"
v-model="ruleForm.activeEndTimeTime"
:picker-options="{start: '00:00',step: '00:15',end: '23:45'}">
</el-time-select>
</el-form-item>
</el-col>
</el-form-item>
<el-form-item label="报名时间" required style="width: 750px;">
<el-col :span="5">
<el-form-item prop="signStartTimeDate">
<el-date-picker
v-model="ruleForm.signStartTimeDate"
type="date"
placeholder="报名开始日期">
</el-date-picker>
</el-form-item>
</el-col>
<el-col :span="5">
<el-form-item prop="signStartTimeTime">
<el-time-select
placeholder="请选择时间点"
v-model="ruleForm.signStartTimeTime"
:picker-options="{start: '00:00',step: '00:15', end: '23:45'}">
</el-time-select>
</el-form-item>
</el-col>
<el-col :span="1" style="text-align: center;">—</el-col>
<el-col :span="5">
<el-form-item prop="signEndTimeDate">
<el-date-picker
v-model="ruleForm.signEndTimeDate"
type="date"
placeholder="报名结束日期">
</el-date-picker>
</el-form-item>
</el-col>
<el-col :span="5">
<el-form-item prop="signEndTimeTime">
<el-time-select
placeholder="请选择时间点"
v-model="ruleForm.signEndTimeTime"
:picker-options="{start: '00:00',step: '00:15',end: '23:45'}">
</el-time-select>
</el-form-item>
</el-col>
</el-form-item>
<el-form-item label="活动地点" required >
<!-- 自己封装的一个二级联动地址选择器 -->
<address-select
:province="ruleForm.province"
:city="ruleForm.city"
:detail="ruleForm.detail"
:isAddressTrue="isAddressTrue"
></address-select>
</el-form-item>
<el-form-item label="活动人数">
<el-row>
<el-col :span="6" style="width: 187px;">
<el-radio class="radio" v-model="ruleForm.activePerson" label="无限制">无限制</el-radio>
<el-radio class="radio" v-model="ruleForm.activePerson" label="限制">限制</el-radio>
</el-col>
<el-col :span="6">
<el-input placeholder="0" :number="true" size="large" v-model="ruleForm.activePersonNum" :disabled=" ruleForm.activePerson == '无限制' "><template slot="append">人</template></el-input>
</el-col>
</el-row>
</el-form-item>
<el-form-item label="活动封面">
<el-upload action="http://jsonplaceholder.typicode.com/" type="drag" :multiple="true" :on-preview="handlePreview" :on-remove="handleRemove" :on-success="handleSuccess" :on-error="handleError">
<i class="el-icon-upload"></i>
<div class="el-dragger__text">将文件拖到此处,或<em>点击上传</em></div>
<div class="el-upload__tip" slot="tip">只能上传jpg/png文件,且不超过2M</div>
</el-upload>
</el-form-item>
<el-form-item label="活动简介">
<el-input
type="textarea"
placeholder="请输入内容"
:autosize="{minRows: 4, maxRows: 8}"
v-model="ruleForm.activeDescribe">
</el-input>
</el-form-item>
<el-form-item label="报名用户信息展示">
<el-radio-group v-model="ruleForm.UseMsgShow">
<el-radio label="不展示"></el-radio>
<el-radio label="展示报名人数"></el-radio>
<el-radio label="展示报名清单"></el-radio>
<el-radio label="报名成功显示完整用户资料"></el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="评价功能">
<el-radio-group v-model="ruleForm.evaluate">
<el-radio label="不开启"></el-radio>
<el-radio label="实时评价"></el-radio>
<el-radio label="审核后评论"></el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="">
<el-row>
<div class="el-form-item__label"> 赞助广告</div>
<el-col class="el-form-item__label is-active" :span="2">
<el-button type="text" @click.native="openAd">开通赞助广告</el-button>
</el-col>
</el-row>
<el-upload action="http://jsonplaceholder.typicode.com/" type="drag" :multiple="true" :on-preview="handlePreview" :on-remove="handleRemove" :on-success="handleSuccess" :on-error="handleError">
<i class="el-icon-upload"></i>
<div class="el-dragger__text">将文件拖到此处,或<em>点击上传</em></div>
<div class="el-upload__tip" slot="tip">图片尺寸建议比例1;4.18,如160*666像素,且不超过2M</div>
</el-upload>
</el-form-item>
<el-form-item>
<el-input
placeholder="请填写您的广告标题"
size="large"
v-model="ruleForm.adTitle">
</el-input>
</el-form-item>
<el-form-item>
<el-input
placeholder="请填写您的广告内容"
size="large"
v-model="ruleForm.adContent">
</el-input>
</el-form-item>
<el-form-item >
<el-input
placeholder="请填写您的赞助链接"
size="large"
v-model="ruleForm.adLink">
</el-input>
</el-form-item>
</el-form>
<!-- 弹框 -->
<el-dialog title="添加活动标签" v-model="dialogFormVisible" top="35%">
<el-form :model="dialogForm">
<el-form-item>
<el-input v-model="dialogForm.name" auto-complete="off" ></el-input>
</el-form-item>
</el-form>
<span slot="footer" class="dialog-footer">
<el-button @click.native="dialogFormVisible = false">取 消</el-button>
<el-button type="primary" @click.native="handleAdd(dialogForm.name,dialogForm,ruleForm.tags)">添加</el-button>
</span>
</el-dialog>
<!-- 设置活动分类 -->
<el-dialog title="设置活动分类" v-model="dialogFormFenLeiVisible" >
<el-form :model="dialogFormFenLei">
<el-form-item>
<el-tag
v-for="feiLei of ruleForm.fenLeis"
:closable="true"
type="primary"
@close="handleCloseFenLei(feiLei)"
>
{{ feiLei.name }}
</el-tag>
</el-form-item>
<el-form-item>
<el-input v-model="dialogFormFenLei.name" auto-complete="off" ></el-input>
</el-form-item>
</el-form>
<span slot="footer" class="dialog-footer">
<el-button @click.native="dialogFormFenLeiVisible = false">取 消</el-button>
<el-button type="primary" @click.native="handleAdd(dialogFormFenLei.name,dialogFormFenLei,ruleForm.fenLeis)">添加</el-button>
</span>
</el-dialog>
</div>
</template>
<script>
// 地址选择器组件
import addressSelect from 'src/components/address.vue'
export default {
name:'step1',
// 组件
components: {
'address-select' : addressSelect
},
data: function () {
return {
tagsValid:false, // 活动标签是否合法
tagsError:'请设置标签', // 活动标签不合法的提示信息
isAddressTrue:false, // 地址是否正确
dialogFormVisible: false, // 添加活动标签的对话框可见?
dialogFormFenLeiVisible:false, // 分类对话框可见?
dialogForm:{name:''}, // 活动标签对话框表单
dialogFormFenLei:{name:''}, // 活动分类对话框表单
ruleFormChange:false, // ruleForm表单是否改变?
ruleFormValid:false, // ruleForm是否合法?
rules: { // 表单验证规则
name:[
{required:true,message:'请输入活动名称',trigger:'change'}
],
fenLei:[
{required:true,message:'请选择活动分类',trigger:'change'}
],
activeStartTimeDate: [{required:true,message:'请选择活动开始日期',trigger:'change'}],
activeStartTimeTime: [{required:true,message:'请选择活动开始时间',trigger:'change'}],
activeEndTimeDate: [{required:true,message:'请选择活动结束日期',trigger:'change'}],
activeEndTimeTime: [{required:true,message:'请选择活动结束时间',trigger:'change'}],
signStartTimeDate: [{required:true,message:'请选择报名开始日期',trigger:'change'}],
signStartTimeTime: [{required:true,message:'请选择报名开始时间',trigger:'change'}],
signEndTimeDate: [{required:true,message:'请选择报名截止日期',trigger:'change'}],
signEndTimeTime: [{required:true,message:'请选择报名截止时间',trigger:'change'}],
},
ruleForm: { // step1页面的表单,记录页面所有表单信息
name: '', // 活动名称
fenLeis:[ // 活动分类选项
{name: '未发布'},
{name: '测试活动'},
{name: '精彩活动'}
],
fenLei: '', // 当前选中的活动分类
tags: [], // 活动标签
activeStartTimeDate: '', // 活动开始时间
activeStartTimeTime: '', // 活动结束时间
activeEndTimeDate: '',
activeEndTimeTime: '',
signStartTimeDate: '',
signStartTimeTime: '',
signEndTimeDate: '',
signEndTimeTime: '',
activePerson:'', // 是否限制活动人数?
activePersonNum:'', // 限制多少人?
activeDescribe:'', // 活动简介
UseMsgShow:'', // 报名活动信息展示
evaluate:'', // 评价功能
adTitle:'', // 广告标题
adContent:'', // 广告内容
adLink:'', // 赞助链接
}
};
},
watch: { // 监控
ruleForm: {
handler: function (val,oldVal) {
store.commit('setRuleForm',this.ruleForm);
this.tagsValid = !this.ruleForm.tags.length ? '' :false ;
this.ruleFormChange = true ;
},
deep: true // 深度监控,可以观察到ruleForm内任意属性的变化
}
},
methods: {
handleRemove: function (file, fileList) {
console.log(file, fileList);
},
handlePreview: function (file) {
console.log(file);
},
handleSuccess: function () {
},
handleError: function () {
},
// 显示添加活动标签对话框
showDialog: function () {
if(this.ruleForm.tags.length >=5 ){
this.$message({
message: '最多设置5个标签',
type: 'warning'
});
}else{
this.dialogFormVisible = true;
this.dialogForm = {};
}
},
// 删除活动标签
handleClose: function (tag) {
var index = this.ruleForm.tags.indexOf(tag);
this.ruleForm.tags.splice(index,1);
},
// 删除活动分类的某一项
handleCloseFenLei: function (fenLei){
var index = this.ruleForm.fenLeis.indexOf(fenLei);
this.ruleForm.fenLeis.splice(index,1);
},
// 添加标签
handleAdd: function (tag,form,tags) {
if(tag && tag.trim().length !== 0){
var isExist = false ;
tag = tag.trim();
for(var i=0;i<tags.length; i++){
if(tags[i].name == tag ){
isExist = true;
break
}
}
if(isExist){
this.$message({
message: '该标签已存在',
type: 'warning'
});
}else{
this.dialogFormVisible = false;
this.dialogFormFenLeiVisible = false;
tags.push({
name: tag
});
}
}else{
this.$message({
message: '标签不能为空',
type: 'warning'
});
}
},
openAd: function (){
this.$message('该功能正在完善');
},
},
// 页面初始化
created: function(){
}
}
</script>
<style>
.step{margin-bottom: 30px;}
.step1 .demo-ruleForm .el-form-item{margin-bottom: 25px;margin-right: 50px;}
.step1 .el-form-item.is-required .el-form-item__label:after {
content: '*';
color: #ff4949;
margin-right: 4px;
}
.step1 .el-form-item.is-required .el-form-item__label:before { display: none; }
/* 标签 */
.step1 .el-tag{padding: 10px 15px;margin:10px;vertical-align: middle;}
.step1 .el-tag:first-child{margin-left: 0;}
/* 对话框 */
.step1 .el-dialog--small{width: 564px;}
.step1 .el-dialog__body{padding-bottom: 0;}
.step1 .el-dialog__body .el-form-item{margin-bottom: 10px;}
.step1 .el-dialog__wrapper .el-button{margin-left: 15px;}
/* 时间选择器 */
.step1 .el-date-editor{width:150px;}
.step1 .el-form-item .router-link{color:#fff;}
.el-form-item__error{white-space: nowrap;}
</style>
这个页面的大部分是使用的element组件,请自行对照官网实现。在这个页面中封装了一个二级地址选择插件,稍后会专门写一篇文章,详细介绍如何封装组件,先为大家奉上地址选择器源码。
10. 重新启动项目,npm run dev
,检查页面上的功能是否都已经实现,是否有报错,如果有解决不了的bug,欢迎留言咨询。
演示 (1).gif