diff --git a/packages/core/src/platform/builtInMixins/index.js b/packages/core/src/platform/builtInMixins/index.js index 2e6aa6d714..e639c85b2d 100644 --- a/packages/core/src/platform/builtInMixins/index.js +++ b/packages/core/src/platform/builtInMixins/index.js @@ -14,13 +14,13 @@ import { dynamicRefsMixin, dynamicRenderHelperMixin, dynamicSlotMixin } from '.. import styleHelperMixin from './styleHelperMixin' import directiveHelperMixin from './directiveHelperMixin' -export default function getBuiltInMixins (options, type) { +export default function getBuiltInMixins ({ type, rawOptions = {}, currentInject }) { let bulitInMixins if (__mpx_mode__ === 'ios' || __mpx_mode__ === 'android') { bulitInMixins = [ proxyEventMixin(), directiveHelperMixin(), - styleHelperMixin(type), + styleHelperMixin(currentInject), refsMixin(), i18nMixin() ] @@ -46,7 +46,7 @@ export default function getBuiltInMixins (options, type) { relationsMixin(type) ] // 此为纯增强类mixins,原生模式下不需要注入 - if (!options.__nativeRender__) { + if (!rawOptions.__nativeRender__) { bulitInMixins = bulitInMixins.concat([ renderHelperMixin(), showMixin(type), diff --git a/packages/core/src/platform/builtInMixins/styleHelperMixin.ios.js b/packages/core/src/platform/builtInMixins/styleHelperMixin.ios.js index b6db5a0760..cc21d3eee2 100644 --- a/packages/core/src/platform/builtInMixins/styleHelperMixin.ios.js +++ b/packages/core/src/platform/builtInMixins/styleHelperMixin.ios.js @@ -1,6 +1,35 @@ -import { isObject, isArray, dash2hump, isFunction, cached } from '@mpxjs/utils' +import { isObject, isArray, dash2hump, cached } from '@mpxjs/utils' import { Dimensions } from 'react-native' +const escapeReg = /[()[\]{}#!.:,%'"+$]/g +const escapeMap = { + '(': '_pl_', + ')': '_pr_', + '[': '_bl_', + ']': '_br_', + '{': '_cl_', + '}': '_cr_', + '#': '_h_', + '!': '_i_', + '/': '_s_', + '.': '_d_', + ':': '_c_', + ',': '_2c_', + '%': '_p_', + "'": '_q_', + '"': '_dq_', + '+': '_a_', + $: '_si_' +} + +const mpEscape = cached((str) => { + return str.replace(escapeReg, function (match) { + if (escapeMap[match]) return escapeMap[match] + // unknown escaped + return '_u_' + }) +}) + function concat (a = '', b = '') { return a ? b ? (a + ' ' + b) : a : b } @@ -99,7 +128,7 @@ function transformStyleObj (context, styleObj) { return transformed } -export default function styleHelperMixin (type) { +export default function styleHelperMixin (currentInject) { return { methods: { __rpx (value) { @@ -111,18 +140,14 @@ export default function styleHelperMixin (type) { __getClass (staticClass, dynamicClass) { return concat(staticClass, stringifyDynamicClass(dynamicClass)) }, - __getStyle (staticClass, dynamicClass, staticStyle, dynamicStyle, show) { - // todo 每次返回新对象会导致react memo优化失效,需要考虑优化手段 + __getStyle (staticClass, dynamicClass, staticStyle, dynamicStyle, hide) { const result = {} - const classMap = {} - if (type === 'page' && isFunction(global.__getAppClassMap)) { - Object.assign(classMap, global.__getAppClassMap.call(this)) - } - if (isFunction(this.__getClassMap)) { - Object.assign(classMap, this.__getClassMap()) - } + // todo 全局样式在每个页面和组件中生效,以支持全局原子类,后续支持样式模块复用后可考虑移除 + const classMap = Object.assign({}, global.__appClassMap, currentInject.classMap) + if (staticClass || dynamicClass) { - const classString = concat(staticClass, stringifyDynamicClass(dynamicClass)) + // todo 当前为了复用小程序unocss产物,暂时进行mpEscape,等后续正式支持unocss后可不进行mpEscape + const classString = mpEscape(concat(staticClass, stringifyDynamicClass(dynamicClass))) classString.split(/\s+/).forEach((className) => { if (classMap[className]) { Object.assign(result, classMap[className]) @@ -134,11 +159,11 @@ export default function styleHelperMixin (type) { } if (staticStyle || dynamicStyle) { - const styleObj = Object.assign(parseStyleText(staticStyle), normalizeDynamicStyle(dynamicStyle)) + const styleObj = Object.assign({}, parseStyleText(staticStyle), normalizeDynamicStyle(dynamicStyle)) Object.assign(result, transformStyleObj(this, styleObj)) } - if (!show) { + if (hide) { Object.assign(result, { display: 'none' }) diff --git a/packages/core/src/platform/patch/index.js b/packages/core/src/platform/patch/index.js index ce1d1523ba..11f006e2bb 100644 --- a/packages/core/src/platform/patch/index.js +++ b/packages/core/src/platform/patch/index.js @@ -58,7 +58,7 @@ export default function createFactory (type) { // 不接受mixin中的setup配置 // 注入内建的mixins, 内建mixin是按原始平台编写的,所以合并规则和rootMixins保持一致 // 将合并后的用户定义的rawOptions传入获取当前应该注入的内建mixins - rawOptions.mixins = getBuiltInMixins(rawOptions, type) + rawOptions.mixins = getBuiltInMixins({ type, rawOptions, currentInject }) const defaultOptions = getDefaultOptions({ type, rawOptions, currentInject }) if (__mpx_mode__ === 'web' || __mpx_mode__ === 'ios' || __mpx_mode__ === 'android') { global.__mpxOptionsMap = global.__mpxOptionsMap || {} diff --git a/packages/webpack-plugin/lib/react/processStyles.js b/packages/webpack-plugin/lib/react/processStyles.js index f07e6b79f2..27ef8d7517 100644 --- a/packages/webpack-plugin/lib/react/processStyles.js +++ b/packages/webpack-plugin/lib/react/processStyles.js @@ -31,6 +31,7 @@ module.exports = function (styles, { scoped, extract: false } + // todo 建立新的request在内部导出classMap,便于样式模块复用 loaderContext.importModule(JSON.parse(getRequestString('styles', style, extraOptions, i))).then((result) => { if (Array.isArray(result)) { result = result.map((item) => { @@ -55,15 +56,9 @@ module.exports = function (styles, { error }) if (ctorType === 'app') { - output += `global.__getAppClassMap = function() { - return ${shallowStringify(classMap)}; - };\n` + output += `global.__appClassMap = ${shallowStringify(classMap)};\n` } else { - output += `global.currentInject.injectMethods = { - __getClassMap: function() { - return ${shallowStringify(classMap)}; - } - };\n` + output += `global.currentInject.classMap = ${shallowStringify(classMap)};\n` } } catch (e) { return callback(e) diff --git a/packages/webpack-plugin/lib/template-compiler/compiler.js b/packages/webpack-plugin/lib/template-compiler/compiler.js index 6a270c21fc..8a0b318815 100644 --- a/packages/webpack-plugin/lib/template-compiler/compiler.js +++ b/packages/webpack-plugin/lib/template-compiler/compiler.js @@ -1078,12 +1078,12 @@ function processStyleReact (el, options) { const dynamicClassExp = parseMustacheWithContext(dynamicClass).result const staticStyleExp = parseMustacheWithContext(staticStyle).result const dynamicStyleExp = parseMustacheWithContext(dynamicStyle).result - const showExp = show === undefined ? 'true' : parseMustacheWithContext(show).result + const showExp = parseMustacheWithContext(show).result addAttrs(el, [{ name: 'style', // runtime helper - value: `{{this.__getStyle(${staticClassExp}, ${dynamicClassExp}, ${staticStyleExp}, ${dynamicStyleExp}, ${showExp})}}` + value: `{{this.__getStyle(${staticClassExp}, ${dynamicClassExp}, ${staticStyleExp}, ${dynamicStyleExp}${show === undefined ? '' : `, !(${showExp})`})}}` }]) }