├── .browserslistrc ├── .eslintrc.js ├── .gitignore ├── README.md ├── babel.config.js ├── index.d.ts ├── package.json ├── public ├── favicon.ico └── index.html ├── rollup.config.js ├── src ├── App.vue ├── index.ts ├── main.ts ├── shims-vue.d.ts ├── utils.ts └── vue3-virtual-list.vue └── tsconfig.json /.browserslistrc: -------------------------------------------------------------------------------- 1 | > 1% 2 | last 2 versions 3 | not dead 4 | -------------------------------------------------------------------------------- /.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | root: true, 3 | env: { 4 | node: true 5 | }, 6 | extends: [ 7 | "plugin:vue/vue3-essential", 8 | "eslint:recommended", 9 | "@vue/typescript/recommended", 10 | "@vue/prettier", 11 | "@vue/prettier/@typescript-eslint" 12 | ], 13 | parserOptions: { 14 | ecmaVersion: 2020 15 | }, 16 | rules: { 17 | "@typescript-eslint/no-explicit-any": "off", 18 | "no-console": process.env.NODE_ENV === "production" ? "warn" : "off", 19 | "no-debugger": process.env.NODE_ENV === "production" ? "warn" : "off" 20 | } 21 | }; 22 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules 3 | /dist 4 | 5 | 6 | # local env files 7 | .env.local 8 | .env.*.local 9 | 10 | # Log files 11 | npm-debug.log* 12 | yarn-debug.log* 13 | yarn-error.log* 14 | pnpm-debug.log* 15 | 16 | # Editor directories and files 17 | .idea 18 | .vscode 19 | *.suo 20 | *.ntvs* 21 | *.njsproj 22 | *.sln 23 | *.sw? 24 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # vue3-virtual-list 2 | 3 | [![npm](https://img.shields.io/npm/v/vue3-virtual-list.svg)](https://www.npmjs.com/package/vue3-virtual-list) 4 | [![downloads](https://img.shields.io/npm/dm/vue3-virtual-list.svg)](https://www.npmjs.com/package/vue3-virtual-list) 5 | [![vue3](https://img.shields.io/badge/vue-3.x-brightgreen.svg)](https://vuejs.org/) 6 | 7 | Scroll list for big acount of data. Based on Vue3. 8 | 9 | [live demo](https://waningflow.com/vue3-virtual-list/) 10 | 11 | ## Install 12 | 13 | ``` 14 | yarn add vue3-virtual-list 15 | ``` 16 | 17 | ## Example 18 | 19 | ```html 20 | 34 | 35 | 50 | 51 | 66 | ``` 67 | 68 | ## Props 69 | 70 | | name | type | description | required | default | 71 | | ---------- | ------ | ----------------------------------------------------------- | -------- | ------- | 72 | | data | Array | The array of data. Every item is a row. | Yes | | 73 | | dataKey | String | Field as key. | No | id | 74 | | itemSize | Number | The height in pixels of each row. | No | 40 | 75 | | poolBuffer | Number | How many rows will be rendered except for the visible ones. | No | 50 | 76 | -------------------------------------------------------------------------------- /babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | // presets: ["@vue/cli-plugin-babel/preset"] 3 | }; 4 | -------------------------------------------------------------------------------- /index.d.ts: -------------------------------------------------------------------------------- 1 | import Vue from "vue"; 2 | 3 | declare class VirtualList extends Vue { 4 | data: any[]; 5 | dataKey: string; 6 | itemSize: number; 7 | poolBuffer: number; 8 | } 9 | 10 | export { VirtualList }; 11 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "vue3-virtual-list", 3 | "version": "1.0.2", 4 | "keywords": [ 5 | "vue", 6 | "vue3", 7 | "scroll", 8 | "list" 9 | ], 10 | "author": "https://github.com/waningflow", 11 | "license": "MIT", 12 | "repository": { 13 | "type": "git", 14 | "url": "https://github.com/waningflow/vue3-virtual-list.git" 15 | }, 16 | "publishConfig": { 17 | "registry": "https://registry.npmjs.org" 18 | }, 19 | "module": "dist/index.esm.js", 20 | "main": "dist/index.cjs.js", 21 | "unpkg": "dist/index.global.js", 22 | "typings": "index.d.ts", 23 | "scripts": { 24 | "serve": "vue-cli-service serve", 25 | "build": "vue-cli-service build", 26 | "lint": "vue-cli-service lint", 27 | "build-npm": "rollup -c rollup.config.js" 28 | }, 29 | "files": [ 30 | "dist/", 31 | "index.d.ts" 32 | ], 33 | "peerDependencies": { 34 | "vue": "^3.0.0" 35 | }, 36 | "devDependencies": { 37 | "@babel/preset-typescript": "^7.12.7", 38 | "@rollup/plugin-babel": "^5.2.2", 39 | "@rollup/plugin-commonjs": "^17.0.0", 40 | "@rollup/plugin-typescript": "^8.1.0", 41 | "@types/faker": "^5.1.5", 42 | "@typescript-eslint/eslint-plugin": "^2.33.0", 43 | "@typescript-eslint/parser": "^2.33.0", 44 | "@vue/cli-plugin-babel": "~4.5.0", 45 | "@vue/cli-plugin-eslint": "~4.5.0", 46 | "@vue/cli-plugin-typescript": "~4.5.0", 47 | "@vue/cli-service": "~4.5.0", 48 | "@vue/compiler-sfc": "^3.0.0", 49 | "@vue/eslint-config-prettier": "^6.0.0", 50 | "@vue/eslint-config-typescript": "^5.0.2", 51 | "eslint": "^6.7.2", 52 | "eslint-plugin-prettier": "^3.1.3", 53 | "eslint-plugin-vue": "^7.0.0-0", 54 | "less": "^3.0.4", 55 | "less-loader": "^5.0.0", 56 | "lint-staged": "^9.5.0", 57 | "postcss": "^8.2.1", 58 | "prettier": "^1.19.1", 59 | "rollup": "^2.35.1", 60 | "rollup-plugin-postcss": "^4.0.0", 61 | "rollup-plugin-vue": "^6.0.0", 62 | "typescript": "~3.9.3" 63 | }, 64 | "gitHooks": { 65 | "pre-commit": "lint-staged" 66 | }, 67 | "lint-staged": { 68 | "*.{js,jsx,vue,ts,tsx}": [ 69 | "vue-cli-service lint", 70 | "git add" 71 | ] 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/waningflow/vue3-virtual-list/8c6c1a0a945659630c48609b5f43fc9b06295238/public/favicon.ico -------------------------------------------------------------------------------- /public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | <%= htmlWebpackPlugin.options.title %> 9 | 10 | 11 | 14 |
15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /rollup.config.js: -------------------------------------------------------------------------------- 1 | import fs from "fs"; 2 | import commonjs from "@rollup/plugin-commonjs"; 3 | import vue from "rollup-plugin-vue"; 4 | import babel from "@rollup/plugin-babel"; 5 | import PostCSS from "rollup-plugin-postcss"; 6 | import pkg from "./package.json"; // import our package.json file to re-use the naming 7 | 8 | const esbrowserslist = fs 9 | .readFileSync("./.browserslistrc") 10 | .toString() 11 | .split("\n") 12 | .filter(entry => entry && entry.substring(0, 2) !== "ie"); 13 | 14 | export default { 15 | // this is the file containing all our exported components/functions 16 | input: "src/index.ts", 17 | // this is an array of outputed formats 18 | output: [ 19 | { 20 | file: pkg.module, // the name of our esm librry 21 | format: "esm" // the format of choice 22 | // sourcemap: true // ask rollup to include sourcemaps 23 | }, 24 | { 25 | file: pkg.main, 26 | format: "cjs" 27 | // sourcemap: true 28 | }, 29 | { 30 | file: pkg.unpkg, 31 | format: "umd", 32 | name: "Vue3VirtualList", 33 | // sourcemap: true, 34 | globals: { 35 | vue: "Vue" 36 | } 37 | } 38 | ], 39 | // this is an array of the plugins that we are including 40 | plugins: [ 41 | vue(), 42 | PostCSS({ 43 | modules: { 44 | generateScopedName: "[local]___[hash:base64:5]" 45 | }, 46 | include: /&module=.*\.css$/ 47 | }), 48 | // Process all ` 89 | -------------------------------------------------------------------------------- /src/index.ts: -------------------------------------------------------------------------------- 1 | import VirtualList from "./vue3-virtual-list.vue"; 2 | 3 | export { VirtualList }; 4 | -------------------------------------------------------------------------------- /src/main.ts: -------------------------------------------------------------------------------- 1 | import { createApp } from "vue"; 2 | import App from "./App.vue"; 3 | 4 | createApp(App).mount("#app"); 5 | -------------------------------------------------------------------------------- /src/shims-vue.d.ts: -------------------------------------------------------------------------------- 1 | declare module '*.vue' { 2 | import type { DefineComponent } from 'vue' 3 | const component: DefineComponent<{}, {}, any> 4 | export default component 5 | } 6 | -------------------------------------------------------------------------------- /src/utils.ts: -------------------------------------------------------------------------------- 1 | import faker from "faker"; 2 | 3 | export function uuid() { 4 | let d = Date.now(); 5 | if ( 6 | typeof performance !== "undefined" && 7 | typeof performance.now === "function" 8 | ) { 9 | d += performance.now(); //use high-precision timer if available 10 | } 11 | return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, function(c) { 12 | const r = (d + Math.random() * 16) % 16 | 0; 13 | d = Math.floor(d / 16); 14 | return (c === "x" ? r : (r & 0x3) | 0x8).toString(16); 15 | }); 16 | } 17 | 18 | export function mock(length = 1000) { 19 | return Array.from({ length }, () => { 20 | return { 21 | id: uuid(), 22 | name: faker.name.findName(), 23 | email: faker.internet.email(), 24 | address: faker.address.country(), 25 | img: faker.image.imageUrl() 26 | }; 27 | }); 28 | } 29 | -------------------------------------------------------------------------------- /src/vue3-virtual-list.vue: -------------------------------------------------------------------------------- 1 | 22 | 23 | 111 | 112 | 127 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "esnext", 4 | "module": "esnext", 5 | "strict": true, 6 | "jsx": "preserve", 7 | "importHelpers": true, 8 | "moduleResolution": "node", 9 | "skipLibCheck": true, 10 | "esModuleInterop": true, 11 | "allowSyntheticDefaultImports": true, 12 | "sourceMap": true, 13 | "baseUrl": ".", 14 | "types": [ 15 | "webpack-env" 16 | ], 17 | "paths": { 18 | "@/*": [ 19 | "src/*" 20 | ] 21 | }, 22 | "lib": [ 23 | "esnext", 24 | "dom", 25 | "dom.iterable", 26 | "scripthost" 27 | ] 28 | }, 29 | "include": [ 30 | "src/**/*.ts", 31 | "src/**/*.tsx", 32 | "src/**/*.vue", 33 | "tests/**/*.ts", 34 | "tests/**/*.tsx" 35 | ], 36 | "exclude": [ 37 | "node_modules" 38 | ] 39 | } 40 | --------------------------------------------------------------------------------