vue2后台管理项目(三) 组件+echarts使用+解决menu刷新不高亮

83 阅读5分钟

0b6d2b9b3ad57add196c88fa3d3b68d.jpg

图是小红书博主格格不茹,以它为原型实现网站

1.实现一个card组件

所有页面都使用了卡片模式,所以将其生成一个卡片组件以便使用

1.卡片的宽高可自定义

2.卡面的标题和内容自定义

3.实现基本样式

4.不同单位最后的宽高是不同的,%需要减去padding的宽高,应该是可以使用box-sizing这个属性改变。

注意:最好是给一个默认值

在src/components中创建card文件夹-> 创建card-index.vue文件

<template>
  <!--  卡片样式模板 -->
  <div class="card-style" :style="{ width: realWidth, height: realHeight }">
    <div class="title">
      <slot name="title"></slot>
    </div>
    <div class="content">
      <slot name="content"></slot>
    </div>
  </div>
</template>
<script>
export default {
  name: "Card",
  props: {
    // 卡片的宽度,默认200
    cardWidth: {
      type: Number,
      default: 400,
    },
    // 卡片的高度,默认100
    cardHeight: {
      type: Number,
      default: 250,
    },
    // 长宽单位,默认单位为px
    unit: {
      type: String,
      default: "px",
    },
  },
  computed: {
    realWidth(val) {
      if (val.unit === "%") {
        return "calc(" + this.cardWidth + "% - 30px)";
      } else {
        return this.cardWidth + this.unit;
      }
    },
    realHeight(val) {
      if (val.unit === "%") {
        return "calc(" + this.cardHeight + "% - 30px)";
      } else {
        return this.cardHeight + this.unit;
      }
    },
  },
};
</script>
<style scoped lang="less">
.card-style {
  background: #ffffff;
  box-shadow: 0 4px 8px 0 #efefef, 0 6px 20px 0 #efefef;
  border-radius: 10px;
  padding: 15px;
}
.title {
  color: #555555;
  font-weight: 600;
  font-size: 22px;
  margin-left: 10px;
  letter-spacing: 2px;
}
.content {
  width: 100%;
  height: calc(100% - 50px);
}
</style>

如何使用该组件呢?使用了父子组件传参,slot插槽

<template>
  <card :cardWidth="cardWidth" :cardHeight="cardHeight" :unit="unit">
    <template #title>本月支出占比</template>
  </card>
</template>
<script>
// 引入组件
import Card from "@/components/card/card-index.vue";
export default {
  name: "MonthPay",
  components: {
    Card,
  },
  data() {
    return {
      cardWidth: 100,
      cardHeight: 34,
      unit: "%",
    };
  },
};
</script>
<style scoped lang="less"></style>

2. vue中使用echarts

  1. 安装echarts
首先安装
npm install echarts --save
  1. 在文件中引入
import * as echarts from "echarts";
  1. 创建容器-注意容器需要在大小要不就会显示
<template>
   <div id="barChart"></div>
</template>
<script>
import * as echarts from "echarts";
export default {
  name: "Transaction",
  data() {
    return {
      goodsData: [520,909,1769,841,977,1683,1138,1985,1512,758,1541,1482],
      badsData: [129,72,190,238,208,8,34,37,64,64,116,95],
      months: [1,2,3,4,5,6,7,8,9,10,11,12],
    };
  },
  created() {
    this.initCharts();
  },
  methods: {
    initCharts() {
      const options = {
        tooltip: {
          trigger: "axis",
          axisPointer: {
            // 坐标轴指示器,坐标轴触发有效
            type: "shadow", // 默认为直线,可选为:'line' | 'shadow'
          },
        },
        legend: {
          data: ["好评", "差评"],
          align: "right",
          right: 10,
        },
        grid: {
          left: "3%",
          right: "4%",
          bottom: "3%",
          containLabel: true,
        },
        xAxis: [
          {
            type: "category",
            data: this.months,
          },
        ],
        yAxis: [
          {
            type: "value",
            axisLabel: {
              formatter: "{value}",
            },
          },
        ],
        series: [
          {
            name: "好评",
            type: "bar",
            // 实现颜色的渐变
            color: new echarts.graphic.LinearGradient(0, 1, 0, 0, [
              {
                offset: 0,
                color: "#faa169",
              },
              {
                offset: 1,
                color: "#fed88c",
              },
            ]),
            data: this.goodsData,
          },
          {
            name: "差评",
            type: "bar",
            color: new echarts.graphic.LinearGradient(0, 1, 0, 0, [
              {
                offset: 0,
                color: "#70afc2",
              },
              {
                offset: 1,
                color: "#98d8c1",
              },
            ]),
            data: this.badsData,
          },
        ],
      };
      const myChart = echarts.init(document.getElementById("barChart"));
      myChart.setOption(options);
    },
  },
};
</script>
<style scoped lang="less">
#barChart {
  height: 100%;
  width: 100%;
}
</style>

  1. 如何查看echarts文档

官方文档地址:echarts.apache.org/zh/option.h…

比如我现在想实现给柱状图添加圆角

找到series->柱状图type是bar,找到对应的bar的属性->柱状图圆角是图形样式,找到itemStyle->找到对应的属性borderRadius,看右边文档怎么使用 image.png 所以我们需要在series中的itemStyle属性设置itemStyle

itemStyle: {
   borderRadius: [5, 5, 0, 0],
},
 const options = {
        tooltip: {
          trigger: "axis",
          axisPointer: {
            // 坐标轴指示器,坐标轴触发有效
            type: "shadow", // 默认为直线,可选为:'line' | 'shadow'
          },
        },
        legend: {
          data: ["好评", "差评"],
          align: "right",
          right: 10,
        },
        grid: {
          left: "3%",
          right: "4%",
          bottom: "3%",
          containLabel: true,
        },
        xAxis: [
          {
            type: "category",
            data: this.months,
          },
        ],
        yAxis: [
          {
            type: "value",
            axisLabel: {
              formatter: "{value}",
            },
          },
        ],
        series: [
          {
            name: "好评",
            type: "bar",
            color: new echarts.graphic.LinearGradient(0, 1, 0, 0, [
              {
                offset: 0,
                color: "#faa169",
              },
              {
                offset: 1,
                color: "#fed88c",
              },
            ]),
            // 添加圆角
            itemStyle: {
              borderRadius: [5, 5, 0, 0],
            },
            data: this.goodsData,
          },
          {
            name: "差评",
            type: "bar",
            color: new echarts.graphic.LinearGradient(0, 1, 0, 0, [
              {
                offset: 0,
                color: "#70afc2",
              },
              {
                offset: 1,
                color: "#98d8c1",
              },
            ]),
            // 添加圆角
            itemStyle: {
              borderRadius: [5, 5, 0, 0],
            },
            data: this.badsData,
          },
        ],
      };

实现如下图 image.png

3.echarts中实现自适应

若不实现自适应,当我们窗口大小改变时,图表是不会变化的,如下图

image.png 在代码中添加就可以解决这个问题

  window.onresize = function () {
        myChart.resize();
 };
<template>
   <div id="barChart"></div>
</template>
<script>
import * as echarts from "echarts";
export default {
  name: "Transaction",
  data() {
    return {
      goodsData: [520,909,1769,841,977,1683,1138,1985,1512,758,1541,1482],
      badsData: [129,72,190,238,208,8,34,37,64,64,116,95],
      months: [1,2,3,4,5,6,7,8,9,10,11,12],
    };
  },
  created() {
    this.initCharts();
  },
  methods: {
    initCharts() {
      const options = {
        tooltip: {
          trigger: "axis",
          axisPointer: {
            // 坐标轴指示器,坐标轴触发有效
            type: "shadow", // 默认为直线,可选为:'line' | 'shadow'
          },
        },
        legend: {
          data: ["好评", "差评"],
          align: "right",
          right: 10,
        },
        grid: {
          left: "3%",
          right: "4%",
          bottom: "3%",
          containLabel: true,
        },
        xAxis: [
          {
            type: "category",
            data: this.months,
          },
        ],
        yAxis: [
          {
            type: "value",
            axisLabel: {
              formatter: "{value}",
            },
          },
        ],
        series: [
          {
            name: "好评",
            type: "bar",
            // 实现颜色的渐变
            color: new echarts.graphic.LinearGradient(0, 1, 0, 0, [
              {
                offset: 0,
                color: "#faa169",
              },
              {
                offset: 1,
                color: "#fed88c",
              },
            ]),
            data: this.goodsData,
          },
          {
            name: "差评",
            type: "bar",
            color: new echarts.graphic.LinearGradient(0, 1, 0, 0, [
              {
                offset: 0,
                color: "#70afc2",
              },
              {
                offset: 1,
                color: "#98d8c1",
              },
            ]),
            data: this.badsData,
          },
        ],
      };
      const myChart = echarts.init(document.getElementById("barChart"));
      myChart.setOption(options);
      // 添加自适应
      window.onresize = function () {
        myChart.resize();
      };
    },
  },
};
</script>
<style scoped lang="less">
#barChart {
  height: 100%;
  width: 100%;
}
</style>

4.解决左侧菜单栏刷新不高亮的问题

使用中发现,点击左侧菜单跳转后,菜单栏不能被高亮选中。若选择的是折叠的菜单的子菜单,刷新后菜单会折叠,并且菜单也不会被选中

需要用到default-active和router这两个属性 image.png

并且需要在路由中的meta中添加apiActiveMenu这个属性用来在menu中进行路径匹配

image.png

在menu.vue页面中el-menu-item和el-submenu中的index修改成对应的apiActiveMenu

image.png activeRouter设置为$route.path

image.png menu.vue全部代码如下

<template>
  <div>
    <div class="toggle-button" @click="toggleCollapse">
      <span>|||</span>
    </div>
    <el-menu
      class="menu-style"
      background-color="#FDD78E"
      text-color="#62504C"
      active-text-color="#EFEFEF"
      :collapse-transition="false"
      :collapse="isCollapse"
      unique-opened
      router
      :default-active="activeRouter"
    >
      <template v-for="item in menuList">
        <el-submenu
          v-if="item.children && item.children.length > 0"
          :index="item.meta.apiActiveMenu"
          :key="item.name"
        >
          <!-- 一级菜单 -->
          <template slot="title">
            <!-- 图标以及名称 -->
            <i :class="item.meta.icon"></i>
            <span class="title-style">{{ item.meta.name }}</span>
          </template>
          <!-- 二级菜单 -->
          <el-menu-item
            v-for="subItem in item.children"
            :index="subItem.meta.apiActiveMenu"
            :key="subItem.name"
          >
            <i :class="subItem.meta.icon"></i>
            <span class="title-style">{{ subItem.meta.name }}</span>
          </el-menu-item>
        </el-submenu>
        <el-menu-item v-else :index="item.meta.apiActiveMenu" :key="item.path">
          <i :class="item.meta.icon"></i>
          <span class="title-style">{{ item.meta.name }}</span>
        </el-menu-item>
      </template>
    </el-menu>
  </div>
</template>
<script>
export default {
  name: "Menu",
  data() {
    return {
      isCollapse: false,
      menuList: [],
      activeRouter: "",
    };
  },
  created() {
    this.menuList = this.$store.state.permission.sidebarMenu;
    this.activeRouter = this.$route.path;
  },
  methods: {
    toggleCollapse() {
      this.isCollapse = !this.isCollapse;
      this.$emit("toggleCollapse", this.isCollapse);
    },
    gotoRoute(pathName) {
      this.$router
        .push({
          name: pathName,
        })
        .catch((err) => {
          console.log(err);
        });
    },
  },
};
</script>
<style lang="less" scoped>
.toggle-button {
  background-color: #fdd78e;
  color: #6e595d;
  padding: 6px;
  line-height: 24px;
  cursor: pointer;
  letter-spacing: 0.1em;
  text-align: center;
}
.menu-style {
  width: 80%;
  border: none;
  margin: 5%;
}
.el-menu-item.is-active {
  background-color: #624e4e !important;
  border-radius: 15px;
  font-weight: 600;
}
.el-submenu .el-menu-item {
  min-width: 120px;
}
.el-menu-item:hover,
.el-menu-item:focus {
  background-color: rgba(98, 78, 78, 0.1);
  border-radius: 15px;
}

/deep/ .el-submenu__title:hover,
.el-submenu__title:focus {
  background-color: rgba(98, 78, 78, 0.1);
  border-radius: 15px;
}
.title-style {
  padding-left: 10px;
}
</style>