├── .gitignore ├── .vscode ├── extensions.json └── settings.json ├── src ├── main.ts ├── env.d.ts ├── components │ ├── storage.ts │ ├── useKeepScroll.ts │ ├── MyToolbar.vue │ └── MyTable.vue ├── api │ └── index.ts └── App.vue ├── auto-imports.d.ts ├── .prettierrc ├── README.md ├── index.html ├── tsconfig.json ├── vite.config.ts ├── .github └── workflows │ └── deploy.yml ├── package.json └── components.d.ts /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .DS_Store 3 | dist 4 | dist-ssr 5 | *.local 6 | -------------------------------------------------------------------------------- /.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | "recommendations": ["johnsoncodehk.volar"] 3 | } 4 | -------------------------------------------------------------------------------- /src/main.ts: -------------------------------------------------------------------------------- 1 | import { createApp } from 'vue' 2 | import App from './App.vue' 3 | 4 | const app = createApp(App) 5 | app.mount('#app') 6 | -------------------------------------------------------------------------------- /auto-imports.d.ts: -------------------------------------------------------------------------------- 1 | // Generated by 'unplugin-auto-import' 2 | // We suggest you to commit this file into source control 3 | declare global { 4 | 5 | } 6 | export {} 7 | -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "eslintIntegration": true, 3 | "stylelintIntegration": true, 4 | "tabWidth": 2, 5 | "singleQuote": true, 6 | "semi": false, 7 | "proseWrap": "always" 8 | } -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "typescript.tsdk": "node_modules\\typescript\\lib", 3 | "editor.formatOnSave": true, 4 | "files.associations": { 5 | "*.svg": "html" 6 | }, 7 | "editor.tabSize": 2 8 | } 9 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Element Plus Table Proxy Demo 2 | Element Plus 的 Table 组件二次封装的 Demo。 3 | 4 | `Vue2` + `Element UI` 请跳转至 [aweikalee/element-ui-table-proxy-demo](https://github.com/aweikalee/element-ui-table-proxy-demo) 5 | 6 | ## 安装和运行 7 | ``` 8 | npm install 9 | npm run dev 10 | ``` -------------------------------------------------------------------------------- /src/env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | 3 | declare module '*.vue' { 4 | import { DefineComponent } from 'vue' 5 | // eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/ban-types 6 | const component: DefineComponent<{}, {}, any> 7 | export default component 8 | } 9 | -------------------------------------------------------------------------------- /src/components/storage.ts: -------------------------------------------------------------------------------- 1 | export function set(key: string, value: any) { 2 | localStorage.setItem(key, JSON.stringify(value)) 3 | } 4 | 5 | export function get(key: string) { 6 | try { 7 | return JSON.parse(localStorage.getItem(key) as string) as T 8 | } catch (error) { 9 | return 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Element Plus Table 二次封装Demo 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "esnext", 4 | "useDefineForClassFields": true, 5 | "module": "esnext", 6 | "moduleResolution": "node", 7 | "strict": true, 8 | "jsx": "preserve", 9 | "sourceMap": true, 10 | "resolveJsonModule": true, 11 | "esModuleInterop": true, 12 | "lib": ["esnext", "dom"], 13 | "types": ["element-plus/global"] 14 | }, 15 | "include": ["src/**/*.ts", "src/**/*.d.ts", "src/**/*.tsx", "src/**/*.vue"] 16 | } 17 | -------------------------------------------------------------------------------- /vite.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig } from 'vite' 2 | import vue from '@vitejs/plugin-vue' 3 | 4 | import AutoImport from 'unplugin-auto-import/vite' 5 | import Components from 'unplugin-vue-components/vite' 6 | import { ElementPlusResolver } from 'unplugin-vue-components/resolvers' 7 | 8 | // https://vitejs.dev/config/ 9 | export default defineConfig({ 10 | base: './', 11 | plugins: [ 12 | vue(), 13 | AutoImport({ 14 | resolvers: [ElementPlusResolver()], 15 | }), 16 | Components({ 17 | resolvers: [ElementPlusResolver()], 18 | }), 19 | ], 20 | }) 21 | -------------------------------------------------------------------------------- /.github/workflows/deploy.yml: -------------------------------------------------------------------------------- 1 | name: Build and Deploy 2 | on: 3 | push: 4 | branches: 5 | - main 6 | 7 | jobs: 8 | build-and-deploy: 9 | runs-on: ubuntu-latest 10 | steps: 11 | - name: Checkout 12 | uses: actions/checkout@v2.3.1 13 | with: 14 | persist-credentials: false 15 | 16 | - name: Install and Build 17 | run: | 18 | npm install 19 | npm run build 20 | - name: Deploy to gh-pages 21 | uses: JamesIves/github-pages-deploy-action@4.1.8 22 | with: 23 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 24 | BRANCH: gh-pages 25 | FOLDER: dist 26 | CLEAN: true 27 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "element-plus-table-proxy-demo", 3 | "version": "1.0.0", 4 | "scripts": { 5 | "dev": "vite", 6 | "build": "vue-tsc --noEmit && vite build", 7 | "preview": "vite preview" 8 | }, 9 | "dependencies": { 10 | "element-plus": "^1.2.0-beta.6", 11 | "vue": "^3.2.23", 12 | "vue-draggable-next": "^2.1.1", 13 | "vue-router": "^4.0.12" 14 | }, 15 | "devDependencies": { 16 | "@types/sortablejs": "^1.10.7", 17 | "@vitejs/plugin-vue": "^1.10.2", 18 | "less": "^4.1.2", 19 | "typescript": "^4.4.4", 20 | "unplugin-auto-import": "^0.5.3", 21 | "unplugin-vue-components": "^0.17.9", 22 | "vite": "^2.7.0", 23 | "vue-tsc": "^0.28.10" 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/api/index.ts: -------------------------------------------------------------------------------- 1 | export interface IDataItem { 2 | id: number 3 | order: string 4 | price: number 5 | amount: number 6 | title: string 7 | } 8 | 9 | let id = 0 10 | export function list() { 11 | return new Promise((resolve) => { 12 | setTimeout(() => { 13 | resolve( 14 | Array.from(new Array(20), () => ({ 15 | id: ++id, 16 | order: `O${Math.random().toFixed(20).slice(2, 22)}`, 17 | price: Number((Math.random() * 500).toFixed(2)), 18 | amount: Math.floor(Math.random() * 100), 19 | title: Number(Math.random().toFixed(10).slice(2, 10)) 20 | .toString(32) 21 | .toUpperCase(), 22 | })) 23 | ) 24 | }, 500) 25 | }) 26 | } 27 | -------------------------------------------------------------------------------- /components.d.ts: -------------------------------------------------------------------------------- 1 | // generated by unplugin-vue-components 2 | // We suggest you to commit this file into source control 3 | // Read more: https://github.com/vuejs/vue-next/pull/3399 4 | 5 | declare module 'vue' { 6 | export interface GlobalComponents { 7 | ElButton: typeof import('element-plus/es')['ElButton'] 8 | ElCheckbox: typeof import('element-plus/es')['ElCheckbox'] 9 | ElDropdown: typeof import('element-plus/es')['ElDropdown'] 10 | ElDropdownMenu: typeof import('element-plus/es')['ElDropdownMenu'] 11 | ElTable: typeof import('element-plus/es')['ElTable'] 12 | ElTableColumn: typeof import('element-plus/es')['ElTableColumn'] 13 | MyTable: typeof import('./src/components/MyTable.vue')['default'] 14 | MyToolbar: typeof import('./src/components/MyToolbar.vue')['default'] 15 | } 16 | } 17 | 18 | export { } 19 | -------------------------------------------------------------------------------- /src/components/useKeepScroll.ts: -------------------------------------------------------------------------------- 1 | import { onActivated, onDeactivated, Ref, watch } from 'vue' 2 | 3 | export function useKeepScroll(el: Ref) { 4 | let scrollTop = 0 5 | let scrollLeft = 0 6 | 7 | function save() { 8 | if (!el.value) return 9 | 10 | scrollTop = el.value.scrollTop 11 | scrollLeft = el.value.scrollLeft 12 | } 13 | function restore() { 14 | if (!el.value) return 15 | 16 | el.value.scrollTop = scrollTop 17 | el.value.scrollLeft = scrollLeft 18 | } 19 | 20 | let listenedEl: HTMLElement | null = null 21 | function removeEventListener() { 22 | listenedEl?.removeEventListener('scroll', save) 23 | listenedEl = null 24 | } 25 | function addEventListener() { 26 | if (!el.value) return 27 | if (listenedEl === el.value) return 28 | removeEventListener() 29 | 30 | listenedEl = el.value 31 | listenedEl?.addEventListener('scroll', save) 32 | } 33 | 34 | watch(el, addEventListener) 35 | onActivated(addEventListener) 36 | onDeactivated(removeEventListener) 37 | 38 | onActivated(restore) 39 | } 40 | -------------------------------------------------------------------------------- /src/App.vue: -------------------------------------------------------------------------------- 1 | 2 | 3 | 10 | 11 | 12 | 13 | 14 | 15 | ¥{{ row.price }} 16 | 17 | 18 | 19 | {{ row.amount }}件 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 显隐(KeepAlive) 28 | 29 | 30 | 47 | -------------------------------------------------------------------------------- /src/components/MyToolbar.vue: -------------------------------------------------------------------------------- 1 | 2 | 3 | 动态列 4 | 5 | 6 | 7 | 8 | 9 | 13 | {{ element.label }} 18 | 19 | 左固定 25 | 右固定 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 86 | 87 | 103 | -------------------------------------------------------------------------------- /src/components/MyTable.vue: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 13 | 14 | 159 | --------------------------------------------------------------------------------