-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathslot.js
132 lines (117 loc) · 3.07 KB
/
slot.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
import { SLOT } from '../priorities'
import {
parseTemplate,
cloneNode
} from '../../parsers/template'
import {
extend,
extractContent,
replace,
remove,
isTemplate
} from '../../util/index'
// This is the elementDirective that handles <content>
// transclusions. It relies on the raw content of an
// instance being stored as `$options._content` during
// the transclude phase.
// We are exporting two versions, one for named and one
// for unnamed, because the unnamed slots must be compiled
// AFTER all named slots have selected their content. So
// we need to give them different priorities in the compilation
// process. (See #1965)
export const slot = {
priority: SLOT,
bind () {
var host = this.vm
var raw = host.$options._content
if (!raw) {
this.fallback()
return
}
var context = host._context
var slotName = this.params && this.params.name
if (!slotName) {
// Default slot
this.tryCompile(extractFragment(raw.childNodes, raw, true), context, host)
} else {
// Named slot
var selector = '[slot="' + slotName + '"]'
var nodes = raw.querySelectorAll(selector)
if (nodes.length) {
this.tryCompile(extractFragment(nodes, raw), context, host)
} else {
this.fallback()
}
}
},
tryCompile (content, context, host) {
if (content.hasChildNodes()) {
this.compile(content, context, host)
} else {
this.fallback()
}
},
compile (content, context, host) {
if (content && context) {
var scope = host
? host._scope
: this._scope
this.unlink = context.$compile(
content, host, scope, this._frag
)
}
if (content) {
replace(this.el, content)
} else {
remove(this.el)
}
},
fallback () {
this.compile(extractContent(this.el, true), this.vm)
},
unbind () {
if (this.unlink) {
this.unlink()
}
}
}
export const namedSlot = extend(extend({}, slot), {
priority: slot.priority + 1,
params: ['name']
})
/**
* Extract qualified content nodes from a node list.
*
* @param {NodeList} nodes
* @param {Element} parent
* @param {Boolean} main
* @return {DocumentFragment}
*/
function extractFragment (nodes, parent, main) {
var frag = document.createDocumentFragment()
for (var i = 0, l = nodes.length; i < l; i++) {
var node = nodes[i]
// if this is the main outlet, we want to skip all
// previously selected nodes;
// otherwise, we want to mark the node as selected.
// clone the node so the original raw content remains
// intact. this ensures proper re-compilation in cases
// where the outlet is inside a conditional block
if (main && !node.__v_selected) {
append(node)
} else if (!main && node.parentNode === parent) {
node.__v_selected = true
append(node)
}
}
return frag
function append (node) {
if (isTemplate(node) &&
!node.hasAttribute('v-if') &&
!node.hasAttribute('v-for')) {
node = parseTemplate(node)
}
node = cloneNode(node)
frag.appendChild(node)
}
}