Skip to content

Commit e02f0f5

Browse files
WIP: using item slot
1 parent b5fd01f commit e02f0f5

File tree

8 files changed

+94
-105
lines changed

8 files changed

+94
-105
lines changed

example/components/headerslot.vue

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -6,17 +6,19 @@
66
<draggable
77
:list="list"
88
class="list-group"
9-
draggable=".item"
109
@start="dragging = true"
1110
@end="dragging = false"
11+
item-key="name"
1212
>
13-
<div
14-
class="list-group-item item"
15-
v-for="element in list"
16-
:key="element.name"
17-
>
18-
{{ element.name }}
19-
</div>
13+
<template v-slot:footer>
14+
<div
15+
class="btn-group list-group-item"
16+
role="group"
17+
aria-label="Basic example"
18+
>
19+
<button class="btn btn-secondary" @click="replace">Replace</button>
20+
</div>
21+
</template>
2022

2123
<template v-slot:header>
2224
<div
@@ -25,7 +27,12 @@
2527
aria-label="Basic example"
2628
>
2729
<button class="btn btn-secondary" @click="add">Add</button>
28-
<button class="btn btn-secondary" @click="replace">Replace</button>
30+
</div>
31+
</template>
32+
33+
<template v-slot:item="{ element }">
34+
<div class="list-group-item item">
35+
{{ element.name }}
2936
</div>
3037
</template>
3138
</draggable>

example/components/simple.vue

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -29,20 +29,18 @@
2929
<draggable
3030
:list="list"
3131
:disabled="!enabled"
32+
item-key="name"
3233
class="list-group"
3334
ghost-class="ghost"
3435
:move="checkMove"
3536
@start="dragging = true"
3637
@end="dragging = false"
3738
>
38-
<div
39-
class="list-group-item"
40-
:class="{ 'not-draggable': !enabled }"
41-
v-for="element in list"
42-
:key="element.name"
43-
>
44-
{{ element.name }}
45-
</div>
39+
<template v-slot:item="{ element }">
40+
<div class="list-group-item" :class="{ 'not-draggable': !enabled }">
41+
{{ element.name }}
42+
</div>
43+
</template>
4644
</draggable>
4745
</div>
4846

example/components/third-party.vue

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -14,15 +14,13 @@
1414
tag="el-collapse"
1515
:list="list"
1616
:component-data="collapseComponentData"
17+
item-key="id"
1718
>
18-
<el-collapse-item
19-
v-for="item in list"
20-
:key="item.id"
21-
:title="item.title"
22-
:name="item.id"
23-
>
24-
<div v-for="(lign, idx) in item.text" :key="idx">{{ lign }}</div>
25-
</el-collapse-item>
19+
<template v-slot:item="{ element }">
20+
<el-collapse-item :title="element.title" :name="element.id">
21+
<div v-for="(lign, idx) in element.text" :key="idx">{{ lign }}</div>
22+
</el-collapse-item>
23+
</template>
2624
</draggable>
2725
</div>
2826
<rawDisplayer class="col-3" :value="list" title="List" />

example/components/transition-example-2.vue

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -10,18 +10,20 @@
1010
<h3>Transition</h3>
1111
<draggable
1212
class="list-group"
13-
tag="ul"
13+
tag="transition-group"
14+
:component-data="{
15+
tag: 'ul',
16+
type: 'transition-group',
17+
name: !drag ? 'flip-list' : null
18+
}"
1419
v-model="list"
1520
v-bind="dragOptions"
1621
@start="drag = true"
1722
@end="drag = false"
23+
item-key="order"
1824
>
19-
<transition-group type="transition" :name="!drag ? 'flip-list' : null">
20-
<li
21-
class="list-group-item"
22-
v-for="element in list"
23-
:key="element.order"
24-
>
25+
<template v-slot:item="{ element }">
26+
<li class="list-group-item">
2527
<i
2628
:class="
2729
element.fixed ? 'fa fa-anchor' : 'glyphicon glyphicon-pushpin'
@@ -31,7 +33,7 @@
3133
></i>
3234
{{ element.name }}
3335
</li>
34-
</transition-group>
36+
</template>
3537
</draggable>
3638
</div>
3739

example/components/transition-example.vue

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,24 +4,26 @@
44
<button class="btn btn-secondary button" @click="sort">
55
To original order
66
</button>
7+
8+
<button class="btn btn-secondary button" @click="add">
9+
Add \
10+
</button>
711
</div>
812

913
<div class="col-6">
1014
<h3>Transition</h3>
1115
<draggable
1216
class="list-group"
13-
tag="ul"
17+
item-key="order"
18+
tag="transition-group"
19+
:component-data="{ tag: 'ul', name: 'flip-list', type: 'transition' }"
1420
v-model="list"
1521
v-bind="dragOptions"
1622
@start="isDragging = true"
1723
@end="isDragging = false"
1824
>
19-
<transition-group type="transition" name="flip-list">
20-
<li
21-
class="list-group-item"
22-
v-for="element in list"
23-
:key="element.order"
24-
>
25+
<template v-slot:item="{ element }">
26+
<li class="list-group-item">
2527
<i
2628
:class="
2729
element.fixed ? 'fa fa-anchor' : 'glyphicon glyphicon-pushpin'
@@ -31,7 +33,7 @@
3133
></i>
3234
{{ element.name }}
3335
</li>
34-
</transition-group>
36+
</template>
3537
</draggable>
3638
</div>
3739

@@ -51,6 +53,7 @@ const message = [
5153
"on",
5254
"Sortablejs"
5355
];
56+
let order = message.length;
5457
5558
export default {
5659
name: "transition-example",
@@ -69,6 +72,9 @@ export default {
6972
methods: {
7073
sort() {
7174
this.list = this.list.sort((a, b) => a.order - b.order);
75+
},
76+
add() {
77+
this.list.push({ name: "nanannana", order: ++order });
7278
}
7379
},
7480
computed: {

src/core/componentStructure.js

Lines changed: 3 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,6 @@
11
import { nextTick } from "vue";
2-
import { isTransition as isTransitionName } from "../util/tags";
32

43
const getHtmlElementFromNode = ({ el }) => el;
5-
const getNodeFromHtmlElement = ({ __vnode: node }) => node;
6-
7-
function isTransition(nodes) {
8-
if (nodes.length !== 1) {
9-
return false;
10-
}
11-
const [{ type }] = nodes;
12-
return !!type && (isTransitionName(type) || isTransitionName(type.name));
13-
}
14-
15-
function getRootContainer({ $el, transitionMode }) {
16-
if (!transitionMode) {
17-
return $el;
18-
}
19-
const { children } = $el;
20-
if (children.length !== 1) {
21-
return $el;
22-
}
23-
const firstChild = children.item(0);
24-
return !getNodeFromHtmlElement(firstChild).transition ? firstChild : $el;
25-
}
264

275
class ComponentStructure {
286
constructor({ nodes: { header, default: defaultNodes, footer }, root, $el }) {
@@ -32,15 +10,14 @@ class ComponentStructure {
3210
header: header.length,
3311
footer: footer.length
3412
};
35-
this.transitionMode = isTransition(defaultNodes);
3613
this.externalComponent = root.externalComponent;
3714
this.rootTransition = root.transition;
3815
this.tag = root.tag;
3916
this.setHtmlRoot($el);
4017
}
4118

4219
get _domChildrenFromNodes() {
43-
return this._getChildrenNodes().map(getHtmlElementFromNode);
20+
return this.nodes.default.map(getHtmlElementFromNode);
4421
}
4522

4623
get _isRootComponent() {
@@ -58,49 +35,26 @@ class ComponentStructure {
5835
return;
5936
}
6037
this.$el = $el;
61-
this.rootContainer = getRootContainer(this);
6238
nextTick(() => {
6339
this.visibleIndexes = this._computeIndexes();
6440
});
6541
return this;
6642
}
6743

68-
_getChildrenNodes() {
69-
const {
70-
transitionMode,
71-
nodes: { default: defaultNodes }
72-
} = this;
73-
74-
if (!transitionMode) {
75-
return defaultNodes.length === 1 && defaultNodes[0].el.nodeType === 3
76-
? defaultNodes[0].children
77-
: defaultNodes;
78-
}
79-
80-
const [{ children }] = defaultNodes;
81-
if (Array.isArray(children)) {
82-
return children;
83-
}
84-
return [...this.rootContainer.children]
85-
.map(getNodeFromHtmlElement)
86-
.filter(node => !!node.transition);
87-
}
88-
8944
_computeIndexes() {
9045
const {
9146
_domChildrenFromNodes,
92-
transitionMode,
9347
offsets: { footer: footerOffset }
9448
} = this;
9549

96-
const domChildren = this.rootContainer.children;
50+
const domChildren = this.$el.children;
9751
const footerIndex = domChildren.length - footerOffset;
9852
const rawIndexes = [...domChildren].map((elt, idx) =>
9953
idx >= footerIndex
10054
? _domChildrenFromNodes.length
10155
: _domChildrenFromNodes.indexOf(elt)
10256
);
103-
return transitionMode ? rawIndexes.filter(ind => ind !== -1) : rawIndexes;
57+
return rawIndexes;
10458
}
10559

10660
computeVmIndex(domElement) {

src/core/renderHelper.js

Lines changed: 25 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,29 @@
11
import { ComponentStructure } from "./componentStructure";
22
import { isHtmlTag, isTransition } from "../util/tags";
3-
import { resolveComponent } from "vue";
3+
import { resolveComponent, TransitionGroup } from "vue";
44

55
function getSlot(slots, key) {
66
const slotValue = slots[key];
77
return slotValue ? slotValue() : [];
88
}
99

10-
function computeNodes(slots) {
11-
const [header, defaultNodes, footer] = [
12-
"header",
13-
"default",
14-
"footer"
15-
].map(name => getSlot(slots, name));
10+
function computeNodes({ $slots, realList, itemKey }) {
11+
const [header, footer] = ["header", "footer"].map(name =>
12+
getSlot($slots, name)
13+
);
14+
const { item } = $slots;
15+
if (!item) {
16+
throw new Error("draggable element must have an item slot");
17+
}
18+
const defaultNodes = realList.flatMap((element, index) =>
19+
item({ element, index }).map(node => {
20+
node.key = element[itemKey];
21+
return node;
22+
})
23+
);
24+
if (defaultNodes.length !== realList.length) {
25+
throw new Error("Item slot must have only one child");
26+
}
1627
return {
1728
header,
1829
footer,
@@ -26,12 +37,16 @@ function getRootInformation(tag) {
2637
return {
2738
transition,
2839
externalComponent,
29-
tag: externalComponent ? resolveComponent(tag) : tag
40+
tag: externalComponent
41+
? resolveComponent(tag)
42+
: transition
43+
? TransitionGroup
44+
: tag
3045
};
3146
}
3247

33-
function computeComponentStructure({ $slots, tag, $el }) {
34-
const nodes = computeNodes($slots);
48+
function computeComponentStructure({ $slots, tag, $el, realList, itemKey }) {
49+
const nodes = computeNodes({ $slots, realList, itemKey });
3550
const root = getRootInformation(tag);
3651
return new ComponentStructure({ nodes, root, $el });
3752
}

src/vuedraggable.js

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,10 @@ const props = {
4242
required: false,
4343
default: null
4444
},
45+
itemKey: {
46+
type: [String, Function],
47+
required: true
48+
},
4549
clone: {
4650
type: Function,
4751
default: original => {
@@ -71,8 +75,14 @@ const draggableComponent = defineComponent({
7175
props,
7276

7377
render() {
74-
const { $slots, $attrs, tag, componentData, $el } = this;
75-
const componentStructure = computeComponentStructure({ $slots, tag, $el });
78+
const { $slots, $attrs, tag, componentData, $el, realList, itemKey } = this;
79+
const componentStructure = computeComponentStructure({
80+
$slots,
81+
tag,
82+
$el,
83+
realList,
84+
itemKey
85+
});
7686
this.componentStructure = componentStructure;
7787
const attributes = getComponentAttributes({ $attrs, componentData });
7888
return componentStructure.render(h, attributes);
@@ -98,9 +108,8 @@ const draggableComponent = defineComponent({
98108
manage: event => manage.call(this, event)
99109
}
100110
});
101-
const { rootContainer } = componentStructure;
102-
this._sortable = new Sortable(rootContainer, sortableOptions);
103-
rootContainer.__draggable_component__ = this;
111+
this._sortable = new Sortable($el, sortableOptions);
112+
$el.__draggable_component__ = this;
104113
},
105114

106115
beforeUnmount() {

0 commit comments

Comments
 (0)