element ui的表格列
- 遍历tableData 与表头,找出该列最长的字符max
- 创建span标签计算最长字符所占宽度offsetWidth
- 设置min-width属性(String类型)
在组件渲染前计算出最小宽度,避免表格渲染过程宽度高度不稳定
其他方案参考:1. render-header 计算出宽度,然后渲染表头 2. header 插槽
<script>
/**
* @description: 计算字符串的字节长度
* @param {*} str
* @return {*}
*/
function strByteLength(str) {
if (!str) return 0
let len = str.length
for (let i = 0; i < str.length; i++) {
if (str.charCodeAt(i) > 255) { len++ }
}
return len
}
/**
* copy:
* 1.超出长度可复制
* 2. 设置canCopy = true
*/
import tableColumn from './TableColumn.vue'
export default {
components: {
tableColumn
},
render(h) {
/**
* 计算minWidth,是否可复制
* minWidth/maxWidth string eg: 60px
*/
const { label, prop, formatter, sortable } = this.$attrs
const tableData = this.$attrs['table-data']
const minWidth = this.$attrs['min-width']
const maxWidth = this.$attrs['max-width']
const max = { str: '', length: 0 }
const strs = tableData.map(item => {
if (formatter && typeof formatter === 'function') {
return formatter(null, null, item[prop], null)
} else {
return item[prop]
}
})
strs.unshift(label)
strs.forEach((item, i) => {
const len = strByteLength(item)
if (len > max.length) {
max.str = item
max.length = len
max.i = i
}
})
const span = document.createElement('span')
span.innerHTML = max.str
let width = document.body.appendChild(span).offsetWidth + 20
// 如果有排序 排序箭头宽度24
if (sortable) {
span.innerHTML = label
const labelWidth = document.body.appendChild(span).offsetWidth + 20 + 24
if (labelWidth > width) width = labelWidth
}
document.body.removeChild(span)
let minW = 60
if (typeof minWidth === 'string') {
minW = minWidth.match(/\d*/)[0] * 1
}
let maxW = 240
if (typeof maxWidth === 'string') {
maxW = maxWidth.match(/\d*/)[0] * 1
}
// 超出长度 可复制
if (width >= maxW) {
width = maxW
}
if (width <= minW) {
width = minW
}
const reMinWidth = isNaN(width) ? '' : width + 'px'
return (<tableColumn minWidth={reMinWidth} {...{ attrs: this.$attrs }}/>)
}
}
</script>
// tableColumn.vue
// 根据需求扩展column
<template>
<el-table-column v-if="type === 'index'" v-bind="$props" />
<el-table-column v-else v-bind="{ ...$props, ...$attrs}" />
</template>
复制指令
clipboard: {
// inserted 可获取父元素
inserted: (el, binding) => {
if (!binding.arg) return
const button = document.createElement('a')
button.innerHTML = '复制'
button.className = 'cell-copy-btn hidden'
button.handler = (e) => {
e.stopPropagation()
const content = el.innerText
if (!content) {
button.innerText = '无复制内容'
}
const textarea = document.createElement('textarea')
textarea.readOnly = 'readonly'
textarea.style.position = 'absolute'
textarea.style.left = '-9999px'
textarea.value = content
document.body.appendChild(textarea)
textarea.select()
const res = document.execCommand('Copy')
if (res) {
button.innerText = '已复制'
button.removeEventListener('click', button.handler, true)
setTimeout(() => {
button.innerText = '复制'
button.addEventListener('click', button.handler, true)
}, 2000)
}
document.body.removeChild(textarea)
}
button.addEventListener('click', button.handler, true)
el.button = button
el.parentNode.appendChild(el.button)
el.showButton = () => {
el.button.classList.remove('hidden')
}
el.hideButton = () => {
el.button.classList.add('hidden')
}
const element = el.parentNode
element.addEventListener('mouseenter', el.showButton, { passive: false })
element.addEventListener('mouseleave', el.hideButton, { passive: false })
},
unbind(el, binding) {
if (!binding.arg) return
const element = el.parentNode
if (element) {
element.removeEventListener('mouseenter', el.showButton, { passive: false })
element.addEventListener('mouseleave', el.hideButton, { passive: false })
}
}
}