From ea808591d8492f834f5a6dfce0fae7fba2383770 Mon Sep 17 00:00:00 2001 From: qiang Date: Wed, 15 Jun 2022 23:36:33 +0800 Subject: [PATCH] wip: virtualHost style --- .../uni-template-compiler/lib/constants.js | 2 + .../lib/script/traverse/data/class.js | 62 +++++++++++-------- .../lib/script/traverse/data/style.js | 33 +++++++--- .../lib/script/traverse/data/util.js | 21 ++++--- .../lib/template/generate.js | 23 ++++++- src/core/runtime/wrapper/util.js | 24 +++++-- .../runtime/wrapper/component-base-parser.js | 2 +- 7 files changed, 115 insertions(+), 52 deletions(-) diff --git a/packages/uni-template-compiler/lib/constants.js b/packages/uni-template-compiler/lib/constants.js index 8d35520f7..c7f832b4c 100644 --- a/packages/uni-template-compiler/lib/constants.js +++ b/packages/uni-template-compiler/lib/constants.js @@ -66,6 +66,8 @@ module.exports = { ATTR_DATA_EVENT_PARAMS: 'data-event-params', ATTR_DATA_EVENT_LIST: 'data-event-list', ATTE_DATA_CUSTOM_HIDDEN: 'data-custom-hidden', + VIRTUAL_HOST_STYLE: 'virtualHostStyle', + VIRTUAL_HOST_CLASS: 'virtualHostClass', INTERNAL_GET_ORIG, INTERNAL_GET_CLASS, INTERNAL_GET_STYLE, diff --git a/packages/uni-template-compiler/lib/script/traverse/data/class.js b/packages/uni-template-compiler/lib/script/traverse/data/class.js index 264070265..572d6b0e2 100644 --- a/packages/uni-template-compiler/lib/script/traverse/data/class.js +++ b/packages/uni-template-compiler/lib/script/traverse/data/class.js @@ -1,10 +1,18 @@ const t = require('@babel/types') const uniI18n = require('@dcloudio/uni-cli-i18n') +const { + VIRTUAL_HOST_CLASS +} = require('../../../constants') + const { getCode } = require('../../../util') +const { + isRootElement +} = require('./util') + function processClassArrayExpressionElements (classArrayExpression) { let binaryExpression @@ -76,45 +84,30 @@ function processClassArrayExpression (classValuePath) { module.exports = function processClass (paths, path, state) { const classPath = paths.class const staticClassPath = paths.staticClass + const platformName = state.options.platform.name + const virtualHost = platformName === 'mp-weixin' || platformName === 'mp-alipay' + let classArrayExpression if (classPath) { const classValuePath = classPath.get('value') if (classValuePath.isObjectExpression()) { // object - classValuePath.replaceWith( - processStaticClass( - processClassObjectExpression(classValuePath), - staticClassPath, - state - ) - ) + classArrayExpression = processClassObjectExpression(classValuePath) } else if (classValuePath.isArrayExpression()) { // array - classValuePath.replaceWith( - processStaticClass( - processClassArrayExpression(classValuePath), - staticClassPath, - state - ) - ) + classArrayExpression = processClassArrayExpression(classValuePath) } else if ( classValuePath.isStringLiteral() || // :class="'a'" - classValuePath.isIdentifier() || // TODO 需要优化到下一个条件,:class="classObject" - classValuePath.isMemberExpression() || // 需要优化到下一个条件,:class="item.classObject" - classValuePath.isConditionalExpression() || - classValuePath.isLogicalExpression() || - classValuePath.isBinaryExpression() + classValuePath.isIdentifier() || // TODO 需要优化到下一个条件,:class="classObject" + classValuePath.isMemberExpression() || // 需要优化到下一个条件,:class="item.classObject" + classValuePath.isConditionalExpression() || + classValuePath.isLogicalExpression() || + classValuePath.isBinaryExpression() ) { // 理论上 ConditionalExpression,LogicalExpression 可能存在 classObject,应该__get_class,还是先不考虑这种情况吧 // ConditionalExpression :class="index === currentIndex ? activeStyle : itemStyle" // BinaryExpression :class="'m-content-head-'+message.user" - classValuePath.replaceWith( - processStaticClass( - t.arrayExpression([classValuePath.node]), - staticClassPath, - state - ) - ) + classArrayExpression = t.arrayExpression([classValuePath.node]) } else if ( classValuePath.isIdentifier() || - classValuePath.isMemberExpression() + classValuePath.isMemberExpression() ) { // classObject :class="classObject" :class="vm.classObject" // TODO 目前先不考虑 classObject,styleObject @@ -135,5 +128,20 @@ module.exports = function processClass (paths, path, state) { state.errors.add(':class' + uniI18n.__('templateCompiler.noSupportSyntax', { 0: getCode(classValuePath.node) })) } } + if (virtualHost && isRootElement(path.parentPath)) { + const virtualHostClass = t.identifier(VIRTUAL_HOST_CLASS) + if (classArrayExpression) { + classArrayExpression.elements.push(virtualHostClass) + } else { + classArrayExpression = t.arrayExpression([virtualHostClass]) + const property = t.objectProperty(t.identifier('class'), processStaticClass(classArrayExpression, staticClassPath, state)) + path.node.properties.push(property) + return [] + } + } + if (classArrayExpression) { + const classValuePath = classPath.get('value') + classValuePath.replaceWith(processStaticClass(classArrayExpression, staticClassPath, state)) + } return [] } diff --git a/packages/uni-template-compiler/lib/script/traverse/data/style.js b/packages/uni-template-compiler/lib/script/traverse/data/style.js index 923a988d5..0ea6d8977 100644 --- a/packages/uni-template-compiler/lib/script/traverse/data/style.js +++ b/packages/uni-template-compiler/lib/script/traverse/data/style.js @@ -2,7 +2,8 @@ const t = require('@babel/types') const { IDENTIFIER_STYLE, - INTERNAL_GET_STYLE + INTERNAL_GET_STYLE, + VIRTUAL_HOST_STYLE } = require('../../../constants') const { @@ -10,6 +11,10 @@ const { hyphenate } = require('../../../util') +const { + isRootElement +} = require('./util') + const getMemberExpr = require('../member-expr') const REGEX_PX = /(:|\s|\(|\/)[+-]?\d+(\.\d+)?u?px/g @@ -120,6 +125,8 @@ function generateGetStyle (stylePath, styleValuePath, staticStylePath, state) { module.exports = function processStyle (paths, path, state) { const stylePath = paths.style const staticStylePath = paths.staticStyle + const platformName = state.options.platform.name + const virtualHost = platformName === 'mp-weixin' || platformName === 'mp-alipay' if (stylePath) { const styleValuePath = stylePath.get('value') if (styleValuePath.isObjectExpression()) { @@ -146,11 +153,11 @@ module.exports = function processStyle (paths, path, state) { } } else if ( styleValuePath.isStringLiteral() || // :style="'background:red'" - styleValuePath.isIdentifier() || // TODO 需要优化到下一个条件,:style="styleObject" - styleValuePath.isMemberExpression() || // TODO 需要优化到下一个条件,:style="item.styleObject" - styleValuePath.isConditionalExpression() || - styleValuePath.isLogicalExpression() || - styleValuePath.isBinaryExpression() + styleValuePath.isIdentifier() || // TODO 需要优化到下一个条件,:style="styleObject" + styleValuePath.isMemberExpression() || // TODO 需要优化到下一个条件,:style="item.styleObject" + styleValuePath.isConditionalExpression() || + styleValuePath.isLogicalExpression() || + styleValuePath.isBinaryExpression() ) { // 理论上 ConditionalExpression,LogicalExpression 可能存在 styleObject,应该__get_style,还是先不考虑这种情况吧 // ConditionalExpression :style="index === currentIndex ? activeStyle : itemStyle" @@ -164,14 +171,24 @@ module.exports = function processStyle (paths, path, state) { ) } else if ( styleValuePath.isIdentifier() || - styleValuePath.isMemberExpression() + styleValuePath.isMemberExpression() ) { // TODO 目前先不考虑 classObject,styleObject // generateGetStyle(stylePath, styleValuePath, staticStylePath, state) } else { state.errors.add(`:style 不支持 ${getCode(styleValuePath.node)} 语法`) } + if (virtualHost && isRootElement(path.parentPath)) { + styleValuePath.replaceWith(t.binaryExpression('+', styleValuePath.node, t.identifier(VIRTUAL_HOST_STYLE))) + } } else if (staticStylePath) { + if (virtualHost && isRootElement(path.parentPath)) { + const styleNode = processStaticStyle([t.identifier(VIRTUAL_HOST_STYLE)], staticStylePath, state) + + const property = t.objectProperty(t.identifier('style'), styleNode) + path.node.properties.push(property) + return [] + } staticStylePath.get('value').replaceWith(getStaticStyleStringLiteral(staticStylePath, state)) } return [] -} +} diff --git a/packages/uni-template-compiler/lib/script/traverse/data/util.js b/packages/uni-template-compiler/lib/script/traverse/data/util.js index e4aa7dd77..d6f41e6ce 100644 --- a/packages/uni-template-compiler/lib/script/traverse/data/util.js +++ b/packages/uni-template-compiler/lib/script/traverse/data/util.js @@ -1,10 +1,11 @@ -const t = require('@babel/types') -const babelTraverse = require('@babel/traverse').default - -const { - INTERNAL_SET_MODEL -} = require('../../../constants') - +const t = require('@babel/types') +const babelTraverse = require('@babel/traverse').default + +const { + INTERNAL_SET_MODEL, + METHOD_CREATE_ELEMENT +} = require('../../../constants') + module.exports = { getModelEventFunctionExpr (funcExpr, propPath, modifiers = []) { let targetExpr @@ -43,5 +44,9 @@ module.exports = { ] ) ) + }, + isRootElement (path) { + const result = path.findParent(path => (path.isCallExpression() && path.get('callee').isIdentifier({ name: METHOD_CREATE_ELEMENT })) || path.isReturnStatement()) + return result.isReturnStatement() } -} +} diff --git a/packages/uni-template-compiler/lib/template/generate.js b/packages/uni-template-compiler/lib/template/generate.js index df91c829d..64b88e5fa 100644 --- a/packages/uni-template-compiler/lib/template/generate.js +++ b/packages/uni-template-compiler/lib/template/generate.js @@ -4,12 +4,16 @@ const { const { SELF_CLOSING_TAGS, - INTERNAL_EVENT_LINK + INTERNAL_EVENT_LINK, + VIRTUAL_HOST_STYLE, + VIRTUAL_HOST_CLASS } = require('../constants') const uniI18n = require('@dcloudio/uni-cli-i18n') function processElement (ast, state, isRoot) { - const platformName = state.options.platform.name + const platform = state.options.platform + const platformName = platform.name + const virtualHost = platformName === 'mp-weixin' || platformName === 'mp-alipay' // if (ast.type === 'template' && hasOwn(ast.attr, 'slot')) { ast.type = 'view' @@ -36,13 +40,26 @@ function processElement (ast, state, isRoot) { }] delete ast.attr.innerHTML } - if (state.options.platform.isComponent(ast.type)) { + if (platform.isComponent(ast.type)) { if (platformName === 'mp-alipay') { ast.attr.onVueInit = INTERNAL_EVENT_LINK } else if (platformName !== 'mp-baidu') { ast.attr['bind:' + INTERNAL_EVENT_LINK] = INTERNAL_EVENT_LINK } + if (virtualHost && platform.isComponent(ast.type)) { + const obj = { + style: VIRTUAL_HOST_STYLE, + class: VIRTUAL_HOST_CLASS + } + Object.keys(obj).forEach(key => { + ast.attr[obj[key]] = ast.attr[key] + if (platformName === 'mp-alipay') { + delete ast.attr[key] + } + }) + } + const children = ast.children // default slot let defaultSlot = false diff --git a/src/core/runtime/wrapper/util.js b/src/core/runtime/wrapper/util.js index 9901a056a..d7d1ffb74 100644 --- a/src/core/runtime/wrapper/util.js +++ b/src/core/runtime/wrapper/util.js @@ -225,17 +225,31 @@ function parsePropType (key, type, defaultValue, file) { return type } -export function initProperties (props, isBehavior = false, file = '') { +export function initProperties (props, isBehavior = false, file = '', options) { const properties = {} if (!isBehavior) { properties.vueId = { type: String, value: '' } - // 用于字节跳动小程序模拟抽象节点 - properties.generic = { - type: Object, - value: null + if (__PLATFORM__ === 'mp-toutiao' || __PLATFORM__ === 'mp-lark') { + // 用于字节跳动小程序模拟抽象节点 + properties.generic = { + type: Object, + value: null + } + } + if (__PLATFORM__ === 'mp-weixin' || __PLATFORM__ === 'mp-alipay') { + if (__PLATFORM__ === 'mp-alipay' || options.virtualHost) { + properties.virtualHostStyle = { + type: null, + value: '' + } + properties.virtualHostClass = { + type: null, + value: '' + } + } } // scopedSlotsCompiler auto properties.scopedSlotsCompiler = { diff --git a/src/platforms/mp-weixin/runtime/wrapper/component-base-parser.js b/src/platforms/mp-weixin/runtime/wrapper/component-base-parser.js index 6e681ea03..44fa0299f 100644 --- a/src/platforms/mp-weixin/runtime/wrapper/component-base-parser.js +++ b/src/platforms/mp-weixin/runtime/wrapper/component-base-parser.js @@ -38,7 +38,7 @@ export default function parseBaseComponent (vueComponentOptions, { options, data: initData(vueOptions, Vue.prototype), behaviors: initBehaviors(vueOptions, initBehavior), - properties: initProperties(vueOptions.props, false, vueOptions.__file), + properties: initProperties(vueOptions.props, false, vueOptions.__file, options), lifetimes: { attached () { const properties = this.properties -- GitLab