欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

vue3二次封裝element-ui中的table組件的過(guò)程詳解

 更新時(shí)間:2024年01月17日 09:38:05   作者:趁著年輕吃點(diǎn)苦  
這篇文章主要給大家介紹了vue3二次封裝element-ui中的table組件的過(guò)程,文中通過(guò)代碼示例給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作有一定的幫助,需要的朋友跟著小編一起來(lái)學(xué)習(xí)吧

為什么要做這件事

借助封裝table組件的過(guò)程來(lái)鞏固一下vue3相關(guān)知識(shí)點(diǎn)。

組件有哪些配置項(xiàng)

  1. options:表格的配置項(xiàng)
  2. data: 表格數(shù)據(jù)源
  3. elementLoadingText:加載文案
  4. elementLoadingSpinner:加載圖標(biāo)
  5. elementLoadingBackground:背景遮罩的顏色
  6. elementLoadingSvg:加載圖標(biāo)(svg)
  7. elementLoadingSvgViewBox:加載圖標(biāo)是svg的話,配置項(xiàng)
  8. editIcon:編輯圖標(biāo)
  9. isEditRow:是否支持編輯
  10. editRowIndex:編輯行的標(biāo)識(shí)符
  11. pagination:是否支持分頁(yè)
  12. paginationAlign:分頁(yè)對(duì)齊方式
  13. currentPage:當(dāng)前頁(yè)數(shù)
  14. pageSize:每頁(yè)顯示條目個(gè)數(shù)
  15. pageSizes:每頁(yè)顯示個(gè)數(shù)選擇器的選項(xiàng)設(shè)置
  16. total:總條目數(shù)

實(shí)現(xiàn)過(guò)程

首先,將一個(gè)普通的element-plus中的table組件引入進(jìn)來(lái),表格數(shù)據(jù)源就是我們通過(guò)父組件傳遞進(jìn)來(lái)的data,所以我們使用defineProps來(lái)定義,并且它的數(shù)據(jù)類型是一個(gè)數(shù)組;同時(shí)我們遵循單向數(shù)據(jù)流的原則,使用lodash中的深拷貝方法將data拷貝一份出來(lái)賦值給變量tableData,將tableData傳遞給element-plus中的table組件,用來(lái)渲染數(shù)據(jù)。

// 子組件 m-table-copy
 
<template>
  <el-table :data="tableData">
    <el-table-column prop="date" label="Date" width="180" />
    <el-table-column prop="name" label="Name" width="180" />
    <el-table-column prop="address" label="Address" />
  </el-table>
</template>
 
<script setup>
import { ref } from 'vue'
import cloneDeep from 'lodash/cloneDeep'
let props = defineProps({
  data: {
    type: Array,
    required: true
  }
})
 
// 拷貝一份兒數(shù)據(jù)
let tableData = ref(cloneDeep(props.data))
</script>

父組件在使用這個(gè)自定義組件的時(shí)候應(yīng)該這么使用:

<!-- 父組件 -->
<template>
  <m-table-copy :data="tableData"></m-table-copy>
</template>
 
<script setup>
import { ref } from 'vue'
 
let tableData = ref([])
 
tableData.value = [
  {
    name: '張三',
    address: '杭州市',
    date: '1998-07-16'
  },
  {
    name: '李四',
    address: '石家莊市',
    date: '2013-09-02'
  }
]
</script>

這樣頁(yè)面上就能夠顯示出來(lái)我們的數(shù)據(jù)了:

第一步完成了,我們接著再分析,還有什么是可以封裝的呢?仔細(xì)看上面的代碼,是不是有了想法?是的,label、width、prop這些也是可以放在一個(gè)配置項(xiàng)里面的,那我們繼續(xù)來(lái)進(jìn)行封裝:

// 父組件準(zhǔn)備好的數(shù)據(jù)結(jié)構(gòu)
let options = [
  {
    prop: 'date',
    label: '日期',
    align: 'center',
    slot: 'date',
    editable: true,
    width: '230'
  },
  {
    prop: 'name',
    label: '姓名',
    align: 'center',
    slot: 'name'
  },
  {
    prop: 'address',
    label: '地址',
    align: 'center',
    editable: true
  },
  {
    label: '操作',
    align: 'center',
    action: true
  }
]
<template>
  <el-table :data="tableData">
    <template v-for="(item, index) in tableOption" :key="index">
      <el-table-column
        :label="item.label"
        :prop="item.prop"
        :align="item.align"
        :width="item.width" />
    </template>
  </el-table>
</template>
 
<script setup>
import { ref, computed } from 'vue'
let props = defineProps({
  // 表格配置項(xiàng)
  options: {
    type: Array,
    required: true
  }
})
 
// 過(guò)濾操作項(xiàng)之后的配置
let tableOption = computed(() => props.options.filter((item) => !item.action))
</script>

一般來(lái)說(shuō),表格都會(huì)配置一下loading狀態(tài),所以我們繼續(xù)封裝,將loading相關(guān)的配置項(xiàng)也添加進(jìn)來(lái):

完整代碼 

<template>
  <el-table
    :data="tableData"
    v-loading="isLoading"
    :element-loading-text="elementLoadingText"
    :element-loading-spinner="elementLoadingSpinner"
    :element-loading-svg="elementLoadingSvg"
    :element-loading-svg-view-box="elementLoadingSvgViewBox"
    :element-loading-background="elementLoadingBackground"
    @row-click="rowClick"
    v-bind="$attrs">
    <template v-for="(item, index) in tableOption" :key="index">
      <el-table-column
        :label="item.label"
        :prop="item.prop"
        :align="item.align"
        :width="item.width">
        <template #default="scope">
          <!-- 編輯模式 -->
          <template v-if="scope.row.rowEdit">
            <el-input v-model="scope.row[item.prop]"></el-input>
          </template>
          <template v-else>
            <template v-if="scope.$index + scope.column.id === currentEdit">
              <div style="display: flex">
                <el-input v-model="scope.row[item.prop]"></el-input>
                <div>
                  <slot
                    v-if="$slots.cellEdit"
                    name="cellEdit"
                    :scope="scope"></slot>
                  <div class="action-icon" v-else>
                    <el-icon-check
                      class="check"
                      @click.stop="check(scope)"></el-icon-check>
                    <el-icon-close
                      class="close"
                      @click.stop="close(scope)"></el-icon-close>
                  </div>
                </div>
              </div>
            </template>
            <template v-else>
              <!-- slot是一個(gè)插槽出口,表示了父元素提供的插槽內(nèi)容將在哪里被渲染 -->
              <slot v-if="item.slot" :name="item.slot" :scope="scope"></slot>
              <span v-else>{{ scope.row[item.prop] }}</span>
              <component
                v-if="item.editable"
                :is="`el-icon-${toLine(editIcon)}`"
                class="edit"
                @click.stop="clickEditIcon(scope)"></component>
            </template>
          </template>
        </template>
      </el-table-column>
    </template>
    <el-table-column
      :align="actionOption.align"
      :label="actionOption.label"
      :width="actionOption.width">
      <template #default="scope">
        <!-- 編輯模式下顯示確認(rèn)和取消 -->
        <slot name="editRow" :scope="scope" v-if="scope.row.rowEdit"></slot>
        <!-- 正常狀態(tài)下顯示 編輯和刪除 -->
        <slot name="action" :scope="scope" v-else></slot>
      </template>
    </el-table-column>
  </el-table>
  <div
    v-if="pagination && !isLoading"
    class="pagination"
    :style="{ justifyContent }">
    <el-pagination
      v-model:currentPage="currentPage"
      :page-size="pageSize"
      :page-sizes="pageSizes"
      @size-change="handleSizeChange"
      @current-change="handleCurrentChange"
      layout="total, sizes, prev, pager, next, jumper"
      :total="total" />
  </div>
</template>
<script setup>
import cloneDeep from 'lodash/cloneDeep'
import { computed, onMounted, ref, watch } from 'vue'
import { toLine } from '../../../utils'
let props = defineProps({
  // 表格配置項(xiàng)
  options: {
    type: Array,
    required: true
  },
  // 表格數(shù)據(jù)
  data: {
    type: Array,
    required: true
  },
  // 編輯圖標(biāo)
  editIcon: {
    type: String,
    default: 'Edit'
  },
  // 顯示在加載圖標(biāo)下方的加載文案
  elementLoadingText: {
    type: String
  },
  // 自定義加載圖標(biāo)
  elementLoadingSpinner: {
    type: String
  },
  // 自定義加載圖標(biāo)(svg)
  elementLoadingSvg: {
    type: String
  },
  // 自定義加載圖標(biāo)(svg)的配置
  elementLoadingSvgViewBox: {
    type: String
  },
  // 背景遮罩的顏色
  elementLoadingBackground: {
    type: String
  },
  // 是否可用編輯行
  isEditRow: {
    type: Boolean,
    default: false
  },
  // 編輯行按鈕的標(biāo)識(shí)
  editRowIndex: {
    type: String,
    default: ''
  },
  // 是否顯示分頁(yè)
  pagination: {
    type: Boolean,
    default: false
  },
  // 分頁(yè)的對(duì)齊方式
  paginationAlign: {
    type: String,
    default: 'left'
  },
  // 當(dāng)前第幾頁(yè)
  currentPage: {
    type: Number,
    default: 1
  },
  // 顯示分頁(yè)數(shù)據(jù)多少條的選項(xiàng)
  pageSizes: {
    type: Array,
    default: () => [10, 20, 30, 40]
  },
  // 數(shù)據(jù)總條數(shù)
  total: {
    type: Number,
    default: 0
  }
})
 
// 深拷貝一份表格的數(shù)據(jù)
let tableData = ref(cloneDeep(props.data))
 
let cloneEditRowIndex = ref(props.editRowIndex)
// 過(guò)濾操作項(xiàng)之后的配置
let tableOption = computed(() => props.options.filter((item) => !item.action))
 
let actionOption = computed(() => props.options.find((item) => item.action))
 
// 監(jiān)聽(tīng)的標(biāo)識(shí)
let watchData = ref<boolean>(false)
 
// 如果data的數(shù)據(jù)變了 要重新給tableData賦值
// 只需要監(jiān)聽(tīng)一次就可以了
let stopWatchData = watch(
  () => props.data,
  (val) => {
    watchData.value = true
    tableData.value = val
    tableData.value.map((item) => {
      item.rowEdit = false
    })
    if (watchData.value) stopWatchData()
  },
  { deep: true }
)
 
watch(
  () => props.editRowIndex,
  (val) => {
    if (val) cloneEditRowIndex.value = val
  }
)
 
// 當(dāng)前被點(diǎn)擊的單元格的標(biāo)志
let currentEdit = ref('')
let currentPage = computed(() => props.currentPage)
let justifyContent = computed(() => {
  if (props.paginationAlign === 'left') return 'flex-start'
  else if (props.paginationAlign === 'right') return 'flex-end'
  else return 'center'
})
let isLoading = computed(() => !props.data || !props.data.length)
 
let emits = defineEmits([
  'confirm',
  'cancel',
  'update:editRowIndex',
  'size-change',
  'current-change'
])
 
onMounted(() => {
  tableData.value.map((item) => {
    item.rowEdit = false
  })
})
 
let clickEditIcon = (scope) => {
  currentEdit.value = scope.$index + scope.column.id
}
 
let handleSizeChange = (val) => {
  emits('size-change', val)
}
 
let handleCurrentChange = (val) => {
  emits('current-change', val)
}
 
let check = (scope) => {
  emits('confirm', scope)
  currentEdit.value = ''
}
 
let close = (scope) => {
  emits('cancel', scope)
  currentEdit.value = ''
}
 
let rowClick = (row, column) => {
  if (column.label === actionOption.value.label) {
    if (props.isEditRow && cloneEditRowIndex.value === props.editRowIndex) {
      row.rowEdit = !row.rowEdit
      tableData.value.map((item) => {
        if (item !== row) item.rowEdit = false
      })
      if (!row.rowEdit) emits('update:editRowIndex', '')
    }
  }
}
</script>

以上就是vue3二次封裝element-ui中的table組件的過(guò)程詳解的詳細(xì)內(nèi)容,更多關(guān)于vue3二次封裝table的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • Vue的緩存方法示例詳解

    Vue的緩存方法示例詳解

    這篇文章主要給大家介紹了關(guān)于Vue緩存方法的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2021-03-03
  • vue?3.0?使用ref獲取dom元素的示例

    vue?3.0?使用ref獲取dom元素的示例

    這篇文章主要介紹了vue?3.0?使用ref獲取dom元素,包括vue2.x獲取dom和vue3.0獲取單個(gè)dom,通過(guò)示例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2022-08-08
  • vue3?頭像上傳?組件功能實(shí)現(xiàn)

    vue3?頭像上傳?組件功能實(shí)現(xiàn)

    這篇文章主要介紹了vue3頭像上傳組件功能,用到了自定義組件v-model的雙向綁定,使用axios + formData 上傳文件,本文結(jié)合實(shí)例代碼給大家介紹的非常詳細(xì),需要的朋友可以參考下
    2023-05-05
  • vue實(shí)現(xiàn)nav導(dǎo)航欄的方法

    vue實(shí)現(xiàn)nav導(dǎo)航欄的方法

    這篇文章主要為大家詳細(xì)介紹了vue項(xiàng)目nav導(dǎo)航欄的實(shí)現(xiàn)方法,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-12-12
  • Vue批量更新dom的實(shí)現(xiàn)步驟

    Vue批量更新dom的實(shí)現(xiàn)步驟

    本文將結(jié)合實(shí)例代碼,介紹Vue批量更新dom的實(shí)現(xiàn)步驟,文中通過(guò)示例代碼介紹的非常詳細(xì),需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2021-07-07
  • Vue實(shí)現(xiàn)導(dǎo)航吸頂效果的教程詳解

    Vue實(shí)現(xiàn)導(dǎo)航吸頂效果的教程詳解

    在瀏覽器上下滾動(dòng)的時(shí)候,如何距離頂部的距離大于78px,吸頂顯示,小于78px則隱藏,所以本文小編給大家介紹了Vue設(shè)置導(dǎo)航吸頂?shù)脑敿?xì)教程,文中有相關(guān)的代碼示例供大家參考,具有一定的參考價(jià)值,需要的朋友可以參考下
    2024-01-01
  • vue 自動(dòng)化路由實(shí)現(xiàn)代碼

    vue 自動(dòng)化路由實(shí)現(xiàn)代碼

    這篇文章主要介紹了vue 自動(dòng)化路由實(shí)現(xiàn)代碼,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2019-09-09
  • 從Echarts報(bào)錯(cuò)中學(xué)習(xí)Vue3?ref和shallowRef區(qū)別及其組件二次封裝demo

    從Echarts報(bào)錯(cuò)中學(xué)習(xí)Vue3?ref和shallowRef區(qū)別及其組件二次封裝demo

    這篇文章主要介紹了從Echarts報(bào)錯(cuò)中學(xué)習(xí)Vue3?ref和shallowRef區(qū)別及其組件二次封裝demo,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-11-11
  • Electron?store及shareObject進(jìn)程間數(shù)據(jù)交互存儲(chǔ)功能封裝

    Electron?store及shareObject進(jìn)程間數(shù)據(jù)交互存儲(chǔ)功能封裝

    這篇文章主要為大家介紹了Electron?store及shareObject進(jìn)程間數(shù)據(jù)交互存儲(chǔ)功能封裝示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-09-09
  • vue-cli3添加模式配置多環(huán)境變量的方法

    vue-cli3添加模式配置多環(huán)境變量的方法

    這篇文章主要介紹了vue-cli3添加模式配置多環(huán)境變量的方法,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2019-06-06

最新評(píng)論