提交 4595542f 编写于 作者: Q qiang

Merge branch 'dev' into alpha

......@@ -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
}
......
......@@ -31,11 +31,11 @@ describe('mp:compiler-mp-alipay', () => {
it('generate ref', () => {
assertCodegen(
'<component1 ref="c1">text</component1>',
'<component1 vue-id="551070e6-1" ref="__r" data-ref="c1" onVueInit="__l">text</component1>'
'<component1 vue-id="551070e6-1" ref="__r" data-ref="c1" onVueInit="__l" vue-slots="{{[\'default\']}}">text</component1>'
)
assertCodegen(
'<component1 :ref="c2">text<text>123213</text></component1>',
'<component1 vue-id="551070e6-1" ref="__r" data-ref="{{c2}}" onVueInit="__l">text<text>123213</text></component1>'
'<component1 vue-id="551070e6-1" ref="__r" data-ref="{{c2}}" onVueInit="__l" vue-slots="{{[\'default\']}}">text<text>123213</text></component1>'
)
assertCodegen(
'<component1 v-for="item in items" ref="c3"></component1>',
......@@ -47,7 +47,7 @@ describe('mp:compiler-mp-alipay', () => {
)
assertCodegen(
'<component1>text</component1>',
'<component1 vue-id="551070e6-1" data-com-type="wx" ref="__r" onVueInit="__l">text</component1>',
'<component1 vue-id="551070e6-1" data-com-type="wx" ref="__r" onVueInit="__l" vue-slots="{{[\'default\']}}">text</component1>',
undefined,
undefined,
{
......@@ -56,7 +56,7 @@ describe('mp:compiler-mp-alipay', () => {
)
assertCodegen(
'<component1 @change="onChange" @cancle="onCancle">text</component1>',
'<component1 onChange="__e" onCancle="__e" vue-id="551070e6-1" data-event-opts="{{[[\'^change\',[[\'onChange\']]],[\'^cancle\',[[\'onCancle\']]]]}}" data-com-type="wx" ref="__r" data-event-list="onChange,onCancle" onVueInit="__l">text</component1>',
'<component1 onChange="__e" onCancle="__e" vue-id="551070e6-1" data-event-opts="{{[[\'^change\',[[\'onChange\']]],[\'^cancle\',[[\'onCancle\']]]]}}" data-com-type="wx" ref="__r" data-event-list="onChange,onCancle" onVueInit="__l" vue-slots="{{[\'default\']}}">text</component1>',
undefined,
undefined,
{
......@@ -65,7 +65,7 @@ describe('mp:compiler-mp-alipay', () => {
)
assertCodegen(
'<credit-pay @change="onChange" @cancle="onCancle">text</credit-pay>',
'<plugin-wrapper onChange="__e" onCancle="__e" vue-id="551070e6-1" onPluginWrap="__w" data-event-opts="{{[[\'^change\',[[\'onChange\']]],[\'^cancle\',[[\'onCancle\']]]]}}" data-com-type="wx" data-event-list="onChange,onCancle" onVueInit="__l"><credit-pay onChange="{{\'onChange\'+\'551070e6-1\'}}" onCancle="{{\'onCancle\'+\'551070e6-1\'}}" onVueInit="__l">text</credit-pay></plugin-wrapper>',
'<plugin-wrapper onChange="__e" onCancle="__e" vue-id="551070e6-1" onPluginWrap="__w" data-event-opts="{{[[\'^change\',[[\'onChange\']]],[\'^cancle\',[[\'onCancle\']]]]}}" data-com-type="wx" data-event-list="onChange,onCancle" onVueInit="__l" vue-slots="{{[\'default\']}}"><credit-pay onChange="{{\'onChange\'+\'551070e6-1\'}}" onCancle="{{\'onCancle\'+\'551070e6-1\'}}" onVueInit="__l" vue-slots="{{[\'default\']}}">text</credit-pay></plugin-wrapper>',
undefined,
undefined,
{
......@@ -82,33 +82,33 @@ describe('mp:compiler-mp-alipay', () => {
it('generate default slot', () => {
assertCodegen(
'<component1>text</component1>',
'<component1 vue-id="551070e6-1" onVueInit="__l">text</component1>'
'<component1 vue-id="551070e6-1" onVueInit="__l" vue-slots="{{[\'default\']}}">text</component1>'
)
assertCodegen(
'<component1>text<text>123213</text></component1>',
'<component1 vue-id="551070e6-1" onVueInit="__l">text<text>123213</text></component1>'
'<component1 vue-id="551070e6-1" onVueInit="__l" vue-slots="{{[\'default\']}}">text<text>123213</text></component1>'
)
assertCodegen(
'<component1>text<block slot="right"></block></component1>',
'<component1 vue-id="551070e6-1" onVueInit="__l">text<view slot="right"></view></component1>'
'<component1 vue-id="551070e6-1" onVueInit="__l" vue-slots="{{[\'default\',\'right\']}}">text<view slot="right"></view></component1>'
)
})
it('generate scoped slot', () => {
assertCodegen(
'<component1 :text="\'text\'"><template v-slot="props"><view :class="{text:props.text}">{{props.text}}</view></template></component1>',
'<component1 vue-id="551070e6-1" text="text" onVueInit="__l"><view slot-scope="props"><view class="{{((props.text)?\'text\':\'\')}}">{{props.text}}</view></view></component1>'
'<component1 vue-id="551070e6-1" text="text" onVueInit="__l" vue-slots="{{[\'default\']}}"><view slot-scope="props"><view class="{{((props.text)?\'text\':\'\')}}">{{props.text}}</view></view></component1>'
)
assertCodegen(
'<component1 :text="\'text\'"><template v-slot="{text}"><view :class="{text:text}">{{text}}</view></template></component1>',
'<component1 vue-id="551070e6-1" text="text" onVueInit="__l"><view slot-scope="__SCOPED__"><view class="{{((__SCOPED__.text)?\'text\':\'\')}}">{{__SCOPED__.text}}</view></view></component1>'
'<component1 vue-id="551070e6-1" text="text" onVueInit="__l" vue-slots="{{[\'default\']}}"><view slot-scope="__SCOPED__"><view class="{{((__SCOPED__.text)?\'text\':\'\')}}">{{__SCOPED__.text}}</view></view></component1>'
)
})
it('generate scoped slot with scopedSlotsCompiler: auto', () => {
assertCodegen(
'<my-component><template v-slot="{item}">{{item}}<template></my-component>',
'<my-component vue-id="551070e6-1" onVueInit="__l"><view slot-scope="__SCOPED__">{{__SCOPED__.item}}</view></my-component>',
'<my-component vue-id="551070e6-1" onVueInit="__l" vue-slots="{{[\'default\']}}"><view slot-scope="__SCOPED__">{{__SCOPED__.item}}</view></my-component>',
'with(this){}',
{
scopedSlotsCompiler: 'auto'
......@@ -116,7 +116,7 @@ describe('mp:compiler-mp-alipay', () => {
)
assertCodegen(
'<my-component><template v-slot="{item}">{{getValue(item)}}<template></my-component>',
'<my-component scoped-slots-compiler="augmented" vue-id="551070e6-1" onVueInit="__l"><block a:if="{{$root.m0}}">{{$root.m1}}</block></my-component>',
'<my-component scoped-slots-compiler="augmented" vue-id="551070e6-1" onVueInit="__l" vue-slots="{{[\'default\']}}"><block a:if="{{$root.m0}}">{{$root.m1}}</block></my-component>',
'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(
'<my-component><template v-slot="item">{{getValue(item.text)}}<template></my-component>',
'<my-component scoped-slots-compiler="augmented" vue-id="551070e6-1" onVueInit="__l"><block a:if="{{$root.m0}}">{{$root.m1}}</block></my-component>',
'<my-component scoped-slots-compiler="augmented" vue-id="551070e6-1" onVueInit="__l" vue-slots="{{[\'default\']}}"><block a:if="{{$root.m0}}">{{$root.m1}}</block></my-component>',
'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(
'<custom-view>hello world</custom-view>',
'<custom-view vue-id="551070e6-1" onVueInit="__l" virtualHostStyle="{{virtualHostStyle}}" virtualHostClass="{{(virtualHostClass)}}">hello world</custom-view>',
'<custom-view vue-id="551070e6-1" onVueInit="__l" virtualHostStyle="{{virtualHostStyle}}" virtualHostClass="{{(virtualHostClass)}}" vue-slots="{{[\'default\']}}">hello world</custom-view>',
'with(this){}',
{
mergeVirtualHostAttributes: true
......@@ -215,7 +215,7 @@ describe('mp:compiler-mp-alipay', () => {
)
assertCodegen(
'<custom-view :class="class1" :style="style">hello world</custom-view>',
'<custom-view vue-id="551070e6-1" onVueInit="__l" virtualHostStyle="{{(style)+virtualHostStyle}}" virtualHostClass="{{((class1)+\' \'+virtualHostClass)}}">hello world</custom-view>',
'<custom-view vue-id="551070e6-1" onVueInit="__l" virtualHostStyle="{{(style)+virtualHostStyle}}" virtualHostClass="{{((class1)+\' \'+virtualHostClass)}}" vue-slots="{{[\'default\']}}">hello world</custom-view>',
'with(this){}',
{
mergeVirtualHostAttributes: true
......@@ -223,7 +223,7 @@ describe('mp:compiler-mp-alipay', () => {
)
assertCodegen(
'<view><custom-view>hello world</custom-view></view>',
'<view class="{{(virtualHostClass)}}" style="{{virtualHostStyle}}"><custom-view vue-id="551070e6-1" onVueInit="__l">hello world</custom-view></view>',
'<view class="{{(virtualHostClass)}}" style="{{virtualHostStyle}}"><custom-view vue-id="551070e6-1" onVueInit="__l" vue-slots="{{[\'default\']}}">hello world</custom-view></view>',
'with(this){}',
{
mergeVirtualHostAttributes: true
......@@ -231,7 +231,7 @@ describe('mp:compiler-mp-alipay', () => {
)
assertCodegen(
'<view><custom-view :class="class1" :style="style">hello world</custom-view></view>',
'<view class="{{(virtualHostClass)}}" style="{{virtualHostStyle}}"><custom-view vue-id="551070e6-1" onVueInit="__l" virtualHostStyle="{{(style)}}" virtualHostClass="{{(class1)}}">hello world</custom-view></view>',
'<view class="{{(virtualHostClass)}}" style="{{virtualHostStyle}}"><custom-view vue-id="551070e6-1" onVueInit="__l" virtualHostStyle="{{(style)}}" virtualHostClass="{{(class1)}}" vue-slots="{{[\'default\']}}">hello world</custom-view></view>',
'with(this){}',
{
mergeVirtualHostAttributes: true
......
......@@ -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 作为命名插槽根节点
* 此处为了统一仅忽略默认插槽
* <block slot="left"></block> => <view slot="left"></view>
*/
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 作为命名插槽根节点
* 此处为了统一仅忽略默认插槽
* <block slot="left"></block> => <view slot="left"></view>
*/
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 }))
}
......
......@@ -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) => {
......
......@@ -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 = {
......
......@@ -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) {
......
......@@ -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 => {
......
......@@ -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]) {
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册