提交 19fb8cec 编写于 作者: fxy060608's avatar fxy060608

fix(mp): scoped slots (#3055)

上级 5f1ba133
...@@ -25,7 +25,8 @@ declare module '@vue/runtime-core' { ...@@ -25,7 +25,8 @@ declare module '@vue/runtime-core' {
__isActive?: boolean // tabBar __isActive?: boolean // tabBar
__isTabBar?: boolean __isTabBar?: boolean
// mp // mp
$propsCaches?: Record<string, Record<string, any>[]> $updateScopedSlots: () => void
$scopedSlotsData?: { path: string; index: number; data: Data }[]
// h5 | app // h5 | app
$wxsModules?: string[] $wxsModules?: string[]
} }
......
...@@ -183,9 +183,11 @@ function fileToBuiltUrl( ...@@ -183,9 +183,11 @@ function fileToBuiltUrl(
const contentHash = getAssetHash(content) const contentHash = getAssetHash(content)
const { search, hash } = parseUrl(id) const { search, hash } = parseUrl(id)
const postfix = (search || '') + (hash || '') const postfix = (search || '') + (hash || '')
const fileName = normalizePath( const fileName = path.posix.relative(
path.posix.relative(process.env.UNI_INPUT_DIR, file) normalizePath(process.env.UNI_INPUT_DIR),
file
) )
if (!map.has(contentHash)) { if (!map.has(contentHash)) {
map.set(contentHash, fileName) map.set(contentHash, fileName)
} }
......
...@@ -29,7 +29,7 @@ describe('mp-alipay: transform v-slot', () => { ...@@ -29,7 +29,7 @@ describe('mp-alipay: transform v-slot', () => {
`<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" onVI="__l"><view a:for="{{a}}" a:for-item="v0" a:key="c" slot="{{v0.d}}"><view a:if="{{v0.a}}">{{v0.b}}</view><view a:else></view></view></unicloud-db>`, `<unicloud-db u-s="{{['d']}}" slot="d" u-i="2a9ec0b0-0" onVI="__l"><view a:for="{{a}}" a:for-item="v0" a:key="c" slot="{{v0.d}}"><view a:if="{{v0.a}}">{{v0.b}}</view><view a:else></view></view></unicloud-db>`,
`(_ctx, _cache) => { `(_ctx, _cache) => {
return { a: _w(({ data, loading, error, options }, s0, i0) => { return _e({ a: error }, error ? { b: _t(error.message) } : {}, { c: s0, d: i0 }); }, { name: 'd', vueId: '2a9ec0b0-0' }) } return { a: _w(({ data, loading, error, options }, s0, i0) => { return _e({ a: error }, error ? { b: _t(error.message) } : {}, { c: i0, d: s0 }); }, { name: 'd', path: 'a', vueId: '2a9ec0b0-0' }) }
}` }`
) )
}) })
...@@ -39,7 +39,7 @@ describe('mp-alipay: transform v-slot', () => { ...@@ -39,7 +39,7 @@ describe('mp-alipay: transform v-slot', () => {
`<custom><template v-slot:default="slotProps"><view>{{ slotProps.item }}</view></template></custom>`, `<custom><template v-slot:default="slotProps"><view>{{ slotProps.item }}</view></template></custom>`,
`<custom u-s="{{['d']}}" u-i="2a9ec0b0-0" onVI="__l"><view a:for="{{a}}" a:for-item="slotProps" a:key="b" slot="{{slotProps.c}}"><view>{{slotProps.a}}</view></view></custom>`, `<custom u-s="{{['d']}}" u-i="2a9ec0b0-0" onVI="__l"><view a:for="{{a}}" a:for-item="slotProps" a:key="b" slot="{{slotProps.c}}"><view>{{slotProps.a}}</view></view></custom>`,
`(_ctx, _cache) => { `(_ctx, _cache) => {
return { a: _w((slotProps, s0, i0) => { return { a: _t(slotProps.item), b: s0, c: i0 }; }, { name: 'd', vueId: '2a9ec0b0-0' }) } return { a: _w((slotProps, s0, i0) => { return { a: _t(slotProps.item), b: i0, c: s0 }; }, { name: 'd', path: 'a', vueId: '2a9ec0b0-0' }) }
}` }`
) )
}) })
...@@ -49,7 +49,7 @@ describe('mp-alipay: transform v-slot', () => { ...@@ -49,7 +49,7 @@ describe('mp-alipay: transform v-slot', () => {
`<custom><template v-slot:default="slotProps"><custom1><template v-slot:default="slotProps1">{{ slotProps.item }}{{ slotProps1.item }}</template></custom1></template></custom>`, `<custom><template v-slot:default="slotProps"><custom1><template v-slot:default="slotProps1">{{ slotProps.item }}{{ slotProps1.item }}</template></custom1></template></custom>`,
`<custom u-s="{{['d']}}" u-i="2a9ec0b0-0" onVI="__l"><view a:for="{{a}}" a:for-item="slotProps" a:key="d" slot="{{slotProps.e}}"><custom1 u-s="{{['d']}}" u-i="{{slotProps.c}}" onVI="__l"><view a:for="{{slotProps.a}}" a:for-item="slotProps1" a:key="b" slot="{{slotProps1.c}}">{{slotProps.b}}{{slotProps1.a}}</view></custom1></view></custom>`, `<custom u-s="{{['d']}}" u-i="2a9ec0b0-0" onVI="__l"><view a:for="{{a}}" a:for-item="slotProps" a:key="d" slot="{{slotProps.e}}"><custom1 u-s="{{['d']}}" u-i="{{slotProps.c}}" onVI="__l"><view a:for="{{slotProps.a}}" a:for-item="slotProps1" a:key="b" slot="{{slotProps1.c}}">{{slotProps.b}}{{slotProps1.a}}</view></custom1></view></custom>`,
`(_ctx, _cache) => { `(_ctx, _cache) => {
return { a: _w((slotProps, s0, i0) => { return { a: _w((slotProps1, s1, i1) => { return { a: _t(slotProps1.item), b: s1, c: i1 }; }, { name: 'd', vueId: '2a9ec0b0-1' + '-' + i0 + ',' + '2a9ec0b0-0' }), b: _t(slotProps.item), c: '2a9ec0b0-1' + '-' + i0 + ',' + '2a9ec0b0-0', d: s0, e: i0 }; }, { name: 'd', vueId: '2a9ec0b0-0' }) } return { a: _w((slotProps, s0, i0) => { return { a: _w((slotProps1, s1, i1) => { return { a: _t(slotProps1.item), b: i1, c: s1 }; }, { name: 'd', path: 'a[' + i0 + '].' + 'a', vueId: '2a9ec0b0-1' + '-' + i0 + ',' + '2a9ec0b0-0' }), b: _t(slotProps.item), c: '2a9ec0b0-1' + '-' + i0 + ',' + '2a9ec0b0-0', d: i0, e: s0 }; }, { name: 'd', path: 'a', vueId: '2a9ec0b0-0' }) }
}` }`
) )
}) })
...@@ -59,7 +59,7 @@ describe('mp-alipay: transform v-slot', () => { ...@@ -59,7 +59,7 @@ describe('mp-alipay: transform v-slot', () => {
`<custom><template v-if="ok" v-slot:default="slotProps"><view>{{ slotProps.item }}</view></template></custom>`, `<custom><template v-if="ok" v-slot:default="slotProps"><view>{{ slotProps.item }}</view></template></custom>`,
`<custom u-s="{{['d']}}" u-i="2a9ec0b0-0" onVI="__l"><block a:if="{{a}}"><view a:for="{{b}}" a:for-item="slotProps" a:key="b" slot="{{slotProps.c}}"><view>{{slotProps.a}}</view></view></block></custom>`, `<custom u-s="{{['d']}}" u-i="2a9ec0b0-0" onVI="__l"><block a:if="{{a}}"><view a:for="{{b}}" a:for-item="slotProps" a:key="b" slot="{{slotProps.c}}"><view>{{slotProps.a}}</view></view></block></custom>`,
`(_ctx, _cache) => { `(_ctx, _cache) => {
return _e({ a: _ctx.ok }, _ctx.ok ? { b: _w((slotProps, s0, i0) => { return { a: _t(slotProps.item), b: s0, c: i0 }; }, { name: 'd', vueId: '2a9ec0b0-0' }) } : {}) return _e({ a: _ctx.ok }, _ctx.ok ? { b: _w((slotProps, s0, i0) => { return { a: _t(slotProps.item), b: i0, c: s0 }; }, { name: 'd', path: 'b', vueId: '2a9ec0b0-0' }) } : {})
}` }`
) )
}) })
...@@ -69,7 +69,7 @@ describe('mp-alipay: transform v-slot', () => { ...@@ -69,7 +69,7 @@ describe('mp-alipay: transform v-slot', () => {
`<custom v-for="item in items"><template v-slot:default="slotProps"><view>{{ slotProps.item }}</view></template></custom>`, `<custom v-for="item in items"><template v-slot:default="slotProps"><view>{{ slotProps.item }}</view></template></custom>`,
`<custom a:for="{{a}}" a:for-item="item" u-s="{{['d']}}" u-i="{{item.b}}" onVI="__l"><view a:for="{{item.a}}" a:for-item="slotProps" a:key="b" slot="{{slotProps.c}}"><view>{{slotProps.a}}</view></view></custom>`, `<custom a:for="{{a}}" a:for-item="item" u-s="{{['d']}}" u-i="{{item.b}}" onVI="__l"><view a:for="{{item.a}}" a:for-item="slotProps" a:key="b" slot="{{slotProps.c}}"><view>{{slotProps.a}}</view></view></custom>`,
`(_ctx, _cache) => { `(_ctx, _cache) => {
return { a: _f(_ctx.items, (item, k0, i0) => { return { a: _w((slotProps, s1, i1) => { return { a: _t(slotProps.item), b: s1, c: i1 }; }, { name: 'd', vueId: '2a9ec0b0-0' + '-' + i0 }), b: '2a9ec0b0-0' + '-' + i0 }; }) } return { a: _f(_ctx.items, (item, k0, i0) => { return { a: _w((slotProps, s1, i1) => { return { a: _t(slotProps.item), b: i1, c: s1 }; }, { name: 'd', path: 'a[' + i0 + '].' + 'a', vueId: '2a9ec0b0-0' + '-' + i0 }), b: '2a9ec0b0-0' + '-' + i0 }; }) }
}` }`
) )
}) })
...@@ -79,7 +79,7 @@ describe('mp-alipay: transform v-slot', () => { ...@@ -79,7 +79,7 @@ describe('mp-alipay: transform v-slot', () => {
`<view v-for="item in items"><custom v-for="item1 in item.list" :item="item1"><template v-slot:default="slotProps"><view>{{ slotProps.item }}</view></template></custom></view>`, `<view v-for="item in items"><custom v-for="item1 in item.list" :item="item1"><template v-slot:default="slotProps"><view>{{ slotProps.item }}</view></template></custom></view>`,
`<view a:for="{{a}}" a:for-item="item"><custom a:for="{{item.a}}" a:for-item="item1" u-s="{{['d']}}" u-i="{{item1.b}}" onVI="__l" u-p="{{item1.c}}"><view a:for="{{item1.a}}" a:for-item="slotProps" a:key="b" slot="{{slotProps.c}}"><view>{{slotProps.a}}</view></view></custom></view>`, `<view a:for="{{a}}" a:for-item="item"><custom a:for="{{item.a}}" a:for-item="item1" u-s="{{['d']}}" u-i="{{item1.b}}" onVI="__l" u-p="{{item1.c}}"><view a:for="{{item1.a}}" a:for-item="slotProps" a:key="b" slot="{{slotProps.c}}"><view>{{slotProps.a}}</view></view></custom></view>`,
`(_ctx, _cache) => { `(_ctx, _cache) => {
return { a: _f(_ctx.items, (item, k0, i0) => { return { a: _f(item.list, (item1, k1, i1) => { return { a: _w((slotProps, s2, i2) => { return { a: _t(slotProps.item), b: s2, c: i2 }; }, { name: 'd', vueId: '2a9ec0b0-0' + '-' + i0 + '-' + i1 }), b: '2a9ec0b0-0' + '-' + i0 + '-' + i1, c: _p({ item: item1 }) }; }) }; }) } return { a: _f(_ctx.items, (item, k0, i0) => { return { a: _f(item.list, (item1, k1, i1) => { return { a: _w((slotProps, s2, i2) => { return { a: _t(slotProps.item), b: i2, c: s2 }; }, { name: 'd', path: 'a[' + i0 + '].' + ('a[' + i1 + '].') + 'a', vueId: '2a9ec0b0-0' + '-' + i0 + '-' + i1 }), b: '2a9ec0b0-0' + '-' + i0 + '-' + i1, c: _p({ item: item1 }) }; }) }; }) }
}` }`
) )
}) })
......
...@@ -29,7 +29,7 @@ describe('compiler: transform v-slot', () => { ...@@ -29,7 +29,7 @@ describe('compiler: transform v-slot', () => {
`<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"><block s-for="v0 in a trackBy v0.a"><view s-if="{{v0.b}}">{{v0.c}}</view><view s-else></view></block></unicloud-db>`,
`(_ctx, _cache) => { `(_ctx, _cache) => {
return { a: _w(({ data, loading, error, options }, s0, i0) => { return _e({ a: s0, b: error }, error ? { c: _t(error.message) } : {}); }, { name: 'd', 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' }) }
}` }`
) )
}) })
...@@ -39,7 +39,7 @@ describe('compiler: transform v-slot', () => { ...@@ -39,7 +39,7 @@ describe('compiler: transform v-slot', () => {
`<custom><template v-slot:default="slotProps"><view>{{ slotProps.item }}</view></template></custom>`, `<custom><template v-slot:default="slotProps"><view>{{ slotProps.item }}</view></template></custom>`,
`<custom u-s="{{['d']}}" u-i="2a9ec0b0-0"><view slot="d"><block s-for="slotProps in a trackBy slotProps.a"><view>{{slotProps.b}}</view></block></view></custom>`, `<custom u-s="{{['d']}}" u-i="2a9ec0b0-0"><view slot="d"><block s-for="slotProps in a trackBy slotProps.a"><view>{{slotProps.b}}</view></block></view></custom>`,
`(_ctx, _cache) => { `(_ctx, _cache) => {
return { a: _w((slotProps, s0, i0) => { return { a: s0, b: _t(slotProps.item) }; }, { name: 'd', vueId: '2a9ec0b0-0' }) } return { a: _w((slotProps, s0, i0) => { return { a: i0, b: _t(slotProps.item) }; }, { name: 'd', path: 'a', vueId: '2a9ec0b0-0' }) }
}` }`
) )
}) })
...@@ -49,7 +49,7 @@ describe('compiler: transform v-slot', () => { ...@@ -49,7 +49,7 @@ describe('compiler: transform v-slot', () => {
`<custom><template v-slot:default="slotProps"><custom1><template v-slot:default="slotProps1">{{ slotProps.item }}{{ slotProps1.item }}</template></custom1></template></custom>`, `<custom><template v-slot:default="slotProps"><custom1><template v-slot:default="slotProps1">{{ slotProps.item }}{{ slotProps1.item }}</template></custom1></template></custom>`,
`<custom u-s="{{['d']}}" u-i="2a9ec0b0-0"><view slot="d"><block s-for="slotProps in a trackBy slotProps.a"><custom1 u-s="{{['d']}}" u-i="{{slotProps.d}}"><view slot="d"><block s-for="slotProps1 in slotProps.b trackBy slotProps1.a">{{slotProps.c}}{{slotProps1.b}}</block></view></custom1></block></view></custom>`, `<custom u-s="{{['d']}}" u-i="2a9ec0b0-0"><view slot="d"><block s-for="slotProps in a trackBy slotProps.a"><custom1 u-s="{{['d']}}" u-i="{{slotProps.d}}"><view slot="d"><block s-for="slotProps1 in slotProps.b trackBy slotProps1.a">{{slotProps.c}}{{slotProps1.b}}</block></view></custom1></block></view></custom>`,
`(_ctx, _cache) => { `(_ctx, _cache) => {
return { a: _w((slotProps, s0, i0) => { return { a: s0, b: _w((slotProps1, s1, i1) => { return { a: s1, b: _t(slotProps1.item) }; }, { name: 'd', vueId: '2a9ec0b0-1' + '-' + i0 + ',' + '2a9ec0b0-0' }), c: _t(slotProps.item), d: '2a9ec0b0-1' + '-' + i0 + ',' + '2a9ec0b0-0' }; }, { name: 'd', vueId: '2a9ec0b0-0' }) } return { a: _w((slotProps, s0, i0) => { return { a: i0, b: _w((slotProps1, s1, i1) => { return { a: i1, b: _t(slotProps1.item) }; }, { name: 'd', path: 'a[' + i0 + '].' + 'b', vueId: '2a9ec0b0-1' + '-' + i0 + ',' + '2a9ec0b0-0' }), c: _t(slotProps.item), d: '2a9ec0b0-1' + '-' + i0 + ',' + '2a9ec0b0-0' }; }, { name: 'd', path: 'a', vueId: '2a9ec0b0-0' }) }
}` }`
) )
}) })
...@@ -59,7 +59,7 @@ describe('compiler: transform v-slot', () => { ...@@ -59,7 +59,7 @@ describe('compiler: transform v-slot', () => {
`<custom><template v-if="ok" v-slot:default="slotProps"><view>{{ slotProps.item }}</view></template></custom>`, `<custom><template v-if="ok" v-slot:default="slotProps"><view>{{ slotProps.item }}</view></template></custom>`,
`<custom u-s="{{['d']}}" u-i="2a9ec0b0-0"><view s-if="{{a}}" slot="d"><block s-for="slotProps in b trackBy slotProps.a"><view>{{slotProps.b}}</view></block></view></custom>`, `<custom u-s="{{['d']}}" u-i="2a9ec0b0-0"><view s-if="{{a}}" slot="d"><block s-for="slotProps in b trackBy slotProps.a"><view>{{slotProps.b}}</view></block></view></custom>`,
`(_ctx, _cache) => { `(_ctx, _cache) => {
return _e({ a: _ctx.ok }, _ctx.ok ? { b: _w((slotProps, s0, i0) => { return { a: s0, b: _t(slotProps.item) }; }, { name: 'd', vueId: '2a9ec0b0-0' }) } : {}) return _e({ a: _ctx.ok }, _ctx.ok ? { b: _w((slotProps, s0, i0) => { return { a: i0, b: _t(slotProps.item) }; }, { name: 'd', path: 'b', vueId: '2a9ec0b0-0' }) } : {})
}` }`
) )
}) })
...@@ -69,7 +69,7 @@ describe('compiler: transform v-slot', () => { ...@@ -69,7 +69,7 @@ describe('compiler: transform v-slot', () => {
`<custom v-for="item in items"><template v-slot:default="slotProps"><view>{{ slotProps.item }}</view></template></custom>`, `<custom v-for="item in items"><template v-slot:default="slotProps"><view>{{ slotProps.item }}</view></template></custom>`,
`<custom s-for="item in a" u-s="{{['d']}}" u-i="{{item.b}}"><view slot="d"><block s-for="slotProps in item.a trackBy slotProps.a"><view>{{slotProps.b}}</view></block></view></custom>`, `<custom s-for="item in a" u-s="{{['d']}}" u-i="{{item.b}}"><view slot="d"><block s-for="slotProps in item.a trackBy slotProps.a"><view>{{slotProps.b}}</view></block></view></custom>`,
`(_ctx, _cache) => { `(_ctx, _cache) => {
return { a: _f(_ctx.items, (item, k0, i0) => { return { a: _w((slotProps, s1, i1) => { return { a: s1, b: _t(slotProps.item) }; }, { name: 'd', vueId: '2a9ec0b0-0' + '-' + i0 }), b: '2a9ec0b0-0' + '-' + i0 }; }) } return { a: _f(_ctx.items, (item, k0, i0) => { return { a: _w((slotProps, s1, i1) => { return { a: i1, b: _t(slotProps.item) }; }, { name: 'd', path: 'a[' + i0 + '].' + 'a', vueId: '2a9ec0b0-0' + '-' + i0 }), b: '2a9ec0b0-0' + '-' + i0 }; }) }
}` }`
) )
}) })
...@@ -79,7 +79,7 @@ describe('compiler: transform v-slot', () => { ...@@ -79,7 +79,7 @@ describe('compiler: transform v-slot', () => {
`<view v-for="item in items"><custom v-for="item1 in item.list" :item="item1"><template v-slot:default="slotProps"><view>{{ slotProps.item }}</view></template></custom></view>`, `<view v-for="item in items"><custom v-for="item1 in item.list" :item="item1"><template v-slot:default="slotProps"><view>{{ slotProps.item }}</view></template></custom></view>`,
`<view s-for="item in a"><custom s-for="item1 in item.a" u-s="{{['d']}}" u-i="{{item1.b}}" u-p="{{item1.c}}"><view slot="d"><block s-for="slotProps in item1.a trackBy slotProps.a"><view>{{slotProps.b}}</view></block></view></custom></view>`, `<view s-for="item in a"><custom s-for="item1 in item.a" u-s="{{['d']}}" u-i="{{item1.b}}" u-p="{{item1.c}}"><view slot="d"><block s-for="slotProps in item1.a trackBy slotProps.a"><view>{{slotProps.b}}</view></block></view></custom></view>`,
`(_ctx, _cache) => { `(_ctx, _cache) => {
return { a: _f(_ctx.items, (item, k0, i0) => { return { a: _f(item.list, (item1, k1, i1) => { return { a: _w((slotProps, s2, i2) => { return { a: s2, b: _t(slotProps.item) }; }, { name: 'd', vueId: '2a9ec0b0-0' + '-' + i0 + '-' + i1 }), b: '2a9ec0b0-0' + '-' + i0 + '-' + i1, c: _p({ item: item1 }) }; }) }; }) } return { a: _f(_ctx.items, (item, k0, i0) => { return { a: _f(item.list, (item1, k1, i1) => { return { a: _w((slotProps, s2, i2) => { return { a: i2, b: _t(slotProps.item) }; }, { name: 'd', path: 'a[' + i0 + '].' + ('a[' + i1 + '].') + 'a', vueId: '2a9ec0b0-0' + '-' + i0 + '-' + i1 }), b: '2a9ec0b0-0' + '-' + i0 + '-' + i1, c: _p({ item: item1 }) }; }) }; }) }
}` }`
) )
}) })
......
...@@ -67,7 +67,7 @@ describe('compiler: transform slot', () => { ...@@ -67,7 +67,7 @@ describe('compiler: transform slot', () => {
`<view v-for="(item,index) in items" :key="index"><slot v-for="(item1,index1) in item.list" :key="index1"></slot></view>`, `<view v-for="(item,index) in items" :key="index"><slot v-for="(item1,index1) in item.list" :key="index1"></slot></view>`,
`<view wx:for="{{a}}" wx:for-item="item" wx:key="b"><slot wx:for="{{item.a}}" wx:for-item="item1" name="{{item1.a}}"></slot></view>`, `<view wx:for="{{a}}" wx:for-item="item" wx:key="b"><slot wx:for="{{item.a}}" wx:for-item="item1" name="{{item1.a}}"></slot></view>`,
`(_ctx, _cache) => { `(_ctx, _cache) => {
return { a: _f(_ctx.items, (item, index, i0) => { return { a: _f(item.list, (item1, index1, i1) => { return { a: "d-" + i0 + '-' + i1, b: _r("d", { key: index1 }, i0 + '-' + i1) }; }), b: index }; }) } return { a: _f(_ctx.items, (item, index, i0) => { return { a: _f(item.list, (item1, index1, i1) => { return { a: "d-" + i0 + '-' + i1, b: _r("d", { key: index1 }, i1) }; }), b: index }; }) }
}` }`
) )
}) })
......
...@@ -29,7 +29,7 @@ describe('compiler: transform v-slot', () => { ...@@ -29,7 +29,7 @@ describe('compiler: transform v-slot', () => {
`<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"><view wx:for="{{a}}" wx:for-item="v0" wx:key="c" slot="{{v0.d}}"><view wx:if="{{v0.a}}">{{v0.b}}</view><view wx:else></view></view></unicloud-db>`, `<unicloud-db u-s="{{['d']}}" slot="d" u-i="2a9ec0b0-0"><view wx:for="{{a}}" wx:for-item="v0" wx:key="c" slot="{{v0.d}}"><view wx:if="{{v0.a}}">{{v0.b}}</view><view wx:else></view></view></unicloud-db>`,
`(_ctx, _cache) => { `(_ctx, _cache) => {
return { a: _w(({ data, loading, error, options }, s0, i0) => { return _e({ a: error }, error ? { b: _t(error.message) } : {}, { c: s0, d: i0 }); }, { name: 'd', vueId: '2a9ec0b0-0' }) } return { a: _w(({ data, loading, error, options }, s0, i0) => { return _e({ a: error }, error ? { b: _t(error.message) } : {}, { c: i0, d: s0 }); }, { name: 'd', path: 'a', vueId: '2a9ec0b0-0' }) }
}` }`
) )
}) })
...@@ -49,7 +49,7 @@ describe('compiler: transform v-slot', () => { ...@@ -49,7 +49,7 @@ describe('compiler: transform v-slot', () => {
`<custom><template v-slot:default="slotProps"><view>{{ slotProps.item }}</view></template></custom>`, `<custom><template v-slot:default="slotProps"><view>{{ slotProps.item }}</view></template></custom>`,
`<custom u-s="{{['d']}}" u-i="2a9ec0b0-0"><view wx:for="{{a}}" wx:for-item="slotProps" wx:key="b" slot="{{slotProps.c}}"><view>{{slotProps.a}}</view></view></custom>`, `<custom u-s="{{['d']}}" u-i="2a9ec0b0-0"><view wx:for="{{a}}" wx:for-item="slotProps" wx:key="b" slot="{{slotProps.c}}"><view>{{slotProps.a}}</view></view></custom>`,
`(_ctx, _cache) => { `(_ctx, _cache) => {
return { a: _w((slotProps, s0, i0) => { return { a: _t(slotProps.item), b: s0, c: i0 }; }, { name: 'd', vueId: '2a9ec0b0-0' }) } return { a: _w((slotProps, s0, i0) => { return { a: _t(slotProps.item), b: i0, c: s0 }; }, { name: 'd', path: 'a', vueId: '2a9ec0b0-0' }) }
}` }`
) )
}) })
...@@ -59,7 +59,7 @@ describe('compiler: transform v-slot', () => { ...@@ -59,7 +59,7 @@ describe('compiler: transform v-slot', () => {
`<custom><template v-slot:default="slotProps"><custom1><template v-slot:default="slotProps1">{{ slotProps.item }}{{ slotProps1.item }}</template></custom1></template></custom>`, `<custom><template v-slot:default="slotProps"><custom1><template v-slot:default="slotProps1">{{ slotProps.item }}{{ slotProps1.item }}</template></custom1></template></custom>`,
`<custom u-s="{{['d']}}" u-i="2a9ec0b0-0"><view wx:for="{{a}}" wx:for-item="slotProps" wx:key="d" slot="{{slotProps.e}}"><custom1 u-s="{{['d']}}" u-i="{{slotProps.c}}"><view wx:for="{{slotProps.a}}" wx:for-item="slotProps1" wx:key="b" slot="{{slotProps1.c}}">{{slotProps.b}}{{slotProps1.a}}</view></custom1></view></custom>`, `<custom u-s="{{['d']}}" u-i="2a9ec0b0-0"><view wx:for="{{a}}" wx:for-item="slotProps" wx:key="d" slot="{{slotProps.e}}"><custom1 u-s="{{['d']}}" u-i="{{slotProps.c}}"><view wx:for="{{slotProps.a}}" wx:for-item="slotProps1" wx:key="b" slot="{{slotProps1.c}}">{{slotProps.b}}{{slotProps1.a}}</view></custom1></view></custom>`,
`(_ctx, _cache) => { `(_ctx, _cache) => {
return { a: _w((slotProps, s0, i0) => { return { a: _w((slotProps1, s1, i1) => { return { a: _t(slotProps1.item), b: s1, c: i1 }; }, { name: 'd', vueId: '2a9ec0b0-1' + '-' + i0 + ',' + '2a9ec0b0-0' }), b: _t(slotProps.item), c: '2a9ec0b0-1' + '-' + i0 + ',' + '2a9ec0b0-0', d: s0, e: i0 }; }, { name: 'd', vueId: '2a9ec0b0-0' }) } return { a: _w((slotProps, s0, i0) => { return { a: _w((slotProps1, s1, i1) => { return { a: _t(slotProps1.item), b: i1, c: s1 }; }, { name: 'd', path: 'a[' + i0 + '].' + 'a', vueId: '2a9ec0b0-1' + '-' + i0 + ',' + '2a9ec0b0-0' }), b: _t(slotProps.item), c: '2a9ec0b0-1' + '-' + i0 + ',' + '2a9ec0b0-0', d: i0, e: s0 }; }, { name: 'd', path: 'a', vueId: '2a9ec0b0-0' }) }
}` }`
) )
}) })
...@@ -69,7 +69,7 @@ describe('compiler: transform v-slot', () => { ...@@ -69,7 +69,7 @@ describe('compiler: transform v-slot', () => {
`<custom><template v-if="ok" v-slot:default="slotProps"><view>{{ slotProps.item }}</view></template></custom>`, `<custom><template v-if="ok" v-slot:default="slotProps"><view>{{ slotProps.item }}</view></template></custom>`,
`<custom u-s="{{['d']}}" u-i="2a9ec0b0-0"><block wx:if="{{a}}"><view wx:for="{{b}}" wx:for-item="slotProps" wx:key="b" slot="{{slotProps.c}}"><view>{{slotProps.a}}</view></view></block></custom>`, `<custom u-s="{{['d']}}" u-i="2a9ec0b0-0"><block wx:if="{{a}}"><view wx:for="{{b}}" wx:for-item="slotProps" wx:key="b" slot="{{slotProps.c}}"><view>{{slotProps.a}}</view></view></block></custom>`,
`(_ctx, _cache) => { `(_ctx, _cache) => {
return _e({ a: _ctx.ok }, _ctx.ok ? { b: _w((slotProps, s0, i0) => { return { a: _t(slotProps.item), b: s0, c: i0 }; }, { name: 'd', vueId: '2a9ec0b0-0' }) } : {}) return _e({ a: _ctx.ok }, _ctx.ok ? { b: _w((slotProps, s0, i0) => { return { a: _t(slotProps.item), b: i0, c: s0 }; }, { name: 'd', path: 'b', vueId: '2a9ec0b0-0' }) } : {})
}` }`
) )
}) })
...@@ -79,7 +79,7 @@ describe('compiler: transform v-slot', () => { ...@@ -79,7 +79,7 @@ describe('compiler: transform v-slot', () => {
`<custom v-for="item in items"><template v-slot:default="slotProps"><view>{{ slotProps.item }}</view></template></custom>`, `<custom v-for="item in items"><template v-slot:default="slotProps"><view>{{ slotProps.item }}</view></template></custom>`,
`<custom wx:for="{{a}}" wx:for-item="item" u-s="{{['d']}}" u-i="{{item.b}}"><view wx:for="{{item.a}}" wx:for-item="slotProps" wx:key="b" slot="{{slotProps.c}}"><view>{{slotProps.a}}</view></view></custom>`, `<custom wx:for="{{a}}" wx:for-item="item" u-s="{{['d']}}" u-i="{{item.b}}"><view wx:for="{{item.a}}" wx:for-item="slotProps" wx:key="b" slot="{{slotProps.c}}"><view>{{slotProps.a}}</view></view></custom>`,
`(_ctx, _cache) => { `(_ctx, _cache) => {
return { a: _f(_ctx.items, (item, k0, i0) => { return { a: _w((slotProps, s1, i1) => { return { a: _t(slotProps.item), b: s1, c: i1 }; }, { name: 'd', vueId: '2a9ec0b0-0' + '-' + i0 }), b: '2a9ec0b0-0' + '-' + i0 }; }) } return { a: _f(_ctx.items, (item, k0, i0) => { return { a: _w((slotProps, s1, i1) => { return { a: _t(slotProps.item), b: i1, c: s1 }; }, { name: 'd', path: 'a[' + i0 + '].' + 'a', vueId: '2a9ec0b0-0' + '-' + i0 }), b: '2a9ec0b0-0' + '-' + i0 }; }) }
}` }`
) )
}) })
...@@ -89,7 +89,7 @@ describe('compiler: transform v-slot', () => { ...@@ -89,7 +89,7 @@ describe('compiler: transform v-slot', () => {
`<view v-for="item in items"><custom v-for="item1 in item.list" :item="item1"><template v-slot:default="slotProps"><view>{{ slotProps.item }}</view></template></custom></view>`, `<view v-for="item in items"><custom v-for="item1 in item.list" :item="item1"><template v-slot:default="slotProps"><view>{{ slotProps.item }}</view></template></custom></view>`,
`<view wx:for="{{a}}" wx:for-item="item"><custom wx:for="{{item.a}}" wx:for-item="item1" u-s="{{['d']}}" u-i="{{item1.b}}" u-p="{{item1.c}}"><view wx:for="{{item1.a}}" wx:for-item="slotProps" wx:key="b" slot="{{slotProps.c}}"><view>{{slotProps.a}}</view></view></custom></view>`, `<view wx:for="{{a}}" wx:for-item="item"><custom wx:for="{{item.a}}" wx:for-item="item1" u-s="{{['d']}}" u-i="{{item1.b}}" u-p="{{item1.c}}"><view wx:for="{{item1.a}}" wx:for-item="slotProps" wx:key="b" slot="{{slotProps.c}}"><view>{{slotProps.a}}</view></view></custom></view>`,
`(_ctx, _cache) => { `(_ctx, _cache) => {
return { a: _f(_ctx.items, (item, k0, i0) => { return { a: _f(item.list, (item1, k1, i1) => { return { a: _w((slotProps, s2, i2) => { return { a: _t(slotProps.item), b: s2, c: i2 }; }, { name: 'd', vueId: '2a9ec0b0-0' + '-' + i0 + '-' + i1 }), b: '2a9ec0b0-0' + '-' + i0 + '-' + i1, c: _p({ item: item1 }) }; }) }; }) } return { a: _f(_ctx.items, (item, k0, i0) => { return { a: _f(item.list, (item1, k1, i1) => { return { a: _w((slotProps, s2, i2) => { return { a: _t(slotProps.item), b: i2, c: s2 }; }, { name: 'd', path: 'a[' + i0 + '].' + ('a[' + i1 + '].') + 'a', vueId: '2a9ec0b0-0' + '-' + i0 + '-' + i1 }), b: '2a9ec0b0-0' + '-' + i0 + '-' + i1, c: _p({ item: item1 }) }; }) }; }) }
}` }`
) )
}) })
......
...@@ -17,7 +17,7 @@ import { camelize } from '@vue/shared' ...@@ -17,7 +17,7 @@ import { camelize } from '@vue/shared'
import { dynamicSlotName, SLOT_DEFAULT_NAME } from '@dcloudio/uni-shared' import { dynamicSlotName, SLOT_DEFAULT_NAME } from '@dcloudio/uni-shared'
import { RENDER_SLOT } from '../runtimeHelpers' import { RENDER_SLOT } from '../runtimeHelpers'
import { genExpr } from '../codegen' import { genExpr } from '../codegen'
import { isVForScope, TransformContext } from '../transform' import { isScopedSlotVFor, isVForScope, TransformContext } from '../transform'
import { processProps } from './transformElement' import { processProps } from './transformElement'
import { rewriteExpression } from './utils' import { rewriteExpression } from './utils'
import { import {
...@@ -85,14 +85,15 @@ export function rewriteSlot(node: SlotOutletNode, context: TransformContext) { ...@@ -85,14 +85,15 @@ export function rewriteSlot(node: SlotOutletNode, context: TransformContext) {
} }
}) })
if (properties.length) { if (properties.length) {
const slotKey = transformScopedSlotKey(node, context) transformScopedSlotName(node, context)
const vForIndexAlias = parseVForIndexAlias(context)
rewriteExpression( rewriteExpression(
createCompoundExpression([ createCompoundExpression([
context.helperString(RENDER_SLOT) + '(', context.helperString(RENDER_SLOT) + '(',
slotName, slotName,
',', ',',
`{${properties.join(',')}}`, `{${properties.join(',')}}`,
`${slotKey ? ',' + slotKey : ''}`, `${vForIndexAlias ? ',' + vForIndexAlias : ''}`,
')', ')',
]), ]),
context context
...@@ -101,7 +102,17 @@ export function rewriteSlot(node: SlotOutletNode, context: TransformContext) { ...@@ -101,7 +102,17 @@ export function rewriteSlot(node: SlotOutletNode, context: TransformContext) {
} }
} }
function transformScopedSlotKey( function parseVForIndexAlias(context: TransformContext) {
let { currentScope } = context
while (currentScope) {
if (isVForScope(currentScope) && !isScopedSlotVFor(currentScope)) {
return currentScope.indexAlias
}
currentScope = currentScope.parent!
}
}
function transformScopedSlotName(
node: SlotOutletNode, node: SlotOutletNode,
context: TransformContext context: TransformContext
) { ) {
...@@ -127,7 +138,6 @@ function transformScopedSlotKey( ...@@ -127,7 +138,6 @@ function transformScopedSlotKey(
props.push(createAttributeNode('name', SLOT_DEFAULT_NAME)) props.push(createAttributeNode('name', SLOT_DEFAULT_NAME))
} }
} }
return slotKey
} }
function parseScopedSlotKey(context: TransformContext) { function parseScopedSlotKey(context: TransformContext) {
......
...@@ -236,8 +236,11 @@ function createVForTemplate( ...@@ -236,8 +236,11 @@ function createVForTemplate(
}, },
context: TransformContext context: TransformContext
) { ) {
const key = 's' + context.scopes.vFor const slotName = 's' + context.scopes.vFor
const keyProp: DirectiveNode = createBindDirectiveNode('key', key) const keyProp: DirectiveNode = createBindDirectiveNode(
'key',
'i' + context.scopes.vFor
)
const source = isString(name) ? `'${name}'` : genExpr(name) const source = isString(name) ? `'${name}'` : genExpr(name)
const vForProp: DirectiveNode = { const vForProp: DirectiveNode = {
type: NodeTypes.DIRECTIVE, type: NodeTypes.DIRECTIVE,
...@@ -246,14 +249,14 @@ function createVForTemplate( ...@@ -246,14 +249,14 @@ function createVForTemplate(
modifiers: [], modifiers: [],
arg: undefined, arg: undefined,
exp: createSimpleExpression( exp: createSimpleExpression(
`(${value}, ${key}) in ${SCOPED_SLOT_IDENTIFIER}(${source}, ${ `(${value}, ${slotName}) in ${SCOPED_SLOT_IDENTIFIER}(${source}, ${
findCurrentVForValueAlias(context) || `''` findCurrentVForValueAlias(context) || `''`
})` })`
), ),
} }
const props = [vForProp, keyProp] const props = [vForProp, keyProp]
if (context.miniProgram.slot.dynamicSlotNames) { if (context.miniProgram.slot.dynamicSlotNames) {
props.push(createBindDirectiveNode('slot', `i${context.scopes.vFor}`)) props.push(createBindDirectiveNode('slot', slotName))
} }
return { return {
loc: slotElement.loc, loc: slotElement.loc,
...@@ -286,15 +289,18 @@ function findCurrentSlotName(source: ExpressionNode) { ...@@ -286,15 +289,18 @@ function findCurrentSlotName(source: ExpressionNode) {
) )
} }
function createPathBinaryExpr(scope: CodegenVForScope) { function createPathBinaryExpr(
scope: CodegenVForScope,
computed: boolean = true
) {
return binaryExpression( return binaryExpression(
'+', '+',
binaryExpression( binaryExpression(
'+', '+',
stringLiteral(parseVForPath(scope.sourceAlias) + '.'), stringLiteral(parseVForPath(scope.sourceAlias) + (computed ? '[' : '.')),
identifier(scope.indexAlias) identifier(scope.indexAlias)
), ),
stringLiteral('.') stringLiteral(computed ? '].' : '.')
) )
} }
...@@ -303,6 +309,7 @@ export function findCurrentPath(id: string, scope: CodegenScope) { ...@@ -303,6 +309,7 @@ export function findCurrentPath(id: string, scope: CodegenScope) {
let binaryExpr: BinaryExpression | null = null let binaryExpr: BinaryExpression | null = null
while (parent) { while (parent) {
if (isVForScope(parent)) { if (isVForScope(parent)) {
// const computed = !isScopedSlotVFor(parent)
if (!binaryExpr) { if (!binaryExpr) {
binaryExpr = createPathBinaryExpr(parent) binaryExpr = createPathBinaryExpr(parent)
} else { } else {
...@@ -362,15 +369,15 @@ export function createVSlotCallExpression( ...@@ -362,15 +369,15 @@ export function createVSlotCallExpression(
vForScope: CodegenVForScope, vForScope: CodegenVForScope,
context: TransformContext context: TransformContext
) { ) {
const { source /*, sourceAlias*/ } = vForScope const { source, sourceAlias } = vForScope
// const id = parseVForPath(sourceAlias) const id = parseVForPath(sourceAlias)
return callExpression(identifier(context.helperString(WITH_SCOPED_SLOT)), [ return callExpression(identifier(context.helperString(WITH_SCOPED_SLOT)), [
createVForArrowFunctionExpression(vForScope), createVForArrowFunctionExpression(vForScope),
objectExpression([ objectExpression([
// 插槽名称,数据更新path,vueId // 插槽名称,数据更新 path,vueId
objectProperty(identifier('name'), findCurrentSlotName(source)), objectProperty(identifier('name'), findCurrentSlotName(source)),
// 暂不生成path // 暂不生成 path
// objectProperty(identifier('path'), findCurrentPath(id, vForScope)), objectProperty(identifier('path'), findCurrentPath(id, vForScope)),
objectProperty( objectProperty(
identifier('vueId'), identifier('vueId'),
findCurrentVueIdExpr(slotComponent, context) findCurrentVueIdExpr(slotComponent, context)
......
import { extend, isSymbol, isObject, toRawType, def, hasChanged, isArray, isFunction, NOOP, remove, toHandlerKey, hasOwn, camelize, hyphenate, isReservedProp, capitalize, isString, normalizeClass, normalizeStyle, isOn, isPromise, EMPTY_OBJ, isSet, isMap, isPlainObject, isIntegerKey, makeMap, toTypeString, invokeArrayFns, NO, toNumber, EMPTY_ARR, stringifyStyle as stringifyStyle$1, toDisplayString } from '@vue/shared'; import { extend, isSymbol, isObject, toRawType, def, hasChanged, isArray, isFunction, NOOP, remove, toHandlerKey, hasOwn, camelize, hyphenate, isReservedProp, capitalize, isString, normalizeClass, normalizeStyle, isOn, isPromise, EMPTY_OBJ, isSet, isMap, isPlainObject, toTypeString, isIntegerKey, makeMap, invokeArrayFns, NO, toNumber, EMPTY_ARR, stringifyStyle as stringifyStyle$1, toDisplayString } from '@vue/shared';
export { camelize, normalizeClass, normalizeProps, normalizeStyle, toDisplayString, toHandlerKey } from '@vue/shared'; export { camelize, normalizeClass, normalizeProps, normalizeStyle, toDisplayString, toHandlerKey } from '@vue/shared';
import { isRootHook, ON_ERROR, UniLifecycleHooks, dynamicSlotName } from '@dcloudio/uni-shared'; import { isRootHook, getValueByDataPath, ON_ERROR, UniLifecycleHooks, dynamicSlotName } from '@dcloudio/uni-shared';
function warn(msg, ...args) { function warn(msg, ...args) {
console.warn(`[Vue warn] ${msg}`, ...args); console.warn(`[Vue warn] ${msg}`, ...args);
...@@ -4785,7 +4785,48 @@ const updateComponentPreRender = (instance) => { ...@@ -4785,7 +4785,48 @@ const updateComponentPreRender = (instance) => {
flushPreFlushCbs(undefined, instance.update); flushPreFlushCbs(undefined, instance.update);
resetTracking(); resetTracking();
}; };
function componentUpdateScopedSlotsFn() {
const scopedSlotsData = this.$scopedSlotsData;
if (!scopedSlotsData || scopedSlotsData.length === 0) {
return;
}
const start = Date.now();
const mpInstance = this.ctx.$scope;
const oldData = mpInstance.data;
const diffData = Object.create(null);
scopedSlotsData.forEach(({ path, index, data }) => {
const oldScopedSlotData = getValueByDataPath(oldData, path);
const diffPath = `${path}[${index}]`;
if (typeof oldScopedSlotData === 'undefined' ||
typeof oldScopedSlotData[index] === 'undefined') {
diffData[diffPath] = data;
}
else {
const diffScopedSlotData = diff(data, oldScopedSlotData[index]);
Object.keys(diffScopedSlotData).forEach(name => {
diffData[diffPath + '.' + name] = diffScopedSlotData[name];
});
}
});
scopedSlotsData.length = 0;
if (Object.keys(diffData).length) {
if (process.env.UNI_DEBUG) {
console.log('[' +
+new Date() +
'][' +
(mpInstance.is || mpInstance.route) +
'][' +
this.uid +
'][耗时' +
(Date.now() - start) +
']作用域插槽差量更新', JSON.stringify(diffData));
}
mpInstance.setData(diffData);
}
}
function setupRenderEffect(instance) { function setupRenderEffect(instance) {
const updateScopedSlots = componentUpdateScopedSlotsFn.bind(instance);
instance.$updateScopedSlots = () => nextTick(() => queueJob(updateScopedSlots));
const componentUpdateFn = () => { const componentUpdateFn = () => {
if (!instance.isMounted) { if (!instance.isMounted) {
patch(instance, renderComponentRoot(instance)); patch(instance, renderComponentRoot(instance));
...@@ -5267,7 +5308,7 @@ function renderSlot(name, props = {}, key) { ...@@ -5267,7 +5308,7 @@ function renderSlot(name, props = {}, key) {
}, instance); }, instance);
return; return;
} }
const invoker = findScopedSlotInvoker(vueIds.split(',')[0], instance); const invoker = findScopedSlotInvoker(vueIds, instance);
// 可能不存在,因为插槽不是必需的 // 可能不存在,因为插槽不是必需的
if (invoker) { if (invoker) {
invoker(name, props, key); invoker(name, props, key);
...@@ -5284,7 +5325,6 @@ function findScopedSlotInvoker(vueId, instance) { ...@@ -5284,7 +5325,6 @@ function findScopedSlotInvoker(vueId, instance) {
} }
} }
//@ts-ignore
function withScopedSlot(fn, { name, path, vueId, }) { function withScopedSlot(fn, { name, path, vueId, }) {
const instance = getCurrentInstance(); const instance = getCurrentInstance();
fn.path = path; fn.path = path;
...@@ -5294,30 +5334,30 @@ function withScopedSlot(fn, { name, path, vueId, }) { ...@@ -5294,30 +5334,30 @@ function withScopedSlot(fn, { name, path, vueId, }) {
(scopedSlots[vueId] = createScopedSlotInvoker(instance)); (scopedSlots[vueId] = createScopedSlotInvoker(instance));
if (!invoker.slots[name]) { if (!invoker.slots[name]) {
invoker.slots[name] = { invoker.slots[name] = {
data: {},
fn, fn,
}; };
} }
else { else {
invoker.slots[name].fn = fn; invoker.slots[name].fn = fn;
} }
return invoker.slots[name].data; return getValueByDataPath(instance.ctx.$scope.data, path);
} }
function createScopedSlotInvoker(instance) { function createScopedSlotInvoker(instance) {
const invoker = (slotName, args, key) => { const invoker = (slotName, args, index) => {
const slot = invoker.slots[slotName]; const slot = invoker.slots[slotName];
const hasKey = typeof key !== 'undefined'; const hasIndex = typeof index !== 'undefined';
key = (key || '0') + ''; index = index || 0;
if (!hasKey) {
// 循环第一个 slot 时,重置 data
slot.data = {};
}
// 确保当前 slot 的上下文,类似 withCtx // 确保当前 slot 的上下文,类似 withCtx
const prevInstance = setCurrentRenderingInstance(instance); const prevInstance = setCurrentRenderingInstance(instance);
slot.data[key] = slot.fn(args, key, slotName + (hasKey ? '-' + key : '')); const data = slot.fn(args, slotName + (hasIndex ? '-' + index : ''), index);
const path = slot.fn.path;
setCurrentRenderingInstance(prevInstance); setCurrentRenderingInstance(prevInstance);
// TODO 简单的 forceUpdate,理论上,可以仅对 scoped slot 部分数据 diff 更新 (instance.$scopedSlotsData || (instance.$scopedSlotsData = [])).push({
instance.proxy.$forceUpdate(); path,
index,
data,
});
instance.$updateScopedSlots();
}; };
invoker.slots = {}; invoker.slots = {};
return invoker; return invoker;
...@@ -5402,4 +5442,4 @@ function createApp(rootComponent, rootProps = null) { ...@@ -5402,4 +5442,4 @@ function createApp(rootComponent, rootProps = null) {
} }
const createSSRApp = createApp; const createSSRApp = createApp;
export { EffectScope, Fragment, ReactiveEffect, Text, c, callWithAsyncErrorHandling, callWithErrorHandling, computed, createApp, createSSRApp, createVNode$1 as createVNode, createVueApp, customRef, d, defineAsyncComponent, defineComponent, defineEmits, defineExpose, defineProps, e, effect, effectScope, f, findComponentPropsData, getCurrentInstance, getCurrentScope, guardReactiveProps, h, inject, injectHook, invalidateJob, isInSSRComponentSetup, isProxy, isReactive, isReadonly, isRef, logError, markRaw, mergeDefaults, mergeProps, n, nextTick, o, onActivated, onBeforeMount, onBeforeUnmount, onBeforeUpdate, onDeactivated, onErrorCaptured, onMounted, onRenderTracked, onRenderTriggered, onScopeDispose, onServerPrefetch, onUnmounted, onUpdated, p, patch, provide, proxyRefs, pruneComponentPropsCache, queuePostFlushCb, r, reactive, readonly, ref, resolveComponent, resolveDirective, resolveFilter, s, setCurrentRenderingInstance, setupDevtoolsPlugin, shallowReactive, shallowReadonly, shallowRef, sr, stop, t, toHandlers, toRaw, toRef, toRefs, triggerRef, unref, updateProps, useAttrs, useCssModule, useCssVars, useSSRContext, useSlots, version, w, warn$1 as warn, watch, watchEffect, watchPostEffect, watchSyncEffect, withAsyncContext, withCtx, withDefaults, withDirectives, withModifiers, withScopeId }; export { EffectScope, Fragment, ReactiveEffect, Text, c, callWithAsyncErrorHandling, callWithErrorHandling, computed, createApp, createSSRApp, createVNode$1 as createVNode, createVueApp, customRef, d, defineAsyncComponent, defineComponent, defineEmits, defineExpose, defineProps, diff, e, effect, effectScope, f, findComponentPropsData, getCurrentInstance, getCurrentScope, guardReactiveProps, h, inject, injectHook, invalidateJob, isInSSRComponentSetup, isProxy, isReactive, isReadonly, isRef, logError, markRaw, mergeDefaults, mergeProps, n, nextTick, o, onActivated, onBeforeMount, onBeforeUnmount, onBeforeUpdate, onDeactivated, onErrorCaptured, onMounted, onRenderTracked, onRenderTriggered, onScopeDispose, onServerPrefetch, onUnmounted, onUpdated, p, patch, provide, proxyRefs, pruneComponentPropsCache, queuePostFlushCb, r, reactive, readonly, ref, resolveComponent, resolveDirective, resolveFilter, s, setCurrentRenderingInstance, setupDevtoolsPlugin, shallowReactive, shallowReadonly, shallowRef, sr, stop, t, toHandlers, toRaw, toRef, toRefs, triggerRef, unref, updateProps, useAttrs, useCssModule, useCssVars, useSSRContext, useSlots, version, w, warn$1 as warn, watch, watchEffect, watchPostEffect, watchSyncEffect, withAsyncContext, withCtx, withDefaults, withDirectives, withModifiers, withScopeId };
import { extend, isArray, isMap, isIntegerKey, isSymbol, hasOwn, isObject, hasChanged, makeMap, capitalize, toRawType, def, isFunction, NOOP, isOn, hyphenate, EMPTY_OBJ, toHandlerKey, toNumber, camelize, remove, isPromise, isString, isReservedProp, EMPTY_ARR, NO, normalizeClass, normalizeStyle, isSet, isPlainObject, toTypeString, invokeArrayFns } from '@vue/shared'; import { extend, isArray, isMap, isIntegerKey, isSymbol, hasOwn, isObject, hasChanged, makeMap, capitalize, toRawType, def, isFunction, NOOP, isOn, hyphenate, EMPTY_OBJ, toHandlerKey, toNumber, camelize, remove, isPromise, isString, isReservedProp, EMPTY_ARR, NO, normalizeClass, normalizeStyle, isSet, isPlainObject, toTypeString, invokeArrayFns } from '@vue/shared';
export { camelize, normalizeClass, normalizeProps, normalizeStyle, toDisplayString, toHandlerKey } from '@vue/shared'; export { camelize, normalizeClass, normalizeProps, normalizeStyle, toDisplayString, toHandlerKey } from '@vue/shared';
import { isRootHook } from '@dcloudio/uni-shared'; import { isRootHook, getValueByDataPath } from '@dcloudio/uni-shared';
function warn(msg, ...args) { function warn(msg, ...args) {
console.warn(`[Vue warn] ${msg}`, ...args); console.warn(`[Vue warn] ${msg}`, ...args);
...@@ -4785,7 +4785,48 @@ const updateComponentPreRender = (instance) => { ...@@ -4785,7 +4785,48 @@ const updateComponentPreRender = (instance) => {
flushPreFlushCbs(undefined, instance.update); flushPreFlushCbs(undefined, instance.update);
resetTracking(); resetTracking();
}; };
function componentUpdateScopedSlotsFn() {
const scopedSlotsData = this.$scopedSlotsData;
if (!scopedSlotsData || scopedSlotsData.length === 0) {
return;
}
const start = Date.now();
const mpInstance = this.ctx.$scope;
const oldData = mpInstance.data;
const diffData = Object.create(null);
scopedSlotsData.forEach(({ path, index, data }) => {
const oldScopedSlotData = getValueByDataPath(oldData, path);
const diffPath = `${path}[${index}]`;
if (typeof oldScopedSlotData === 'undefined' ||
typeof oldScopedSlotData[index] === 'undefined') {
diffData[diffPath] = data;
}
else {
const diffScopedSlotData = diff(data, oldScopedSlotData[index]);
Object.keys(diffScopedSlotData).forEach(name => {
diffData[diffPath + '.' + name] = diffScopedSlotData[name];
});
}
});
scopedSlotsData.length = 0;
if (Object.keys(diffData).length) {
if (process.env.UNI_DEBUG) {
console.log('[' +
+new Date() +
'][' +
(mpInstance.is || mpInstance.route) +
'][' +
this.uid +
'][耗时' +
(Date.now() - start) +
']作用域插槽差量更新', JSON.stringify(diffData));
}
mpInstance.setData(diffData);
}
}
function setupRenderEffect(instance) { function setupRenderEffect(instance) {
const updateScopedSlots = componentUpdateScopedSlotsFn.bind(instance);
instance.$updateScopedSlots = () => nextTick(() => queueJob(updateScopedSlots));
const componentUpdateFn = () => { const componentUpdateFn = () => {
if (!instance.isMounted) { if (!instance.isMounted) {
patch(instance, renderComponentRoot(instance)); patch(instance, renderComponentRoot(instance));
...@@ -4936,4 +4977,4 @@ function initCssVarsRender(instance, getter) { ...@@ -4936,4 +4977,4 @@ function initCssVarsRender(instance, getter) {
function withModifiers() { } function withModifiers() { }
function createVNode$1() { } function createVNode$1() { }
export { EffectScope, Fragment, ReactiveEffect, Text, callWithAsyncErrorHandling, callWithErrorHandling, computed, createVNode$1 as createVNode, createVueApp, customRef, defineAsyncComponent, defineComponent, defineEmits, defineExpose, defineProps, effect, effectScope, getCurrentInstance, getCurrentScope, guardReactiveProps, inject, injectHook, invalidateJob, isInSSRComponentSetup, isProxy, isReactive, isReadonly, isRef, logError, markRaw, mergeDefaults, mergeProps, nextTick, onActivated, onBeforeMount, onBeforeUnmount, onBeforeUpdate, onDeactivated, onErrorCaptured, onMounted, onRenderTracked, onRenderTriggered, onScopeDispose, onServerPrefetch, onUnmounted, onUpdated, patch, provide, proxyRefs, queuePostFlushCb, reactive, readonly, ref, resolveComponent, resolveDirective, resolveFilter, setCurrentRenderingInstance, shallowReactive, shallowReadonly, shallowRef, stop, toHandlers, toRaw, toRef, toRefs, triggerRef, unref, updateProps, useAttrs, useCssModule, useCssVars, useSSRContext, useSlots, version, warn$1 as warn, watch, watchEffect, watchPostEffect, watchSyncEffect, withAsyncContext, withCtx, withDefaults, withDirectives, withModifiers, withScopeId }; export { EffectScope, Fragment, ReactiveEffect, Text, callWithAsyncErrorHandling, callWithErrorHandling, computed, createVNode$1 as createVNode, createVueApp, customRef, defineAsyncComponent, defineComponent, defineEmits, defineExpose, defineProps, diff, effect, effectScope, getCurrentInstance, getCurrentScope, guardReactiveProps, inject, injectHook, invalidateJob, isInSSRComponentSetup, isProxy, isReactive, isReadonly, isRef, logError, markRaw, mergeDefaults, mergeProps, nextTick, onActivated, onBeforeMount, onBeforeUnmount, onBeforeUpdate, onDeactivated, onErrorCaptured, onMounted, onRenderTracked, onRenderTriggered, onScopeDispose, onServerPrefetch, onUnmounted, onUpdated, patch, provide, proxyRefs, queuePostFlushCb, reactive, readonly, ref, resolveComponent, resolveDirective, resolveFilter, setCurrentRenderingInstance, shallowReactive, shallowReadonly, shallowRef, stop, toHandlers, toRaw, toRef, toRefs, triggerRef, unref, updateProps, useAttrs, useCssModule, useCssVars, useSSRContext, useSlots, version, warn$1 as warn, watch, watchEffect, watchPostEffect, watchSyncEffect, withAsyncContext, withCtx, withDefaults, withDirectives, withModifiers, withScopeId };
...@@ -3,11 +3,7 @@ import type { MPComponentInstance } from '@dcloudio/uni-mp-core' ...@@ -3,11 +3,7 @@ import type { MPComponentInstance } from '@dcloudio/uni-mp-core'
import type { ScopedSlotInvokers } from './withScopedSlot' import type { ScopedSlotInvokers } from './withScopedSlot'
import { onMounted, getCurrentInstance } from 'vue' import { onMounted, getCurrentInstance } from 'vue'
export function renderSlot( export function renderSlot(name: string, props: Data = {}, key?: number) {
name: string,
props: Data = {},
key?: string | number
) {
const instance = getCurrentInstance() as ComponentInternalInstance & { const instance = getCurrentInstance() as ComponentInternalInstance & {
ctx: { $scope: MPComponentInstance } ctx: { $scope: MPComponentInstance }
} }
...@@ -28,7 +24,7 @@ export function renderSlot( ...@@ -28,7 +24,7 @@ export function renderSlot(
}, instance) }, instance)
return return
} }
const invoker = findScopedSlotInvoker(vueIds.split(',')[0], instance) const invoker = findScopedSlotInvoker(vueIds, instance)
// 可能不存在,因为插槽不是必需的 // 可能不存在,因为插槽不是必需的
if (invoker) { if (invoker) {
invoker(name, props, key) invoker(name, props, key)
......
import { getValueByDataPath } from '@dcloudio/uni-shared'
import type { ComponentInternalInstance } from 'vue' import type { ComponentInternalInstance } from 'vue'
//@ts-ignore //@ts-ignore
import { patch, getCurrentInstance, setCurrentRenderingInstance } from 'vue' import { diff, getCurrentInstance, setCurrentRenderingInstance } from 'vue'
export interface ScopedSlotInvokers { export interface ScopedSlotInvokers {
[vueId: string]: ScopedSlotInvoker [vueId: string]: ScopedSlotInvoker
} }
interface ScopedSlotFn { interface ScopedSlotFn {
(args: Data, key: string, slotName: string): Record<string, any> (args: Data, slotName: string, index: number): Record<string, any>
path: string path: string
} }
interface ScopedSlotData {
[key: string]: Data
}
interface ScopedSlotInvoker { interface ScopedSlotInvoker {
(slotName: string, args: Data, key?: string | number): void (slotName: string, args: Data, index?: number): void
slots: { slots: {
[slotName: string]: { [slotName: string]: {
fn: ScopedSlotFn fn: ScopedSlotFn
data: ScopedSlotData
} }
} }
} }
...@@ -45,34 +42,34 @@ export function withScopedSlot( ...@@ -45,34 +42,34 @@ export function withScopedSlot(
(scopedSlots[vueId] = createScopedSlotInvoker(instance)) (scopedSlots[vueId] = createScopedSlotInvoker(instance))
if (!invoker.slots[name]) { if (!invoker.slots[name]) {
invoker.slots[name] = { invoker.slots[name] = {
data: {},
fn, fn,
} }
} else { } else {
invoker.slots[name].fn = fn invoker.slots[name].fn = fn
} }
return invoker.slots[name].data return getValueByDataPath((instance as any).ctx.$scope.data, path)
} }
function createScopedSlotInvoker(instance: ComponentInternalInstance) { function createScopedSlotInvoker(instance: ComponentInternalInstance) {
const invoker: ScopedSlotInvoker = ( const invoker: ScopedSlotInvoker = (
slotName: string, slotName: string,
args: Data, args: Data,
key?: string | number index?: number
) => { ) => {
const slot = invoker.slots[slotName] const slot = invoker.slots[slotName]
const hasKey = typeof key !== 'undefined' const hasIndex = typeof index !== 'undefined'
key = (key || '0') + '' index = index || 0
if (!hasKey) {
// 循环第一个 slot 时,重置 data
slot.data = {}
}
// 确保当前 slot 的上下文,类似 withCtx // 确保当前 slot 的上下文,类似 withCtx
const prevInstance = setCurrentRenderingInstance(instance) const prevInstance = setCurrentRenderingInstance(instance)
slot.data[key] = slot.fn(args, key, slotName + (hasKey ? '-' + key : '')) const data = slot.fn(args, slotName + (hasIndex ? '-' + index : ''), index)
const path = slot.fn.path
setCurrentRenderingInstance(prevInstance) setCurrentRenderingInstance(prevInstance)
// TODO 简单的 forceUpdate,理论上,可以仅对 scoped slot 部分数据 diff 更新 ;(instance.$scopedSlotsData || (instance.$scopedSlotsData = [])).push({
instance.proxy!.$forceUpdate() path,
index,
data,
})
instance.$updateScopedSlots()
} }
invoker.slots = {} invoker.slots = {}
return invoker return invoker
......
...@@ -484,18 +484,6 @@ function formatAppLog(type, filename, ...args) { ...@@ -484,18 +484,6 @@ function formatAppLog(type, filename, ...args) {
res && console[type](res); res && console[type](res);
} }
function getDataByPath(obj, path) {
const parts = path.split('.');
const key = parts[0];
if (!obj) {
obj = {};
}
if (parts.length === 1) {
return obj[key];
}
return getDataByPath(obj[key], parts.slice(1).join('.'));
}
let latestNodeId = 1; let latestNodeId = 1;
class NVueTextNode { class NVueTextNode {
constructor(text) { constructor(text) {
...@@ -1063,6 +1051,10 @@ function callOptions(options, data) { ...@@ -1063,6 +1051,10 @@ function callOptions(options, data) {
} }
} }
function getValueByDataPath(obj, path) { function getValueByDataPath(obj, path) {
if (!shared.isString(path)) {
return;
}
path = path.replace(/\[(\d+)\]/g, '.$1');
const parts = path.split('.'); const parts = path.split('.');
let key = parts[0]; let key = parts[0];
if (!obj) { if (!obj) {
...@@ -1309,7 +1301,6 @@ exports.formatAppLog = formatAppLog; ...@@ -1309,7 +1301,6 @@ exports.formatAppLog = formatAppLog;
exports.formatDateTime = formatDateTime; exports.formatDateTime = formatDateTime;
exports.formatLog = formatLog; exports.formatLog = formatLog;
exports.getCustomDataset = getCustomDataset; exports.getCustomDataset = getCustomDataset;
exports.getDataByPath = getDataByPath;
exports.getEnvLocale = getEnvLocale; exports.getEnvLocale = getEnvLocale;
exports.getLen = getLen; exports.getLen = getLen;
exports.getValueByDataPath = getValueByDataPath; exports.getValueByDataPath = getValueByDataPath;
......
...@@ -193,8 +193,6 @@ export declare function formatLog(module: string, ...args: any[]): string; ...@@ -193,8 +193,6 @@ export declare function formatLog(module: string, ...args: any[]): string;
export declare function getCustomDataset(el: HTMLElement | HTMLElementWithDataset): DOMStringMap & Record<string, any>; export declare function getCustomDataset(el: HTMLElement | HTMLElementWithDataset): DOMStringMap & Record<string, any>;
export declare function getDataByPath(obj: Record<string | number, any>, path: string): unknown;
export declare function getEnvLocale(): string; export declare function getEnvLocale(): string;
export declare function getLen(str?: string): number; export declare function getLen(str?: string): number;
......
...@@ -480,18 +480,6 @@ function formatAppLog(type, filename, ...args) { ...@@ -480,18 +480,6 @@ function formatAppLog(type, filename, ...args) {
res && console[type](res); res && console[type](res);
} }
function getDataByPath(obj, path) {
const parts = path.split('.');
const key = parts[0];
if (!obj) {
obj = {};
}
if (parts.length === 1) {
return obj[key];
}
return getDataByPath(obj[key], parts.slice(1).join('.'));
}
let latestNodeId = 1; let latestNodeId = 1;
class NVueTextNode { class NVueTextNode {
constructor(text) { constructor(text) {
...@@ -1059,6 +1047,10 @@ function callOptions(options, data) { ...@@ -1059,6 +1047,10 @@ function callOptions(options, data) {
} }
} }
function getValueByDataPath(obj, path) { function getValueByDataPath(obj, path) {
if (!isString(path)) {
return;
}
path = path.replace(/\[(\d+)\]/g, '.$1');
const parts = path.split('.'); const parts = path.split('.');
let key = parts[0]; let key = parts[0];
if (!obj) { if (!obj) {
...@@ -1191,4 +1183,4 @@ function getEnvLocale() { ...@@ -1191,4 +1183,4 @@ function getEnvLocale() {
return (lang && lang.replace(/[.:].*/, '')) || 'en'; return (lang && lang.replace(/[.:].*/, '')) || 'en';
} }
export { ACTION_TYPE_ADD_EVENT, ACTION_TYPE_ADD_WXS_EVENT, ACTION_TYPE_CREATE, ACTION_TYPE_EVENT, ACTION_TYPE_INSERT, ACTION_TYPE_PAGE_CREATE, ACTION_TYPE_PAGE_CREATED, ACTION_TYPE_PAGE_SCROLL, ACTION_TYPE_REMOVE, ACTION_TYPE_REMOVE_ATTRIBUTE, ACTION_TYPE_REMOVE_EVENT, ACTION_TYPE_SET_ATTRIBUTE, ACTION_TYPE_SET_TEXT, ATTR_CHANGE_PREFIX, ATTR_CLASS, ATTR_INNER_HTML, ATTR_STYLE, ATTR_TEXT_CONTENT, ATTR_V_OWNER_ID, ATTR_V_RENDERJS, ATTR_V_SHOW, BACKGROUND_COLOR, BUILT_IN_TAGS, COMPONENT_NAME_PREFIX, COMPONENT_PREFIX, COMPONENT_SELECTOR_PREFIX, DATA_RE, EventChannel, EventModifierFlags, I18N_JSON_DELIMITERS, JSON_PROTOCOL, LINEFEED, NAVBAR_HEIGHT, NODE_TYPE_COMMENT, NODE_TYPE_ELEMENT, NODE_TYPE_PAGE, NODE_TYPE_TEXT, NVueTextNode, ON_ADD_TO_FAVORITES, ON_APP_ENTER_BACKGROUND, ON_APP_ENTER_FOREGROUND, ON_BACK_PRESS, ON_ERROR, ON_HIDE, ON_KEYBOARD_HEIGHT_CHANGE, ON_LAUNCH, ON_LOAD, ON_NAVIGATION_BAR_BUTTON_TAP, ON_NAVIGATION_BAR_SEARCH_INPUT_CHANGED, ON_NAVIGATION_BAR_SEARCH_INPUT_CLICKED, ON_NAVIGATION_BAR_SEARCH_INPUT_CONFIRMED, ON_NAVIGATION_BAR_SEARCH_INPUT_FOCUS_CHANGED, ON_PAGE_NOT_FOUND, ON_PAGE_SCROLL, ON_PULL_DOWN_REFRESH, ON_REACH_BOTTOM, ON_REACH_BOTTOM_DISTANCE, ON_READY, ON_RESIZE, ON_SHARE_APP_MESSAGE, ON_SHARE_TIMELINE, ON_SHOW, ON_TAB_ITEM_TAP, ON_THEME_CHANGE, ON_UNHANDLE_REJECTION, ON_UNLOAD, ON_WEB_INVOKE_APP_SERVICE, ON_WXS_INVOKE_CALL_METHOD, PLUS_RE, PRIMARY_COLOR, RENDERJS_MODULES, RESPONSIVE_MIN_WIDTH, SCHEME_RE, SELECTED_COLOR, SLOT_DEFAULT_NAME, TABBAR_HEIGHT, TAGS, UNI_SSR, UNI_SSR_DATA, UNI_SSR_GLOBAL_DATA, UNI_SSR_STORE, UNI_SSR_TITLE, UNI_STORAGE_LOCALE, UniBaseNode, UniCommentNode, UniElement, UniEvent, UniInputElement, UniLifecycleHooks, UniNode, UniTextAreaElement, UniTextNode, WEB_INVOKE_APPSERVICE, WXS_MODULES, WXS_PROTOCOL, addFont, addLeadingSlash, cache, cacheStringFunction, callOptions, createIsCustomElement, createRpx2Unit, createUniEvent, debounce, decode, decodedQuery, defaultMiniProgramRpx2Unit, defaultRpx2Unit, dynamicSlotName, forcePatchProp, formatAppLog, formatDateTime, formatLog, getCustomDataset, getDataByPath, getEnvLocale, getLen, getValueByDataPath, initCustomDataset, invokeArrayFns, isAppNativeTag, isBuiltInComponent, isComponentTag, isH5CustomElement, isH5NativeTag, isMiniProgramNativeTag, isRootHook, normalizeDataset, normalizeEventType, normalizeTarget, once, parseEventName, parseQuery, parseUrl, passive, plusReady, removeLeadingSlash, resolveOwnerEl, resolveOwnerVm, sanitise, scrollTo, stringifyQuery, updateElementStyle }; export { ACTION_TYPE_ADD_EVENT, ACTION_TYPE_ADD_WXS_EVENT, ACTION_TYPE_CREATE, ACTION_TYPE_EVENT, ACTION_TYPE_INSERT, ACTION_TYPE_PAGE_CREATE, ACTION_TYPE_PAGE_CREATED, ACTION_TYPE_PAGE_SCROLL, ACTION_TYPE_REMOVE, ACTION_TYPE_REMOVE_ATTRIBUTE, ACTION_TYPE_REMOVE_EVENT, ACTION_TYPE_SET_ATTRIBUTE, ACTION_TYPE_SET_TEXT, ATTR_CHANGE_PREFIX, ATTR_CLASS, ATTR_INNER_HTML, ATTR_STYLE, ATTR_TEXT_CONTENT, ATTR_V_OWNER_ID, ATTR_V_RENDERJS, ATTR_V_SHOW, BACKGROUND_COLOR, BUILT_IN_TAGS, COMPONENT_NAME_PREFIX, COMPONENT_PREFIX, COMPONENT_SELECTOR_PREFIX, DATA_RE, EventChannel, EventModifierFlags, I18N_JSON_DELIMITERS, JSON_PROTOCOL, LINEFEED, NAVBAR_HEIGHT, NODE_TYPE_COMMENT, NODE_TYPE_ELEMENT, NODE_TYPE_PAGE, NODE_TYPE_TEXT, NVueTextNode, ON_ADD_TO_FAVORITES, ON_APP_ENTER_BACKGROUND, ON_APP_ENTER_FOREGROUND, ON_BACK_PRESS, ON_ERROR, ON_HIDE, ON_KEYBOARD_HEIGHT_CHANGE, ON_LAUNCH, ON_LOAD, ON_NAVIGATION_BAR_BUTTON_TAP, ON_NAVIGATION_BAR_SEARCH_INPUT_CHANGED, ON_NAVIGATION_BAR_SEARCH_INPUT_CLICKED, ON_NAVIGATION_BAR_SEARCH_INPUT_CONFIRMED, ON_NAVIGATION_BAR_SEARCH_INPUT_FOCUS_CHANGED, ON_PAGE_NOT_FOUND, ON_PAGE_SCROLL, ON_PULL_DOWN_REFRESH, ON_REACH_BOTTOM, ON_REACH_BOTTOM_DISTANCE, ON_READY, ON_RESIZE, ON_SHARE_APP_MESSAGE, ON_SHARE_TIMELINE, ON_SHOW, ON_TAB_ITEM_TAP, ON_THEME_CHANGE, ON_UNHANDLE_REJECTION, ON_UNLOAD, ON_WEB_INVOKE_APP_SERVICE, ON_WXS_INVOKE_CALL_METHOD, PLUS_RE, PRIMARY_COLOR, RENDERJS_MODULES, RESPONSIVE_MIN_WIDTH, SCHEME_RE, SELECTED_COLOR, SLOT_DEFAULT_NAME, TABBAR_HEIGHT, TAGS, UNI_SSR, UNI_SSR_DATA, UNI_SSR_GLOBAL_DATA, UNI_SSR_STORE, UNI_SSR_TITLE, UNI_STORAGE_LOCALE, UniBaseNode, UniCommentNode, UniElement, UniEvent, UniInputElement, UniLifecycleHooks, UniNode, UniTextAreaElement, UniTextNode, WEB_INVOKE_APPSERVICE, WXS_MODULES, WXS_PROTOCOL, addFont, addLeadingSlash, cache, cacheStringFunction, callOptions, createIsCustomElement, createRpx2Unit, createUniEvent, debounce, decode, decodedQuery, defaultMiniProgramRpx2Unit, defaultRpx2Unit, dynamicSlotName, forcePatchProp, formatAppLog, formatDateTime, formatLog, getCustomDataset, getEnvLocale, getLen, getValueByDataPath, initCustomDataset, invokeArrayFns, isAppNativeTag, isBuiltInComponent, isComponentTag, isH5CustomElement, isH5NativeTag, isMiniProgramNativeTag, isRootHook, normalizeDataset, normalizeEventType, normalizeTarget, once, parseEventName, parseQuery, parseUrl, passive, plusReady, removeLeadingSlash, resolveOwnerEl, resolveOwnerVm, sanitise, scrollTo, stringifyQuery, updateElementStyle };
export function getDataByPath(
obj: Record<string | number, any>,
path: string
): unknown {
const parts = path.split('.')
const key: number | string = parts[0]
if (!obj) {
obj = {}
}
if (parts.length === 1) {
return obj[key]
}
return getDataByPath(obj[key], parts.slice(1).join('.'))
}
...@@ -3,7 +3,6 @@ export * from './log' ...@@ -3,7 +3,6 @@ export * from './log'
export * from './dom' export * from './dom'
export * from './url' export * from './url'
export * from './hbx' export * from './hbx'
export * from './data'
export * from './nvue' export * from './nvue'
export * from './plus' export * from './plus'
export * from './tags' export * from './tags'
......
import { isString } from '@vue/shared'
export function cache<T>(fn: (str: string) => T) { export function cache<T>(fn: (str: string) => T) {
const cache: Record<string, T> = Object.create(null) const cache: Record<string, T> = Object.create(null)
return (str: string) => { return (str: string) => {
...@@ -113,6 +115,10 @@ export function callOptions( ...@@ -113,6 +115,10 @@ export function callOptions(
} }
export function getValueByDataPath(obj: any, path: string): unknown { export function getValueByDataPath(obj: any, path: string): unknown {
if (!isString(path)) {
return
}
path = path.replace(/\[(\d+)\]/g, '.$1')
const parts = path.split('.') const parts = path.split('.')
let key: number | string = parts[0] let key: number | string = parts[0]
if (!obj) { if (!obj) {
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册