99偷拍视频精品区一区二,口述久久久久久久久久久久,国产精品夫妇激情啪发布,成人永久免费网站在线观看,国产精品高清免费在线,青青草在线观看视频观看,久久久久久国产一区,天天婷婷久久18禁,日韩动漫av在线播放直播

怎么用Vue3實現可復制表格

這篇文章主要講解了“怎么用Vue3實現可復制表格”,文中的講解內容簡單清晰,易于學習與理解,下面請大家跟著小編的思路慢慢深入,一起來研究和學習“怎么用Vue3實現可復制表格”吧!

公司主營業務:網站建設、成都網站建設、移動網站開發等業務。幫助企業客戶真正實現互聯網宣傳,提高企業的競爭能力。創新互聯是一支青春激揚、勤奮敬業、活力青春激揚、勤奮敬業、活力澎湃、和諧高效的團隊。公司秉承以“開放、自由、嚴謹、自律”為核心的企業文化,感謝他們對我們的高要求,感謝他們從不同領域給我們帶來的挑戰,讓我們激情的團隊有機會用頭腦與智慧不斷的給客戶帶來驚喜。創新互聯推出蘭山免費做網站回饋大家。

最基礎的表格封裝

最基礎基礎的表格封裝所要做的事情就是讓用戶只關注行和列的數據,而不需要關注 DOM 結構是怎樣的,我們可以參考 AntDesigncolumns dataSource 這兩個屬性是必不可少的,代碼如下:

import { defineComponent } from 'vue'
import type { PropType } from 'vue'

interface Column {
  title: string;
  dataIndex: string;
  slotName?: string;
}
type TableRecord = Record<string, unknown>;

export const Table = defineComponent({
  props: {
    columns: {
      type: Array as PropType<Column[]>,
      required: true,
    },
    dataSource: {
      type: Array as PropType<TableRecord[]>,
      default: () => [],
    },
    rowKey: {
      type: Function as PropType<(record: TableRecord) => string>,
    }
  },
  setup(props, { slots }) {
    const getRowKey = (record: TableRecord, index: number) => {
      if (props.rowKey) {
        return props.rowKey(record)
      }
      return record.id ? String(record.id) : String(index)
    }
    const getTdContent = (
      text: any,
      record: TableRecord,
      index: number,
      slotName?: string
    ) => {
      if (slotName) {
        return slots[slotName]?.(text, record, index)
      }
      return text
    }

    return () => {
      return (
        <table>
          <tr>
            {props.columns.map(column => {
              const { title, dataIndex } = column
              return <th key={dataIndex}>{title}</th>
            })}
          </tr>
          {props.dataSource.map((record, index) => {
            return (
              <tr key={getRowKey(record, index)}>
                {props.columns.map((column, i) => {
                  const { dataIndex, slotName } = column
                  const text = record[dataIndex]

                  return (
                    <td key={dataIndex}>
                      {getTdContent(text, record, i, slotName)}
                    </td>
                  )
                })}
              </tr>
            )
          })}
        </table>
      )
    }
  }
})

需要關注一下的是 Column 中有一個 slotName 屬性,這是為了能夠自定義該列的所需要渲染的內容(在 AntDesign 中是通過 TableColumn 組件實現的,這里為了方便直接使用 slotName)。

實現復制功能

首先我們可以手動選中表格復制嘗試一下,發現表格是支持選中復制的,那么實現思路也就很簡單了,通過代碼選中表格再執行復制命令就可以了,代碼如下:

export const Table = defineComponent({
  props: {
      // ...
  },
  setup(props, { slots, expose }) {
    // 新增,存儲table節點
    const tableRef = ref<HTMLTableElement | null>(null)

    // ...
    
    // 復制的核心方法
    const copy = () => {
      if (!tableRef.value) return

      const range = document.createRange()
      range.selectNode(tableRef.value)
      const selection = window.getSelection()
      if (!selection) return

      if (selection.rangeCount > 0) {
        selection.removeAllRanges()
      }
      selection.addRange(range)
      document.execCommand('copy')
    }
    
    // 將復制方法暴露出去以供父組件可以直接調用
    expose({ copy })

    return (() => {
      return (
        // ...
      )
    }) as unknown as { copy: typeof copy } // 這里是為了讓ts能夠通過類型校驗,否則調用`copy`方法ts會報錯
  }
})

這樣復制功能就完成了,外部是完全不需要關注如何復制的,只需要調用組件暴露出去的 copy 方法即可。

處理表格中的不可復制元素

雖然復制功能很簡單,但是這也僅僅是復制文字,如果表格中有一些不可復制元素(如圖片),而復制時需要將這些替換成對應的文字符號,這種該如何實現呢?

解決思路就是在組件內部定義一個復制狀態,調用復制方法時把狀態設置為正在復制,根據這個狀態渲染不同的內容(非復制狀態時渲染圖片,復制狀態是渲染對應的文字符號),代碼如下:

export const Table = defineComponent({
  props: {
      // ...
  },
  setup(props, { slots, expose }) {
    const tableRef = ref<HTMLTableElement | null>(null)
    // 新增,定義復制狀態
    const copying = ref(false)

    // ...
    const getTdContent = (
      text: any,
      record: TableRecord,
      index: number,
      slotName?: string,
      slotNameOnCopy?: string
    ) => {
      // 如果處于復制狀態,則渲染復制狀態下的內容
      if (copying.value && slotNameOnCopy) {
        return slots[slotNameOnCopy]?.(text, record, index)
      }

      if (slotName) {
        return slots[slotName]?.(text, record, index)
      }
      return text
    }
    
    const copy = () => {
      copying.value = true
      // 將復制行為放到 nextTick 保證復制到正確的內容
      nextTick(() => {
        if (!tableRef.value) return
  
        const range = document.createRange()
        range.selectNode(tableRef.value)
        const selection = window.getSelection()
        if (!selection) return
  
        if (selection.rangeCount > 0) {
          selection.removeAllRanges()
        }
        selection.addRange(range)
        document.execCommand('copy')
        
        // 別忘了把狀態重置回來
        copying.value = false
      })
    }
    
    expose({ copy })

    return (() => {
      return (
        // ...
      )
    }) as unknown as { copy: typeof copy }
  }
})

測試

最后我們可以寫一個demo測一下功能是否正常,代碼如下:

<template>
  <button @click="handleCopy">點擊按鈕復制表格</button>
  <c-table
    :columns="columns"
    :data-source="dataSource"
    border="1"
    
    ref="table"
  >
    <template #status>
      <img class="status-icon" :src="arrowUpIcon" />
    </template>
    <template #statusOnCopy>
      →
    </template>
  </c-table>
</template>

<script setup lang="ts">
import { ref } from 'vue'
import { Table as CTable } from '../components'
import arrowUpIcon from '../assets/arrow-up.svg'

const columns = [
  { title: '序號', dataIndex: 'serial' },
  { title: '班級', dataIndex: 'class' },
  { title: '姓名', dataIndex: 'name' },
  { title: '狀態', dataIndex: 'status', slotName: 'status', slotNameOnCopy: 'statusOnCopy' }
]

const dataSource = [
  { serial: 1, class: '三年級1班', name: '張三' },
  { serial: 2, class: '三年級2班', name: '李四' },
  { serial: 3, class: '三年級3班', name: '王五' },
  { serial: 4, class: '三年級4班', name: '趙六' },
  { serial: 5, class: '三年級5班', name: '宋江' },
  { serial: 6, class: '三年級6班', name: '盧俊義' },
  { serial: 7, class: '三年級7班', name: '吳用' },
  { serial: 8, class: '三年級8班', name: '公孫勝' },
]

const table = ref<InstanceType<typeof CTable> | null>(null)
const handleCopy = () => {
  table.value?.copy()
}
</script>

<style scoped>
.status-icon {
  width: 20px;
  height: 20px;
}
</style>

附上完整代碼:

import { defineComponent, ref, nextTick } from 'vue'
import type { PropType } from 'vue'

interface Column {
  title: string;
  dataIndex: string;
  slotName?: string;
  slotNameOnCopy?: string;
}
type TableRecord = Record<string, unknown>;

export const Table = defineComponent({
  props: {
    columns: {
      type: Array as PropType<Column[]>,
      required: true,
    },
    dataSource: {
      type: Array as PropType<TableRecord[]>,
      default: () => [],
    },
    rowKey: {
      type: Function as PropType<(record: TableRecord) => string>,
    }
  },
  setup(props, { slots, expose }) {
    const tableRef = ref<HTMLTableElement | null>(null)
    const copying = ref(false)

    const getRowKey = (record: TableRecord, index: number) => {
      if (props.rowKey) {
        return props.rowKey(record)
      }
      return record.id ? String(record.id) : String(index)
    }
    const getTdContent = (
      text: any,
      record: TableRecord,
      index: number,
      slotName?: string,
      slotNameOnCopy?: string
    ) => {
      if (copying.value && slotNameOnCopy) {
        return slots[slotNameOnCopy]?.(text, record, index)
      }

      if (slotName) {
        return slots[slotName]?.(text, record, index)
      }
      return text
    }
    const copy = () => {
      copying.value = true

      nextTick(() => {
        if (!tableRef.value) return
  
        const range = document.createRange()
        range.selectNode(tableRef.value)
        const selection = window.getSelection()
        if (!selection) return
  
        if (selection.rangeCount > 0) {
          selection.removeAllRanges()
        }
        selection.addRange(range)
        document.execCommand('copy')
        copying.value = false
      })
    }
    
    expose({ copy })

    return (() => {
      return (
        <table ref={tableRef}>
          <tr>
            {props.columns.map(column => {
              const { title, dataIndex } = column
              return <th key={dataIndex}>{title}</th>
            })}
          </tr>
          {props.dataSource.map((record, index) => {
            return (
              <tr key={getRowKey(record, index)}>
                {props.columns.map((column, i) => {
                  const { dataIndex, slotName, slotNameOnCopy } = column
                  const text = record[dataIndex]

                  return (
                    <td key={dataIndex}>
                      {getTdContent(text, record, i, slotName, slotNameOnCopy)}
                    </td>
                  )
                })}
              </tr>
            )
          })}
        </table>
      )
    }) as unknown as { copy: typeof copy }
  }
})

感謝各位的閱讀,以上就是“怎么用Vue3實現可復制表格”的內容了,經過本文的學習后,相信大家對怎么用Vue3實現可復制表格這一問題有了更深刻的體會,具體使用情況還需要大家實踐驗證。這里是創新互聯,小編將為大家推送更多相關知識點的文章,歡迎關注!

分享標題:怎么用Vue3實現可復制表格
網頁URL:http://www.yijiale78.com/article44/gjhche.html

成都網站建設公司_創新互聯,為您提供網站導航外貿建站企業建站建站公司自適應網站虛擬主機

廣告

聲明:本網站發布的內容(圖片、視頻和文字)以用戶投稿、用戶轉載內容為主,如果涉及侵權請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網站立場,如需處理請聯系客服。電話:028-86922220;郵箱:631063699@qq.com。內容未經允許不得轉載,或轉載時需注明來源: 創新互聯

網站建設網站維護公司