接上一章vue入門 | 使用vue.js2.0 + ElementUI開(kāi)發(fā)后臺(tái)管理系統(tǒng)詳細(xì)教程(一)
在線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 [
{
// 配置路由市埋,當(dāng)路徑為'/activePublic',使用組件activePublic
path:'/activePublic',component:activePublic,
}
]
4. 使用路由
|--app.vue
<template>
<div id="app">
<!-- 頭部導(dǎo)航 -->
...
<main>
<!-- 左側(cè)導(dǎo)航 -->
<div class="main-left">
...
</div>
<!-- 右側(cè)主內(nèi)容區(qū) -->
<div class="main-right" >
<!-- 視圖 -->
<router-view class="view"></router-view>
</div>
</main>
</div>
</template>
5. 打開(kāi)activePublic/index.vue文件,在頁(yè)面隨便寫點(diǎn)東西互墓,測(cè)試一下必尼,路由是否配置成功
<template>
<div class="activePublic ">
<!-- element步驟組件 -->
<el-steps :space="200" :active="step" class="step">
<el-step title="活動(dòng)信息" description=""></el-step>
<el-step title="報(bào)名簽到" description=""></el-step>
<el-step title="分享設(shè)置" description=""></el-step>
<el-step title="個(gè)性設(shè)置" description=""></el-step>
</el-steps>
</template>
6. 啟動(dòng)項(xiàng)目npm run dev
,看到如下頁(yè)面篡撵,說(shuō)明路由配置成功
step1.png
7. 接下來(lái)判莉,在activePublic/index.vue直接調(diào)用element-ui組件,完成活動(dòng)發(fā)布的首頁(yè)育谬,完成好的代碼如下
|-- activePublic/index.vue
<template>
<div class="activePublic ">
<!-- 步驟組件 -->
<el-steps :space="200" :active="step" class="step">
<el-step title="活動(dòng)信息" description=""></el-step>
<el-step title="報(bào)名簽到" description=""></el-step>
<el-step title="分享設(shè)置" description=""></el-step>
<el-step title="個(gè)性設(shè)置" description=""></el-step>
</el-steps>
<!-- 視圖 -->
<router-view class="view"></router-view>
<div class="but-group">
<el-button >預(yù)覽</el-button>
<el-button >上一步</el-button>
<el-button type="primary">下一步</el-button>
<el-button type="primary">發(fā)布活動(dòng)</el-button>
</div>
</div>
</template>
上面這個(gè)頁(yè)面又出現(xiàn)了一個(gè)router-view券盅,為什么要這樣放呢?因?yàn)閟tep1膛檀、step2锰镀、step3、step4四個(gè)頁(yè)面都含有頂部的"步驟"組件宿刮,所以這里把step1/2/3/4單獨(dú)提出來(lái)放在4個(gè)頁(yè)面中
8. 在router-config.js文件中配置二級(jí)路由
|-- router-config.js
import activePublic from './page/activePublic/index.vue'
<!-- 引入子頁(yè)面 -->
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. 重新啟動(dòng)項(xiàng)目cnpm run dev
,在瀏覽器中默認(rèn)路徑為http://localhost:8080/#/activePublic,根據(jù)我們?cè)O(shè)置的路由規(guī)則胡桃,就會(huì)顯示step1.vue頁(yè)面中的內(nèi)容,接著完成step1.vue,代碼如下磕潮,參考element表單組件
|-- step1.vue
<template>
// TODO:這個(gè)頁(yè)面有一個(gè)不足之處翠胰,時(shí)間選擇器組件容贝,表單驗(yàn)證出錯(cuò),這是element組件的問(wèn)題之景,留給大家自己去完善
<div class="step1">
<!-- element表單組件 -->
<el-form :model="ruleForm" class="demo-ruleForm" :rules="rules" ref="ruleForm" label-position="top">
<!-- 表單項(xiàng)斤富,prop屬性表示要進(jìn)行表單驗(yàn)證,驗(yàn)證規(guī)則對(duì)應(yīng)為rules的屬性name -->
<el-form-item label="活動(dòng)名稱" prop="name">
<el-input v-model="ruleForm.name" size="large"></el-input>
</el-form-item>
<el-form-item label="" prop="fenLei">
<!-- 改裝后的表單項(xiàng)锻狗,在標(biāo)簽欄添加了一個(gè)按鈕 -->
<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;"> 活動(dòng)分類</div>
</el-col>
<el-col class="" :span="2">
<el-button type="text" @click.native="dialogFormFenLeiVisible = true" style="margin: 0;padding: 0;">設(shè)置</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>
<!-- 這里有一個(gè)坑满力,活動(dòng)標(biāo)簽并不是一個(gè)表單元素,無(wú)法使用element自帶的驗(yàn)證功能 -->
<el-form-item label="活動(dòng)標(biāo)簽" 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="活動(dòng)時(shí)間" required style="width: 750px;">
<el-col :span="5">
<!-- 時(shí)間選擇器轻纪,表單驗(yàn)證時(shí)也有點(diǎn)坑油额,報(bào)錯(cuò)異常,建議不用element自帶表單驗(yàn)證刻帚,自己寫驗(yàn)證規(guī)則 -->
<el-form-item prop="activeStartTimeDate">
<el-date-picker
v-model="ruleForm.activeStartTimeDate"
type="date"
placeholder="活動(dòng)開(kāi)始日期">
</el-date-picker>
</el-form-item>
</el-col>
<el-col :span="5">
<el-form-item prop="activeStartTimeTime">
<el-time-select
placeholder="請(qǐng)選擇時(shí)間點(diǎn)"
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="活動(dòng)結(jié)束日期">
</el-date-picker>
</el-form-item>
</el-col>
<el-col :span="5">
<el-form-item prop="activeEndTimeTime">
<el-time-select
placeholder="請(qǐng)選擇時(shí)間點(diǎn)"
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="報(bào)名時(shí)間" required style="width: 750px;">
<el-col :span="5">
<el-form-item prop="signStartTimeDate">
<el-date-picker
v-model="ruleForm.signStartTimeDate"
type="date"
placeholder="報(bào)名開(kāi)始日期">
</el-date-picker>
</el-form-item>
</el-col>
<el-col :span="5">
<el-form-item prop="signStartTimeTime">
<el-time-select
placeholder="請(qǐng)選擇時(shí)間點(diǎn)"
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="報(bào)名結(jié)束日期">
</el-date-picker>
</el-form-item>
</el-col>
<el-col :span="5">
<el-form-item prop="signEndTimeTime">
<el-time-select
placeholder="請(qǐng)選擇時(shí)間點(diǎn)"
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="活動(dòng)地點(diǎn)" required >
<!-- 自己封裝的一個(gè)二級(jí)聯(lián)動(dòng)地址選擇器 -->
<address-select
:province="ruleForm.province"
:city="ruleForm.city"
:detail="ruleForm.detail"
:isAddressTrue="isAddressTrue"
></address-select>
</el-form-item>
<el-form-item label="活動(dòng)人數(shù)">
<el-row>
<el-col :span="6" style="width: 187px;">
<el-radio class="radio" v-model="ruleForm.activePerson" label="無(wú)限制">無(wú)限制</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 == '無(wú)限制' "><template slot="append">人</template></el-input>
</el-col>
</el-row>
</el-form-item>
<el-form-item label="活動(dòng)封面">
<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>點(diǎn)擊上傳</em></div>
<div class="el-upload__tip" slot="tip">只能上傳jpg/png文件,且不超過(guò)2M</div>
</el-upload>
</el-form-item>
<el-form-item label="活動(dòng)簡(jiǎn)介">
<el-input
type="textarea"
placeholder="請(qǐng)輸入內(nèi)容"
:autosize="{minRows: 4, maxRows: 8}"
v-model="ruleForm.activeDescribe">
</el-input>
</el-form-item>
<el-form-item label="報(bào)名用戶信息展示">
<el-radio-group v-model="ruleForm.UseMsgShow">
<el-radio label="不展示"></el-radio>
<el-radio label="展示報(bào)名人數(shù)"></el-radio>
<el-radio label="展示報(bào)名清單"></el-radio>
<el-radio label="報(bào)名成功顯示完整用戶資料"></el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="評(píng)價(jià)功能">
<el-radio-group v-model="ruleForm.evaluate">
<el-radio label="不開(kāi)啟"></el-radio>
<el-radio label="實(shí)時(shí)評(píng)價(jià)"></el-radio>
<el-radio label="審核后評(píng)論"></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">開(kāi)通贊助廣告</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>點(diǎn)擊上傳</em></div>
<div class="el-upload__tip" slot="tip">圖片尺寸建議比例1掂僵;4.18,如160*666像素顷歌,且不超過(guò)2M</div>
</el-upload>
</el-form-item>
<el-form-item>
<el-input
placeholder="請(qǐng)?zhí)顚懩膹V告標(biāo)題"
size="large"
v-model="ruleForm.adTitle">
</el-input>
</el-form-item>
<el-form-item>
<el-input
placeholder="請(qǐng)?zhí)顚懩膹V告內(nèi)容"
size="large"
v-model="ruleForm.adContent">
</el-input>
</el-form-item>
<el-form-item >
<el-input
placeholder="請(qǐng)?zhí)顚懩馁澲溄?
size="large"
v-model="ruleForm.adLink">
</el-input>
</el-form-item>
</el-form>
<!-- 彈框 -->
<el-dialog title="添加活動(dòng)標(biāo)簽" 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>
<!-- 設(shè)置活動(dòng)分類 -->
<el-dialog title="設(shè)置活動(dòng)分類" 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, // 活動(dòng)標(biāo)簽是否合法
tagsError:'請(qǐng)?jiān)O(shè)置標(biāo)簽', // 活動(dòng)標(biāo)簽不合法的提示信息
isAddressTrue:false, // 地址是否正確
dialogFormVisible: false, // 添加活動(dòng)標(biāo)簽的對(duì)話框可見(jiàn)锰蓬?
dialogFormFenLeiVisible:false, // 分類對(duì)話框可見(jiàn)?
dialogForm:{name:''}, // 活動(dòng)標(biāo)簽對(duì)話框表單
dialogFormFenLei:{name:''}, // 活動(dòng)分類對(duì)話框表單
ruleFormChange:false, // ruleForm表單是否改變衙吩?
ruleFormValid:false, // ruleForm是否合法互妓?
rules: { // 表單驗(yàn)證規(guī)則
name:[
{required:true,message:'請(qǐng)輸入活動(dòng)名稱',trigger:'change'}
],
fenLei:[
{required:true,message:'請(qǐng)選擇活動(dòng)分類',trigger:'change'}
],
activeStartTimeDate: [{required:true,message:'請(qǐng)選擇活動(dòng)開(kāi)始日期',trigger:'change'}],
activeStartTimeTime: [{required:true,message:'請(qǐng)選擇活動(dòng)開(kāi)始時(shí)間',trigger:'change'}],
activeEndTimeDate: [{required:true,message:'請(qǐng)選擇活動(dòng)結(jié)束日期',trigger:'change'}],
activeEndTimeTime: [{required:true,message:'請(qǐng)選擇活動(dòng)結(jié)束時(shí)間',trigger:'change'}],
signStartTimeDate: [{required:true,message:'請(qǐng)選擇報(bào)名開(kāi)始日期',trigger:'change'}],
signStartTimeTime: [{required:true,message:'請(qǐng)選擇報(bào)名開(kāi)始時(shí)間',trigger:'change'}],
signEndTimeDate: [{required:true,message:'請(qǐng)選擇報(bào)名截止日期',trigger:'change'}],
signEndTimeTime: [{required:true,message:'請(qǐng)選擇報(bào)名截止時(shí)間',trigger:'change'}],
},
ruleForm: { // step1頁(yè)面的表單,記錄頁(yè)面所有表單信息
name: '', // 活動(dòng)名稱
fenLeis:[ // 活動(dòng)分類選項(xiàng)
{name: '未發(fā)布'},
{name: '測(cè)試活動(dòng)'},
{name: '精彩活動(dòng)'}
],
fenLei: '', // 當(dāng)前選中的活動(dòng)分類
tags: [], // 活動(dòng)標(biāo)簽
activeStartTimeDate: '', // 活動(dòng)開(kāi)始時(shí)間
activeStartTimeTime: '', // 活動(dòng)結(jié)束時(shí)間
activeEndTimeDate: '',
activeEndTimeTime: '',
signStartTimeDate: '',
signStartTimeTime: '',
signEndTimeDate: '',
signEndTimeTime: '',
activePerson:'', // 是否限制活動(dòng)人數(shù)?
activePersonNum:'', // 限制多少人?
activeDescribe:'', // 活動(dòng)簡(jiǎn)介
UseMsgShow:'', // 報(bào)名活動(dòng)信息展示
evaluate:'', // 評(píng)價(jià)功能
adTitle:'', // 廣告標(biāo)題
adContent:'', // 廣告內(nèi)容
adLink:'', // 贊助鏈接
}
};
},
watch: { // 監(jiān)控
ruleForm: {
handler: function (val,oldVal) {
store.commit('setRuleForm',this.ruleForm);
this.tagsValid = !this.ruleForm.tags.length ? '' :false ;
this.ruleFormChange = true ;
},
deep: true // 深度監(jiān)控坤塞,可以觀察到ruleForm內(nèi)任意屬性的變化
}
},
methods: {
handleRemove: function (file, fileList) {
console.log(file, fileList);
},
handlePreview: function (file) {
console.log(file);
},
handleSuccess: function () {
},
handleError: function () {
},
// 顯示添加活動(dòng)標(biāo)簽對(duì)話框
showDialog: function () {
if(this.ruleForm.tags.length >=5 ){
this.$message({
message: '最多設(shè)置5個(gè)標(biāo)簽',
type: 'warning'
});
}else{
this.dialogFormVisible = true;
this.dialogForm = {};
}
},
// 刪除活動(dòng)標(biāo)簽
handleClose: function (tag) {
var index = this.ruleForm.tags.indexOf(tag);
this.ruleForm.tags.splice(index,1);
},
// 刪除活動(dòng)分類的某一項(xiàng)
handleCloseFenLei: function (fenLei){
var index = this.ruleForm.fenLeis.indexOf(fenLei);
this.ruleForm.fenLeis.splice(index,1);
},
// 添加標(biāo)簽
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: '該標(biāo)簽已存在',
type: 'warning'
});
}else{
this.dialogFormVisible = false;
this.dialogFormFenLeiVisible = false;
tags.push({
name: tag
});
}
}else{
this.$message({
message: '標(biāo)簽不能為空',
type: 'warning'
});
}
},
openAd: function (){
this.$message('該功能正在完善');
},
},
// 頁(yè)面初始化
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; }
/* 標(biāo)簽 */
.step1 .el-tag{padding: 10px 15px;margin:10px;vertical-align: middle;}
.step1 .el-tag:first-child{margin-left: 0;}
/* 對(duì)話框 */
.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;}
/* 時(shí)間選擇器 */
.step1 .el-date-editor{width:150px;}
.step1 .el-form-item .router-link{color:#fff;}
.el-form-item__error{white-space: nowrap;}
</style>
這個(gè)頁(yè)面的大部分是使用的element組件,請(qǐng)自行對(duì)照官網(wǎng)實(shí)現(xiàn)澈蚌。在這個(gè)頁(yè)面中封裝了一個(gè)二級(jí)地址選擇插件摹芙,稍后會(huì)專門寫一篇文章,詳細(xì)介紹如何封裝組件宛瞄,先為大家奉上地址選擇器源碼浮禾。
10. 重新啟動(dòng)項(xiàng)目,npm run dev
,檢查頁(yè)面上的功能是否都已經(jīng)實(shí)現(xiàn),是否有報(bào)錯(cuò)份汗,如果有解決不了的bug盈电,歡迎留言咨詢。
演示 (1).gif