vue+element-ui el-descriptions 详情渲染组件二次封装(Vue项目)

目录

1、需求

2.想要的效果就是由图一变成图二

​编辑

3.组件集成了以下功能

4.参数配置

示例代码

参数说明 

5,组件 

6.页面使用


1、需求

一般后台管理系统,通常页面都有增删改查;而不外乎就是渲染新增/修改的数据(由输入框变成输入框禁用),因为输入框禁用后颜色透明度会降低,显的颜色偏暗;为解决这个需求于是封装了详情组件

2.想要的效果就是由图一变成图二

3.组件集成了以下功能

操作按钮自定义
字典类型(即后台返回的是数字类型)过滤转成中文
自定义模版 数组类型 对象类型 
渲染图片

4.参数配置

示例代码

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

参数说明 

 * [
     * {
     * title:String 分类标题
     * column:Number 每行几个(默认2)
     * size:String 大小 medium / small / mini(默认 medium)
     * border:Boolean边框(默认true)
     * keyArr:[
     * {
     * icon:String,(描述标题的图标)
     * label:String,描述标题
     * keyName:String(对应的翻译值)
     * innerKey:String 数组时对应的翻译值
     * detailType:"image"渲染图片
     * formatter:Function :自定义渲染
     * getTranslation:Function:为对象时处理翻译的值
     * }
     * ]
     * extra:{ '操作按钮'
     * text:String(按钮文案)
     * methods:function(方法回调)
     * }
     * }
     * ]

5,组件 

<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>
      <!-- 描述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>
        <!-- 图片类型数据 -->
        <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>
        <!-- 自定义模版 -->
        <div v-else-if="descKey.formatter" v-html="descKey.formatter(data)"></div>
        <!-- 数组对象、或数组 -->
        <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>
        <!-- 默认键值对 -->
        <span v-else-if="(data[descKey.keyName] || data[descKey.keyName] === 0) &&
          typeof data[descKey.keyName] !== 'object'
          ">
          {
   
   {
            data[descKey.keyName] || data[descKey.keyName] == 0
            ? data[descKey.keyName]
            : "--"
          }}
        </span>
        <!-- 对象类型数据 -->
        <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>
        <!-- 没有匹配项目 -->
        <span v-else>--</span>

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

<script>
export default {
  props: {
    /**
     * [
     * {
     * title:String 分类标题
     * column:Number 每行几个(默认2)
     * size:String 大小 medium / small / mini(默认 medium)
     * border:Boolean边框(默认true)
     * keyArr:[
     * {
     * icon:String,(描述标题的图标)
     * label:String,描述标题
     * keyName:String(对应的翻译值)
     * innerKey:String 数组时对应的翻译值
     * detailType:"image"渲染图片
     * formatter:Function :自定义渲染
     * getTranslation:Function:为对象时处理翻译的值
     * }
     * ]
     * extra:{ '操作按钮'
     * text:String(文案)
     * methods:function(方法回调)
     * }
     * }
     * ]
     */
    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.页面使用

<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: "年龄", name: '姓名' },
          title: "信息",
          keyArr: [
            { label: "账户名称", keyName: "AccountName" },
            { label: "账户id", keyName: "AccountId" },
            { detailType: 'image', label: '头像', keyName: 'image' },
            {
              formatter: (data) => {
                console.log(data, '------');
                return `<span style="white-space: nowrap;color: dodgerblue;">${data.status}</span>`;
              },
              label: '自定义',
            },
            { label: '数组', keyName: 'list', innerKey: 'asList' },
            {
              label: "测试", keyName: "obj",
              getTranslation: (key, index) => {
                return this.detailModule[index].translations[key] || key; // 如果找不到翻译,返回键本身
              }
            }
          ],
          extra: {
            text: 'text',
            methods: (item, index) => {
              console.log(item, index);
            }
          },


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

猜你喜欢

转载自blog.csdn.net/qq_63358859/article/details/132948540