动态表格

63 阅读2分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第22天,点击查看活动详情

前言

今天学习了动态表格,写一篇记录动态表格如何实现,效果如下

2.png

3.png

动态表格就是根据上方动态展示的勾选,表格中展示选中的列

动态表格的实现分为两部分

  1. 动态展示部分
  2. 表格

动态表格

动态展示

可勾选项可以使用element-plus el-checkbox实现

首先创建可勾选项的数据

新建article-ranking/dynamic/DynamicData.js,导出一个函数,函数的返回值为可勾选项的数据数组,至于为什么导出方法而不是直接导出数组,下方会告诉答案

import i18n from '@/i18n'

const t = i18n.global.t

export default () => [
  {
    label: t('msg.article.ranking'),
    prop: 'ranking'
  },
  {
    label: t('msg.article.title'),
    prop: 'title'
  },
  {
    label: t('msg.article.author'),
    prop: 'author'
  },
  {
    label: t('msg.article.publicDate'),
    prop: 'publicDate'
  },
  {
    label: t('msg.article.desc'),
    prop: 'desc'
  },
  {
    label: t('msg.article.action'),
    prop: 'action'
  }
]

接下来去处理数据

新建article-ranking/dynamic/index.js,需要先导出可勾选项数据和被勾选的数据

可勾选项数据使用上方定义的数据即可

import DynamicData from './DynamicData'
import { ref } from 'vue'

// 可勾选项数据
export const dynamicData = ref(DynamicData())

接着导出被勾选的数据,初始默认全部勾选

// 默认被勾选的列的label
export const selectDynamicLabel = ref([])
// 默认全部勾选
const initSelectDynamicLabel = () => {
  selectDynamicLabel.value = dynamicData.value.map((item) => item.label)
}
initSelectDynamicLabel()

最后处理国际化问题,在监听到语言变化后,将可勾选项重新赋值

dynamicData.value = DynamicData()

这里就体现出了为什么定义数据时使用函数返回数组而不是直接导出数组,如果直接导出数组,语言变化后,获取的还是之前语言的数据,而定义为函数,获取的就是最新语言的数据

import { watchSwitchLang } from '@/utils/i18n'

// 监听语言变化
watchSwitchLang(() => {
  dynamicData.value = DynamicData()
  initSelectDynamicLabel()
})

监听语言变化方法如下

utils/i18n

// 监听语言变化
export function watchSwitchLang(...cbs) {
  watch(
    () => store.getters.language,
    () => {
      cbs.forEach((cb) => cb())
    }
  )
}

最后在模板中渲染数据

<el-card class="header">
  <div class="dynamic-box">
    <span class="title">{{ $t('msg.article.dynamicTitle') }}</span>
    <el-checkbox-group v-model="selectDynamicLabel">
      <el-checkbox
        v-for="(item, index) in dynamicData"
        :label="item.label"
        :key="index"
      >
        {{ item.label }}
      </el-checkbox>
    </el-checkbox-group>
  </div>
</el-card>

表格处理

通常展示数据,是直接使用多个el-table-column来展示,如果我们换一种思路,利用v-for去渲染表格,当渲染的数据变化,表格也会动态变化,而我们想要的就是这个效果

首先处理表格数据,因为表格展示的内容是根据动态展示选中的项决定,所以可以监听动态展示项绑定的数据,如果数据发生变化,就根据选中项去改变table的值

article-ranking/dynamic/index.js

import { ref, watch } from 'vue'

// table列数据
export const tableColumns = ref([])
// 监听选中标签变化 动态改变列数据
watch(
  selectDynamicLabel,
  (val) => {
    tableColumns.value = []
    tableColumns.value = dynamicData.value.filter((item) => {
      return val.includes(item.label)
    })
  },
  {
    immediate: true
  }
)

有了数据之后,利用v-for去渲染数据

<el-table ref="tableRef" :data="tableData" border>
    <el-table-column
      v-for="(item, index) in tableColumns"
      :key="index"
      :label="item.label"
      :prop="item.prop"
    >
    </el-table-column>
</el-table>

4.png

可以看到发布时间和操作列还需要处理,这里直接使用插槽即可

<el-table ref="tableRef" :data="tableData" border>
    <el-table-column
      v-for="(item, index) in tableColumns"
      :key="index"
      :label="item.label"
      :prop="item.prop"
    >
      <template v-if="item.prop === 'publicDate'" #default="{ row }">
        {{ $filters.relativeTime(row.publicDate) }}
      </template>
      <template v-else-if="item.prop === 'action'" #default="{ row }">
        <el-button type="primary" size="mini" @click="onShowClick(row)">
          {{ $t('msg.article.show') }}
        </el-button>
        <el-button type="danger" size="mini" @click="onRemoveClick(row)">
          {{ $t('msg.article.remove') }}
        </el-button>
      </template>
    </el-table-column>
  </el-table>

注意插槽一个使用v-if,另一个使用v-else-if,否则会报以下错误

5.png

至此动态表格处理完成

6.png

当我们改变动态展示选中项,监听到选中项改变后,会重新获取表格的数据,在模板渲染时,就会只展示选中项数据