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

Detailed steps to use Redis in Docker

1. Introduction This article will show you how to...

Example code for implementing a simple search engine with MySQL

Table of contents Preface Introduction ngram full...

Summary of common operation skills of MySQL database

This article summarizes common operating techniqu...

A brief introduction to VUE uni-app basic components

1. scroll-view When using vertical scrolling, you...

A Preliminary Study on Vue Unit Testing

Table of contents Preface Why introduce unit test...

CSS optimization skills self-practice experience

1. Use css sprites. The advantage is that the smal...

mysql code to implement sequence function

MySQL implements sequence function 1. Create a se...

MySQL query tree structure method

Table of contents MySQL query tree structure 1. A...

How to redirect to https through nginx load balancing

Copy the certificate and key on the web scp -rp -...

MySQL column to row conversion, method of merging fields (must read)

Data Sheet: Column to row: using max(case when th...

Basic ideas and codes for implementing video players in browsers

Table of contents Preface Summary of audio and vi...

Nginx Linux installation and deployment detailed tutorial

1. Introduction to Nginx Nginx is a web server th...

Complete steps to enable gzip compression in nginx

Table of contents Preface 1. Configure gzip compr...

JavaScript explains the encapsulation and use of slow-motion animation

Implementing process analysis (1) How to call rep...