IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> JavaScript知识库 -> vue之封装一个 table组件 ( 列表之中 渲染其他组件 ) -> 正文阅读

[JavaScript知识库]vue之封装一个 table组件 ( 列表之中 渲染其他组件 )

vue之封装一个 table组件 ( 列表之中 渲染其他组件 )

listTable / index.vue

<template>
  <div class="search-table">
    <!-- v-loading="listLoading" -->
    <el-table
      ref="searchTable"
      :data="tablelist"
      border
      stripe
      size="mini"
      @selection-change="handleSelectionChange"
      @sort-change="handleSortChange"
      @cell-click="handleCellClick"
    >
      <el-table-column v-if="isSelect" type="selection" width="55" />
      <el-table-column
        v-else
        label="序号"
        width="65px"
        type="index"
        :index="indexMethod"
        align="center"
      />
      <template v-for="item in columns">
        <el-table-column
          v-if="!item.hidden"
          :key="item.prop"
          :prop="item.prop"
          :label="item.label"
          :sortable="item.sortable"
          :width="item.width"
          :min-width="item.minWidth"
          :formatter="item.render"
          :render-header="item.renderHeader"
          :show-overflow-tooltip="!item.hiddenTooltip"
        >
          <template
            v-if="item.formatter && typeof item.formatter !== 'function'"
            v-slot:default="{ row, column, $index }"
          >
            <component
              :is="item.formatter"
              :key="row.id"
              :table-data="tablelist"
              :row="row"
              :column="column"
              :index="$index"
              :col="item"
              :cell-value="row[item.prop]"
              :status="item.status"
            />
          </template>
          <template v-else-if="item.link" v-slot:default="{ row, column }">
            <span class="jump-color" @click="handleOperate(row, column)">{{
              row[item.prop]
            }}</span>
          </template>
        </el-table-column>
      </template>
      <el-table-column v-if="isAction" label="操作" :width="operation[0].width ? operation[0].width : 120 ">
        <template v-slot:default="{ row, index }">
          <div v-for="(item, key) in operation" :key="key" class="opt-btn">
            <span
              v-if="checkRenderStatus(row, item)"
              class="operate-btn"
              :disabled="checkDisabled(row, item)"
              @click="handleOperate(item, index, row)"
            >
              {{ item.label }}
            </span>
          </div>
        </template>
      </el-table-column>
    </el-table>
    <!-- @size-change="handleSizeChange" :page-sizes="pagesizes"-->
    <el-pagination
      v-if="!hiddenPagination"
      class="table-pagination"
      layout="total, prev, pager, next"
      :total="total"
      :page-size="pagesize"
      :current-page="currentPage"
      @current-change="handlePageChange"
    />
  </div>
</template>

<script>
// import { getTableList } from '@/api/common'
// import { deleteAttr } from '@/utils/str'

export default {
  name: 'SearchTable',
  props: {
    isInit: {
      type: [Boolean, String],
      default: false
    },
    searchForm: {
      type: Object,
      default: () => {}
    },
    defalutData: {
      type: Array,
      default: () => {
        return []
      }
    },
    url: {
      type: String,
      default: () => {
        return ''
      }
    },
    requestMethod: {
      type: String,
      default: () => {
        return 'GET'
      }
    },
    columns: {
      type: Array,
      default: () => {
        return []
      }
    },
    hiddenPagination: {
      type: Boolean,
      default: false
    },
    operation: {
      type: Array,
      default: () => {
        return []
      }
    },
    origin2formated: {
      type: Function,
      default(val) {
        return val
      }
    },
    isSelect: {
      type: Boolean,
      default: () => {
        return false
      }
    }
  },
  data() {
    return {
      tablelist: [],
      total: 0,
      // pagesizes: [15, 50, 100],
      pagesize: 20,
      currentPage: 1,
      // listLoading: false,
      currentOrderStr: null
    }
  },
  computed: {
    offset() {
      return (this.currentPage - 1) * this.pagesize
    },
    isAction() {
      return this.operation && this.operation.length > 0
    }
  },
  created() {
    if (this.isInit) return
    this.fetchData()
  },
  methods: {
    indexMethod(index) {
      return index + 1 + (this.currentPage - 1) * this.pagesize
    },
    resetPage() {
      this.currentPage = 1
    },
    async fetchData() {
      // this.listLoading = true
      const info = {}
      const params = {
        limit: this.pagesize,
        offset: this.offset,
        ordering: this.currentOrderStr,
        // ...this.$_.cloneDeep(this.searchForm)
        ...this.searchForm
      }
      console.log('params', params)
      this.tablelist = [
        {
          pathUrl: '/about11',
          errorType: 1,
          status: 1,
          txt_time: '2022-08-24 17:27:49'
        },
        {
          pathUrl: '/about12',
          errorType: 2,
          status: 0,
          txt_time: '2022-08-24 17:27:49'
        }
      ]
      // deleteAttr(params)
      // info = await getTableList(this.url, params, this.requestMethod).then(
      //   res => {
      //     const data = res.data
      //     if (res.code === 0) {
      //       if (data.results.length === 0 && this.defalutData.length > 0) {
      //         this.tablelist = this.defalutData
      //       } else {
      //         this.tablelist = []
      //         const results = this.origin2formated(data.results)
      //         this.tablelist = results
      //         this.total = data.count
      //       }
      //       this.listLoading = false
      //     }
      //     return data
      //   }
      // )
      return info
    },
    // handleSizeChange(val) {
    //   this.pagesize = val
    //   this.fetchData()
    // },
    handlePageChange(val) {
      this.currentPage = val
      this.fetchData()
    },
    handleOperate(item, index, row) {
      const operateInfo = {
        item: item,
        index: index,
        row: row
      }
      this.$emit('handleOperate', operateInfo)
    },
    handleSortChange({ column, prop, order }) {
      if (order === null) {
        this.currentOrderStr = null
      } else if (order === 'descending') {
        this.currentOrderStr = '-' + prop
      } else {
        this.currentOrderStr = prop
      }
      this.fetchData()
    },
    handleCellClick(row, column, cell, event) {
      const payload = { row, column, cell, event }
      this.$emit('handleCellClick', payload)
    },
    checkRenderStatus(row, operation) {
      if (operation.alwaysShow) {
        return true
      }

      const role = this.$store.state.user.role
      const accessedRoles = operation.accessedRoles || []
      if (accessedRoles.length > 0 && accessedRoles.indexOf(role) < 0) {
        return false
      }
      const defaultShowbyRow = {
        key: null,
        value: []
      }
      const showByRow = Object.assign(defaultShowbyRow, operation.showByRow)
      if (showByRow.key != null && showByRow.value.length !== 0) {
        const actionValue = row[showByRow.key]
        if (showByRow.value.indexOf(actionValue) < 0) {
          return false
        }
      }
      return true
    },
    checkDisabled(row, operation) {
      const showDisabled = operation.showDisabled
      if (showDisabled) {
        return row[showDisabled.key] !== showDisabled.value
      } else {
        return false
      }
    },
    handleSelectionChange(val) {
      this.$emit('handleOperate', val)
    },
    clearSelection() {
      this.$refs['searchTable'].clearSelection()
    }
  }
}
</script>

<style lang="scss" scoped>
.search-table {
  .table-pagination {
    margin-top: 10px;
    margin-bottom: 10px;
    text-align: center;
  }
  .opt-btn {
    display: inline;
    &:not(:first-child) {
      .el-button {
        margin-left: 5px;
      }
    }
  }
  .operate-btn {
    margin-right: 10px;
    font-size: 14px;
    color: rgba(64, 158, 255, 1);
    cursor: pointer;
  }
}
</style>

table组件相关

base.vue

<template>
  <div />
</template>

<script>
export default {
  name: 'BaseFormatter',
  props: {
    row: {
      type: Object,
      default: () => ({})
    },
    column: {
      type: Object,
      default: null
    },
    index: {
      type: Number,
      default: 0
    },
    col: {
      type: Object,
      default: () => ({})
    },
    cellValue: {
      type: [String, Boolean, Number, Object, Array],
      default: null
    }
  },
  data() {
    return {}
  }
}
</script>

DataFormatter.vue 时间格式化

<template>
  <span>{{ iDateTime }}</span>
</template>

<script>
import BaseFormatter from './base'
export default {
  name: 'DataFormatter',
  extends: BaseFormatter,
  computed: {
    iDateTime() {
      let res = ''
      this.cellValue ? res = this.cellValue.substring(0, 10) : ''
      return res
    }
  }
}
</script>

TagStatusFormatter.vue 状态格式化

<template>
  <el-tag v-if="iType" :type="iType" effect="plain" size="small">{{ iLabel }}</el-tag>
</template>

<script>
import BaseFormatter from './base.vue'
export default {
  name: 'TagStatusFormatter',
  extends: BaseFormatter,
  props: {
    status: {
      type: Object,
      default: () => {}
    }
  },
  data() {
    return {}
  },
  computed: {
    iType() {
      return this.status[this.cellValue]?.type
    },
    iLabel() {
      return this.status[this.cellValue]?.label
    }
  }
}
</script>

LinkTo.vue ( 跳转组件 )

<template>
  <div class="assets-id-copy">
    <div class="router-link" @click="goto">
      {{ row.pathUrl }}
    </div>
  </div>
</template>

<script>
import BaseFormatter from './base.vue'
export default {
  name: 'LinkTo',
  extends: BaseFormatter,
  props: {
    row: {
      type: Object,
      default: () => {}
    }
  },
  data() {
    return {}
  },
  computed: {
    url() {
      const pathUrl = this.row.pathUrl
      return pathUrl
    }
  },
  methods: {
    goto() {
      this.$router.push(this.url)
      // 浏览器 打开一个新的窗口
      // const routeData = this.$router.resolve(this.url)
      // window.open(routeData.href, '_blank')
    }
  }
}
</script>
<style lang="scss" scoped>
.assets-id-copy {
  display: flex;
  .router-link {
    color: #0000ff;
    cursor: pointer;
    &:hover {
      text-decoration: none;
      color: #606266;
    }
  }
}
</style>

使用组件

···js

User2
<list-table ref="searchTable" v-bind="tableConfig" :search-form="searchForm" @handleOperate="handleOperate" />

···

效果

在这里插入图片描述

  JavaScript知识库 最新文章
ES6的相关知识点
react 函数式组件 & react其他一些总结
Vue基础超详细
前端JS也可以连点成线(Vue中运用 AntVG6)
Vue事件处理的基本使用
Vue后台项目的记录 (一)
前后端分离vue跨域,devServer配置proxy代理
TypeScript
初识vuex
vue项目安装包指令收集
上一篇文章      下一篇文章      查看所有文章
加:2022-09-04 01:02:48  更:2022-09-04 01:06:35 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/23 10:48:44-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码