Skip to content

Commit 527e4ec

Browse files
authored
Merge branch 'master' into feat-convert-ks-v2
2 parents bd4fd1b + 3c8030d commit 527e4ec

14 files changed

Lines changed: 167 additions & 70 deletions

File tree

docs-vitepress/api/composition-api.md

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,67 @@ createComponent({
128128
`Function`
129129

130130
小程序页面 onLoad 事件,监听页面加载。
131+
::: tip 注意
132+
在页面拼接参数时,不同平台对 URL 参数的处理方式存在差异:
133+
- **微信、QQ、字节跳动、RN**:参数透传,保持原始格式
134+
- **其他平台**:会自动对 encode 后的参数进行 decode
135+
136+
为了提供统一的参数处理方式,`onLoad` 钩子额外提供了一个经过 encode 处理的参数对象,方便业务使用统一的参数格式,同时不影响各平台原有的参数返回。
137+
138+
**微信、QQ、字节跳动、RN下的效果:**
139+
```js
140+
// A页面
141+
...
142+
createPage({
143+
methods: {
144+
jumpPage () {
145+
mpx.navigateTo({
146+
url: `./pages/test?name=${encodeURIComponent('')}&encode=true`
147+
})
148+
}
149+
}
150+
})
151+
...
152+
153+
// test页面
154+
...
155+
createPage({
156+
onLoad(rawQuery, decodedQuery) {
157+
// rawQuery = {name: "%E6%88%91", encode: "true"}
158+
// decodedQuery = {name: "我", encode: "true"}
159+
...
160+
}
161+
})
162+
...
163+
```
164+
**其他平台的效果:**
165+
```js
166+
// A页面
167+
...
168+
createPage({
169+
methods: {
170+
jumpPage () {
171+
mpx.navigateTo({
172+
url: `./pages/test?name=${encodeURIComponent('')}&encode=true`
173+
})
174+
}
175+
}
176+
})
177+
...
178+
179+
// test页面
180+
...
181+
createPage({
182+
onLoad(rawQuery, decodedQuery) {
183+
// rawQuery = {name: "我", encode: "true"}
184+
// decodedQuery = {name: "我", encode: "true"}
185+
...
186+
}
187+
})
188+
...
189+
```
190+
191+
:::
131192

132193
### onShow
133194
`Function`

docs-vitepress/guide/rn/style.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1369,6 +1369,10 @@ transform: scale(1.2) skewX(10deg);
13691369
/* RN 数组格式,仅 rn 支持 */
13701370
transform: [{translateX: 50}, {rotate: '45deg'}];
13711371
```
1372+
> [!tip] 注意
1373+
>
1374+
> 1.RN transform 不支持 scaleZ/scale3d/translateZ/translate3d/rotate3d/matrix3d
1375+
> 2.skew/skewX/skewY 在 RN Android 上不生效
13721376

13731377
### transform-origin
13741378

packages/api-proxy/src/platform/api/route/index.ios.js

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ function isLock (navigationHelper, type, options) {
2525
clearTimeout(timerId)
2626
timerId = setTimeout(() => {
2727
if (navigationHelper.lastSuccessCallback && navigationHelper.lastFailCallback) {
28-
navigationHelper.lastFailCallback('timeout')
28+
navigationHelper.lastFailCallback(`${type}:fail timeout ${options.url || ''}`)
2929
navigationHelper.lastFailCallback = null
3030
}
3131
}, 1000)
@@ -43,7 +43,7 @@ function navigateTo (options = {}) {
4343
if (options.events) {
4444
eventChannel._addListeners(options.events)
4545
}
46-
const { path, queryObj } = parseUrl(options.url)
46+
const { path, queryObj } = parseUrl(options.url, true)
4747
const basePath = getBasePath(navigation)
4848
const finalPath = resolvePath(path, basePath).slice(1)
4949

@@ -70,7 +70,7 @@ function redirectTo (options = {}) {
7070
return
7171
}
7272
if (navigation && navigationHelper) {
73-
const { path, queryObj } = parseUrl(options.url)
73+
const { path, queryObj } = parseUrl(options.url, true)
7474
const basePath = getBasePath(navigation)
7575
const finalPath = resolvePath(path, basePath).slice(1)
7676
navigation.replace(finalPath, queryObj)
@@ -120,7 +120,7 @@ function reLaunch (options = {}) {
120120
return
121121
}
122122
if (navigation && navigationHelper) {
123-
const { path, queryObj } = parseUrl(options.url)
123+
const { path, queryObj } = parseUrl(options.url, true)
124124
const basePath = getBasePath(navigation)
125125
const finalPath = resolvePath(path, basePath).slice(1)
126126
navigation.reset({

packages/core/src/platform/builtInMixins/pageStatusMixin.js

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { CREATED, ONLOAD, ONSHOW, ONHIDE, ONRESIZE } from '../../core/innerLifecycle'
2+
import { isObject } from '@mpxjs/utils'
23

34
export default function pageStatusMixin (mixinType) {
45
if (mixinType === 'page') {
@@ -12,8 +13,19 @@ export default function pageStatusMixin (mixinType) {
1213
onResize (e) {
1314
this.__mpxProxy.callHook(ONRESIZE, [e])
1415
},
15-
onLoad (query) {
16-
this.__mpxProxy.callHook(ONLOAD, [query])
16+
onLoad (rawQuery) {
17+
if (__mpx_mode__ === 'wx' || __mpx_mode__ === 'qq' || __mpx_mode__ === 'tt') {
18+
const decodedQuery = {}
19+
// 处理以上平台直接透传encode的结果,给到onload第二个参数供开发者使用
20+
if (isObject(rawQuery)) {
21+
for (const key in rawQuery) {
22+
decodedQuery[key] = decodeURIComponent(rawQuery[key])
23+
}
24+
}
25+
this.__mpxProxy.callHook(ONLOAD, [rawQuery, decodedQuery])
26+
} else {
27+
this.__mpxProxy.callHook(ONLOAD, [rawQuery, rawQuery])
28+
}
1729
}
1830
}
1931
if (__mpx_mode__ === 'ali') {

packages/core/src/platform/builtInMixins/refsMixin.js

Lines changed: 47 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,52 @@ const setRef = function (target, ref, isAsync) {
1515
}
1616
})
1717
}
18+
const proxyMethods = ['boundingClientRect', 'scrollOffset']
19+
function rewriteAliCreateSelectorQuery (target) {
20+
const rawCreateSelectorQuery = target.createSelectorQuery
21+
target.createSelectorQuery = function (...args) {
22+
let selectorQuery = rawCreateSelectorQuery.apply(target, args)
23+
const cbs = []
24+
25+
if (typeof selectorQuery === 'undefined') {
26+
// 兜底 selectorQuery 在ali为 undefined 情况
27+
// 调用 createSelectorQuery时,组件实例已经被销毁,ali this._originCreateSelectorQuery 返回 undefined。导致后续 selectorQuery[name] 报错
28+
// 方案:对齐微信,微信实例销毁时,其他调用正常,仅 createSelectorQuery.exec 不执行回调
29+
// 复现:setTimeout 中调用,倒计时未回调时切换页面
30+
selectorQuery = {}
31+
// ['boundingClientRect', 'context', 'exec', 'fields', 'in', 'node', 'scrollOffset', 'select', 'selectAll', 'selectViewport', 'toImage']
32+
const backupMethodKeys = Object.keys(envObj.createSelectorQuery())
33+
const backupFn = function () {
34+
return selectorQuery
35+
}
36+
backupMethodKeys.forEach(key => {
37+
selectorQuery[key] = backupFn
38+
})
39+
return selectorQuery
40+
}
41+
42+
proxyMethods.forEach((name) => {
43+
const originalMethod = selectorQuery[name]
44+
selectorQuery[name] = function (cb = noop) {
45+
cbs.push(cb)
46+
return originalMethod.call(this)
47+
}
48+
})
49+
50+
const originalExec = selectorQuery.exec
51+
selectorQuery.exec = function (originalCb = noop) {
52+
const cb = function (results) {
53+
results.forEach((item, index) => {
54+
cbs[index] && cbs[index](item)
55+
})
56+
originalCb(results)
57+
}
58+
return originalExec.call(this, cb)
59+
}
60+
61+
return selectorQuery
62+
}
63+
}
1864

1965
export default function getRefsMixin () {
2066
const refsMixin = {
@@ -24,8 +70,7 @@ export default function getRefsMixin () {
2470
this.__getRefs()
2571

2672
if (__mpx_mode__ === 'ali') {
27-
this._originCreateSelectorQuery = this.createSelectorQuery
28-
this.createSelectorQuery = this._createSelectorQuery
73+
rewriteAliCreateSelectorQuery(this)
2974
}
3075
},
3176
methods: {
@@ -68,51 +113,7 @@ export default function getRefsMixin () {
68113
}
69114
})
70115

71-
const proxyMethods = ['boundingClientRect', 'scrollOffset']
72-
73116
Object.assign(refsMixin.methods, {
74-
_createSelectorQuery (...args) {
75-
let selectorQuery = this._originCreateSelectorQuery(...args)
76-
const cbs = []
77-
78-
if (typeof selectorQuery === 'undefined') {
79-
// 兜底 selectorQuery 在ali为 undefined 情况
80-
// 调用 createSelectorQuery时,组件实例已经被销毁,ali this._originCreateSelectorQuery 返回 undefined。导致后续 selectorQuery[name] 报错
81-
// 方案:对齐微信,微信实例销毁时,其他调用正常,仅 createSelectorQuery.exec 不执行回调
82-
// 复现:setTimeout 中调用,倒计时未回调时切换页面
83-
selectorQuery = {}
84-
// ['boundingClientRect', 'context', 'exec', 'fields', 'in', 'node', 'scrollOffset', 'select', 'selectAll', 'selectViewport', 'toImage']
85-
const backupMethodKeys = Object.keys(envObj.createSelectorQuery())
86-
const backupFn = function () {
87-
return selectorQuery
88-
}
89-
backupMethodKeys.forEach(key => {
90-
selectorQuery[key] = backupFn
91-
})
92-
return selectorQuery
93-
}
94-
95-
proxyMethods.forEach((name) => {
96-
const originalMethod = selectorQuery[name]
97-
selectorQuery[name] = function (cb = noop) {
98-
cbs.push(cb)
99-
return originalMethod.call(this)
100-
}
101-
})
102-
103-
const originalExec = selectorQuery.exec
104-
selectorQuery.exec = function (originalCb = noop) {
105-
const cb = function (results) {
106-
results.forEach((item, index) => {
107-
cbs[index] && cbs[index](item)
108-
})
109-
originalCb(results)
110-
}
111-
return originalExec.call(this, cb)
112-
}
113-
114-
return selectorQuery
115-
},
116117
selectComponent (selector) {
117118
return this.$selectComponent(selector)
118119
},

packages/core/src/platform/builtInMixins/styleHelperMixin.ios.js

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,8 @@ global.__mpxAppDimensionsInfo = {
1010
global.__mpxSizeCount = 0
1111
global.__mpxPageSizeCountMap = reactive({})
1212

13-
global.__classCaches = []
1413
global.__GCC = function (className, classMap, classMapValueCache) {
15-
if (!classMapValueCache.get(className)) {
14+
if (!classMapValueCache.has(className)) {
1615
const styleObj = classMap[className]?.()
1716
styleObj && classMapValueCache.set(className, styleObj)
1817
}

packages/core/src/platform/patch/getDefaultOptions.ios.js

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -314,14 +314,14 @@ function createInstance ({ propsRef, type, rawOptions, currentInject, validProps
314314

315315
if (type === 'page') {
316316
const props = propsRef.current
317-
const loadParams = {}
318-
// 此处拿到的props.route.params内属性的value被进行过了一次decode, 不符合预期,此处额外进行一次encode来与微信对齐
319-
if (isObject(props.route.params)) {
320-
for (const key in props.route.params) {
321-
loadParams[key] = encodeURIComponent(props.route.params[key])
317+
const decodedQuery = {}
318+
const rawQuery = props.route.params
319+
if (isObject(rawQuery)) {
320+
for (const key in rawQuery) {
321+
decodedQuery[key] = decodeURIComponent(rawQuery[key])
322322
}
323323
}
324-
proxy.callHook(ONLOAD, [loadParams])
324+
proxy.callHook(ONLOAD, [rawQuery, decodedQuery])
325325
}
326326

327327
Object.assign(proxy, {

packages/utils/src/url.js

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ const specialValues = {
8080
false: false
8181
}
8282

83-
function parseQuery (query) {
83+
function parseQuery (query, noDecode = false) {
8484
if (query.slice(0, 1) !== '?') {
8585
throw new Error(
8686
"A valid query string passed to parseQuery should begin with '?'"
@@ -104,8 +104,8 @@ function parseQuery (query) {
104104
const idx = arg.indexOf('=')
105105

106106
if (idx >= 0) {
107-
let name = decode(arg.slice(0, idx))
108-
let value = decode(arg.slice(idx + 1))
107+
let name = noDecode ? arg.slice(0, idx) : decode(arg.slice(0, idx))
108+
let value = noDecode ? arg.slice(idx + 1) : decode(arg.slice(idx + 1))
109109

110110
// eslint-disable-next-line no-prototype-builtins
111111
if (specialValues.hasOwnProperty(value)) {
@@ -137,15 +137,15 @@ function parseQuery (query) {
137137
return result
138138
}
139139

140-
function parseUrlQuery (url) {
140+
function parseUrlQuery (url, noDecode = false) {
141141
let path = url
142142
let query = ''
143143
const queryIndex = url.indexOf('?')
144144
if (queryIndex >= 0) {
145145
path = url.slice(0, queryIndex)
146146
query = url.slice(queryIndex)
147147
}
148-
const queryObj = parseQuery(query || '?')
148+
const queryObj = parseQuery(query || '?', noDecode)
149149
return {
150150
path,
151151
queryObj

packages/webpack-plugin/lib/index.js

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1729,7 +1729,14 @@ class MpxWebpackPlugin {
17291729

17301730
if (isReact(mpx.mode)) {
17311731
// 添加 @refresh reset 注释用于在 React HMR 时刷新组件
1732-
source.add('/* @refresh reset */\n')
1732+
if (process.env.NODE_ENV !== 'production') {
1733+
source.add(`/* @refresh reset */
1734+
if (module.hot) {
1735+
module.hot.accept(() => {
1736+
require("react-native").DevSettings.reload();
1737+
});
1738+
}\n`)
1739+
}
17331740
// 注入页面的配置,供screen前置设置导航情况
17341741
if (isRuntime) {
17351742
source.add('// inject pageconfigmap for screen\n' +

packages/webpack-plugin/lib/react/LoadAsyncChunkModule.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ class LoadAsyncChunkRuntimeModule extends HelperRuntimeModule {
5454
]),
5555
'}',
5656
`var timeout = setTimeout(callback.bind(null, 'timeout'), ${this.timeout})`,
57-
'var loadChunkAsyncFn = global.__mpx.config.rnConfig && global.__mpx.config.rnConfig.loadChunkAsync',
57+
`var loadChunkAsyncFn = ${RuntimeGlobals.global}.__mpx.config.rnConfig && ${RuntimeGlobals.global}.__mpx.config.rnConfig.loadChunkAsync`,
5858
'try {',
5959
Template.indent([
6060
'loadChunkAsyncFn(config).then(callback).catch(callback)'

0 commit comments

Comments
 (0)