vue+element-ui el-descriptions details rendering component secondary encapsulation (Vue project)

Table of Contents

1. Demand

2. The desired effect is to change from picture 1 to picture 2

?edit

3. The component integrates the following functions

4. Parameter configuration

Sample code

Parameter Description

5, components

6. Page usage


1. Demand

In general backend management systems, pages usually have additions, deletions, modifications, and checks; and check is nothing more than rendering the newly added/modified data (from an input box to a disabled input box), because the color of the input box after it is disabled The transparency will be reduced and the displayed color will be darker; to solve this requirement, the Details component was encapsulated

2. The desired effect is to change from picture 1 to picture 2

3. The component integrates the following functions

Operation button customization
Dictionary type (that is, the numeric type returned in the background) is filtered and converted into Chinese
Custom template array type object type
Render image

4. Parameter configuration

sample code

 <orderDetail :descList="detailModule" :data="renderData"></orderDetail>

Parameter Description

 * [
     * {
     * title:String category title
     * column:Number How many per row (default 2)
     * size:String size medium / small / mini (default medium)
     * border:Boolean border (default true)
     * keyArr:[
     * {
     * icon:String, (icon describing the title)
     * label:String, description title
     * keyName:String (corresponding translation value)
     * Corresponding translation value when innerKey: String array
     * detailType: "image" render image
     * formatter:Function: Custom rendering
     * getTranslation: Function: handles the value of translation when it is an object
     * }
     * ]
     * extra:{ 'Action button'
     * text:String (button copy)
     * methods:function (method callback)
     * }
     * }
     * ]

5,component

<template>
  <div class="detail-box demo-image__error cell-44">
    <el-descriptions v-for="(item, index) in descList" :border="item.border || true" :key="'descList' + index"
      class="mb20" :title="item.title || ''" :column="item.column || 2" labelClassName="custom-label"
      contentClassName="custom-content" :size="item.size || 'medium'">
      <template slot="extra" v-if="item.extra">
        <el-button type="primary" size="small" @click="item.extra.methods(item, index)">{<!-- -->{ item.extra.text }}</el- button>
      </template>
      <!-- Description title -->
      <el-descriptions-item v-for="(descKey, innerIndex) in item.keyArr" :key="innerIndex + 'desc'">
        <template slot="label" v-if="descKey.label">
          <i class="el-icon-user" v-if="item.icon"></i>
          {<!-- -->{ descKey.label }}
        </template>
        <!-- Picture type data -->
        <div class="cell" v-if="descKey.detailType == 'image'">
          <el-image style="width: 44px; height: 44px" :src="data[descKey.keyName]">
            <div slot="error" class="image-slot">
              <i class="el-icon-picture-outline"></i>
            </div>
          </el-image>
        </div>
        <!-- Custom template -->
        <div v-else-if="descKey.formatter" v-html="descKey.formatter(data)"></div>
        <!-- Array object, or array -->
        <template v-else-if="Array.isArray(data[descKey.keyName])">
          <el-tag v-for="(innerItem, innerI) in data[descKey.keyName]" :key="'tag' + innerI" size="small"
            class="mr10 mb10">
            {<!-- -->{ (descKey.innerKey ? innerItem[descKey.innerKey] : innerItem) || "--" }}
          </el-tag>
        </template>
        <!-- Default key-value pair -->
        <span v-else-if="(data[descKey.keyName] || data[descKey.keyName] === 0) & amp; & amp;
          typeof data[descKey.keyName] !== 'object'
          ">
          {<!-- -->{
            data[descKey.keyName] || data[descKey.keyName] == 0
            ?data[descKey.keyName]
            : "--"
          }}
        </span>
        <!-- Object type data -->
        <span v-else-if="typeof data[descKey.keyName] === 'object'">
          <el-descriptions :data="data[descKey.keyName]" :border="false">
            <el-descriptions-item v-for="(value, key) in data[descKey.keyName]" :key="key">
              <template slot="label">{<!-- -->{ descKey.getTranslation(key, index) }}</template>
              <span>{<!-- -->{ value }}</span>
            </el-descriptions-item>
          </el-descriptions>
        </span>
        <!-- No matching items -->
        <span v-else>--</span>

      </el-descriptions-item>
    </el-descriptions>
  </div>
</template>

<script>
export default {
  props: {
    /**
     *[
     * {
     * title:String category title
     * column:Number How many per row (default 2)
     * size:String size medium / small / mini (default medium)
     * border:Boolean border (default true)
     * keyArr:[
     * {
     * icon:String, (icon describing the title)
     * label:String, description title
     * keyName:String (corresponding translation value)
     * Corresponding translation value when innerKey: String array
     * detailType: "image" render image
     * formatter:Function: Custom rendering
     * getTranslation: Function: handles the value of translation when it is an object
     * }
     * ]
     * extra:{ 'Action button'
     * text:String(copywriting)
     * methods:function (method callback)
     * }
     * }
     * ]
     */
    descList: {
      type: Array,
      default: () => {
        return [];
      },
    },
    data: {
      type: Object,
      default: () => {
        return {};
      },
    },
  },
};
</script>

<style lang="scss">
.custom-label,
.custom-content {
  width: 25% !important;
}

.demo-image__error .image-slot,
.demo-image__placeholder .image-slot {
  display: flex;
  justify-content: center;
  align-items: center;
  width: 100%;
  height: 100%;
  background: #f5f7fa;
  color: #909399;
  font-size: 14px;
}

.cell-44 {
  .cell {
    height: 44px;
    line-height: 44px;
  }
}
</style>

6. Page usage

<template>
  <div class="table-page">
    <FormDetail :descList="detailModule" :data="renderData"></FormDetail>
  </div>
</template>
<script>
import FormDetail from "@/components/FormDetail/details.vue";
export default {
  components: {
    FormDetail,
  },
  data() {
    return {
      detailModule: [
        {
          translations: { age: "age", name: 'name' },
          title: "information",
          keyArr: [
            { label: "AccountName", keyName: "AccountName" },
            { label: "AccountId", keyName: "AccountId" },
            { detailType: 'image', label: 'avatar', keyName: 'image' },
            {
              formatter: (data) => {
                console.log(data, '------');
                return `<span style="white-space: nowrap;color: dodgerblue;">${data.status}</span>`;
              },
              label: 'Custom',
            },
            { label: 'array', keyName: 'list', innerKey: 'asList' },
            {
              label: "test", keyName: "obj",
              getTranslation: (key, index) => {
                return this.detailModule[index].translations[key] || key; // If no translation is found, return the key itself
              }
            }
          ],
          extra: {
            text: 'text',
            methods: (item, index) => {
              console.log(item, index);
            }
          },


        },
      ],
      renderData: {
        AccountId: "1",
        AccountName: "Zhang San",
        image: 'https://cube.elemecdn.com/e/fd/0fc7d20532fdaf769a25683617711png.png',
        status: 'on',
        list: [
          { asList: "5" },
          { status: "5" },
          { asList: "5" },
        ],
        obj: {
          age: 8,
          name: 'zs',
          sex: 'nan',
        }
      },
    }
  },
};
</script>

The knowledge points of the article match the official knowledge files, and you can further learn relevant knowledge. Vue entry-level skills treeVue server-side renderingSSR37555 people are learning the system