Vue Element UI custom description list component

Vue Element UI custom description list component

This article example shares the specific code of the Vue Element UI custom description list component for your reference. The specific content is as follows

Rendering

Written in front

When writing backend management, we often click on the list to view details and display data information. Although Element UI has a table component, it does not have a description component. Previously, team members had to write their own styles when encountering this situation, which was troublesome to write, and the styles written by each person were not unified, which destroyed the overall style of the project.
For example, Ant Design UI has a description component, which is very comfortable to use, so I simply wrote one myself by combining Element UI's el-row and el-col.

What functions are implemented

1. The height of each row is automatically expanded according to the maximum height of a column in the row.
2. Automatically complete the column width to avoid the last column being incomplete
3. Support plain text and HTML slots
4. Support the setting of several columns per row
5. Support customization of each column width
6. Support dynamic data redrawing

Component Design

1. Use parent-child component nesting, the parent component is e-desc, and the child component is e-desc-item.
2. e-desc-item passes the label of props and the value of the slot, and uses $slots.content to display the DOM
3. Use el-row and el-col to implement overall component layout

Encapsulate e-desc components

<template>
  <div class="desc" :style="{margin}">
    <!-- Title -->
    <h1 v-if="title" class="desc-title" v-html="title"></h1>
    <el-row class="desc-row">
      <slot/>
    </el-row>
  </div>
</template>

<script>
export default {
  name: 'EDesc',
  // Provided to child components through provide () {
    return {
      labelWidth: this.labelWidth,
      column: this.column,
      size: this.size
    }
  },
  props: {
    // Data source, listen to data and redraw data: {
      type: Object,
      required: true,
      default () {
        return {}
      }
    },
    // Title: {
      type: String,
      default: ''
    },
    // Margin: {
      type: String,
      default: '0'
    },
    // label width labelWidth: {
      type: String,
      default: '120px'
    },
    column: {
      // The number of items displayed per line type: [Number, String],
      default: 3
    },
    size: {
      // size type: String,
      default: ''
    }
  },
  watch:
    data: {
      handler () {
        this.$nextTick(() => {
          // Filter out the subcomponent e-desc-item
          const dataSource = this.$slots.default
          const dataList = []
          dataSource.forEach(item => {
            if (item.componentOptions && item.componentOptions.tag === 'e-desc-item') {
              dataList.push(item.componentInstance)
            }
          })
          // Remaining span
          let leftSpan = this.column
          const len ​​= dataList.length
          dataList.forEach((item, index) => {
            // Handle the relationship between column and span // The number of remaining columns is less than the set number of spans const hasLeft = leftSpan <= (item.span || 1)
            // The next column of the current column is larger than the remaining span
            const nextColumnSpan = (index < (len - 1)) && (dataList[index + 1].span >= leftSpan)
            // The last column of the last row const isLast = index === (len - 1)
            if (hasLeft || nextColumnSpan || isLast) {
            // If the above conditions are met, span needs to be automatically completed to avoid the last column being incomplete item.selfSpan = leftSpan
              leftSpan = this.column
            } else {
              leftSpan -= item.span || 1
            }
          })
        })
      },
      deep: true,
      immediate: true
    }
  }
}
</script>

<style scoped lang="scss">
  .desc{
    .desc-title {
      margin-bottom: 10px;
      color: #333;
      font-weight: 700;
      font-size: 16px;
      line-height: 1.5715;
    }
    .desc-row{
      display: flex;
      flex-wrap: wrap;
      border-radius: 2px;
      border: 1px solid #EBEEF5;
      border-bottom: 0;
      border-right: 0;
      width: 100%;
    }
  }
</style>

Encapsulate the e-desc-item component

<template>
  <el-col :span="computedSpan" class="desc-item">
    <div class="desc-item-content" :class="size">
      <label class="desc-item-label" :style="{width: labelWidth}" v-html="label"></label>
      <div class="desc-item-value" v-if="$slots">
        <!-- Plain text -->
        <slot v-if="$slots.default && $slots.default[0].text"/>
        <!-- HTML -->
        <slot name="content" v-else-if="$slots.content"/>
        <span v-else>No data</span>
      </div>
    </div>
  </el-col>
</template>

<script>
export default {
  name: 'EDescItem',
  inject: ['labelWidth', 'column', 'size'],
  props: {
    span: {
      type: [Number, String],
      required: false,
      default: 0
    },
    label: {
      type: String,
      required: false,
      default: ''
    }
  },
  data () {
    return {
      // The subcomponent's own span
      selfSpan: 0
    }
  },
  computed: {
    computedSpan() {
      // The child component's own span is used by the parent component to calculate and modify the span
      if (this.selfSpan) {
        return 24 / this.column * this.selfSpan
      } else if (this.span) {
      // span passed by props
        return 24 / this.column * this.span
      } else {
      // When span is not passed, take column
        return 24 / this.column
      }
    }
  }
}
</script>

<style scoped lang="scss">
  .desc-item {
    border-right: 1px solid #EBEEF5;
    border-bottom: 1px solid #EBEEF5;
    .desc-item-content {
      display: flex;
      justify-content: flex-start;
      align-items: center;
      color: rgba(0,0,0,.65);
      font-size: 14px;
      line-height: 1.5;
      width: 100%;
      background-color: #fafafa;
      height: 100%;
      .desc-item-label{
        border-right: 1px solid #EBEEF5;
        display: inline-block;
        padding: 12px 16px;
        flex-grow: 0;
        flex-shrink: 0;
        color: rgba(0, 0, 0, 0.6);
        font-weight: 400;
        font-size: 14px;
        line-height: 1.5;
        height: 100%;
        display: flex;
        align-items: center;
      }
      .desc-item-value{
        background: #fff;
        padding: 12px 16px;
        flex-grow: 1;
        overflow: hidden;
        word-break: break-all;
        height: 100%;
        display: flex;
        align-items: center;
        color: #444;
        span{
          color: #aaa;
        }
      }
      &.small {
        .desc-item-label,
        .desc-item-value {
          padding: 10px 14px;
        }
      }
    }
  }
</style>

How to use

<template>
  <e-desc :data='info' margin='0 12px' label-width='100px'>
    <e-desc-item label="Name">{{info.name}}</e-desc-item>
    <e-desc-item label="Age">{{ info.age }} years old</e-desc-item>
    <e-desc-item label="Gender">{{ info.sex }}</e-desc-item>
    <e-desc-item label="School">{{ info.school }}</e-desc-item>
    <e-desc-item label="Professional">{{ info.major }}</e-desc-item>
    <e-desc-item label="Hobby">{{ info.hobby }}</e-desc-item>
    <e-desc-item label="Mobile number">{{ info.phone }}</e-desc-item>
    <e-desc-item label="微信">{{ info.wx }}</e-desc-item>
    <e-desc-item label="QQ">{{ info.qq }}</e-desc-item>
    <e-desc-item label="Address">{{ info.address }}</e-desc-item>
    <e-desc-item label="Self-description" :span='2'>{{ info.intro }}</e-desc-item>
    <e-desc-item label="Operation" :span='3'>
      <template slot="content">
        <el-button size="small" type="primary">Modify</el-button>
        <el-button size="small" type="danger">Delete</el-button>
      </template>
    </e-desc-item>
  </e-desc>
</template>

<script>
import EDesc from './e-desc'
import EDescItem from './e-desc-item'
export default {
  components:
    EDesc, EDescItem
  },
  data () {
    return {
      info:
        name: 'Jerry',
        age: 26,
        sex: 'male',
        school: 'Sichuan University',
        major: 'Professional coder',
        address: 'Chengdu, Sichuan Province',
        hobby: 'Moving bricks, front-end, making money',
        phone: 18888888888,
        wx: 'Nice2cu_Hu',
        QQ: 332983810,
        intro: 'I am a painter, and I am good at painting. I want to paint the new house to make it more beautiful. After painting the roof, he painted the wall, with the brush flying around busily. Oh my little nose, it has changed. I am a painter and I have strong painting skills. I want to paint the new house to make it more beautiful. After painting the roof, he painted the wall, with the brush flying around busily. Oh my little nose, it has changed. '
      }
    }
  }
}
</script>

Parameter Description

At this point, the code is finished. If there are any inconsiderations or bugs, please leave me a message to let me know.

The above is the full content of this article. I hope it will be helpful for everyone’s study. I also hope that everyone will support 123WORDPRESS.COM.

You may also be interested in:
  • Implementation of Element-ui Layout (Row and Col components)
  • Element-UI tutorial on using el-row column layout
  • Element el-row el-col layout component detailed explanation

<<:  How to modify server uuid in Mysql

>>:  Tutorial on how to use profile in MySQL

Recommend

A detailed introduction to the Linux directory structure

When you first start learning Linux, you first ne...

Installation and configuration tutorial of MySQL 8.0.16 under Win10

1. Unzip MySQL 8.0.16 The dada folder and my.ini ...

A brief discussion on the $notify points of element

My original intention was to encapsulate the $not...

Implementation of docker redis5.0 cluster cluster construction

System environment: Ubuntu 16.04LTS This article ...

The difference between where and on in MySQL and when to use them

When I was writing join table queries before, I a...

Mysql slow query optimization method and optimization principle

1. For comparison of date size, the date format p...

vue-element-admin global loading waiting

Recent requirements: Global loading, all interfac...

Writing a rock-paper-scissors game in JavaScript

This article shares the specific code for writing...

A brief discussion on the performance issues of MySQL paging limit

MySQL paging queries are usually implemented thro...

The process of installing Docker in Linux system

In this blog, I will walk you through the process...

The specific use and difference between attribute and property in Vue

Table of contents As attribute and property value...

Detailed installation tutorial of mysql 5.7 under CentOS 6 and 7

You always need data for development. As a server...

Solution to the Docker container cannot be stopped and deleted

Find the running container id docker ps Find the ...