diff --git a/packages/uni-cli-shared/lib/preprocess.js b/packages/uni-cli-shared/lib/preprocess.js
index 46faf009a8db104ab62c8b68457f36db7956fce3..861cd65b7e3bc19c3899be92eb0c8975d849be22 100644
--- a/packages/uni-cli-shared/lib/preprocess.js
+++ b/packages/uni-cli-shared/lib/preprocess.js
@@ -5,7 +5,10 @@ const DEFAULT_KEYS = [
'APP',
'APP-PLUS-NVUE',
'APP-VUE',
- 'APP-NVUE'
+ 'APP-NVUE',
+ 'APP-ANDROID',
+ 'APP-IOS',
+ 'WEB'
]
function normalize (name) {
@@ -44,14 +47,25 @@ module.exports = function initPreprocess (name, platforms, userDefines = {}) {
nvueContext.APP_PLUS = true
nvueContext.APP_NVUE = true
nvueContext.APP_PLUS_NVUE = true
- }
+ if (process.env.UNI_APP_PLATFORM === 'android') {
+ defaultContext.APP_ANDROID = true
+ } else if (process.env.UNI_APP_PLATFORM === 'ios') {
+ defaultContext.APP_IOS = true
+ } else {
+ defaultContext.APP_ANDROID = true
+ defaultContext.APP_IOS = true
+ }
+ }
+ if (name === 'h5') {
+ defaultContext.WEB = true
+ }
if (name.startsWith('mp-')) {
vueContext.MP = true
}
if (name.startsWith('app-')) {
- vueContext.APP = true
+ vueContext.APP = true
nvueContext.APP = true
}
diff --git a/packages/uni-template-compiler/__tests__/compiler-mp-alipay.spec.js b/packages/uni-template-compiler/__tests__/compiler-mp-alipay.spec.js
index 14c71afe5709b0240c209b9bdfdc88bc0c2e2102..8d16912de32c6bb61b45c41ab04c86734c5c36d6 100644
--- a/packages/uni-template-compiler/__tests__/compiler-mp-alipay.spec.js
+++ b/packages/uni-template-compiler/__tests__/compiler-mp-alipay.spec.js
@@ -31,11 +31,11 @@ describe('mp:compiler-mp-alipay', () => {
it('generate ref', () => {
assertCodegen(
'text',
- 'text'
+ 'text'
)
assertCodegen(
'text123213',
- 'text123213'
+ 'text123213'
)
assertCodegen(
'',
@@ -47,7 +47,7 @@ describe('mp:compiler-mp-alipay', () => {
)
assertCodegen(
'text',
- 'text',
+ 'text',
undefined,
undefined,
{
@@ -56,7 +56,7 @@ describe('mp:compiler-mp-alipay', () => {
)
assertCodegen(
'text',
- 'text',
+ 'text',
undefined,
undefined,
{
@@ -65,7 +65,7 @@ describe('mp:compiler-mp-alipay', () => {
)
assertCodegen(
'text',
- 'text',
+ 'text',
undefined,
undefined,
{
@@ -82,33 +82,33 @@ describe('mp:compiler-mp-alipay', () => {
it('generate default slot', () => {
assertCodegen(
'text',
- 'text'
+ 'text'
)
assertCodegen(
'text123213',
- 'text123213'
+ 'text123213'
)
assertCodegen(
'text',
- 'text'
+ 'text'
)
})
it('generate scoped slot', () => {
assertCodegen(
'{{props.text}}',
- '{{props.text}}'
+ '{{props.text}}'
)
assertCodegen(
'{{text}}',
- '{{__SCOPED__.text}}'
+ '{{__SCOPED__.text}}'
)
})
it('generate scoped slot with scopedSlotsCompiler: auto', () => {
assertCodegen(
'{{item}}',
- '{{__SCOPED__.item}}',
+ '{{__SCOPED__.item}}',
'with(this){}',
{
scopedSlotsCompiler: 'auto'
@@ -116,7 +116,7 @@ describe('mp:compiler-mp-alipay', () => {
)
assertCodegen(
'{{getValue(item)}}',
- '{{$root.m1}}',
+ '{{$root.m1}}',
'with(this){var m0=$hasScopedSlotsParams("551070e6-1");var m1=m0?getValue($getScopedSlotsParams("551070e6-1","default","item")):null;$mp.data=Object.assign({},{$root:{m0:m0,m1:m1}})}',
{
scopedSlotsCompiler: 'auto'
@@ -124,7 +124,7 @@ describe('mp:compiler-mp-alipay', () => {
)
assertCodegen(
'{{getValue(item.text)}}',
- '{{$root.m1}}',
+ '{{$root.m1}}',
'with(this){var m0=$hasScopedSlotsParams("551070e6-1");var m1=m0?getValue($getScopedSlotsParams("551070e6-1","default").text):null;$mp.data=Object.assign({},{$root:{m0:m0,m1:m1}})}',
{
scopedSlotsCompiler: 'auto'
@@ -207,7 +207,7 @@ describe('mp:compiler-mp-alipay', () => {
it('generate attrs with mergeVirtualHostAttributes', () => {
assertCodegen(
'hello world',
- 'hello world',
+ 'hello world',
'with(this){}',
{
mergeVirtualHostAttributes: true
@@ -215,7 +215,7 @@ describe('mp:compiler-mp-alipay', () => {
)
assertCodegen(
'hello world',
- 'hello world',
+ 'hello world',
'with(this){}',
{
mergeVirtualHostAttributes: true
@@ -223,7 +223,7 @@ describe('mp:compiler-mp-alipay', () => {
)
assertCodegen(
'hello world',
- 'hello world',
+ 'hello world',
'with(this){}',
{
mergeVirtualHostAttributes: true
@@ -231,7 +231,7 @@ describe('mp:compiler-mp-alipay', () => {
)
assertCodegen(
'hello world',
- 'hello world',
+ 'hello world',
'with(this){}',
{
mergeVirtualHostAttributes: true
diff --git a/packages/uni-template-compiler/lib/template/generate.js b/packages/uni-template-compiler/lib/template/generate.js
index b2f320d4e3651849d5b4fbb5bf0a65ab71da8404..a2b4071cc575855ea111b28ee47d83dff95acd69 100644
--- a/packages/uni-template-compiler/lib/template/generate.js
+++ b/packages/uni-template-compiler/lib/template/generate.js
@@ -46,61 +46,64 @@ function processElement (ast, state, isRoot) {
} else if (platformName !== 'mp-baidu') {
ast.attr['bind:' + INTERNAL_EVENT_LINK] = INTERNAL_EVENT_LINK
}
-
- if (mergeVirtualHostAttributes && platform.isComponent(ast.type)) {
- const obj = {
- style: VIRTUAL_HOST_STYLE,
- class: VIRTUAL_HOST_CLASS
- }
- Object.keys(obj).forEach(key => {
- if (key in ast.attr) {
- ast.attr[obj[key]] = ast.attr[key]
+ // TODO 过滤小程序原生组件
+ {
+ // 处理自定义组件虚拟节点样式
+ if (mergeVirtualHostAttributes) {
+ const obj = {
+ style: VIRTUAL_HOST_STYLE,
+ class: VIRTUAL_HOST_CLASS
}
- // 支付宝小程序自定义组件外部属性始终无效
- if (platformName === 'mp-alipay') {
- delete ast.attr[key]
+ Object.keys(obj).forEach(key => {
+ if (key in ast.attr) {
+ ast.attr[obj[key]] = ast.attr[key]
+ }
+ // 支付宝小程序自定义组件外部属性始终无效
+ if (platformName === 'mp-alipay') {
+ delete ast.attr[key]
+ }
+ })
+ }
+ // 标记自定义组件插槽
+ const children = ast.children
+ // default slot
+ let defaultSlot = false
+ const slots = []
+ for (let i = children.length - 1; i >= 0; i--) {
+ const childElement = children[i]
+ /**
+ * 仅百度、字节支持使用 block 作为命名插槽根节点
+ * 此处为了统一仅忽略默认插槽
+ * =>
+ */
+ if (typeof childElement !== 'string' && childElement.attr.slot) {
+ const slot = childElement.attr.slot
+ if (slot && slot !== 'default' && childElement.type === 'block') {
+ childElement.type = 'view'
+ }
+ slots.push(slot)
+ } else {
+ defaultSlot = true
}
- })
- }
-
- const children = ast.children
- // default slot
- let defaultSlot = false
- const slots = []
- for (let i = children.length - 1; i >= 0; i--) {
- const childElement = children[i]
- /**
- * 仅百度、字节支持使用 block 作为命名插槽根节点
- * 此处为了统一仅忽略默认插槽
- * =>
- */
- if (typeof childElement !== 'string' && childElement.attr.slot) {
- const slot = childElement.attr.slot
- if (slot && slot !== 'default' && childElement.type === 'block') {
- childElement.type = 'view'
+ }
+ if (defaultSlot) {
+ slots.push('default')
+ }
+ if (ast.attr.generic) {
+ Object.keys(ast.attr.generic).forEach(scopedSlotName => {
+ slots.push(scopedSlotName)
+ })
+ if (platformName === 'mp-toutiao' || platformName === 'mp-lark') {
+ // 用于字节跳动|飞书小程序模拟抽象节点
+ ast.attr.generic = `{{${JSON.stringify(ast.attr.generic)}}}`.replace(/"/g, '\'')
+ } else {
+ delete ast.attr.generic
}
- slots.push(slot)
- } else {
- defaultSlot = true
}
- }
- if (defaultSlot) {
- slots.push('default')
- }
- if (ast.attr.generic) {
- Object.keys(ast.attr.generic).forEach(scopedSlotName => {
- slots.push(scopedSlotName)
- })
- if (platformName === 'mp-toutiao' || platformName === 'mp-lark') {
- // 用于字节跳动|飞书小程序模拟抽象节点
- ast.attr.generic = `{{${JSON.stringify(ast.attr.generic)}}}`.replace(/"/g, '\'')
- } else {
- delete ast.attr.generic
+ if (slots.length) { // 标记 slots
+ ast.attr['vue-slots'] = '{{[' + slots.reverse().map(slotName => `'${slotName}'`).join(',') + ']}}'
}
}
- if (slots.length && platformName !== 'mp-alipay') { // 标记 slots
- ast.attr['vue-slots'] = '{{[' + slots.reverse().map(slotName => `'${slotName}'`).join(',') + ']}}'
- }
if (ast.attr.id && ast.attr.id.indexOf('{{') === 0) {
state.tips.add(uniI18n.__('templateCompiler.idAttribNotAllowInCustomComponentProps', { 0: ast.type }))
}
diff --git a/src/platforms/mp-alipay/runtime/wrapper/app-parser.js b/src/platforms/mp-alipay/runtime/wrapper/app-parser.js
index db1dc35db11b95d69cb2f917fb283623b3503182..56bfb3984eee324fc0d7f682b70f7fa029ee92e0 100644
--- a/src/platforms/mp-alipay/runtime/wrapper/app-parser.js
+++ b/src/platforms/mp-alipay/runtime/wrapper/app-parser.js
@@ -8,23 +8,6 @@ import {
} from './util'
export default function parseApp (vm) {
- Object.defineProperty(Vue.prototype, '$slots', {
- get () {
- return this.$scope && this.$scope.props.$slots
- },
- set () {
-
- }
- })
- Object.defineProperty(Vue.prototype, '$scopedSlots', {
- get () {
- return this.$scope && this.$scope.props.$scopedSlots
- },
- set () {
-
- }
- })
-
Vue.prototype.$onAliGetAuthorize = function onAliGetAuthorize (method, $event) {
my.getPhoneNumber({
success: (res) => {
diff --git a/src/platforms/mp-alipay/runtime/wrapper/component-parser.js b/src/platforms/mp-alipay/runtime/wrapper/component-parser.js
index 5dc4c94cf2be066c55a47a34e7cbacf02e95d0dc..9cc232f0bd9166f5441309fb218b7170eff65a56 100644
--- a/src/platforms/mp-alipay/runtime/wrapper/component-parser.js
+++ b/src/platforms/mp-alipay/runtime/wrapper/component-parser.js
@@ -22,6 +22,29 @@ import {
initSpecialMethods
} from './util'
+function initSlots (vm, vueSlots) {
+ const $slots = Object.create(null)
+ // 未启用小程序基础库 2.0 时,组件实例支持支持访问 $slots、$scopedSlots
+ Object.defineProperty(vm, '$slots', {
+ get () {
+ const $scope = this.$scope
+ return ($scope && $scope.props.$slots) || ($scope && $scope.props.$scopedSlots ? {} : $slots)
+ }
+ })
+ Object.defineProperty(vm, '$scopedSlots', {
+ get () {
+ const $scope = this.$scope
+ return ($scope && $scope.props.$scopedSlots) || ($scope && $scope.props.$slots ? {} : $slots)
+ }
+ })
+ // 处理$slots,$scopedSlots(暂不支持动态变化$slots)
+ if (Array.isArray(vueSlots) && vueSlots.length) {
+ vueSlots.forEach(slotName => {
+ $slots[slotName] = true
+ })
+ }
+}
+
function initVm (VueComponent) {
if (this.$vm) {
return
@@ -46,6 +69,8 @@ function initVm (VueComponent) {
// 初始化 vue 实例
this.$vm = new VueComponent(options)
+ initSlots(this.$vm, properties.vueSlots)
+
// 触发首次 setData
this.$vm.$mount()
} else {
@@ -61,6 +86,9 @@ function initVm (VueComponent) {
// 初始化 vue 实例
this.$vm = new VueComponent(options)
handleRef.call(options.parent.$scope, this)
+
+ initSlots(this.$vm, properties.vueSlots)
+
// 触发首次 setData
this.$vm.$mount()
@@ -83,9 +111,7 @@ export default function parseComponent (vueComponentOptions) {
}
Object.keys(properties).forEach(key => {
- if (key !== 'vueSlots') {
- props[key] = properties[key].value
- }
+ props[key] = properties[key].value
})
const componentOptions = {
diff --git a/src/platforms/mp-toutiao/runtime/wrapper/component-parser.js b/src/platforms/mp-toutiao/runtime/wrapper/component-parser.js
index 8585edfdb082f66f8261709abb52262414e9d4aa..be28d0313c4a1bd90f0080bc117656caad8a4bd8 100644
--- a/src/platforms/mp-toutiao/runtime/wrapper/component-parser.js
+++ b/src/platforms/mp-toutiao/runtime/wrapper/component-parser.js
@@ -69,7 +69,11 @@ export default function parseComponent (vueOptions) {
})
}
+ const oldDetached = lifetimes.detached
lifetimes.detached = function detached () {
+ if (typeof oldDetached === 'function') {
+ oldDetached.call(this)
+ }
currentComponents(this, components => {
const index = components.indexOf(this)
if (index >= 0) {
diff --git a/src/platforms/mp-toutiao/runtime/wrapper/page-parser.js b/src/platforms/mp-toutiao/runtime/wrapper/page-parser.js
index fb2a37b615736ecc126f2dd9daacc254787b235e..4776891a4cb033286997ed247d77e4f96069e7d0 100644
--- a/src/platforms/mp-toutiao/runtime/wrapper/page-parser.js
+++ b/src/platforms/mp-toutiao/runtime/wrapper/page-parser.js
@@ -38,7 +38,6 @@ export default function parsePage (vuePageOptions) {
if (typeof oldDetached === 'function') {
oldDetached.call(this)
}
- this.$vm && this.$vm.$destroy()
// 清理
const webviewId = this.__webviewId__
webviewId && Object.keys(instances).forEach(key => {
diff --git a/src/platforms/mp-toutiao/runtime/wrapper/util.js b/src/platforms/mp-toutiao/runtime/wrapper/util.js
index 3682738eb886237e3d0995771f43a73ae65b7741..44aadf0c4227c8747508e1fc689b9e82ade0e31c 100644
--- a/src/platforms/mp-toutiao/runtime/wrapper/util.js
+++ b/src/platforms/mp-toutiao/runtime/wrapper/util.js
@@ -16,12 +16,13 @@ export function initRefs (vm) {
Object.defineProperty(vm, '$refs', {
get () {
const $refs = {}
- const components = mpInstance.selectAllComponents('.vue-ref')
+ // mpInstance 销毁后 selectAllComponents 取值为 null
+ const components = mpInstance.selectAllComponents('.vue-ref') || []
components.forEach(component => {
const ref = component.dataset.ref
$refs[ref] = component.$vm || component
})
- const forComponents = mpInstance.selectAllComponents('.vue-ref-in-for')
+ const forComponents = mpInstance.selectAllComponents('.vue-ref-in-for') || []
forComponents.forEach(component => {
const ref = component.dataset.ref
if (!$refs[ref]) {