ElementUi 搭建后台管理系统的常见几个实用功能

table表格

table表格遍历数据


子项是绑定一个prop属性进行全部遍历出来



但有时候需求不是这样的,我们的需求不是照着模板遍历出来,或者想使用v-model绑定数据时,就需要用到插槽的方式进行使用。


form表单同样适用


使用

scope.row.value 取到遍历数组的项
scope.$index 可以直接取到序号

button按钮+dialog对话框

button按钮+dialog对话框应用场景最多的就是后台管理系统的新增页面和编辑页面,由于后台管理系统的新增功能和编辑功能是有异曲同工之妙,所以我们一般不会分成2个页面去写,而是写在一个页面上。

我们来看下新增页面和编辑页面对比。



页面几乎一样,我们要做的其实只是对数据进行如何区分罢了。

那么,这怎么区分用户点击的是编辑按钮还是新增按钮呢?而与此同时,对话框的标题也随之对应呢?




因为我是父子组件的方式写的,所以需要传值,但不影响逻辑



子组件需要接收一个属性过来,用一个三元运算符就可区分出用户点击了新增按钮还是编辑按钮,点击新增按钮就是新增页面的对话框,反之亦然。

关键就是父组件如何进行对应的逻辑编写,其实就是一个if else语句可以搞定了,前提是子组件发送事件传递过来,父组件接收。

只需这样就知道用户点击了哪个按钮,用一个if语句判断,如果用户点击编辑按钮,那就编写编辑功能的代码。



tag标签,状态筛查的逻辑

状态筛查也是后台管理系统使用的比较多的功能



一般后端写接口,都是以0 1 2 3 4 来区分status, 0-4几个数字分别代表不同的状态,而前端这边发起请求,就是将label作为参数传递给后端



在data中定义数据

将用户的选中的状态发送给后台


根据状态码,在表格中展示不同风格的tag和信息



折叠导航栏

先来看效果图,这种需求也是后台管理系统场景常见。


这种操作是怎么实现的呢?

像上面这种需求,我们一般也是父子组件分离写的,不会在一个页面上写,为的就是组件分离,不让页面太繁杂,父子组件开发在vue中十分重要且频繁使用。

话不多说,进入正题,先看下页面结构拆分就知道为什么要父子组件啦。

所以说,做后台管理系统又是200%逃不开layout布局了,在这里建议,一定要学会这种layout布局

回到需求上面来。

从上面那张结构拆解图来看,侧边栏和头部区域还有主体区域都是属于子组件,因此,他们3个都是由一个父亲来控制。


逻辑代码实现部分,关键是弄懂这3个人之间的 :collapse="isCollapse"属性是怎么互相通讯的,弄懂了这个就明白了logo文字的变化,图标的切换等等。

父组件

<template>
  <div class="layout-container">
    <el-container style="height: 100%">
      <el-aside class="aside" width="auto">
        <Aside :isCollapse="isCollapse" class="aside-menu" />
      </el-aside>
      <el-container>
        <el-header class="header">
          <HeaderView
            @changeCollapse="changeCollapse"
            :isCollapse="isCollapse"
          />
        </el-header>
        <el-main class="main">
          <router-view></router-view>
        </el-main>
      </el-container>
    </el-container>
  </div>
</template>

<script>

import Aside from "./components/aside.vue";
import HeaderView from "./components/header.vue";

export default {
  data() {
    return {
      isCollapse: false,
    };
  },
  components: {
    Aside,
    HeaderView,
  },
  methods: {
    changeCollapse() {
      this.isCollapse = !this.isCollapse;
    },
  },
};
</script>

侧边栏

<template>
    <el-menu
      :default-active="this.$route.path"
      class="el-menu-vertical-demo"
      @open="handleOpen"
      @close="handleClose"
      background-color="#002033"
      text-color="#fff"
      active-text-color="#ffd04b"
      router
      :collapse="isCollapse"
      
    >
    <div class="logo">{{ isCollapse ? "logo" : "logo 后台登录系统" }}</div>
      <el-menu-item
        v-for="(item, index) in menu"
        :key="index"
        :index="item.path"

      >
        <i :class="item.icon"></i>
        <span slot="title">{{ item.label }}</span>
      </el-menu-item>
    </el-menu>
  
</template>

<script>
export default {
  data() {
    return {
      menu: [
        {
          label: "首页",
          path: "/home",
          icon: "el-icon-s-home",
        },
        {
          label: "内容管理",
          path: "/article",
          icon: "el-icon-document",
        },
        {
          label: "素材管理",
          path: "/images",

          icon: "el-icon-picture",
        },
        {
          label: "发布文章",
          path: "/publish",
          icon: "el-icon-collection-tag",
        },
        {
          label: "评论管理",
          path: "/comment",
          icon: "el-icon-s-comment",
        },
        {
          label: "粉丝管理",
          path: "/fans",
          icon: "el-icon-connection",
        },
        {
          label: "个人设置",
          path: "/settings",
          icon: "el-icon-setting",
        },
      ],
    };
  },
    props: ["isCollapse"],
  methods: {
    handleOpen(key, keyPath) {
      console.log(key, keyPath);
    },
    handleClose(key, keyPath) {
      console.log(key, keyPath);
    },
  },
};
</script>

<style lang="less" scoped>
.logo {
    font-size: 22px;
    color: white;
    text-align: center;
    user-select: none;
}
  .el-menu-vertical-demo:not(.el-menu--collapse) {
    width: 200px;
    min-height: 400px;
    
  }
</style>

头部

<template>
  <div class="header-container">
    <div style="font-size: 24px">
      <i
        @click="change"
        :class="{
          'el-icon-s-fold': !isCollapse,
          'el-icon-s-unfold': isCollapse,
        }"
      ></i>
      <span style="margin-left: 10px">XXXXXX有限公司</span>
    </div>
    <el-dropdown>
      <div class="avatar-wrap">
        <img class="avatar" :src="user.photo" alt="" />
        <span>{{user.name}}</span>
        <i class="el-icon-arrow-down el-icon--right"></i>
      </div>
      <el-dropdown-menu slot="dropdown">
        <el-dropdown-item icon="el-icon-s-tools">个人设置</el-dropdown-item>
        <el-dropdown-item
          icon="el-icon-switch-button"
          @click.native="onLogout"
          >用户退出</el-dropdown-item
        >
      </el-dropdown-menu>
    </el-dropdown>
  </div>
</template>

<script>
import { getUserProfile } from '@/api/user';
export default {
    data(){
        return {
            user:{}
        }
    },
  props: ["isCollapse"],
  created() {
    //组件初始化好,请求获取用户资料
    this.loadUserProfile();
  },
  methods: {
    change() {
      this.$emit("changeCollapse"); //tips:涉及3个组件用store改良方案最好
    },
    loadUserProfile() {
      getUserProfile().then((res) => {
        this.user = res.data
      });
    },
    onLogout(){
                this.$confirm('确认退出登录吗?', '退出提示', {
          confirmButtonText: '确定',
          cancelButtonText: '取消',
          type: 'warning'
        }).then(() => {
             localStorage.removeItem('user')
        this.$router.push('/')
        }).catch(() => {
          this.$message({
            type: 'info',
            message: '已取消退出'
          });          
        });
      }

    }
  }
</script>

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

推荐阅读更多精彩内容