diff --git a/packages/core/src/platform/builtInMixins/styleHelperMixin.ios.js b/packages/core/src/platform/builtInMixins/styleHelperMixin.ios.js index 8113fb97cb..fea47aa337 100644 --- a/packages/core/src/platform/builtInMixins/styleHelperMixin.ios.js +++ b/packages/core/src/platform/builtInMixins/styleHelperMixin.ios.js @@ -12,8 +12,22 @@ global.__mpxPageSizeCountMap = reactive({}) global.__GCC = function (className, classMap, classMapValueCache) { if (!classMapValueCache.has(className)) { - const styleObj = classMap[className]?.(global.__formatValue) - styleObj && classMapValueCache.set(className, styleObj) + const originalDependentScreenSize = dependentScreenSize + dependentScreenSize = false + + let styleObj = classMap[className]?.(formatValue) + if (!styleObj) return + if (!styleObj._media?.length) { + styleObj = { + _default: styleObj + } + } + + // 记录是否依赖屏幕尺寸,在屏幕尺寸变化时决定是否重新渲染对应组件 + styleObj._dependentScreenSize = dependentScreenSize + dependentScreenSize = dependentScreenSize || originalDependentScreenSize + + classMapValueCache.set(className, styleObj) } return classMapValueCache.get(className) } @@ -79,12 +93,15 @@ const unit = { const empty = {} +// 记录style是否依赖屏幕尺寸 +let dependentScreenSize = false function formatValue (value, unitType) { if (!dimensionsInfoInitialized) useDimensionsInfo(global.__mpxAppDimensionsInfo) if (unitType === 'hairlineWidth') { return StyleSheet.hairlineWidth } if (unitType && typeof unit[unitType] === 'function') { + dependentScreenSize = true return unit[unitType](+value) } const matched = unitRegExp.exec(value) @@ -254,11 +271,11 @@ export default function styleHelperMixin () { return concat(staticClass, stringifyDynamicClass(dynamicClass)) }, __getStyle (staticClass, dynamicClass, staticStyle, dynamicStyle, hide) { + // 重置依赖标记 + dependentScreenSize = false const isNativeStaticStyle = staticStyle && isNativeStyle(staticStyle) let result = isNativeStaticStyle ? [] : {} const mergeResult = isNativeStaticStyle ? (...args) => result.push(...args) : (...args) => Object.assign(result, ...args) - // 使用一下 __getSizeCount 触发其 get - this.__getSizeCount() if (staticClass || dynamicClass) { // todo 当前为了复用小程序unocss产物,暂时进行mpEscape,等后续正式支持unocss后可不进行mpEscape @@ -267,20 +284,15 @@ export default function styleHelperMixin () { classString.split(/\s+/).forEach((className) => { let localStyle, appStyle if (localStyle = this.__getClassStyle?.(className)) { - if (localStyle._media?.length) { - mergeResult(localStyle._default, getMediaStyle(localStyle._media)) - } else { - mergeResult(localStyle) - } + mergeResult(localStyle._default, getMediaStyle(localStyle._media)) + // class style 计算可能触发缓存,需要单独在结果中记录是否依赖屏幕尺寸,不能直接使用全局变量。 + this.__dependentScreenSize = this.__dependentScreenSize || localStyle._dependentScreenSize } else if (appStyle = global.__getAppClassStyle?.(className)) { - if (appStyle._media?.length) { - mergeResult(appStyle._default, getMediaStyle(appStyle._media)) - } else { - mergeResult(appStyle) - } - } else if (isObject(this.__props[className])) { + mergeResult(appStyle._default, getMediaStyle(appStyle._media)) + this.__dependentScreenSize = this.__dependentScreenSize || appStyle._dependentScreenSize + } else if (isObject(this.__mpxProxy.props[className])) { // externalClasses必定以对象形式传递下来 - mergeResult(this.__props[className]) + mergeResult(this.__mpxProxy.props[className]) } }) } @@ -319,6 +331,12 @@ export default function styleHelperMixin () { }) } const isEmpty = isNativeStaticStyle ? !result.length : isEmptyObject(result) + + // 仅在依赖屏幕尺寸时才触发__getSizeCount进行相应式关联,避免屏幕尺寸变化时不必要的性能损耗 + this.__dependentScreenSize = this.__dependentScreenSize || dependentScreenSize + if (this.__dependentScreenSize) { + this.__getSizeCount() + } return isEmpty ? empty : result } } diff --git a/packages/core/src/platform/patch/getDefaultOptions.ios.js b/packages/core/src/platform/patch/getDefaultOptions.ios.js index 62770ce107..b1a2240cfe 100644 --- a/packages/core/src/platform/patch/getDefaultOptions.ios.js +++ b/packages/core/src/platform/patch/getDefaultOptions.ios.js @@ -398,7 +398,7 @@ const triggerResizeEvent = (mpxProxy, sizeRef) => { } } -function usePageEffect (mpxProxy, pageId) { +function usePageEffect (mpxProxy, pageId, type) { const sizeRef = useRef(getSystemInfo()) useEffect(() => { @@ -415,7 +415,7 @@ function usePageEffect (mpxProxy, pageId) { triggerResizeEvent(mpxProxy, sizeRef) // 如果当前全局size与pagesize不一致,在show之后触发一次resize事件 - if (newVal === 'show' && global.__mpxPageSizeCountMap[pageId] !== global.__mpxSizeCount) { + if (type === 'page' && newVal === 'show' && global.__mpxPageSizeCountMap[pageId] !== global.__mpxSizeCount) { // 刷新__mpxPageSizeCountMap, 每个页面仅会执行一次,直接驱动render刷新 global.__mpxPageSizeCountMap[pageId] = global.__mpxSizeCount } @@ -427,7 +427,9 @@ function usePageEffect (mpxProxy, pageId) { } return () => { unWatch && unWatch() - del(global.__mpxPageSizeCountMap, pageId) + if (type === 'page') { + del(global.__mpxPageSizeCountMap, pageId) + } } }, []) } @@ -637,6 +639,11 @@ export function getDefaultOptions ({ type, rawOptions = {}, currentInject }) { }) } const validProps = Object.assign({}, rawOptions.props, rawOptions.properties) + if (global.__externalClasses && global.__externalClasses.length > 0) { + global.__externalClasses.forEach((name) => { + validProps[name] = null + }) + } const { hasDescendantRelation, hasAncestorRelation } = checkRelation(rawOptions) if (rawOptions.methods) rawOptions.methods = wrapMethodsWithErrorHandling(rawOptions.methods) const defaultOptions = memo(forwardRef((props, ref) => { @@ -697,7 +704,7 @@ export function getDefaultOptions ({ type, rawOptions = {}, currentInject }) { } }) - usePageEffect(proxy, pageId) + usePageEffect(proxy, pageId, type) useEffect(() => { proxy.mounted() return () => { diff --git a/packages/webpack-plugin/lib/loader.js b/packages/webpack-plugin/lib/loader.js index cfb6f030a5..89c7960e20 100644 --- a/packages/webpack-plugin/lib/loader.js +++ b/packages/webpack-plugin/lib/loader.js @@ -38,7 +38,7 @@ module.exports = function (content) { return content } const { resourcePath, queryObj } = parseRequest(this.resource) - + const externalClasses = mpx.externalClasses || [] const packageRoot = queryObj.packageRoot || mpx.currentPackageRoot const packageName = packageRoot || 'main' const independent = queryObj.independent @@ -178,6 +178,7 @@ module.exports = function (content) { originalUsingComponents, componentGenerics, autoScope, + externalClasses, callback }) } diff --git a/packages/webpack-plugin/lib/react/index.js b/packages/webpack-plugin/lib/react/index.js index 4673d270f0..9969a34dd4 100644 --- a/packages/webpack-plugin/lib/react/index.js +++ b/packages/webpack-plugin/lib/react/index.js @@ -24,6 +24,7 @@ module.exports = function ({ originalUsingComponents, componentGenerics, autoScope, + externalClasses, callback }) { if (ctorType === 'app' && !queryObj.isApp) { @@ -95,7 +96,8 @@ module.exports = function ({ wxsModuleMap: templateRes.wxsModuleMap, localComponentsMap: jsonRes.localComponentsMap, localPagesMap: jsonRes.localPagesMap, - rnConfig + rnConfig, + externalClasses }, callback) } ], (err, scriptRes) => { diff --git a/packages/webpack-plugin/lib/react/processScript.js b/packages/webpack-plugin/lib/react/processScript.js index 9b88cb9b3a..d0d640b6fc 100644 --- a/packages/webpack-plugin/lib/react/processScript.js +++ b/packages/webpack-plugin/lib/react/processScript.js @@ -15,7 +15,8 @@ module.exports = function (script, { localPagesMap, rnConfig, componentGenerics, - genericsInfo + genericsInfo, + externalClasses }, callback) { const { appInfo, i18n } = loaderContext.getMpx() @@ -49,7 +50,7 @@ import { getComponent, getAsyncSuspense } from ${stringifyRequest(loaderContext, jsonConfig, rnConfig }) - output += buildGlobalParams({ moduleId, scriptSrcMode, loaderContext, isProduction, ctorType, jsonConfig, componentsMap, pagesMap, firstPage, hasApp }) + output += buildGlobalParams({ moduleId, scriptSrcMode, loaderContext, isProduction, ctorType, jsonConfig, componentsMap, pagesMap, firstPage, hasApp, externalClasses }) output += getRequireScript({ ctorType, script, loaderContext }) output += `export default global.__mpxOptionsMap[${JSON.stringify(moduleId)}]\n` } else { diff --git a/packages/webpack-plugin/lib/react/script-helper.js b/packages/webpack-plugin/lib/react/script-helper.js index a86e3ad72d..8347251dd2 100644 --- a/packages/webpack-plugin/lib/react/script-helper.js +++ b/packages/webpack-plugin/lib/react/script-helper.js @@ -150,7 +150,8 @@ function buildGlobalParams ({ firstPage, outputPath, genericsInfo, - hasApp + hasApp, + externalClasses }) { let content = '' if (ctorType === 'app') { @@ -165,6 +166,7 @@ global.__style = ${JSON.stringify(jsonConfig.style || 'v1')} global.__mpxPageConfig = ${JSON.stringify(jsonConfig.window)} global.__appComponentsMap = ${shallowStringify(componentsMap)} global.__preloadRule = ${JSON.stringify(jsonConfig.preloadRule)} +global.__externalClasses = ${JSON.stringify(externalClasses || [])} global.currentInject.pagesMap = ${shallowStringify(pagesMap)} global.currentInject.firstPage = ${JSON.stringify(firstPage)}\n` } else {