mirror of
https://github.com/pure-admin/vue-pure-admin.git
synced 2025-06-07 08:57:19 +08:00
feat: add Virtual List demo
This commit is contained in:
parent
6ea020c8d2
commit
348916e567
@ -82,5 +82,6 @@ menus:
|
|||||||
hsQrcode: Qrcode
|
hsQrcode: Qrcode
|
||||||
hsCascader: Area Cascader
|
hsCascader: Area Cascader
|
||||||
hsSwiper: Swiper Plugin
|
hsSwiper: Swiper Plugin
|
||||||
|
hsVirtualList: Virtual List
|
||||||
status:
|
status:
|
||||||
hsLoad: Loading...
|
hsLoad: Loading...
|
||||||
|
@ -82,5 +82,6 @@ menus:
|
|||||||
hsQrcode: 二维码
|
hsQrcode: 二维码
|
||||||
hsCascader: 区域级联选择器
|
hsCascader: 区域级联选择器
|
||||||
hsSwiper: Swiper插件
|
hsSwiper: Swiper插件
|
||||||
|
hsVirtualList: 虚拟列表
|
||||||
status:
|
status:
|
||||||
hsLoad: 加载中...
|
hsLoad: 加载中...
|
||||||
|
@ -70,6 +70,7 @@
|
|||||||
"vue-json-pretty": "^2.0.2",
|
"vue-json-pretty": "^2.0.2",
|
||||||
"vue-router": "^4.0.15",
|
"vue-router": "^4.0.15",
|
||||||
"vue-types": "^4.1.1",
|
"vue-types": "^4.1.1",
|
||||||
|
"vue-virtual-scroller": "^2.0.0-alpha.1",
|
||||||
"vuedraggable": "4.1.0",
|
"vuedraggable": "4.1.0",
|
||||||
"vxe-table": "^4.2.3",
|
"vxe-table": "^4.2.3",
|
||||||
"xe-utils": "^3.5.4",
|
"xe-utils": "^3.5.4",
|
||||||
@ -78,6 +79,7 @@
|
|||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@commitlint/cli": "13.1.0",
|
"@commitlint/cli": "13.1.0",
|
||||||
"@commitlint/config-conventional": "13.1.0",
|
"@commitlint/config-conventional": "13.1.0",
|
||||||
|
"@faker-js/faker": "^6.3.1",
|
||||||
"@iconify-icons/carbon": "^1.2.4",
|
"@iconify-icons/carbon": "^1.2.4",
|
||||||
"@iconify-icons/ep": "^1.2.4",
|
"@iconify-icons/ep": "^1.2.4",
|
||||||
"@iconify-icons/fa": "^1.2.2",
|
"@iconify-icons/fa": "^1.2.2",
|
||||||
|
55
pnpm-lock.yaml
generated
55
pnpm-lock.yaml
generated
@ -5,6 +5,7 @@ specifiers:
|
|||||||
"@commitlint/cli": 13.1.0
|
"@commitlint/cli": 13.1.0
|
||||||
"@commitlint/config-conventional": 13.1.0
|
"@commitlint/config-conventional": 13.1.0
|
||||||
"@ctrl/tinycolor": ^3.4.1
|
"@ctrl/tinycolor": ^3.4.1
|
||||||
|
"@faker-js/faker": ^6.3.1
|
||||||
"@iconify-icons/carbon": ^1.2.4
|
"@iconify-icons/carbon": ^1.2.4
|
||||||
"@iconify-icons/ep": ^1.2.4
|
"@iconify-icons/ep": ^1.2.4
|
||||||
"@iconify-icons/fa": ^1.2.2
|
"@iconify-icons/fa": ^1.2.2
|
||||||
@ -105,6 +106,7 @@ specifiers:
|
|||||||
vue-json-pretty: ^2.0.2
|
vue-json-pretty: ^2.0.2
|
||||||
vue-router: ^4.0.15
|
vue-router: ^4.0.15
|
||||||
vue-types: ^4.1.1
|
vue-types: ^4.1.1
|
||||||
|
vue-virtual-scroller: ^2.0.0-alpha.1
|
||||||
vuedraggable: 4.1.0
|
vuedraggable: 4.1.0
|
||||||
vxe-table: ^4.2.3
|
vxe-table: ^4.2.3
|
||||||
xe-utils: ^3.5.4
|
xe-utils: ^3.5.4
|
||||||
@ -154,6 +156,7 @@ dependencies:
|
|||||||
vue-json-pretty: 2.0.6_vue@3.2.33
|
vue-json-pretty: 2.0.6_vue@3.2.33
|
||||||
vue-router: 4.0.15_vue@3.2.33
|
vue-router: 4.0.15_vue@3.2.33
|
||||||
vue-types: 4.1.1_vue@3.2.33
|
vue-types: 4.1.1_vue@3.2.33
|
||||||
|
vue-virtual-scroller: 2.0.0-alpha.1_vue@3.2.33
|
||||||
vuedraggable: 4.1.0_vue@3.2.33
|
vuedraggable: 4.1.0_vue@3.2.33
|
||||||
vxe-table: 4.2.3_vue@3.2.33+xe-utils@3.5.4
|
vxe-table: 4.2.3_vue@3.2.33+xe-utils@3.5.4
|
||||||
xe-utils: 3.5.4
|
xe-utils: 3.5.4
|
||||||
@ -162,6 +165,7 @@ dependencies:
|
|||||||
devDependencies:
|
devDependencies:
|
||||||
"@commitlint/cli": 13.1.0
|
"@commitlint/cli": 13.1.0
|
||||||
"@commitlint/config-conventional": 13.1.0
|
"@commitlint/config-conventional": 13.1.0
|
||||||
|
"@faker-js/faker": 6.3.1
|
||||||
"@iconify-icons/carbon": 1.2.5
|
"@iconify-icons/carbon": 1.2.5
|
||||||
"@iconify-icons/ep": 1.2.4
|
"@iconify-icons/ep": 1.2.4
|
||||||
"@iconify-icons/fa": 1.2.2
|
"@iconify-icons/fa": 1.2.2
|
||||||
@ -938,6 +942,14 @@ packages:
|
|||||||
- supports-color
|
- supports-color
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
|
/@faker-js/faker/6.3.1:
|
||||||
|
resolution:
|
||||||
|
{
|
||||||
|
integrity: sha512-8YXBE2ZcU/pImVOHX7MWrSR/X5up7t6rPWZlk34RwZEcdr3ua6X+32pSd6XuOQRN+vbuvYNfA6iey8NbrjuMFQ==
|
||||||
|
}
|
||||||
|
engines: { node: ">=14.0.0", npm: ">=6.0.0" }
|
||||||
|
dev: true
|
||||||
|
|
||||||
/@floating-ui/core/0.6.2:
|
/@floating-ui/core/0.6.2:
|
||||||
resolution:
|
resolution:
|
||||||
{
|
{
|
||||||
@ -5989,6 +6001,13 @@ packages:
|
|||||||
kind-of: 6.0.3
|
kind-of: 6.0.3
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
|
/mitt/2.1.0:
|
||||||
|
resolution:
|
||||||
|
{
|
||||||
|
integrity: sha512-ILj2TpLiysu2wkBbWjAmww7TkZb65aiQO+DkVdUTBpBXq+MHYiETENkKFMtsJZX1Lf4pe4QOrTSjIfUwN5lRdg==
|
||||||
|
}
|
||||||
|
dev: false
|
||||||
|
|
||||||
/mitt/3.0.0:
|
/mitt/3.0.0:
|
||||||
resolution:
|
resolution:
|
||||||
{
|
{
|
||||||
@ -8471,6 +8490,28 @@ packages:
|
|||||||
vue: 3.2.33
|
vue: 3.2.33
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
|
/vue-observe-visibility/2.0.0-alpha.1_vue@3.2.33:
|
||||||
|
resolution:
|
||||||
|
{
|
||||||
|
integrity: sha512-flFbp/gs9pZniXR6fans8smv1kDScJ8RS7rEpMjhVabiKeq7Qz3D9+eGsypncjfIyyU84saU88XZ0zjbD6Gq/g==
|
||||||
|
}
|
||||||
|
peerDependencies:
|
||||||
|
vue: ^3.0.0
|
||||||
|
dependencies:
|
||||||
|
vue: 3.2.33
|
||||||
|
dev: false
|
||||||
|
|
||||||
|
/vue-resize/2.0.0-alpha.1_vue@3.2.33:
|
||||||
|
resolution:
|
||||||
|
{
|
||||||
|
integrity: sha512-7+iqOueLU7uc9NrMfrzbG8hwMqchfVfSzpVlCMeJQe4pyibqyoifDNbKTZvwxZKDvGkB+PdFeKvnGZMoEb8esg==
|
||||||
|
}
|
||||||
|
peerDependencies:
|
||||||
|
vue: ^3.0.0
|
||||||
|
dependencies:
|
||||||
|
vue: 3.2.33
|
||||||
|
dev: false
|
||||||
|
|
||||||
/vue-router/4.0.15_vue@3.2.33:
|
/vue-router/4.0.15_vue@3.2.33:
|
||||||
resolution:
|
resolution:
|
||||||
{
|
{
|
||||||
@ -8509,6 +8550,20 @@ packages:
|
|||||||
vue: 3.2.33
|
vue: 3.2.33
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
|
/vue-virtual-scroller/2.0.0-alpha.1_vue@3.2.33:
|
||||||
|
resolution:
|
||||||
|
{
|
||||||
|
integrity: sha512-Mn5w3Qe06t7c3Imm2RHD43RACab1CCWplpdgzq+/FWJcpQtcGKd5vDep8i+nIwFtzFLsWAqEK0RzM7KrfAcBng==
|
||||||
|
}
|
||||||
|
peerDependencies:
|
||||||
|
vue: ^3.0.11
|
||||||
|
dependencies:
|
||||||
|
mitt: 2.1.0
|
||||||
|
vue: 3.2.33
|
||||||
|
vue-observe-visibility: 2.0.0-alpha.1_vue@3.2.33
|
||||||
|
vue-resize: 2.0.0-alpha.1_vue@3.2.33
|
||||||
|
dev: false
|
||||||
|
|
||||||
/vue/3.2.33:
|
/vue/3.2.33:
|
||||||
resolution:
|
resolution:
|
||||||
{
|
{
|
||||||
|
@ -6,6 +6,7 @@ import { getServerConfig } from "./config";
|
|||||||
import { createApp, Directive } from "vue";
|
import { createApp, Directive } from "vue";
|
||||||
import { useI18n } from "../src/plugins/i18n";
|
import { useI18n } from "../src/plugins/i18n";
|
||||||
import { MotionPlugin } from "@vueuse/motion";
|
import { MotionPlugin } from "@vueuse/motion";
|
||||||
|
import VirtualScroller from "vue-virtual-scroller";
|
||||||
import { useTable } from "../src/plugins/vxe-table";
|
import { useTable } from "../src/plugins/vxe-table";
|
||||||
import { injectResponsiveStorage } from "/@/utils/storage/responsive";
|
import { injectResponsiveStorage } from "/@/utils/storage/responsive";
|
||||||
|
|
||||||
@ -22,6 +23,7 @@ import "@pureadmin/components/dist/theme.css";
|
|||||||
import "./assets/iconfont/iconfont.js";
|
import "./assets/iconfont/iconfont.js";
|
||||||
import "./assets/iconfont/iconfont.css";
|
import "./assets/iconfont/iconfont.css";
|
||||||
import "v-contextmenu/dist/themes/default.css";
|
import "v-contextmenu/dist/themes/default.css";
|
||||||
|
import "vue-virtual-scroller/dist/vue-virtual-scroller.css";
|
||||||
|
|
||||||
const app = createApp(App);
|
const app = createApp(App);
|
||||||
|
|
||||||
@ -46,6 +48,11 @@ getServerConfig(app).then(async config => {
|
|||||||
await router.isReady();
|
await router.isReady();
|
||||||
injectResponsiveStorage(app, config);
|
injectResponsiveStorage(app, config);
|
||||||
setupStore(app);
|
setupStore(app);
|
||||||
app.use(MotionPlugin).use(useI18n).use(ElementPlus).use(useTable);
|
app
|
||||||
|
.use(MotionPlugin)
|
||||||
|
.use(useI18n)
|
||||||
|
.use(ElementPlus)
|
||||||
|
.use(useTable)
|
||||||
|
.use(VirtualScroller);
|
||||||
app.mount("#app");
|
app.mount("#app");
|
||||||
});
|
});
|
||||||
|
@ -122,6 +122,14 @@ const ableRouter = {
|
|||||||
meta: {
|
meta: {
|
||||||
title: $t("menus.hsSwiper")
|
title: $t("menus.hsSwiper")
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: "/able/virtualList",
|
||||||
|
name: "reVirtualList",
|
||||||
|
component: () => import("/@/views/able/virtual-list/index.vue"),
|
||||||
|
meta: {
|
||||||
|
title: $t("menus.hsVirtualList")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
};
|
};
|
||||||
|
70
src/views/able/virtual-list/data.ts
Normal file
70
src/views/able/virtual-list/data.ts
Normal file
@ -0,0 +1,70 @@
|
|||||||
|
import { faker } from "@faker-js/faker";
|
||||||
|
|
||||||
|
let uid = 0;
|
||||||
|
|
||||||
|
function generateItem() {
|
||||||
|
return {
|
||||||
|
name: faker.name.findName(),
|
||||||
|
avatar: faker.internet.avatar()
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getData(count, letters) {
|
||||||
|
const raw = {};
|
||||||
|
|
||||||
|
const alphabet = "abcdefghijklmnopqrstuvwxyz".split("");
|
||||||
|
|
||||||
|
for (const l of alphabet) {
|
||||||
|
raw[l] = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
for (let i = 0; i < count; i++) {
|
||||||
|
const item = generateItem();
|
||||||
|
const letter = item.name.charAt(0).toLowerCase();
|
||||||
|
raw[letter].push(item);
|
||||||
|
}
|
||||||
|
|
||||||
|
const list = [];
|
||||||
|
let index = 1;
|
||||||
|
|
||||||
|
for (const l of alphabet) {
|
||||||
|
raw[l] = raw[l].sort((a, b) => (a.name < b.name ? -1 : 1));
|
||||||
|
if (letters) {
|
||||||
|
list.push({
|
||||||
|
id: uid++,
|
||||||
|
index: index++,
|
||||||
|
type: "letter",
|
||||||
|
value: l,
|
||||||
|
height: 200
|
||||||
|
});
|
||||||
|
}
|
||||||
|
for (const item of raw[l]) {
|
||||||
|
list.push({
|
||||||
|
id: uid++,
|
||||||
|
index: index++,
|
||||||
|
type: "person",
|
||||||
|
value: item,
|
||||||
|
height: 50
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function addItem(list) {
|
||||||
|
list.push({
|
||||||
|
id: uid++,
|
||||||
|
index: list.length + 1,
|
||||||
|
type: "person",
|
||||||
|
value: generateItem(),
|
||||||
|
height: 50
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export function generateMessage() {
|
||||||
|
return {
|
||||||
|
avatar: faker.internet.avatar(),
|
||||||
|
message: faker.lorem.text()
|
||||||
|
};
|
||||||
|
}
|
138
src/views/able/virtual-list/horizontal.vue
Normal file
138
src/views/able/virtual-list/horizontal.vue
Normal file
@ -0,0 +1,138 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import { ref, computed } from "vue";
|
||||||
|
import { generateMessage } from "./data";
|
||||||
|
|
||||||
|
const items = ref([]);
|
||||||
|
const search = ref("");
|
||||||
|
|
||||||
|
for (let i = 0; i < 10000; i++) {
|
||||||
|
items.value.push({
|
||||||
|
id: i,
|
||||||
|
...generateMessage()
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const filteredItems = computed(() => {
|
||||||
|
if (!search.value) return items.value;
|
||||||
|
const lowerCaseSearch = search.value.toLowerCase();
|
||||||
|
return items.value.filter(i =>
|
||||||
|
i.message.toLowerCase().includes(lowerCaseSearch)
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
function changeMessage(message) {
|
||||||
|
Object.assign(message, generateMessage());
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div class="dynamic-scroller-demo">
|
||||||
|
<div class="flex justify-around mb-4">
|
||||||
|
<el-input
|
||||||
|
class="mr-2 !w-1/1.5"
|
||||||
|
clearable
|
||||||
|
v-model="search"
|
||||||
|
placeholder="Filter..."
|
||||||
|
style="width: 300px"
|
||||||
|
/>
|
||||||
|
<el-tag effect="dark">水平模式horizontal</el-tag>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<DynamicScroller
|
||||||
|
:items="filteredItems"
|
||||||
|
:min-item-size="54"
|
||||||
|
direction="horizontal"
|
||||||
|
class="scroller"
|
||||||
|
>
|
||||||
|
<template #default="{ item, index, active }">
|
||||||
|
<DynamicScrollerItem
|
||||||
|
:item="item"
|
||||||
|
:active="active"
|
||||||
|
:size-dependencies="[item.message]"
|
||||||
|
:data-index="index"
|
||||||
|
:data-active="active"
|
||||||
|
:title="`Click to change message ${index}`"
|
||||||
|
:style="{
|
||||||
|
width: `${Math.max(
|
||||||
|
130,
|
||||||
|
Math.round((item.message.length / 20) * 20)
|
||||||
|
)}px`
|
||||||
|
}"
|
||||||
|
class="message"
|
||||||
|
@click="changeMessage(item)"
|
||||||
|
>
|
||||||
|
<div class="avatar">
|
||||||
|
<IconifyIconOnline
|
||||||
|
icon="openmoji:beaming-face-with-smiling-eyes"
|
||||||
|
width="40"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div class="text">
|
||||||
|
{{ item.message }}
|
||||||
|
</div>
|
||||||
|
<div class="index">
|
||||||
|
<span>{{ item.id }} (id)</span>
|
||||||
|
<span>{{ index }} (index)</span>
|
||||||
|
</div>
|
||||||
|
</DynamicScrollerItem>
|
||||||
|
</template>
|
||||||
|
</DynamicScroller>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.dynamic-scroller-demo {
|
||||||
|
overflow: hidden;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
.scroller {
|
||||||
|
flex: auto 1 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.notice {
|
||||||
|
padding: 24px;
|
||||||
|
font-size: 20px;
|
||||||
|
color: #999;
|
||||||
|
}
|
||||||
|
|
||||||
|
.message {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
min-height: 32px;
|
||||||
|
padding: 12px;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
.avatar {
|
||||||
|
flex: auto 0 0;
|
||||||
|
width: 32px;
|
||||||
|
height: 32px;
|
||||||
|
border-radius: 50%;
|
||||||
|
margin-bottom: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.avatar .image {
|
||||||
|
max-width: 100%;
|
||||||
|
max-height: 100%;
|
||||||
|
border-radius: 50%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.index,
|
||||||
|
.text {
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.text {
|
||||||
|
margin-bottom: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.index {
|
||||||
|
opacity: 0.5;
|
||||||
|
}
|
||||||
|
|
||||||
|
.index span {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
</style>
|
26
src/views/able/virtual-list/index.vue
Normal file
26
src/views/able/virtual-list/index.vue
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import verticalList from "./vertical.vue";
|
||||||
|
import horizontalList from "./horizontal.vue";
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<el-card>
|
||||||
|
<template #header>
|
||||||
|
<div class="font-medium">
|
||||||
|
虚拟列表组件(
|
||||||
|
<el-link
|
||||||
|
href="https://github.com/Akryum/vue-virtual-scroller/tree/next/packages/vue-virtual-scroller"
|
||||||
|
target="_blank"
|
||||||
|
style="font-size: 16px; margin: 0 5px 4px 0"
|
||||||
|
>
|
||||||
|
github地址
|
||||||
|
</el-link>
|
||||||
|
)
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<div class="w-full flex justify-around flex-wrap">
|
||||||
|
<vertical-list class="h-500px w-500px" />
|
||||||
|
<horizontal-list class="h-500px w-500px" />
|
||||||
|
</div>
|
||||||
|
</el-card>
|
||||||
|
</template>
|
124
src/views/able/virtual-list/vertical.vue
Normal file
124
src/views/able/virtual-list/vertical.vue
Normal file
@ -0,0 +1,124 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import { ref, computed } from "vue";
|
||||||
|
import { generateMessage } from "./data";
|
||||||
|
|
||||||
|
const items = ref([]);
|
||||||
|
const search = ref("");
|
||||||
|
|
||||||
|
for (let i = 0; i < 10000; i++) {
|
||||||
|
items.value.push({
|
||||||
|
id: i,
|
||||||
|
...generateMessage()
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const filteredItems = computed(() => {
|
||||||
|
if (!search.value) return items.value;
|
||||||
|
const lowerCaseSearch = search.value.toLowerCase();
|
||||||
|
return items.value.filter(i =>
|
||||||
|
i.message.toLowerCase().includes(lowerCaseSearch)
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
function changeMessage(message) {
|
||||||
|
Object.assign(message, generateMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
function onResize() {
|
||||||
|
console.log("resize");
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div class="dynamic-scroller-demo">
|
||||||
|
<div class="flex justify-around mb-4">
|
||||||
|
<el-input
|
||||||
|
class="mr-2 !w-1/1.5"
|
||||||
|
clearable
|
||||||
|
v-model="search"
|
||||||
|
placeholder="Filter..."
|
||||||
|
/>
|
||||||
|
<el-tag effect="dark">垂直模式vertical</el-tag>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<DynamicScroller
|
||||||
|
:items="filteredItems"
|
||||||
|
:min-item-size="54"
|
||||||
|
class="scroller"
|
||||||
|
@resize="onResize"
|
||||||
|
>
|
||||||
|
<template #default="{ item, index, active }">
|
||||||
|
<DynamicScrollerItem
|
||||||
|
:item="item"
|
||||||
|
:active="active"
|
||||||
|
:size-dependencies="[item.message]"
|
||||||
|
:data-index="index"
|
||||||
|
:data-active="active"
|
||||||
|
:title="`Click to change message ${index}`"
|
||||||
|
class="message"
|
||||||
|
@click="changeMessage(item)"
|
||||||
|
>
|
||||||
|
<div class="avatar">
|
||||||
|
<IconifyIconOnline
|
||||||
|
icon="openmoji:beaming-face-with-smiling-eyes"
|
||||||
|
width="40"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div class="text">
|
||||||
|
{{ item.message }}
|
||||||
|
</div>
|
||||||
|
<div class="index">
|
||||||
|
<span>{{ item.id }} (id)</span>
|
||||||
|
<span>{{ index }} (index)</span>
|
||||||
|
</div>
|
||||||
|
</DynamicScrollerItem>
|
||||||
|
</template>
|
||||||
|
</DynamicScroller>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.dynamic-scroller-demo {
|
||||||
|
overflow: hidden;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
.scroller {
|
||||||
|
flex: auto 1 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.message {
|
||||||
|
display: flex;
|
||||||
|
min-height: 32px;
|
||||||
|
padding: 12px;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
.avatar {
|
||||||
|
flex: auto 0 0;
|
||||||
|
width: 32px;
|
||||||
|
height: 32px;
|
||||||
|
border-radius: 50%;
|
||||||
|
margin-right: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.index,
|
||||||
|
.text {
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.text {
|
||||||
|
max-width: 400px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.index {
|
||||||
|
opacity: 0.5;
|
||||||
|
}
|
||||||
|
|
||||||
|
.index span {
|
||||||
|
display: inline-block;
|
||||||
|
width: 160px;
|
||||||
|
text-align: right;
|
||||||
|
}
|
||||||
|
</style>
|
@ -2,7 +2,7 @@
|
|||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
"target": "esnext",
|
"target": "esnext",
|
||||||
"module": "esnext",
|
"module": "esnext",
|
||||||
"moduleResolution": "node",
|
"moduleResolution": "Node",
|
||||||
"strict": false,
|
"strict": false,
|
||||||
"jsx": "preserve",
|
"jsx": "preserve",
|
||||||
"importHelpers": true,
|
"importHelpers": true,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user