Skip to content

refactor(grid-body): [grid] add TInyGridBody renderless logic #1906

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 6 commits into from
Aug 22, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .github/workflows/test-e2e-all.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ jobs:
- name: Setup node
uses: actions/setup-node@v3
with:
node-version: 16
node-version: 20

- name: Get pnpm store directory
id: pnpm-cache
Expand Down Expand Up @@ -67,7 +67,7 @@ jobs:
steps:
- uses: actions/setup-node@v3
with:
node-version: 16
node-version: 20
- name: Install dependencies
run: |
npm install -g @playwright/test
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/test-e2e-dispatch.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ jobs:
- name: Setup node
uses: actions/setup-node@v3
with:
node-version: 16
node-version: 20

- name: Get pnpm store directory
id: pnpm-cache
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/test-e2e-pr.yml
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ jobs:
- name: Setup node
uses: actions/setup-node@v3
with:
node-version: 16
node-version: 20
- name: Cache Playwright Installation
uses: actions/cache@v3
with:
Expand Down
4 changes: 3 additions & 1 deletion examples/sites/demos/pc/app/grid/size/column-width.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ test('设置所有列宽度', async ({ page }) => {
await expect(width1).toEqual(200)
const { width: width2 } = await page.getByRole('cell', { name: '地址' }).boundingBox()
await expect(width2).toEqual(200)
const { width: width3 } = await page.getByRole('cell', { name: '公司简介' }).boundingBox()
const element = page.getByRole('cell', { name: '公司简介' })
await element.scrollIntoViewIfNeeded()
const { width: width3 } = await element.boundingBox()
await expect(width3).toEqual(200)
})
21 changes: 11 additions & 10 deletions internals/vite-plugin-template2jsx/package.json
Original file line number Diff line number Diff line change
@@ -1,12 +1,10 @@
{
"name": "@opentiny/vue-vite-template2jsx",
"type": "module",
"version": "1.1.5",
"description": "A TinyVue vite import plugin",
"main": "index.js",
"module": "index.js",
"author": "Tiny Vue Team",
"license": "MIT",
"type": "module",
"repository": {
"type": "git",
"url": "git@github.com:opentiny/tiny-vue.git"
Expand All @@ -16,13 +14,16 @@
"TinyVue",
"vite"
],
"dependencies": {
"lodash-es": "^4.17.21",
"fs-extra": "^11.2.0",
"vue-template-compiler": "2.6.14",
"html-dom-parser": "~5.0.8"
},
"main": "index.js",
"module": "index.js",
"peerDependencies": {
"vite": ">=4"
},
"dependencies": {
"fs-extra": "^11.2.0",
"html-dom-parser": "~5.0.8",
"lodash-es": "^4.17.21",
"vue": "2.6.14",
"vue-template-compiler": "2.6.14"
}
}
}
108 changes: 108 additions & 0 deletions packages/renderless/src/grid/body/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
import { emitEvent } from '../utils'

import { addClass, removeClass } from '../../common/deps/dom'

export const generateFixedClassName = ({ $table, bodyElem, leftList, rightList }) => {
if (!$table || !bodyElem) {
return
}

const scrollLeft = bodyElem.scrollLeft

if (leftList.length) {
if (scrollLeft === 0) {
removeClass($table.$el, 'tiny-grid-fixed__left')
} else {
addClass($table.$el, 'tiny-grid-fixed__left')
}
}

if (rightList.length) {
const isShowRightFixed = bodyElem.scrollWidth - bodyElem.clientWidth - bodyElem.scrollLeft

if (isShowRightFixed === 0) {
removeClass($table.$el, 'tiny-grid-fixed__right')
} else {
addClass($table.$el, 'tiny-grid-fixed__right')
}
}
}

export const scrollEvent =
({ parent }) =>
(event) => {
// 滚动处理: 如果存在列固定左侧,同步更新滚动状态;如果存在列固定右侧,同步更新滚动状态。
const $table = parent

let { $refs, lastScrollLeft, lastScrollTop, scrollXLoad, scrollYLoad, columnStore } = $table
let { leftList, rightList } = columnStore
let { tableBody, tableFooter, tableHeader } = $refs

// 获取主表头,主表体,主表尾,左表体,右表体
let headerElem = tableHeader ? tableHeader.$el : null
let bodyElem = tableBody.$el
let footerElem = tableFooter ? tableFooter.$el : null

// 获取主表体元素的滚动位置
let scrollLeft = bodyElem.scrollLeft
let scrollTop = bodyElem.scrollTop

// 对比当前滚动位置和最后一次滚动位置,来得到当前滚动的是哪个方向上的滚动条
let isY = scrollTop !== lastScrollTop
let isX = scrollLeft !== lastScrollLeft

// 记录新的滚动位置和时间
$table.lastScrollTime = Date.now()
$table.lastScrollLeft = scrollLeft
$table.lastScrollTop = scrollTop
$table.scrollDirection = isX ? 'X' : 'Y'

// 同步滚动条状态,只同步表头(表尾)滚动条状态,冻结列已优化为sticky方式
syncHeaderAndFooterScroll({ bodyElem, footerElem, headerElem, isX })

// 处理关于冻结列最外层div类名
if (leftList.length || rightList.length) {
generateFixedClassName({ $table, bodyElem, leftList, rightList })
}

// 处理x和y轴方法虚拟滚动数据加载逻辑
doScrollLoad({ $table, _vm: this, bodyElem, event, headerElem, isX, isY, scrollLeft, scrollXLoad, scrollYLoad })

// 触发用户监听的表格滚动事件
emitEvent($table, 'scroll', [{ type: 'body', scrollTop, scrollLeft, isX, isY, $table }, event])
}

const syncHeaderAndFooterScroll = ({ bodyElem, footerElem, headerElem, isX }) => {
if (isX && headerElem) {
headerElem.scrollLeft = bodyElem.scrollLeft
}
if (isX && footerElem) {
footerElem.scrollLeft = bodyElem.scrollLeft
}
}

function doScrollLoad({ $table, _vm, bodyElem, event, headerElem, isX, isY, scrollLeft, scrollXLoad, scrollYLoad }) {
let isScrollX = scrollXLoad && isX

// 如果是水平虚拟滚动,并且正在进行水平滚动,就触发水平虚滚事件
if (isScrollX) {
// 处理x轴方法虚拟滚动加载数据逻辑
$table.triggerScrollXEvent(event)
}

// 同上,并且主表头存在时,修复极端场景(拖动滚动条到最右侧)表头表体水平滚动位置不同步问题
if (isScrollX && headerElem && scrollLeft + bodyElem.clientWidth >= bodyElem.scrollWidth) {
// 修复拖动滚动条时可能存在不同步问题
_vm.$nextTick(() => {
if (bodyElem.scrollLeft !== headerElem.scrollLeft) {
headerElem.scrollLeft = bodyElem.scrollLeft
}
})
}

// 如果是垂直虚拟滚动,并且正在进行垂直滚动,就触发垂直虚滚事件
if (scrollYLoad && isY) {
// 处理y轴方法虚拟滚动加载数据逻辑
$table.triggerScrollYEvent(event)
}
}
61 changes: 61 additions & 0 deletions packages/renderless/src/grid/body/vue.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import { scrollEvent } from './index'
import type { ISharedRenderlessParamHooks } from '@/types'

export const api = ['state', 'scrollEvent']

export const renderless = (props, context: ISharedRenderlessParamHooks, { vm }): any => {
const { onMounted, inject, onBeforeUnmount, onUpdated } = context

const $table = inject('$table')

const api = {
scrollEvent: scrollEvent({ parent: $table })
}

onMounted(() => {
const { $el, $refs } = vm as any

const { elemStore, dropConfig } = $table
const keyPrefix = 'main-body-'

// 表体第一层div,出现滚动条的dom元素
elemStore[`${keyPrefix}wrapper`] = $el
// 表体table元素
elemStore[`${keyPrefix}table`] = $refs.table
// colgroup元素,保持表头和表体宽度保持一致
elemStore[`${keyPrefix}colgroup`] = $refs.colgroup
// tbody元素
elemStore[`${keyPrefix}list`] = $refs.tbody
// x轴滚动条占位元素
elemStore[`${keyPrefix}xSpace`] = $refs.xSpace
// y轴滚动条占位元素
elemStore[`${keyPrefix}ySpace`] = $refs.ySpace
// 空数据元素
elemStore[`${keyPrefix}emptyBlock`] = $refs.emptyBlock

// 表体第一层div监听滚动事件
$el.onscroll = vm.scrollEvent
$el._onscroll = vm.scrollEvent

if (dropConfig) {
const { plugin, row = true } = dropConfig
plugin && row && (vm.rowSortable = $table.rowDrop(vm.$el))
}
})

onBeforeUnmount(() => {
const { $el } = vm as any

$el.onscroll = null
$el._onscroll = null

vm.rowSortable && vm.rowSortable.destroy()
})

onUpdated(() => {
const { fixedType } = vm
!fixedType && $table.updateTableBodyHeight()
})

return api
}
2 changes: 1 addition & 1 deletion packages/vue/src/grid/src/body/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
* SOFTWARE.
*
*/
import Body from './src/body'
import Body from './src/pc.vue'

Body.install = function (Vue) {
Vue.component(Body.name, Body)
Expand Down
Loading
Loading