테이블 컴포넌트를 먼저 개발하기 전에, 작성자가 제작 작업에서 Element를 사용하기 때문에 이전 컴포넌트의 스타일은 Element와 비슷하지만 앞으로는 사용할 계획이 없습니다. 이번에는 요소를 사용하여 이를 변경하여 직접 표시할 계획입니다.
사용자가 다음과 같이 사용할 것으로 예상합니다.
<script setup> const dataList = [ { id: 1, name: '《JavaEE企业应用实战》', author: 'dev1ce', price: '10.22', desc: '书中最后讲解的项目案例,涵盖从前期设计到最终实施的整个过程,对全书知识点进行串联和巩固,使读者融会贯通,掌握Java Web开发的精髓。' }, { id: 2, name: '《代码整洁之道》', author: 'R0bert', price: '10.22', desc: '整洁代码并非遵循一组规则编写的。不可能因为学习一套金规玉律就成为软件大师。专业精神和手工艺来自于推动规则形成的价值。' }, { id: 3, name: '《ECMAScript 6 入门教程》', author: 'y1feng', price: '10.22', desc: '本书是一本开源的 JavaScript 语言教程,全面介绍 ECMAScript 6 新引入的语法特性。' }, ] const columnsList = [ { title: '书名', key: 'name' }, { title: '作者', key: 'author' }, { title: '价格', key: 'price' }, { title: '简介', key: 'desc' } ] </script> <template> <sanorin-table :columns="columnsList" :data="dataList"/> </template>
이에 따라 다음 코드를 작성합니다.
<script setup> import { ref, computed } from 'vue' import { useProp, useNeumorphism } from '../mixin/neumorphism' const props = defineProps({ ...useProp, ...{ data: { // dataList type: Array, default: () => [], }, columns: { // columnsList type: Array, default: () => [], }, } }) const { baseStyleObject } = useNeumorphism(props) let styleObject = computed(() => ({ // '--font-size': `${props.size-26}px`, '--line-height': `${props.size-20}px`, '--limit-size': `${props.size-28}px` })) </script> <template> <div :> <table > <thead> <tr class="neumorphism"> <!-- 表头循环 --> <th v-for="col in columns" :key="col.key">{{col.title}}</th> </tr> </thead> <tbody> <!-- 表体循环 --> <tr class="neumorphism" v-for="row in data" :key="row.id"> <td v-for="col in columns" :key="col.key"> <span> {{row[col.key]}} </span> </td> </tr> </tbody> </table> </div> </template> <script> export default { name: 'sanorin-table', } </script> <style scoped> @import "../../style/index.css"; @import "../../style/neumorphism.css"; table { width: 100%; /* border-collapse: collapse; */ empty-cells: show; border-collapse:separate; border-spacing:0px 10px; } table td, table th { color: var(--text-color); padding: 8px 16px 8px 16px; text-align: left; } table th { color: var(--text-back-color) !important; font-weight: 600; white-space: nowrap; } table tr{ margin-top: 20px; } </style>
최종 효과는 다음과 같습니다.
그런 다음 이것을 구현한 후 시작했습니다. 나머지는 미터 헤드를 고정하는 것부터 시작합니다.
여기에서는 첫 번째 방법이 향후 요구 사항을 충족할 수 없는 경우 나중에 사용되는 방법으로 변경됩니다.
효과 및 코드는 다음과 같습니다.
<script setup> import { ref, computed } from 'vue' import { useProp, useNeumorphism } from '../mixin/neumorphism' const props = defineProps({ ...useProp, ...{ data: { // dataList type: Array, default: () => [], }, columns: { // columnsList type: Array, default: () => [], }, } }) const { baseStyleObject } = useNeumorphism(props) let styleObject = computed(() => ({ })) </script> <template> <div class="san-table scrollbar" :> <table> <thead> <tr class="neumorphism"> <!-- 表头循环 --> <th v-for="col in columns" :key="col.key">{{col.title}}</th> </tr> </thead> <tbody> <!-- 表体循环 --> <tr class="neumorphism" v-for="row in data" :key="row.id"> <td v-for="col in columns" :key="col.key"> <span> {{row[col.key]}} </span> </td> </tr> </tbody> </table> </div> </template> <script> export default { name: 'sanorin-table', } </script> <style scoped> @import "../../style/index.css"; @import "../../style/neumorphism.css"; .san-table{ padding: 0px 20px 20px 20px; height: 200px; position: relative; width: 700px; overflow: auto; } table { width: 100%; table-layout: fixed; empty-cells: show; border-collapse:separate; border-spacing:0px 10px; } thead { position: sticky; top: 10px; } thead:before{ position: absolute; content: ''; width: calc(100% + var(--shadow-blur) * 2); transform: translate(calc(var(--shadow-blur) * -1) , -10px); height: 20px; background-color: var(--main-color); z-index: -1; } table td, table th { color: var(--text-color); padding: 8px 16px 8px 16px; text-align: left; } table th { color: var(--text-back-color) !important; font-weight: 600; white-space: nowrap; } </style>
테이블의 높이를 설정할 수 있습니다. (높이)
데이터의 양이 동적으로 변경되는 경우 테이블의 최대 높이를 설정할 수 있습니다. (maxHeight) max-height 속성을 설정하여 테이블의 최대 높이를 지정합니다. 이때, 필요한 테이블 높이가 최대 높이보다 크면 스크롤바가 표시됩니다.
sanorin-table 요소에 height 또는 maxHeight 속성만 정의하면 추가 코드 없이 헤더가 고정된 테이블을 구현할 수 있습니다.
코드는 다음과 같습니다.
<script setup> import { ref, computed, reactive } from 'vue' import { useProp, useNeumorphism } from '../mixin/neumorphism' const props = defineProps({ ...useProp, ...{ data: { // dataList type: Array, default: () => [], }, columns: { // columnsList type: Array, default: () => [], }, height: { type: Number, }, maxHeight: { type: Number, } } }) // 高度设置 let tableHeightStyleObj = computed(() => { let styleObj = ((e) => { if (e.maxHeight) return { maxHeight: e.maxHeight + 'px' } if (e.height) return { height: e.height + 'px' } return {} })({...props}) return styleObj }) const { baseStyleObject } = useNeumorphism(props) let styleObject = computed(() => ({ ...tableHeightStyleObj.value })) </script> <template> <div class="san-table scrollbar" :> <table> <colgroup> <col v-for="(col, index) in columns" :key="index"> </colgroup> <thead> <tr class="neumorphism"> <th v-for="col in columns" :key="col.key"> {{col.title}} </th> </tr> </thead> <tbody> <tr class="neumorphism" v-for="row in data" :key="row.id"> <td v-for="col in columns" :key="col.key"> {{row[col.key]}} </td> </tr> </tbody> </table> </div> </template> <script> export default { name: 'sanorin-table', } </script> <style scoped> @import "../../style/index.css"; @import "../../style/neumorphism.css"; .san-table{ padding: 0px 20px 20px 20px; position: relative; width: 700px; overflow: auto; } table { width: 100%; table-layout: fixed; empty-cells: show; border-collapse:separate; border-spacing:0px 10px; } thead { position: sticky; top: 10px; } thead:before{ position: absolute; content: ''; width: calc(100% + var(--shadow-blur) * 2); transform: translate(calc(var(--shadow-blur) * -1) , -10px); height: 20px; background-color: var(--main-color); z-index: -1; } table td, table th { color: var(--text-color); padding: 8px 16px 8px 16px; text-align: left; } table th { color: var(--text-back-color) !important; font-weight: 600; white-space: nowrap; } </style>
다음으로 열에 전달된 배열 객체에 너비를 추가하기 위해 너비 컨트롤을 추가합니다. 예제는 다음과 같습니다.
const columnsList = [ { title: '书名', key: 'name', width: 100, }, { title: '作者', key: 'author', width: 100, }, { title: '价格', key: 'price', width: 100, }, { title: '简介', key: 'desc', minWidth: 350, } ]
다음과 같은 효과를 얻기를 바랍니다
1 . 너비가 포함된 열, 너비 고정, 브라우저 너비 변경에 따라 변경되지 않음
2. minWidth가 포함된 열은 설정된 값보다 클 때 테이블의 나머지 너비를 자동으로 채웁니다. 너비가 고정됩니다
3. 너비와 minWidth가 포함되지 않은 열, 테이블의 나머지 너비를 자동으로 채웁니다.
필요에 따라 각 열의 너비 표시를 개별적으로 제어하고 다시 계산하고 다시 렌더링해야 합니다. 브라우저 너비가 변경되면 실시간으로 열이 표시됩니다.
먼저 현재 상황에서 각 열에 필요한 너비를 계산하는 방법을 정의한 다음 원하는 DOM에 바인딩합니다. 그러면 테이블이 변경되거나 브라우저 너비가 변경될 때마다 테이블의 너비가 실시간으로 변경될 수 있습니다.
const initColumns = () => { // 计算每一列在当前情况下所要的宽度 } watch(() => props.columns, () => { initColumns() }); onMounted(() => { nextTick(() => { initColumns(); on(window, 'resize', throttle(() => initColumns(), 400)); }); }); onBeforeUnmount(() => off(window, 'resize', () => initColumns()));
모든 코드:
<script setup> import { ref, computed, watch, onMounted, onBeforeUnmount, nextTick } from 'vue' import { on, off } from '../../utils/listener' import { throttle } from "../../utils/debounce&throttle" import { useProp, useNeumorphism } from '../mixin/neumorphism' const table = ref() // 与html中ref=""对应,定位dom元素 const props = defineProps({ ...useProp, ...{ data: { // dataList type: Array, default: () => [], }, columns: { // columnsList type: Array, default: () => [], }, height: { // height type: Number, }, maxHeight: { // 流体高度 type: Number, }, minUnsetWidth: { // 未设置宽度时最小宽度 type: Number, default: 80 } } }) // 高度设置 let tableHeightStyleObj = computed(() => { let styleObj = ((e) => { if (e.maxHeight) return { maxHeight: e.maxHeight + 'px' } if (e.height) return { height: e.height + 'px' } return {} })({...props}) return styleObj }) // 列宽设置 let col = ref([]) const { columns, minUnsetWidth } = props const _min_column_width = minUnsetWidth // 未设置宽度时最小宽度 const initColumns = () => { col.value = (() => { let _total_width = table.value.offsetWidth // 表格dom元素总宽度 let _needed_minWidth = columns.reduce((t, v) => { // 需要的最小宽度 t += v.width || v.minWidth || _min_column_width return t }, 0) // 需要的最小宽度比总宽度大,则取minWidth即可 if (_needed_minWidth >= _total_width) return columns.reduce((t, v) => { let n = v.width || v.minWidth || _min_column_width t = [...t, n] return t }, []) // 需要的最小宽度比总宽度大,则要把minWidth加权,权重为(未分配的宽度 / minWidth之和) let _unassigned_width = columns.reduce((t, v) => { t += v.minWidth || 0 return t }, 0) let _assigned_width = _needed_minWidth - _unassigned_width let _width_power = (_total_width - _assigned_width) / _unassigned_width return columns.reduce((t, v) => { let n = v.width || (v.minWidth ? (_width_power * v.minWidth).toFixed(2) : _min_column_width) t = [...t, n] return t }, []) })() } watch(() => props.columns, () => { initColumns() }) const throttleInitColumns = () => throttle(() => initColumns(), 400) onMounted(() => { nextTick(() => { initColumns() on(window, 'resize', throttleInitColumns) }) }) onBeforeUnmount(() => off(window, 'resize', throttleInitColumns)) const { baseStyleObject } = useNeumorphism(props) let styleObject = computed(() => ({ ...tableHeightStyleObj.value })) </script> <template> <div class="san-table scrollbar" :> <table ref="table"> <colgroup> <col v-for="(item, index) in col" :key="index" :width="`${item}px`"> </colgroup> <thead> <tr class="neumorphism"> <th v-for="col in columns" :key="col.key"> {{col.title}} </th> </tr> </thead> <tbody> <tr class="neumorphism" v-for="row in data" :key="row.id"> <td v-for="col in columns" :key="col.key"> {{row[col.key]}} </td> </tr> </tbody> </table> </div> </template> <script> export default { name: 'sanorin-table', } </script> <style scoped> @import "../../style/index.css"; @import "../../style/neumorphism.css"; .san-table{ padding: 0px 20px 20px 20px; position: relative; overflow: auto; } table { width: 100%; table-layout: fixed; empty-cells: show; border-collapse:separate; border-spacing:0px 10px; } thead { position: sticky; top: 10px; } thead:before{ position: absolute; content: ''; width: calc(100% + var(--shadow-blur) * 2); transform: translate(calc(var(--shadow-blur) * -1) , -10px); height: 20px; background-color: var(--main-color); z-index: -1; } table td, table th { color: var(--text-color); padding: 8px 16px 8px 16px; text-align: left; word-break:break-all; } table th { color: var(--text-back-color) !important; font-weight: 600; white-space: nowrap; } </style>
여기에 사용된 두 개의 js, 손떨림 방지 조절 및 등록 모니터링도 여기에 기록되어 있습니다
/* 防抖节流函数 */ let timeout = null // 创建一个标记用来存放定时器的返回值 let count = 0; export function debounce(fn, wait = 1000, immediate = false) { return function () { const args = arguments; if (immediate) { if (count == 0) { fn.apply(this, arguments) count++; } else { if (timeout) { clearTimeout(timeout) // 每当用户输入的时候把前一个 setTimeout clear 掉 } timeout = setTimeout(() => { fn.apply(this, arguments) }, wait) } } else { if (timeout) { clearTimeout(timeout) // 每当用户输入的时候把前一个 setTimeout clear 掉 } timeout = setTimeout(() => { fn.apply(this, arguments) }, wait) } }() } let canRun = true; let count1 = 0; export function throttle(fn, wait = 1000, immediate = true) { return function () { if (immediate) { if (count1 == 0) { fn.apply(this, arguments); count1++; } else { if (canRun) { canRun = false setTimeout(function () { fn.apply(this, arguments) canRun = true }, wait); } } } else { if (!canRun) return canRun = false setTimeout(function () { fn.apply(this, arguments) canRun = true }, wait); } }() }
/** * 绑定事件 on(element, event, handler) */ export const on = (element, event, handler) => { if (document.addEventListener) { if (element && event && handler) { element.addEventListener(event, handler, false) } } } /** * 解绑事件 off(element, event, handler) */ export const off = (element, event, handler) => { if (document.removeEventListener) { if (element && event) { element.removeEventListener(event, handler, false) } } }
위 내용은 Vue3 테이블 구성 요소를 사용하는 방법의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!