提交 238dae0f 编写于 作者: fxy060608's avatar fxy060608

fix(mp): default slot (#3094)

上级 d8cbdf72
...@@ -85,7 +85,7 @@ export function addStaticClass(node: ElementNode, clazz: string) { ...@@ -85,7 +85,7 @@ export function addStaticClass(node: ElementNode, clazz: string) {
export function createDirectiveNode( export function createDirectiveNode(
name: string, name: string,
arg: string, arg: string,
exp: string | ExpressionNode exp?: string | ExpressionNode
): DirectiveNode { ): DirectiveNode {
return { return {
type: NodeTypes.DIRECTIVE, type: NodeTypes.DIRECTIVE,
......
...@@ -4,14 +4,14 @@ describe('mp-alipay: transform v-slot', () => { ...@@ -4,14 +4,14 @@ describe('mp-alipay: transform v-slot', () => {
test('default slot', () => { test('default slot', () => {
assert( assert(
`<custom><template v-slot/></custom>`, `<custom><template v-slot/></custom>`,
`<custom u-s="{{['d']}}" u-i="2a9ec0b0-0" onVI="__l"><view/></custom>`, `<custom u-s="{{['d']}}" u-i="2a9ec0b0-0" onVI="__l"><view slot="d"/></custom>`,
`(_ctx, _cache) => { `(_ctx, _cache) => {
return {} return {}
}` }`
) )
assert( assert(
`<custom>test</custom>`, `<custom>test</custom>`,
`<custom u-s="{{['d']}}" u-i="2a9ec0b0-0" onVI="__l">test</custom>`, `<custom u-s="{{['d']}}" u-i="2a9ec0b0-0" onVI="__l"><view slot="d">test</view></custom>`,
`(_ctx, _cache) => { `(_ctx, _cache) => {
return {} return {}
}` }`
......
...@@ -4,14 +4,14 @@ describe('compiler: transform v-slot', () => { ...@@ -4,14 +4,14 @@ describe('compiler: transform v-slot', () => {
test('default slot', () => { test('default slot', () => {
assert( assert(
`<custom><template v-slot/></custom>`, `<custom><template v-slot/></custom>`,
`<custom u-s="{{['d']}}" u-i="2a9ec0b0-0"><view/></custom>`, `<custom u-s="{{['d']}}" u-i="2a9ec0b0-0"><view slot="d"/></custom>`,
`(_ctx, _cache) => { `(_ctx, _cache) => {
return {} return {}
}` }`
) )
assert( assert(
`<custom>test</custom>`, `<custom>test</custom>`,
`<custom u-s="{{['d']}}" u-i="2a9ec0b0-0">test</custom>`, `<custom u-s="{{['d']}}" u-i="2a9ec0b0-0"><view slot="d">test</view></custom>`,
`(_ctx, _cache) => { `(_ctx, _cache) => {
return {} return {}
}` }`
...@@ -27,7 +27,7 @@ describe('compiler: transform v-slot', () => { ...@@ -27,7 +27,7 @@ describe('compiler: transform v-slot', () => {
) )
assert( assert(
`<unicloud-db v-slot:default="{data, loading, error, options}"><view v-if="error">{{error.message}}</view><view v-else></view></unicloud-db>`, `<unicloud-db v-slot:default="{data, loading, error, options}"><view v-if="error">{{error.message}}</view><view v-else></view></unicloud-db>`,
`<unicloud-db u-s="{{['d']}}" slot="d" u-i="2a9ec0b0-0"><block s-for="v0 in a trackBy v0.a"><view s-if="{{v0.b}}">{{v0.c}}</view><view s-else></view></block></unicloud-db>`, `<unicloud-db u-s="{{['d']}}" slot="d" u-i="2a9ec0b0-0"><view slot="d"><block s-for="v0 in a trackBy v0.a"><view s-if="{{v0.b}}">{{v0.c}}</view><view s-else></view></block></view></unicloud-db>`,
`(_ctx, _cache) => { `(_ctx, _cache) => {
return { a: _w(({ data, loading, error, options }, s0, i0) => { return _e({ a: i0, b: error }, error ? { c: _t(error.message) } : {}); }, { name: 'd', path: 'a', vueId: '2a9ec0b0-0' }) } return { a: _w(({ data, loading, error, options }, s0, i0) => { return _e({ a: i0, b: error }, error ? { c: _t(error.message) } : {}); }, { name: 'd', path: 'a', vueId: '2a9ec0b0-0' }) }
}` }`
......
...@@ -10,7 +10,7 @@ describe('compiler: transform component', () => { ...@@ -10,7 +10,7 @@ describe('compiler: transform component', () => {
test('component + component', () => { test('component + component', () => {
assert( assert(
`<custom><custom1/></custom>`, `<custom><custom1/></custom>`,
`<custom u-s="{{['d']}}" u-i="2a9ec0b0-0" bind:__l="__l"><custom1 u-i="2a9ec0b0-1,2a9ec0b0-0" bind:__l="__l"/></custom>`, `<custom u-s="{{['d']}}" u-i="2a9ec0b0-0" bind:__l="__l"><custom1 u-s="{{['d']}}" slot="d" u-i="2a9ec0b0-1,2a9ec0b0-0" bind:__l="__l"/></custom>`,
`(_ctx, _cache) => { `(_ctx, _cache) => {
return {} return {}
}`, }`,
...@@ -22,7 +22,7 @@ describe('compiler: transform component', () => { ...@@ -22,7 +22,7 @@ describe('compiler: transform component', () => {
test('component + component + component', () => { test('component + component + component', () => {
assert( assert(
`<custom><custom1><custom2/><custom2/></custom1></custom>`, `<custom><custom1><custom2/><custom2/></custom1></custom>`,
`<custom u-s="{{['d']}}" u-i="2a9ec0b0-0" bind:__l="__l"><custom1 u-s="{{['d']}}" u-i="2a9ec0b0-1,2a9ec0b0-0" bind:__l="__l"><custom2 u-i="2a9ec0b0-2,2a9ec0b0-1" bind:__l="__l"/><custom2 u-i="2a9ec0b0-3,2a9ec0b0-1" bind:__l="__l"/></custom1></custom>`, `<custom u-s="{{['d']}}" u-i="2a9ec0b0-0" bind:__l="__l"><custom1 u-s="{{['d']}}" slot="d" u-i="2a9ec0b0-1,2a9ec0b0-0" bind:__l="__l"><view slot="d"><custom2 u-i="2a9ec0b0-2,2a9ec0b0-1" bind:__l="__l"/><custom2 u-i="2a9ec0b0-3,2a9ec0b0-1" bind:__l="__l"/></view></custom1></custom>`,
`(_ctx, _cache) => { `(_ctx, _cache) => {
return {} return {}
}`, }`,
...@@ -56,7 +56,7 @@ describe('compiler: transform component', () => { ...@@ -56,7 +56,7 @@ describe('compiler: transform component', () => {
test('component + component with v-for', () => { test('component + component with v-for', () => {
assert( assert(
`<custom><custom1 v-for="item in items"/></custom>`, `<custom><custom1 v-for="item in items"/></custom>`,
`<custom u-s="{{['d']}}" u-i="2a9ec0b0-0" bind:__l="__l"><custom1 wx:for="{{a}}" wx:for-item="item" u-i="{{item.a}}" bind:__l="__l"/></custom>`, `<custom u-s="{{['d']}}" u-i="2a9ec0b0-0" bind:__l="__l"><view slot="d"><custom1 wx:for="{{a}}" wx:for-item="item" u-i="{{item.a}}" bind:__l="__l"/></view></custom>`,
`(_ctx, _cache) => { `(_ctx, _cache) => {
return { a: _f(_ctx.items, (item, k0, i0) => { return { a: '2a9ec0b0-1' + '-' + i0 + ',' + '2a9ec0b0-0' }; }) } return { a: _f(_ctx.items, (item, k0, i0) => { return { a: '2a9ec0b0-1' + '-' + i0 + ',' + '2a9ec0b0-0' }; }) }
}`, }`,
...@@ -68,7 +68,7 @@ describe('compiler: transform component', () => { ...@@ -68,7 +68,7 @@ describe('compiler: transform component', () => {
test('component with v-for + component', () => { test('component with v-for + component', () => {
assert( assert(
`<custom v-for="item in items"><custom1/></custom>`, `<custom v-for="item in items"><custom1/></custom>`,
`<custom wx:for="{{a}}" wx:for-item="item" u-s="{{['d']}}" u-i="{{item.b}}" bind:__l="__l"><custom1 u-i="{{item.a}}" bind:__l="__l"/></custom>`, `<custom wx:for="{{a}}" wx:for-item="item" u-s="{{['d']}}" u-i="{{item.b}}" bind:__l="__l"><custom1 u-s="{{['d']}}" slot="d" u-i="{{item.a}}" bind:__l="__l"/></custom>`,
`(_ctx, _cache) => { `(_ctx, _cache) => {
return { a: _f(_ctx.items, (item, k0, i0) => { return { a: '2a9ec0b0-1' + '-' + i0 + ',' + ('2a9ec0b0-0' + '-' + i0), b: '2a9ec0b0-0' + '-' + i0 }; }) } return { a: _f(_ctx.items, (item, k0, i0) => { return { a: '2a9ec0b0-1' + '-' + i0 + ',' + ('2a9ec0b0-0' + '-' + i0), b: '2a9ec0b0-0' + '-' + i0 }; }) }
}`, }`,
...@@ -80,7 +80,7 @@ describe('compiler: transform component', () => { ...@@ -80,7 +80,7 @@ describe('compiler: transform component', () => {
test('component with v-for + component with v-for', () => { test('component with v-for + component with v-for', () => {
assert( assert(
`<custom v-for="item in items"><custom1 v-for="item1 in item.items"/></custom>`, `<custom v-for="item in items"><custom1 v-for="item1 in item.items"/></custom>`,
`<custom wx:for="{{a}}" wx:for-item="item" u-s="{{['d']}}" u-i="{{item.b}}" bind:__l="__l"><custom1 wx:for="{{item.a}}" wx:for-item="item1" u-i="{{item1.a}}" bind:__l="__l"/></custom>`, `<custom wx:for="{{a}}" wx:for-item="item" u-s="{{['d']}}" u-i="{{item.b}}" bind:__l="__l"><view slot="d"><custom1 wx:for="{{item.a}}" wx:for-item="item1" u-i="{{item1.a}}" bind:__l="__l"/></view></custom>`,
`(_ctx, _cache) => { `(_ctx, _cache) => {
return { a: _f(_ctx.items, (item, k0, i0) => { return { a: _f(item.items, (item1, k1, i1) => { return { a: '2a9ec0b0-1' + '-' + i0 + '-' + i1 + ',' + ('2a9ec0b0-0' + '-' + i0) }; }), b: '2a9ec0b0-0' + '-' + i0 }; }) } return { a: _f(_ctx.items, (item, k0, i0) => { return { a: _f(item.items, (item1, k1, i1) => { return { a: '2a9ec0b0-1' + '-' + i0 + '-' + i1 + ',' + ('2a9ec0b0-0' + '-' + i0) }; }), b: '2a9ec0b0-0' + '-' + i0 }; }) }
}`, }`,
......
...@@ -4,7 +4,7 @@ describe('compiler: transform slot', () => { ...@@ -4,7 +4,7 @@ describe('compiler: transform slot', () => {
test('basic', () => { test('basic', () => {
assert( assert(
`<button><slot/></button>`, `<button><slot/></button>`,
`<button><slot/></button>`, `<button><slot name="d"/></button>`,
`(_ctx, _cache) => { `(_ctx, _cache) => {
return {} return {}
}` }`
...@@ -29,7 +29,7 @@ describe('compiler: transform slot', () => { ...@@ -29,7 +29,7 @@ describe('compiler: transform slot', () => {
test('fallback content', () => { test('fallback content', () => {
assert( assert(
`<button><slot>Submit</slot></button>`, `<button><slot>Submit</slot></button>`,
`<button><block wx:if="{{$slots.d}}"><slot></slot></block><block wx:else>Submit</block></button>`, `<button><block wx:if="{{$slots.d}}"><slot name="d"></slot></block><block wx:else>Submit</block></button>`,
`(_ctx, _cache) => { `(_ctx, _cache) => {
return {} return {}
}` }`
...@@ -75,6 +75,13 @@ describe('compiler: transform slot', () => { ...@@ -75,6 +75,13 @@ describe('compiler: transform slot', () => {
`<slot wx:for="{{a}}" wx:for-item="item" name="{{item.a}}"></slot>`, `<slot wx:for="{{a}}" wx:for-item="item" name="{{item.a}}"></slot>`,
`(_ctx, _cache) => { `(_ctx, _cache) => {
return { a: _f(_ctx.items, (item, index, i0) => { return { a: "d-" + i0, b: _r("d", { key: index }, i0) }; }) } return { a: _f(_ctx.items, (item, index, i0) => { return { a: "d-" + i0, b: _r("d", { key: index }, i0) }; }) }
}`
)
assert(
`<slot v-for="(item,index) in items" :key="index" name="test"></slot>`,
`<slot wx:for="{{a}}" wx:for-item="item" name="{{item.a}}"></slot>`,
`(_ctx, _cache) => {
return { a: _f(_ctx.items, (item, index, i0) => { return { a: "test-" + i0, b: _r("test", { key: index }, i0) }; }) }
}` }`
) )
}) })
......
...@@ -158,7 +158,7 @@ describe(`compiler: v-for`, () => { ...@@ -158,7 +158,7 @@ describe(`compiler: v-for`, () => {
test(`template v-for w/ <slot/>`, () => { test(`template v-for w/ <slot/>`, () => {
assert( assert(
`<template v-for="item in items"><slot/></template>`, `<template v-for="item in items"><slot/></template>`,
`<block wx:for="{{a}}" wx:for-item="item"><slot/></block>`, `<block wx:for="{{a}}" wx:for-item="item"><slot name="d"/></block>`,
`(_ctx, _cache) => { `(_ctx, _cache) => {
return { a: _f(_ctx.items, (item, k0, i0) => { return {}; }) } return { a: _f(_ctx.items, (item, k0, i0) => { return {}; }) }
}` }`
...@@ -177,7 +177,7 @@ describe(`compiler: v-for`, () => { ...@@ -177,7 +177,7 @@ describe(`compiler: v-for`, () => {
test(`v-for on <slot/>`, () => { test(`v-for on <slot/>`, () => {
assert( assert(
`<slot v-for="item in items"></slot>`, `<slot v-for="item in items"></slot>`,
`<slot wx:for="{{a}}" wx:for-item="item"></slot>`, `<slot wx:for="{{a}}" wx:for-item="item" name="d"></slot>`,
`(_ctx, _cache) => { `(_ctx, _cache) => {
return { a: _f(_ctx.items, (item, k0, i0) => { return {}; }) } return { a: _f(_ctx.items, (item, k0, i0) => { return {}; }) }
}` }`
......
...@@ -50,7 +50,7 @@ describe(`compiler: v-if`, () => { ...@@ -50,7 +50,7 @@ describe(`compiler: v-if`, () => {
test(`template v-if w/ single <slot/> child`, () => { test(`template v-if w/ single <slot/> child`, () => {
assert( assert(
`<template v-if="ok"><slot/></template>`, `<template v-if="ok"><slot/></template>`,
`<block wx:if="{{a}}"><slot/></block>`, `<block wx:if="{{a}}"><slot name="d"/></block>`,
`(_ctx, _cache) => { `(_ctx, _cache) => {
return _e({ a: _ctx.ok }, _ctx.ok ? {} : {}) return _e({ a: _ctx.ok }, _ctx.ok ? {} : {})
}` }`
...@@ -59,7 +59,7 @@ describe(`compiler: v-if`, () => { ...@@ -59,7 +59,7 @@ describe(`compiler: v-if`, () => {
test(`v-if on <slot/>`, () => { test(`v-if on <slot/>`, () => {
assert( assert(
`<slot v-if="ok"/>`, `<slot v-if="ok"/>`,
`<slot wx:if="{{a}}"/>`, `<slot wx:if="{{a}}" name="d"/>`,
`(_ctx, _cache) => { `(_ctx, _cache) => {
return _e({ a: _ctx.ok }, _ctx.ok ? {} : {}) return _e({ a: _ctx.ok }, _ctx.ok ? {} : {})
}` }`
......
...@@ -4,14 +4,21 @@ describe('compiler: transform v-slot', () => { ...@@ -4,14 +4,21 @@ describe('compiler: transform v-slot', () => {
test('default slot', () => { test('default slot', () => {
assert( assert(
`<custom><template v-slot/></custom>`, `<custom><template v-slot/></custom>`,
`<custom u-s="{{['d']}}" u-i="2a9ec0b0-0"><view/></custom>`, `<custom u-s="{{['d']}}" u-i="2a9ec0b0-0"><view slot="d"/></custom>`,
`(_ctx, _cache) => {
return {}
}`
)
assert(
`<custom><template #default/></custom>`,
`<custom u-s="{{['d']}}" u-i="2a9ec0b0-0"><view slot="d"/></custom>`,
`(_ctx, _cache) => { `(_ctx, _cache) => {
return {} return {}
}` }`
) )
assert( assert(
`<custom>test</custom>`, `<custom>test</custom>`,
`<custom u-s="{{['d']}}" u-i="2a9ec0b0-0">test</custom>`, `<custom u-s="{{['d']}}" u-i="2a9ec0b0-0"><view slot="d">test</view></custom>`,
`(_ctx, _cache) => { `(_ctx, _cache) => {
return {} return {}
}` }`
......
...@@ -31,6 +31,10 @@ export function rewriteSlot(node: SlotOutletNode, context: TransformContext) { ...@@ -31,6 +31,10 @@ export function rewriteSlot(node: SlotOutletNode, context: TransformContext) {
let hasOtherDir = false let hasOtherDir = false
const nonNameProps: (AttributeNode | DirectiveNode)[] = [] const nonNameProps: (AttributeNode | DirectiveNode)[] = []
const { props } = node const { props } = node
// 默认插槽强制设置name
if (!findProp(node, 'name')) {
props.unshift(createAttributeNode('name', 'default'))
}
for (let i = 0; i < props.length; i++) { for (let i = 0; i < props.length; i++) {
const p = props[i] const p = props[i]
if (p.type === NodeTypes.ATTRIBUTE) { if (p.type === NodeTypes.ATTRIBUTE) {
...@@ -119,24 +123,24 @@ function transformScopedSlotName( ...@@ -119,24 +123,24 @@ function transformScopedSlotName(
if (!context.miniProgram.slot.dynamicSlotNames) { if (!context.miniProgram.slot.dynamicSlotNames) {
return return
} }
const { props } = node
const slotKey = parseScopedSlotKey(context) const slotKey = parseScopedSlotKey(context)
if (!slotKey) {
return
}
const nameProps = findProp(node, 'name') const nameProps = findProp(node, 'name')
if (!nameProps) { if (nameProps && nameProps.type === NodeTypes.ATTRIBUTE && nameProps.value) {
// 生成默认的 default 插槽名 const { props } = node
if (slotKey) { props.splice(
props.push( props.indexOf(nameProps),
createBindDirectiveNode( 1,
'name', createBindDirectiveNode(
rewriteExpression( 'name',
createSimpleExpression(`"${SLOT_DEFAULT_NAME}-"+` + slotKey), rewriteExpression(
context createSimpleExpression(`"${nameProps.value.content}-"+` + slotKey),
).content context
) ).content
) )
} else { )
props.push(createAttributeNode('name', SLOT_DEFAULT_NAME))
}
} }
} }
......
...@@ -15,6 +15,7 @@ import { ...@@ -15,6 +15,7 @@ import {
createCompoundExpression, createCompoundExpression,
createSimpleExpression, createSimpleExpression,
DirectiveNode, DirectiveNode,
ElementNode,
ElementTypes, ElementTypes,
ErrorCodes, ErrorCodes,
ExpressionNode, ExpressionNode,
...@@ -30,6 +31,7 @@ import { ...@@ -30,6 +31,7 @@ import {
import { dynamicSlotName, SLOT_DEFAULT_NAME } from '@dcloudio/uni-shared' import { dynamicSlotName, SLOT_DEFAULT_NAME } from '@dcloudio/uni-shared'
import { import {
createBindDirectiveNode, createBindDirectiveNode,
createDirectiveNode,
isUserComponent, isUserComponent,
} from '@dcloudio/uni-cli-shared' } from '@dcloudio/uni-cli-shared'
import { WITH_SCOPED_SLOT } from '../runtimeHelpers' import { WITH_SCOPED_SLOT } from '../runtimeHelpers'
...@@ -45,7 +47,7 @@ import { ...@@ -45,7 +47,7 @@ import {
SCOPED_SLOT_IDENTIFIER, SCOPED_SLOT_IDENTIFIER,
} from './utils' } from './utils'
import { createVForArrowFunctionExpression } from './vFor' import { createVForArrowFunctionExpression } from './vFor'
import { DYNAMIC_SLOT } from '..' import { DYNAMIC_SLOT } from '../runtimeHelpers'
export const transformSlot: NodeTransform = (node, context) => { export const transformSlot: NodeTransform = (node, context) => {
if (!isUserComponent(node, context as any)) { if (!isUserComponent(node, context as any)) {
...@@ -78,6 +80,10 @@ export const transformSlot: NodeTransform = (node, context) => { ...@@ -78,6 +80,10 @@ export const transformSlot: NodeTransform = (node, context) => {
) )
break break
} }
if (!slotDir.arg) {
// v-slot => v-slot:default
slotDir.arg = createSimpleExpression('default', true)
}
const slotName = transformTemplateSlotElement( const slotName = transformTemplateSlotElement(
slotDir, slotDir,
slotElement, slotElement,
...@@ -97,19 +103,47 @@ export const transformSlot: NodeTransform = (node, context) => { ...@@ -97,19 +103,47 @@ export const transformSlot: NodeTransform = (node, context) => {
slots.add(slotName) slots.add(slotName)
} }
} }
if (isMiniProgramComponent) {
return
}
if (implicitDefaultChildren.length) { if (implicitDefaultChildren.length) {
slots.add(SLOT_DEFAULT_NAME) slots.add(SLOT_DEFAULT_NAME)
} }
if (onComponentSlot) { if (onComponentSlot) {
// <unicloud-db v-slot:default="{data, loading, error, options}"/> // <unicloud-db v-slot:default="{data, loading, error, options}"/>
// => <unicloud-db collection=""><template v-slot:default="{data, loading, error, options}"/></unicloud-db> // => <unicloud-db collection=""><template v-slot:default="{data, loading, error, options}"/></unicloud-db>
slots.add(SLOT_DEFAULT_NAME) slots.add(SLOT_DEFAULT_NAME)
const templateNode = createTemplateNode( const templateNode = createTemplateNode(
onComponentSlot, onComponentSlot,
implicitDefaultChildren implicitDefaultChildren
) )
transformTemplateSlotElement(onComponentSlot, templateNode, node, context) transformTemplateSlotElement(onComponentSlot, templateNode, node, context)
node.children = templateNode.children node.children = [templateNode]
} else {
if (implicitDefaultChildren.length) {
// <custom>test</custom> => <custom><template #default>test</template></custom>
const vSlotDir = createDirectiveNode('slot', 'default')
const child = implicitDefaultChildren[0] as ElementNode
const isSingleElementNode =
implicitDefaultChildren.length === 1 &&
child.type === NodeTypes.ELEMENT &&
!findDir(child, 'for')
if (isSingleElementNode) {
child.props.unshift(vSlotDir)
} else {
const templateNode = createTemplateNode(
vSlotDir,
implicitDefaultChildren
)
implicitDefaultChildren.forEach((child) => {
node.children.splice(node.children.indexOf(child), 1)
})
node.children.unshift(templateNode)
}
}
} }
// 不支持 $slots, 则自动补充 props // 不支持 $slots, 则自动补充 props
if (slots.size && !context.miniProgram.slot.$slots) { if (slots.size && !context.miniProgram.slot.$slots) {
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册