Skip to content

Commit c5c354d

Browse files
committedJan 15, 2019
feat: new scoped slot syntax implementation update per rfc
1 parent aef5b4e commit c5c354d

File tree

3 files changed

+118
-12
lines changed

3 files changed

+118
-12
lines changed
 

‎src/compiler/helpers.js

+14
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,20 @@ export function getAndRemoveAttr (
177177
return val
178178
}
179179

180+
export function getAndRemoveAttrByRegex (
181+
el: ASTElement,
182+
name: RegExp
183+
) {
184+
const list = el.attrsList
185+
for (let i = 0, l = list.length; i < l; i++) {
186+
const attr = list[i]
187+
if (name.test(attr.name)) {
188+
list.splice(i, 1)
189+
return attr
190+
}
191+
}
192+
}
193+
180194
function rangeSetItem (
181195
item: any,
182196
range?: { start?: number, end?: number }

‎src/compiler/parser/index.js

+44-12
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,8 @@ import {
1717
getBindingAttr,
1818
getAndRemoveAttr,
1919
getRawBindingAttr,
20-
pluckModuleFunction
20+
pluckModuleFunction,
21+
getAndRemoveAttrByRegex
2122
} from '../helpers'
2223

2324
export const onRE = /^@|^v-on:/
@@ -31,6 +32,8 @@ export const bindRE = /^:|^\.|^v-bind:/
3132
const propBindRE = /^\./
3233
const modifierRE = /\.[^.]+/g
3334

35+
const scopedSlotShorthandRE = /^:?\(.*\)$/
36+
3437
const lineBreakRE = /[\r\n]/
3538
const whitespaceRE = /\s+/g
3639

@@ -568,9 +571,20 @@ function processSlotContent (el) {
568571
getAndRemoveAttr(el, 'slot-scope') ||
569572
// new in 2.6: slot-props and its shorthand works the same as slot-scope
570573
// when used on <template> containers
571-
getAndRemoveAttr(el, 'slot-props') ||
572-
getAndRemoveAttr(el, '()')
574+
getAndRemoveAttr(el, 'slot-props')
573575
)
576+
// 2.6 shorthand syntax
577+
const shorthand = getAndRemoveAttrByRegex(el, scopedSlotShorthandRE)
578+
if (shorthand) {
579+
if (process.env.NODE_ENV !== 'production' && el.slotScope) {
580+
warn(
581+
`Unexpected mixed usage of different slot syntaxes.`,
582+
el
583+
)
584+
}
585+
el.slotTarget = getScopedSlotShorthandName(shorthand)
586+
el.slotScope = shorthand.value
587+
}
574588
} else if ((slotScope = getAndRemoveAttr(el, 'slot-scope'))) {
575589
/* istanbul ignore if */
576590
if (process.env.NODE_ENV !== 'production' && el.attrsMap['v-for']) {
@@ -585,19 +599,29 @@ function processSlotContent (el) {
585599
el.slotScope = slotScope
586600
} else {
587601
// 2.6: slot-props on component, denotes default slot
588-
slotScope = getAndRemoveAttr(el, 'slot-props') || getAndRemoveAttr(el, '()')
589-
if (slotScope) {
590-
if (process.env.NODE_ENV !== 'production' && !maybeComponent(el)) {
591-
warn(
592-
`slot-props cannot be used on non-component elements.`,
593-
el.rawAttrsMap['slot-props'] || el.rawAttrsMap['()']
594-
)
602+
slotScope = getAndRemoveAttr(el, 'slot-props')
603+
const shorthand = getAndRemoveAttrByRegex(el, scopedSlotShorthandRE)
604+
if (slotScope || shorthand) {
605+
if (process.env.NODE_ENV !== 'production') {
606+
if (!maybeComponent(el)) {
607+
warn(
608+
`slot-props cannot be used on non-component elements.`,
609+
el.rawAttrsMap['slot-props'] || el.rawAttrsMap['()']
610+
)
611+
}
612+
if (slotScope && shorthand) {
613+
warn(
614+
`Unexpected mixed usage of different slot syntaxes.`,
615+
el
616+
)
617+
}
595618
}
596619
// add the component's children to its default slot
597620
const slots = el.scopedSlots || (el.scopedSlots = {})
598-
const slotContainer = slots[`"default"`] = createASTElement('template', [], el)
621+
const target = shorthand ? getScopedSlotShorthandName(shorthand) : `"default"`
622+
const slotContainer = slots[target] = createASTElement('template', [], el)
599623
slotContainer.children = el.children
600-
slotContainer.slotScope = slotScope
624+
slotContainer.slotScope = shorthand ? shorthand.value : slotScope
601625
// remove children as they are returned from scopedSlots now
602626
el.children = []
603627
// mark el non-plain so data gets generated
@@ -617,6 +641,14 @@ function processSlotContent (el) {
617641
}
618642
}
619643

644+
function getScopedSlotShorthandName ({ name }) {
645+
return name.charAt(0) === ':'
646+
// dynamic :(name)
647+
? name.slice(2, -1) || `"default"`
648+
// static (name)
649+
: `"${name.slice(1, -1) || `default`}"`
650+
}
651+
620652
// handle <slot/> outlets
621653
function processSlotOutlet (el) {
622654
if (el.tag === 'slot') {

‎test/unit/features/component/component-scoped-slot.spec.js

+60
Original file line numberDiff line numberDiff line change
@@ -731,5 +731,65 @@ describe('Component scoped slot', () => {
731731
// run tests for both full syntax and shorthand
732732
runSuite('slot-props')
733733
runSuite('()')
734+
735+
it('shorthand named slots', () => {
736+
const vm = new Vue({
737+
template: `
738+
<foo ()="foo">
739+
{{ foo }}
740+
<template (one)="one">
741+
{{ one }}
742+
</template>
743+
<template (two)="two">
744+
{{ two }}
745+
</template>
746+
</foo>
747+
`,
748+
components: { Foo }
749+
}).$mount()
750+
expect(vm.$el.innerHTML.replace(/\s+/g, ' ')).toMatch(`from foo default from foo one from foo two`)
751+
})
752+
753+
it('shorthand without scope variable', () => {
754+
const vm = new Vue({
755+
template: `
756+
<foo>
757+
<template (one)>one</template>
758+
<template (two)>two</template>
759+
</foo>
760+
`,
761+
components: { Foo }
762+
}).$mount()
763+
expect(vm.$el.innerHTML.replace(/\s+/g, ' ')).toMatch(`onetwo`)
764+
})
765+
766+
it('shorthand named slots on root', () => {
767+
const vm = new Vue({
768+
template: `
769+
<foo (one)="one">
770+
{{ one }}
771+
</foo>
772+
`,
773+
components: { Foo }
774+
}).$mount()
775+
expect(vm.$el.innerHTML.replace(/\s+/g, ' ')).toMatch(`from foo one`)
776+
})
777+
778+
it('dynamic shorthand', () => {
779+
const vm = new Vue({
780+
data: {
781+
a: 'one',
782+
b: 'two'
783+
},
784+
template: `
785+
<foo>
786+
<template :(a)="one">{{ one }} </template>
787+
<template :(b)="two">{{ two }}</template>
788+
</foo>
789+
`,
790+
components: { Foo }
791+
}).$mount()
792+
expect(vm.$el.innerHTML.replace(/\s+/g, ' ')).toMatch(`from foo one from foo two`)
793+
})
734794
})
735795
})

0 commit comments

Comments
 (0)
Please sign in to comment.