关于前端:通过vNode实现给列表字段打标签

30次阅读

共计 3402 个字符,预计需要花费 9 分钟才能阅读完成。

问题

如何给列表数据打标签?相似上面这种样子👇

思路

  1. 数模转化(对接口申请回来的数据进行过滤标记,返回新的数据)
  2. 渲染新的数据模型

实现

1、过滤数据,须要打标签的采纳 jsx 写法

业务数据的解决我封装在 mixins 外面

// 寄存全局的 mixin,可拆分到模块独享

import {mapGetters} from 'vuex'
import {fetchListData} from '@/api/global/api.js'
export default {data() {
    return {p_category: [],
      listdata: [],
      p_total: 0,
      p_loading: false,
    }
  },
  computed: {// ...mapGetters(['productLevel', 'productLevelInfo']),
    p_listdata() {
      const data = this.listdata;
      data.forEach((item) => {
        // ...
        // jsx 形式,打标签
        if (item.status === 2 || item.status === 3) {item.status = <span style={{color: '#999'}}> 停售 </span>
        } else {item.status = item.status}
        if (item.age <= 25) {item.age = <span class="badge_info">{item.age}</span>
        }
        if (item.sex === 'Man') {item.sex = <span class="badge_default">{item.sex}</span>
        }
      })
      return data;
    }
  },
  methods: {async getProductList(params = {}) {
      try {
        this.p_loading = true
        this.listdata = []
        const res = await fetchListData(params)
        if (res.code === 0) {const { data = [], total = 0 } = res || {}
          if (Array.isArray(data)) {this.listdata = [...data]
            this.p_total = total
          } else {this.listdata = []
            this.p_total = 0
          }
        } else {this.listdata = []
          this.p_total = 0
          this.$message.error(res.message || '出错了')
        }
        this.p_loading = false;
      } catch (err) {
        this.p_loading = false
        this.listdata = []
        this.p_total = 0
        console.log(err);
      }
    }
  }
}

base.less 定义标签款式

.badge_info {
  color: #4760f0;
  background: #1C84C6;
  padding: 5px 8px;
  color: #fff;
  border-radius: 5px;
}

.badge_default {
  color: #4760f0;
  background: #4760f0;
  padding: 5px 8px;
  color: #fff;
  border-radius: 5px;
}

2、封装列表渲染组件

<template>
  <ul class="listV2">
    <li class="listV2_row-title">
      <span v-for="(col, index) in fieldList" :key="index" class="listV2_cell ellipsis" :name="col.fieldName">
        {{col.fieldLabel}}
      </span>
    </li>
    <!-- 行 -->
    <div v-if="tableData.length === 0" class="nodata"> 暂无数据 </div>
    <li v-for="(row, index) in tableData" :key="index" class="listV2_row pointer" @click="rowClickToDetail(row)">
      <!-- 单元格 - 列 -->
      <span v-for="(col, index) in fieldList" :key="index" class="listV2_cell ellipsis" :name="col.fieldName">
        <RenderDom :vNode="row[col.fieldName] ||'-'"></RenderDom>
      </span>
    </li>
  </ul>
</template>

<script>
  import RenderDom from "./renderDom";
  export default {
    name: 'TableList',
    props: {
      tableData: {
        type: Array,
        required: true,
      },
      fieldList: {
        type: Array,
        required: true,
      },
      align: {
        type: String,
        default: 'left',
      },
    },
    components: {RenderDom,},
    data() {return {}
    },
    computed: {},
    watch: {},
    created() {},
    mounted() {},
    methods: {},
    updated() {},
    beforeDestroy() {},
  }
</script>

<style lang='less' rel='stylesheet/less' scoped>
  @import "./index.less";
</style>

3、封装渲染 vNode 的办法

const renderDom = {
  props: {
    vNode: {type: [Array, String, Object,Number],
    },
  },
  render(h) {
    // jsx - vNode 间接返回,交给框架解决(js 语法带来很多可能,列表打标签性能)if (typeof this.vNode === 'object') {return this.vNode;}
    // 一般数据,间接包一层 div,而后返回给页面
    return h(
      'div',
      {class: 'ellipsis',},
      this.vNode
    )
  }
}

4、页面组件调用

<template>
  <div class="customer">
    <table-list v-loading="p_loading" :tableData="p_listdata" :fieldList="fieldList"></table-list>
  </div>
</template>

<script>
  import TableList from '@/basecomponents/TableList/index'
  import $_pMixins from "@/mixins/product.js";
  import enums from './enum.js'
  export default {
    name: 'Customer',
    props: {},
    components: {'table-list': TableList,},
    mixins: [$_pMixins],
    data() {
      return {tableData: [],
        fieldList: Object.freeze(enums.Enum_customerFieldList),
      }
    },
    computed: {},
    watch: {},
    created() {},
    mounted() {this.initData()
    },
    methods: {initData() {this.getProductList()
      }
    },
    updated() {},
    beforeDestroy() {},
  }
</script>

<style lang='less' rel='stylesheet/less' scoped>
  @import "./index.less";
</style>

成果展现


我是 甜点 cc

酷爱前端,也喜爱专研各种跟本职工作关系不大的技术,技术、产品趣味宽泛且浓重,期待着一个守业机会。次要致力于分享实用技术干货,心愿能够给一小部分人一些渺小帮忙。

我排挤“新人迷茫,老人看戏”的景象,心愿能和大家一起致力破局。营造一个良好的技术气氛,为了集体、为了我国的数字化转型、互联网物联网技术、数字经济倒退做一点点奉献。数风流人物还看中国、看今朝、看你我。

正文完
 0