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

fix(mp): default slot (#3094)

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