vue入门 | 使用vue.js2.0 + ElementUI开发后台管理系统详细教程(二)

458 阅读 58645评论 113喜欢 127

接上一章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

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,425评论 4 361
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,058评论 1 291
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,186评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,848评论 0 204
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,249评论 3 286
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,554评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,830评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,536评论 0 197
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,239评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,505评论 2 244
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,004评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,346评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,999评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,060评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,821评论 0 194
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,574评论 2 271
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,480评论 2 267

推荐阅读更多精彩内容