mirror of
https://gitee.com/vuejs/vue.git
synced 2024-12-02 12:07:39 +08:00
feat: new scoped slot syntax implementation update per rfc
This commit is contained in:
parent
aef5b4e478
commit
c5c354d593
@ -177,6 +177,20 @@ export function getAndRemoveAttr (
|
||||
return val
|
||||
}
|
||||
|
||||
export function getAndRemoveAttrByRegex (
|
||||
el: ASTElement,
|
||||
name: RegExp
|
||||
) {
|
||||
const list = el.attrsList
|
||||
for (let i = 0, l = list.length; i < l; i++) {
|
||||
const attr = list[i]
|
||||
if (name.test(attr.name)) {
|
||||
list.splice(i, 1)
|
||||
return attr
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function rangeSetItem (
|
||||
item: any,
|
||||
range?: { start?: number, end?: number }
|
||||
|
@ -17,7 +17,8 @@ import {
|
||||
getBindingAttr,
|
||||
getAndRemoveAttr,
|
||||
getRawBindingAttr,
|
||||
pluckModuleFunction
|
||||
pluckModuleFunction,
|
||||
getAndRemoveAttrByRegex
|
||||
} from '../helpers'
|
||||
|
||||
export const onRE = /^@|^v-on:/
|
||||
@ -31,6 +32,8 @@ export const bindRE = /^:|^\.|^v-bind:/
|
||||
const propBindRE = /^\./
|
||||
const modifierRE = /\.[^.]+/g
|
||||
|
||||
const scopedSlotShorthandRE = /^:?\(.*\)$/
|
||||
|
||||
const lineBreakRE = /[\r\n]/
|
||||
const whitespaceRE = /\s+/g
|
||||
|
||||
@ -568,9 +571,20 @@ function processSlotContent (el) {
|
||||
getAndRemoveAttr(el, 'slot-scope') ||
|
||||
// new in 2.6: slot-props and its shorthand works the same as slot-scope
|
||||
// when used on <template> containers
|
||||
getAndRemoveAttr(el, 'slot-props') ||
|
||||
getAndRemoveAttr(el, '()')
|
||||
getAndRemoveAttr(el, 'slot-props')
|
||||
)
|
||||
// 2.6 shorthand syntax
|
||||
const shorthand = getAndRemoveAttrByRegex(el, scopedSlotShorthandRE)
|
||||
if (shorthand) {
|
||||
if (process.env.NODE_ENV !== 'production' && el.slotScope) {
|
||||
warn(
|
||||
`Unexpected mixed usage of different slot syntaxes.`,
|
||||
el
|
||||
)
|
||||
}
|
||||
el.slotTarget = getScopedSlotShorthandName(shorthand)
|
||||
el.slotScope = shorthand.value
|
||||
}
|
||||
} else if ((slotScope = getAndRemoveAttr(el, 'slot-scope'))) {
|
||||
/* istanbul ignore if */
|
||||
if (process.env.NODE_ENV !== 'production' && el.attrsMap['v-for']) {
|
||||
@ -585,19 +599,29 @@ function processSlotContent (el) {
|
||||
el.slotScope = slotScope
|
||||
} else {
|
||||
// 2.6: slot-props on component, denotes default slot
|
||||
slotScope = getAndRemoveAttr(el, 'slot-props') || getAndRemoveAttr(el, '()')
|
||||
if (slotScope) {
|
||||
if (process.env.NODE_ENV !== 'production' && !maybeComponent(el)) {
|
||||
slotScope = getAndRemoveAttr(el, 'slot-props')
|
||||
const shorthand = getAndRemoveAttrByRegex(el, scopedSlotShorthandRE)
|
||||
if (slotScope || shorthand) {
|
||||
if (process.env.NODE_ENV !== 'production') {
|
||||
if (!maybeComponent(el)) {
|
||||
warn(
|
||||
`slot-props cannot be used on non-component elements.`,
|
||||
el.rawAttrsMap['slot-props'] || el.rawAttrsMap['()']
|
||||
)
|
||||
}
|
||||
if (slotScope && shorthand) {
|
||||
warn(
|
||||
`Unexpected mixed usage of different slot syntaxes.`,
|
||||
el
|
||||
)
|
||||
}
|
||||
}
|
||||
// add the component's children to its default slot
|
||||
const slots = el.scopedSlots || (el.scopedSlots = {})
|
||||
const slotContainer = slots[`"default"`] = createASTElement('template', [], el)
|
||||
const target = shorthand ? getScopedSlotShorthandName(shorthand) : `"default"`
|
||||
const slotContainer = slots[target] = createASTElement('template', [], el)
|
||||
slotContainer.children = el.children
|
||||
slotContainer.slotScope = slotScope
|
||||
slotContainer.slotScope = shorthand ? shorthand.value : slotScope
|
||||
// remove children as they are returned from scopedSlots now
|
||||
el.children = []
|
||||
// mark el non-plain so data gets generated
|
||||
@ -617,6 +641,14 @@ function processSlotContent (el) {
|
||||
}
|
||||
}
|
||||
|
||||
function getScopedSlotShorthandName ({ name }) {
|
||||
return name.charAt(0) === ':'
|
||||
// dynamic :(name)
|
||||
? name.slice(2, -1) || `"default"`
|
||||
// static (name)
|
||||
: `"${name.slice(1, -1) || `default`}"`
|
||||
}
|
||||
|
||||
// handle <slot/> outlets
|
||||
function processSlotOutlet (el) {
|
||||
if (el.tag === 'slot') {
|
||||
|
@ -731,5 +731,65 @@ describe('Component scoped slot', () => {
|
||||
// run tests for both full syntax and shorthand
|
||||
runSuite('slot-props')
|
||||
runSuite('()')
|
||||
|
||||
it('shorthand named slots', () => {
|
||||
const vm = new Vue({
|
||||
template: `
|
||||
<foo ()="foo">
|
||||
{{ foo }}
|
||||
<template (one)="one">
|
||||
{{ one }}
|
||||
</template>
|
||||
<template (two)="two">
|
||||
{{ two }}
|
||||
</template>
|
||||
</foo>
|
||||
`,
|
||||
components: { Foo }
|
||||
}).$mount()
|
||||
expect(vm.$el.innerHTML.replace(/\s+/g, ' ')).toMatch(`from foo default from foo one from foo two`)
|
||||
})
|
||||
|
||||
it('shorthand without scope variable', () => {
|
||||
const vm = new Vue({
|
||||
template: `
|
||||
<foo>
|
||||
<template (one)>one</template>
|
||||
<template (two)>two</template>
|
||||
</foo>
|
||||
`,
|
||||
components: { Foo }
|
||||
}).$mount()
|
||||
expect(vm.$el.innerHTML.replace(/\s+/g, ' ')).toMatch(`onetwo`)
|
||||
})
|
||||
|
||||
it('shorthand named slots on root', () => {
|
||||
const vm = new Vue({
|
||||
template: `
|
||||
<foo (one)="one">
|
||||
{{ one }}
|
||||
</foo>
|
||||
`,
|
||||
components: { Foo }
|
||||
}).$mount()
|
||||
expect(vm.$el.innerHTML.replace(/\s+/g, ' ')).toMatch(`from foo one`)
|
||||
})
|
||||
|
||||
it('dynamic shorthand', () => {
|
||||
const vm = new Vue({
|
||||
data: {
|
||||
a: 'one',
|
||||
b: 'two'
|
||||
},
|
||||
template: `
|
||||
<foo>
|
||||
<template :(a)="one">{{ one }} </template>
|
||||
<template :(b)="two">{{ two }}</template>
|
||||
</foo>
|
||||
`,
|
||||
components: { Foo }
|
||||
}).$mount()
|
||||
expect(vm.$el.innerHTML.replace(/\s+/g, ' ')).toMatch(`from foo one from foo two`)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
Loading…
Reference in New Issue
Block a user