Small knowledge, big challenge! This article is participating in the creation activity of “Essential Tips for Programmers”

This article also participated in the “Digitalstar Project” to win a creative gift package and creative incentive money

preface

Blessed by Buddha, there is no bug. Hello everyone! I am across the sea!

Sometimes in a project we have to take a prototype from the UI and turn it into a concrete page that uses components that are not readily available. At this point, you need to implement these specific components yourself.

These are components that you can use, that are generic to you, that you can reuse.

Today write a ranking component, this usually use also more. It’s kind of generic

Go straight to code

The effect is as follows:

This custom component is based on the progress bar component in Element-UI

<template>
  <div style="width:382px; height: calc(100vh - 502px); overflow-y: auto; overflow-x: hidden; margin:20px;">
    <div>
      <div class="rank-title">Latest 30-day cumulative emissions ranking</div>
      <div>
        <div v-show="Cumulative_Rank.length>0" style="width: 382px; height:386px;">
          <div v-for="(item,index) in Cumulative_Rank"
            :key="index"
            style="width:350px; padding-left:10px;">
            <el-row style="font-size:14px; color:#606266;">{{index + 1 + "  "+item.name}}</el-row>
            <el-row style="height:18px;">
              <el-col :span="20">
                <el-progress :percentage="item.percent" :stroke-width="10" color="#50c097"></el-progress>
              </el-col>
              <el-col :span="4">
                <span style="color:#50c097; font-weight:bold; margin-left:-35px;">{{item.value? item.value:''}}</span>
              </el-col>
            </el-row>
          </div>
        </div>
        <div v-show="Cumulative_Rank == null || Cumulative_Rank.length == 0" style="width: 382px; height:260px; line-height:260px; text-align:center; color:#909399;">Temporarily no data</div>
      </div>
    </div>
  </div>
</template>
<script>
export default {
  data() {
    return {
      // List of rankings
      Cumulative_Rank: [{name: 'Business Name 1'.value: 6600.percent: 100 },
        { name: 'Business Name 2'.value: 5940.percent: 90 },
        { name: 'Company Name 3'.value: 5280.percent: 80 },
        { name: 'Company Name 4'.value: 4620.percent: 70 },
        { name: 'Company Name 5'.value: 3960.percent: 60 },
        { name: 'Company Name 6'.value: 3300.percent: 50 },
        { name: 'Company Name 7'.value: 2640.percent: 40 },
        { name: 'Company Name 8'.value: 1980.percent: 30},]}; },methods: {},mounted(){},created(){}};</script>
<style lang="scss" scoped>
.rank-title{
  font-size: 18px;
  color: #2D8CF0;
  font-weight: bold;
  margin-top: 10px;
  margin-bottom: 10px;
}


::v-deep .el-progress__text{
  display:none;
}
::v-deep .el-progress-bar__outer{
  background-color: rgba(235.238.245.0);
}

.progress-txt{
  .progress-title{
    width: 68px;
    display: inline-block;
    position: relative;
  }
  .progress-percen{
    display: inline-block;
    position: relative;
    left: 0px; }}.progress-custom{
  position: relative;
  // width: 364px;
  width: 100%;
  height: 20px;
  .progress-content{
    position: absolute;
    width: 100%;
    height: 12px;
    background-color: #ebeef5;
    margin: 1px;
    border-radius: 6px;
  }
  .progress-value{
    position: absolute;
    width: 20%;
    height: 12px;
    background-color: #43bef1;
    margin: 1px;
    border-radius: 6px;
    left: 0px; // After testing,leftTo the most70%It's already on the right}}</style>

Copy the code

If you actually run the project, you will find that as soon as the page loads, first there will be a blank screen, and then, after a while, the data will load out, which is the kind of sudden, the data will come out, and the senses will feel very abrupt. If you actually tune the interface, it will be even more noticeable

In this case, we use loading in element-UI to make the transition

Extension 1 – Increases loading

<template>
  <div style="width:382px; height: calc(100vh - 502px); overflow-y: auto; overflow-x: hidden; margin:20px;">
    <div>
      <div class="rank-title">Latest 30-day cumulative emissions ranking</div>
      <div v-loading="loading"
        element-loading-text="Loading, please wait..."
        element-loading-spinner="el-icon-loading"
        element-loading-background="Rgba (255, 255, 255, 0.8)">
        <div v-show="Cumulative_Rank.length>0" style="width: 382px; height:386px;">
          <div v-for="(item,index) in Cumulative_Rank"
            :key="index"
            style="width:350px; padding-left:10px;">
            <el-row style="font-size:14px; color:#606266;">{{index + 1 + "  "+item.name}}</el-row>
            <el-row style="height:18px;">
              <el-col :span="20">
                <el-progress :percentage="item.percent" :stroke-width="10" color="#50c097"></el-progress>
              </el-col>
              <el-col :span="4">
                <span style="color:#50c097; font-weight:bold; margin-left:-35px;">{{item.value? item.value:''}}</span>
              </el-col>
            </el-row>
          </div>
        </div>
        <div v-show="Cumulative_Rank == null || Cumulative_Rank.length == 0" style="width: 382px; height:260px; line-height:260px; text-align:center; color:#909399;">Temporarily no data</div>
      </div>

    </div>
  </div>
</template>
<script>
export default {
  data() {
    return {
      / / load
      loading: true.// true: the file is being loaded. False: the file is loaded
      // List of rankings
      Cumulative_Rank: [{name: 'Business Name 1'.value: 6600.percent: 100 },
        { name: 'Business Name 2'.value: 5940.percent: 90 },
        { name: 'Company Name 3'.value: 5280.percent: 80 },
        { name: 'Company Name 4'.value: 4620.percent: 70 },
        { name: 'Company Name 5'.value: 3960.percent: 60 },
        { name: 'Company Name 6'.value: 3300.percent: 50 },
        { name: 'Company Name 7'.value: 2640.percent: 40 },
        { name: 'Company Name 8'.value: 1980.percent: 30},]}; },methods: {
    // Simulate the loading process under normal interface experience (without calling axios)
    mockNormal() {
      this.loading = true;
      setTimeout(() = > {
        // This is the concrete implementation logic....
        / /...
        // Close the dialog box
        this.loading = false;
      }, 1000);
    },
    // Normal interface status
    Function_GetData() {
      this.loading = true; // The interface is being loaded.
      this.Cumulative_Rank = []; // Empties the last data retrieved from the interface
      this.$axios({
        method: 'get'.url: 'http://xxx.xxx.xxx.xxx:xxxx/xxxx/xxxx/xxxx'.// The interface address of the actual running project
        params: {
        },
      }).then((res) = > {
        if(res.data.data ! =null) {
          const onlineData = res.data.data;
          / / emissions
          if (onlineData.out.ports.length > 0) {
            for (let i = 0; i < onlineData.out.ports.length; i++) {
              this.Cumulative_Rank.push({ name: The '-'.value: 0.percent: 0 });
              this.Cumulative_Rank[i].portName = onlineData.out.ports[i].portName;
              this.Cumulative_Rank[i].value = onlineData.out.values[i];
              if (i === 0) {
                // Take the first value as the maximum value, which means 100%
                this.Cumulative_Rank[i].percent = 100;
              } else {
                // The following values are not as large as the first value, which is divided by the first value to get the percentage
                this.Cumulative_Rank[i].percent = (onlineData.out.values[i] / onlineData.out.values[0]) * 100; }}this.loading = false; // The interface has been adjusted successfully, and the data has been processed}}else {
          setTimeout(() = > {
            this.loading = false; // After 1 second, close the loading box, wait no longer
          }, 1000);
        }
      }).catch(() = > {
        setTimeout(() = > {
          this.loading = false; // Interface error! ? Count him out. 8 seconds later, close the load box
        }, 8000); }); }},mounted() {
    // Simulate a normal interface
    this.mockNormal();
    // Normal interface status
    // this.Function_GetData();
  },
  created(){}};</script>
<style lang="scss" scoped>
.rank-title{
  font-size: 18px;
  color: #2D8CF0;
  font-weight: bold;
  margin-top: 10px;
  margin-bottom: 10px;
}
::v-deep .el-progress__text{
  display:none;
}
::v-deep .el-progress-bar__outer{
  background-color: rgba(235.238.245.0);
}
.progress-txt{
  .progress-title{
    width: 68px;
    display: inline-block;
    position: relative;
  }
  .progress-percen{
    display: inline-block;
    position: relative;
    left: 0px; }}.progress-custom{
  position: relative;
  // width: 364px;
  width: 100%;
  height: 20px;
  .progress-content{
    position: absolute;
    width: 100%;
    height: 12px;
    background-color: #ebeef5;
    margin: 1px;
    border-radius: 6px;
  }
  .progress-value{
    position: absolute;
    width: 20%;
    height: 12px;
    background-color: #43bef1;
    margin: 1px;
    border-radius: 6px;
    left: 0px; // After testing,leftTo the most70%It's already on the right}}</style>
Copy the code

The mockNormal() method is used to mockNormal the Function_GetData() method

Extension 2 – Works with custom TAB switching

Ranking is sometimes used in combination with custom TAB toggling

The effect is as follows:

Custom TAB toggle, for those of you who are confused, you can take a quick peek: portal

There is an optimization point here, and we can say that TAB switching is usually one page for each TAB, and if the structure of the page for each TAB is different, then each TAB writes its corresponding page separately. However, if the structure of the page is the same for each TAB, you don’t need to repeat the write and just change the data in the structure.

This time the code custom TAB switch, simple and crude direct use of V-show to do, because this time the focus is on the ranking component (actually I am lazy, hahaha)

So if you’re interested in this, you can try it out by changing this TAB switch to the custom TAB switch from the previous article

<template>
  <div style="margin:8px;">
    <div style="padding-top:10px;">
      <span class="icon-block"></span>
      <span class="icon-txt">TOP5 emissions in the last 30 days</span>
    </div>
    <div style="margin-bottom:5px;">
      <span style="padding-left:20px; cursor: pointer; font-weight:bold;" :class="{'selType': curSelType=='2','noSelType':curSelType=='1'}" @click="handleTypeClick(2)">Waste gas</span>
      <i class="el-icon-s-operation" style="padding-left:5px; color:#2D8CF0;"></i>
      <span style="padding-left:5px; cursor: pointer; font-weight:bold;" :class="{'selType': curSelType=='1','noSelType':curSelType=='2'}" @click="handleTypeClick(1)">Waste water</span>

      <span v-show="curSelType=='2'" :class="{'factorName':true, 'selFactor': curSelFactor==' soot ', 'noSelFactor': curSelFactor! = 'smoke'}" @click="HandleFactorClick (' smoke ', 'a34013')">The smoke</span>
      <span v-show="curSelType=='2'" :class="{'factorName':true, 'selFactor': curSelFactor=='SO2', 'noSelFactor': curSelFactor! ='SO2'}" @click="handleFactorClick('SO2','a21026')">SO2</span>
      <span v-show="curSelType=='2'"  :class="{'factorName':true, 'selFactor': curSelFactor=='NOx', 'noSelFactor': curSelFactor! ='NOx'}" @click="handleFactorClick('NOx','a21002')">NOx</span>


      <span v-show="curSelType=='1'" :class="{'factorName':true, 'selFactor': curSelFactor=='COD', 'noSelFactor': curSelFactor! ='COD'}" @click="handleFactorClick('COD','w01018')">COD</span>
      <span v-show="curSelType=='1'" :class="{'factorName':true, 'selFactor': curSelFactor==' ammonia ', 'noSelFactor': curSelFactor! = 'ammonia nitrogen'}" @click="HandleFactorClick (' ammonia nitrogen, 'w21003')">Ammonia nitrogen</span>
      <span v-show="curSelType=='1'"  :class="{'factorName':true, 'selFactor': curSelFactor==' sewage ', 'noSelFactor': curSelFactor! '=' sewage}" @click="HandleFactorClick (' water ', 'w00000')">sewage</span>
    </div>
    <div v-show="top10Data.length>0" style="height:185px;">
      <div v-for="(item,index) in top10Data"
            :key="index"
            style="width:350px; padding-left:10px;"
      >
        <el-row style="font-size:14px; color:#606266;">{{index+1 + "  "+item.psName}}</el-row>
        <el-row style="height:18px;">
          <el-col :span="21">
            <el-progress :percentage="item.percent" :stroke-width="10" color="#43BEF1"></el-progress>
          </el-col>
          <el-col :span="3">
            <span style="color:#2D8CF0; font-weight:bold; margin-left:-20px;">{{item.totalEmissions? item.totalEmissions.toFixed(0):''}}</span>
          </el-col>
        </el-row>
      </div>
    </div>
    <div v-show="top10Data == null || top10Data.length == 0" style="height:185px; line-height:185px; width:360px; text-align:center; color:#909399;">Temporarily no data</div>
  </div>
</template>
<script>
export default {
  props: {
    titleName: {
      type: String.default() {
        return ' '; }},},data() {
    return {
      curSelType: 2.// 1 waste water 2 exhaust gas. The exhaust gas module is selected by default
      curSelFactor: 'smoke'.// The default selected factor is smoke
      curSelFactorCode: 'a34013'.top10Data: [
        // {name: 'enterprise name 1', value: 6629, percent: 100},
        // {name: 'enterprise name 2', value: 6023, percent: 90},
        // {name: 'enterprise name 3', value: 5680, percent: 80},
        // {name: 'enterprise name 4', value: 4258, percent: 70},
        // {name: 'enterprise name 5', value: 2561, percent: 40},
        // {name: 'enterprise name ', value: 2500, percent: 30},
        // {name: 'enterprise name 7', value: 2500, percent: 30},
        // {name: 'enterprise name 8', value: 2500, percent: 30},
        // {name: 'enterprise name 9', value: 2500, percent: 30},
        // {name: 'enterprise name 10', value: 2500, percent: 30},]}; },methods: {
    // Switch modules
    handleTypeClick(type) {
      if(this.curSelType ! = type) {this.curSelType = type;
        if (type == 1) {
          this.curSelFactor = 'COD';
          this.curSelFactorCode = 'w01018';
        }else {
          this.curSelFactor = 'smoke';
          this.curSelFactorCode = 'a34013';
        }
        this.getTop10Data(); }},// Switch factor
    handleFactorClick(name, code) {
      this.curSelFactor = name;
      this.curSelFactorCode = code;
      this.getTop10Data();
    },
    // Get data
    getTop10Data() {
      this.top10Data = [];
      // Implement the specific service tuning interface
      // ...}},mounted() {
    this.getTop10Data();
  },
  created(){}};</script>
<style lang="scss" scoped>
.icon-block{
  display:inline-block;
  width:6px;
  height:22px;
  background-color: #2D8CF0;
  border-radius: 10px;
}
.icon-txt{
  position: relative;
  top: -5px;
  padding-left: 5px;
  font-size: 16px;
  color:#2D8CF0;
  font-weight: bold;
}
::v-deep .el-progress__text{
  display:none;
}
.factorName{
  display: inline-block;
  // background: blue;
  height: 30px;
  width: 55px;
  text-align: center;
  line-height: 30px;
  margin-left: 20px;
  border-radius: 5px;
  cursor: pointer;
  font-weight:bold;
  color: white;
}
.selFactor{
  background: #458BF3;
}
.noSelFactor{
  color: #458BF3;
}
.selType{
  color: #2D8CF0;
}
.noSelType{
  color: # 606266;
}
</style>

Copy the code