开始使用
在线案例
diff --git a/docs/zh-cn/advanced.md b/docs/zh-cn/advanced.md
index 87926a5d0..99b64fa6d 100644
--- a/docs/zh-cn/advanced.md
+++ b/docs/zh-cn/advanced.md
@@ -36,7 +36,7 @@ microApp.start({
> 1、如果跨域请求带cookie,那么`Access-Control-Allow-Origin`不能设置为`*`,这一点需要注意
## 2、适配vite
-当子应用是vite应用时需要做特别的适配,适配vite的代价是巨大的,我们必须关闭沙箱功能,因为沙箱在`module script`下不支持,这导致大部分功能失效,包括:环境变量、样式隔离、元素隔离、数据通信、资源地址补全、baseroute 等。
+当子应用是vite应用时需要做特别的适配,适配vite的代价是巨大的,我们必须关闭沙箱功能,因为沙箱在`module script`下不支持,这导致大部分功能失效,包括:环境变量、样式隔离、元素隔离、资源地址补全、baseroute 等。
在嵌入vite子应用时,`micro-app`的功能只负责渲染,其它的行为由应用自行决定,这包括如何防止样式、JS变量、元素的冲突。
@@ -47,6 +47,9 @@ microApp.start({
##### 1、修改vite.config.js
```js
+import { join } from 'path'
+import { writeFileSync } from 'fs'
+
// vite.config.js
export default defineConfig({
base: `${process.env.NODE_ENV === 'production' ? 'http://my-site.com' : ''}/basename/`,
@@ -57,20 +60,24 @@ export default defineConfig({
let basePath = ''
return {
name: "vite:micro-app",
- apply: 'build', // 只在生产环境生效
+ apply: 'build',
configResolved(config) {
- // 获取资源地址前缀
basePath = `${config.base}${config.build.assetsDir}/`
},
- renderChunk(code, chunk) {
- // build后,import会通过相对地址引入模块,需要将其补全
- if (chunk.fileName.endsWith('.js') && /(from|import)(\s*['"])(\.\.?\/)/g.test(code)) {
- code = code.replace(/(from|import)(\s*['"])(\.\.?\/)/g, (all, $1, $2, $3) => {
- return all.replace($3, new URL($3, basePath))
- })
+ writeBundle (options, bundle) {
+ for (const chunkName in bundle) {
+ if (Object.prototype.hasOwnProperty.call(bundle, chunkName)) {
+ const chunk = bundle[chunkName]
+ if (chunk.fileName && chunk.fileName.endsWith('.js')) {
+ chunk.code = chunk.code.replace(/(from|import\()(\s*['"])(\.\.?\/)/g, (all, $1, $2, $3) => {
+ return all.replace($3, new URL($3, basePath))
+ })
+ const fullPath = join(options.dir, chunk.fileName)
+ writeFileSync(fullPath, chunk.code)
+ }
+ }
}
- return code
- }
+ },
}
})(),
],
@@ -78,11 +85,7 @@ export default defineConfig({
```
##### 2、路由
-vite环境下,当路由的baseName和vite.base值不相等,两者会进行拼接,这导致无法自定义baseName来适配基座应用的路由。
-
-有两种方式解决这个问题:
-- 方式一:子应用使用hash路由
-- 方式二:子应用根据基座路由单独打包一个版本,这个版本的子应用无法单独访问,必须嵌入基座中运行。
+推荐子应用使用hash路由,避免一些可能出现的问题。
##### 3、静态资源
图片等静态资源需要使用绝对地址,可以使用 `new URL('../assets/logo.png', import.meta.url).href` 等方式获取资源的全链接地址。
@@ -127,7 +130,43 @@ microApp.start({
})
```
-> [!TIP]
+### vite数据通信
+沙箱关闭后,子应用默认的通信功能失效,此时可以通过手动注册通信对象实现一致的功能。
+
+**注册方式:在基座应用中为子应用初始化通信对象**
+
+```js
+import { EventCenterForMicroApp } from '@micro-zoe/micro-app'
+
+// 注意:每个vite子应用根据appName单独分配一个通信对象
+window.eventCenterForViteApp1 = new EventCenterForMicroApp(appName)
+```
+
+vite子应用就可以通过注册的`eventCenterForViteApp1`对象进行通信,其api和`window.microApp`一致,*而基座通信方式没有任何变化。*
+
+**子应用通信方式:**
+```js
+/**
+ * 绑定监听函数
+ * dataListener: 绑定函数
+ * autoTrigger: 在初次绑定监听函数时有缓存数据,是否需要主动触发一次,默认为false
+ */
+window.eventCenterForViteApp1.addDataListener(dataListener: (data: Object) => void, autoTrigger?: boolean)
+
+// 解绑指定函数
+window.eventCenterForViteApp1.removeDataListener(dataListener)
+
+// 清空当前子应用的所有绑定函数(全局数据函数除外)
+window.eventCenterForViteApp1.clearDataListener()
+
+// 主动获取数据
+window.eventCenterForViteApp1.getData()
+
+// 子应用向基座应用发送数据
+window.eventCenterForViteApp1.dispatch({type: '子应用发送的数据'})
+```
+
+> [!WARNING]
> 1、关闭沙箱后的子应用可以直接访问全局window,可以通过挂载全局变量来进行数据通信和其它操作。
>
> 2、适配vite本质上是适配module脚本,其它非vite构建的module脚本也可以采用相同的思路处理。
diff --git a/docs/zh-cn/changelog.md b/docs/zh-cn/changelog.md
index 5a58bc55d..0a22fdd7e 100644
--- a/docs/zh-cn/changelog.md
+++ b/docs/zh-cn/changelog.md
@@ -12,9 +12,14 @@
`2021-11-05`
+- **New**
+
+ - 🆕 新增了`EventCenterForMicroApp`方法,用于沙箱关闭时实现通信功能(如vite)
+
- **Bug Fix**
- - 🐞 修复了在不支持`ShadowRoot`的浏览器中的报错问题
+ - 🐞 修复了在不支持`ShadowRoot`的浏览器中的报错问题,fix [#134](https://github.com/micro-zoe/micro-app/issues/134)
+ - 🐞 修复了元素查询时带有特殊字符导致报错的问题,fix [#140](https://github.com/micro-zoe/micro-app/issues/140)
### 0.4.2
diff --git a/docs/zh-cn/data.md b/docs/zh-cn/data.md
index 6638fb48a..6a69433ec 100644
--- a/docs/zh-cn/data.md
+++ b/docs/zh-cn/data.md
@@ -9,7 +9,46 @@
如果想要同时向多个子应用发送数据,可以看一下节[全局数据通信](/zh-cn/data?id=全局数据通信)
-### 1、基座应用向子应用发送数据
+
+### 1、子应用获取来自基座应用的数据
+ `micro-app`会向子应用注入名称为`microApp`的全局对象,子应用通过这个对象和基座应用进行数据交互。
+
+ 有两种方式获取来自基座应用的数据:
+
+ **方式1:绑定/解绑监听函数**
+
+ 监听函数只有在数据变化时才会触发。
+ ```js
+ function dataListener (data) {
+ console.log('来自基座应用的数据', data)
+ }
+
+ /**
+ * 绑定监听函数
+ * dataListener: 绑定函数
+ * autoTrigger: 在初次绑定监听函数时有缓存数据,是否需要主动触发一次,默认为false
+ * 补充: autoTrigger主要是为子应用提供的,因为子应用是异步渲染的,如果在子应用还没渲染时基座应用发送数据,子应用在初始化后不会触发绑定函数,但这个数据会放入缓存中,此时可以设置autoTrigger为true主动触发一次监听函数来获取数据。
+ */
+ window.microApp?.addDataListener(dataListener: Function, autoTrigger?: boolean)
+
+ // 解绑指定函数
+ window.microApp?.removeDataListener(dataListener)
+
+ // 清空当前子应用的所有绑定函数(全局数据函数除外)
+ window.microApp?.clearDataListener()
+ ```
+
+ **方式2:主动获取数据**
+ ```js
+ window.microApp?.getData() // 返回data数据
+ ```
+
+### 2、子应用向基座应用发送数据
+```js
+window.microApp?.dispatch({type: '子应用发送的数据'})
+```
+
+### 3、基座应用向子应用发送数据
基座应用向子应用发送数据有两种方式:
**方式1: 通过data属性发送数据**
@@ -56,44 +95,6 @@
microApp.setData('my-app', {type: '新的数据'})
```
-### 2、子应用获取来自基座应用的数据
- `micro-app`会向子应用注入名称为`microApp`的全局对象,子应用通过这个对象和基座应用进行数据交互。
-
- 有两种方式获取来自基座应用的数据:
-
- **方式1:绑定/解绑监听函数**
-
- 监听函数只有在数据变化时才会触发。
- ```js
- function dataListener (data) {
- console.log('来自基座应用的数据', data)
- }
-
- /**
- * 绑定监听函数
- * dataListener: 绑定函数
- * autoTrigger: 在初次绑定监听函数时有缓存数据,是否需要主动触发一次,默认为false
- * 补充: autoTrigger主要是为子应用提供的,因为子应用是异步渲染的,如果在子应用还没渲染时基座应用发送数据,子应用在初始化后不会触发绑定函数,但这个数据会放入缓存中,此时可以设置autoTrigger为true主动触发一次监听函数来获取数据。
- */
- window.microApp?.addDataListener(dataListener: Function, autoTrigger?: boolean)
-
- // 解绑指定函数
- window.microApp?.removeDataListener(dataListener)
-
- // 清空当前子应用的所有绑定函数(全局数据函数除外)
- window.microApp?.clearDataListener()
- ```
-
- **方式2:主动获取数据**
- ```js
- window.microApp?.getData() // 返回data数据
- ```
-
-### 3、子应用向基座应用发送数据
-```js
-window.microApp?.dispatch({type: '子应用发送的数据'})
-```
-
### 4、基座应用获取来自子应用的数据
基座应用获取来自子应用的数据有三种方式:
diff --git a/examples/children/vite/src/main.js b/examples/children/vite/src/main.js
index 0e414beba..8c0d9049e 100644
--- a/examples/children/vite/src/main.js
+++ b/examples/children/vite/src/main.js
@@ -18,7 +18,6 @@ const routes = [
// app.use(router)
// app.mount('#vite-app')
-
let app = null
let router = null
let history = null
@@ -35,12 +34,28 @@ function mount () {
app.mount('#vite-app')
console.log('微应用child-vite渲染了')
+
+ // eventCenterForVite 是基座添加到window的数据通信对象
+ // 主动获取基座下发的数据
+ console.log('child-vite getData:', window.eventCenterForVite?.getData())
+
+ // 监听基座下发的数据变化
+ window.eventCenterForVite?.addDataListener((data) => {
+ console.log('child-vite addDataListener:', data)
+ })
+
+ // 向基座发送数据
+ setTimeout(() => {
+ window.eventCenterForVite?.dispatch({ myname: 'child-vite' })
+ }, 3000)
}
// 将卸载操作放入 unmount 函数
function unmount () {
app?.unmount()
history?.destroy()
+ // 卸载所有数据监听函数
+ window.eventCenterForVite?.clearDataListener()
app = null
router = null
history = null
diff --git a/examples/main-react16/src/pages/vite/vite.js b/examples/main-react16/src/pages/vite/vite.js
index 0adc65853..b3c57e214 100644
--- a/examples/main-react16/src/pages/vite/vite.js
+++ b/examples/main-react16/src/pages/vite/vite.js
@@ -4,9 +4,13 @@ import jsxCustomEvent from '@micro-zoe/micro-app/polyfill/jsx-custom-event'
import { useState } from 'react'
import { Button, Spin } from 'antd'
import { LoadingOutlined } from '@ant-design/icons'
+import { EventCenterForMicroApp } from '@micro-zoe/micro-app'
import config from '../../config'
import './vite.less'
+// 注册子应用vite的数据通信对象
+window.eventCenterForVite = new EventCenterForMicroApp('vite')
+
const antIcon =
function vite () {
@@ -18,9 +22,13 @@ function vite () {
console.log('生命周期: vite 渲染完成了')
}
+ function handleDataChange (e) {
+ console.log('来自 vite 子应用的数据', e.detail.data)
+ }
+
return (
- {/*
+
-
*/}
+
{
showLoading &&
}
@@ -39,6 +47,7 @@ function vite () {
data={data}
// onBeforemount={() => hideLoading(false)}
onMounted={handleMounted}
+ onDataChange={handleDataChange}
// destroy
// inline
disableSandbox
diff --git a/jest.config.js b/jest.config.js
index 996802b9e..655872bd2 100755
--- a/jest.config.js
+++ b/jest.config.js
@@ -39,6 +39,7 @@ module.exports = {
],
globals: {
__DEV__: true,
+ __TEST__: true,
'ts-jest': {
tsconfig: {
target: 'es5',
diff --git a/package.json b/package.json
index bb96c46a1..247cb5583 100644
--- a/package.json
+++ b/package.json
@@ -1,7 +1,7 @@
{
"name": "@micro-zoe/micro-app",
- "version": "0.4.2",
- "description": "A minimalist solution for building micro front-end applications",
+ "version": "0.4.3",
+ "description": "A lightweight, efficient and powerful micro front-end framework",
"private": false,
"main": "lib/index.min.js",
"module": "lib/index.esm.js",
@@ -82,9 +82,6 @@
]
},
"dependencies": {},
- "peerDependencies": {
- "@babel/runtime": ">=7.0.0"
- },
"devDependencies": {
"@babel/core": "~7.12.10",
"@babel/plugin-transform-runtime": "~7.12.10",
diff --git a/rollup.config.js b/rollup.config.js
index 08a8cae4d..3cbea7f3c 100644
--- a/rollup.config.js
+++ b/rollup.config.js
@@ -33,6 +33,7 @@ const commonPlugins = [
replace({
preventAssignment: true,
__VERSION__: version,
+ __TEST__: 'false',
})
]
diff --git a/src/__tests__/libs/utils.test.ts b/src/__tests__/libs/utils.test.ts
index bbae745ff..8fab30a7a 100644
--- a/src/__tests__/libs/utils.test.ts
+++ b/src/__tests__/libs/utils.test.ts
@@ -179,3 +179,11 @@ test('get element that not marked by micro-app', () => {
test('coverage of isNull function', () => {
expect(Utils.isNull(null)).toBeTruthy()
})
+
+test('coverage of isInvalidQuerySelectorKey', () => {
+ // @ts-ignore
+ window.__TEST__ = false
+ expect(Utils.isInvalidQuerySelectorKey('a&bc')).toBeTruthy()
+ // @ts-ignore
+ window.__TEST__ = true
+})
diff --git a/src/__tests__/source/patch.test.ts b/src/__tests__/source/patch.test.ts
index 6414ab25f..5a584c797 100644
--- a/src/__tests__/source/patch.test.ts
+++ b/src/__tests__/source/patch.test.ts
@@ -298,43 +298,32 @@ describe('source patch', () => {
setAppName('test-app2')
const fakerDoc = new Document()
- // 以下覆盖Document原型方法this为空或this不是document的情况
- const createElement = Document.prototype.createElement
- createElement.call(fakerDoc, 'div')
- createElement.call('', 'div')
-
- const createElementNS = Document.prototype.createElementNS
- createElementNS.call(fakerDoc, 'http://www.w3.org/1999/xhtml', 'svg')
- createElementNS.call('', 'http://www.w3.org/1999/xhtml', 'svg')
-
- const createDocumentFragment = Document.prototype.createDocumentFragment
- createDocumentFragment.call(fakerDoc)
- createDocumentFragment.call('')
-
const querySelector = Document.prototype.querySelector
querySelector.call(fakerDoc, 'div')
- querySelector.call('', 'div')
const querySelectorAll = Document.prototype.querySelectorAll
querySelectorAll.call(fakerDoc, 'div')
- querySelectorAll.call('', 'div')
- clearAppName() // clear scoped
- const getElementById = Document.prototype.getElementById
- getElementById.call(fakerDoc, 'id')
- getElementById.call('', 'id')
+ reslove(true)
+ })
+ })
+ })
- const getElementsByClassName = Document.prototype.getElementsByClassName
- getElementsByClassName.call(fakerDoc, 'classname')
- getElementsByClassName.call('', 'classname')
+ // 分支覆盖 - 错误的 querySelector key
+ test('coverage of error querySelector key', async () => {
+ const microappElement3 = document.createElement('micro-app')
+ microappElement3.setAttribute('name', 'test-app3')
+ microappElement3.setAttribute('url', `http://127.0.0.1:${ports.source_patch}/ssr-render/`)
- const getElementsByTagName = Document.prototype.getElementsByTagName
- getElementsByTagName.call(fakerDoc, 'div')
- getElementsByTagName.call('', 'div')
+ appCon.appendChild(microappElement3)
- const getElementsByName = Document.prototype.getElementsByName
- getElementsByName.call(fakerDoc, 'name')
- getElementsByName.call('', 'name')
+ await new Promise((reslove) => {
+ microappElement3.addEventListener('mounted', () => {
+ setAppName('test-app3')
+ document.getElementById('sd$fs')
+ document.getElementsByClassName('sd$fs')
+ document.getElementsByTagName('sd$fs')
+ document.getElementsByName('sd$fs')
reslove(true)
})
diff --git a/src/index.ts b/src/index.ts
index b08ac50da..42cc1be68 100644
--- a/src/index.ts
+++ b/src/index.ts
@@ -1,3 +1,4 @@
-export { default as preFetch } from './prefetch'
export { default } from './micro_app'
+export { default as preFetch } from './prefetch'
export { removeDomScope, pureCreateElement, version, setCurrentAppName } from './libs/utils'
+export { EventCenterForMicroApp } from './interact'
diff --git a/src/libs/utils.ts b/src/libs/utils.ts
index e73d12ede..10fc254af 100644
--- a/src/libs/utils.ts
+++ b/src/libs/utils.ts
@@ -139,6 +139,11 @@ export function formatURL (url: string | null, appName: string | null = null): s
}
}
+// export function formatName (name: string): string {
+// if (!isString(name) || !name) return ''
+// return name.replace(/(^\d+)|([^\w\d-_])/gi, '')
+// }
+
/**
* Get valid address, such as https://xxx/xx/xx.html to https://xxx/xx/
* @param url app.url
@@ -314,3 +319,18 @@ export function cloneNode
(
})
}
}
+
+// is invalid key of querySelector
+export function isInvalidQuerySelectorKey (key: string): boolean {
+ if (__TEST__) return !key || /(^\d)|([^\w\d-_$])/gi.test(key)
+ return !key || /(^\d)|([^\w\d-_\u4e00-\u9fa5])/gi.test(key)
+}
+
+// unique element
+export function isUniqueElement (key: string): boolean {
+ return (
+ /^body$/i.test(key) ||
+ /^head$/i.test(key) ||
+ /^html$/i.test(key)
+ )
+}
diff --git a/src/source/patch.ts b/src/source/patch.ts
index e73448676..aaad5b809 100644
--- a/src/source/patch.ts
+++ b/src/source/patch.ts
@@ -8,6 +8,8 @@ import {
logWarn,
isPlainObject,
isString,
+ isInvalidQuerySelectorKey,
+ isUniqueElement,
} from '../libs/utils'
import scopedCSS from './scoped_css'
import { extractLinkFromHtml, foramtDynamicLink } from './links'
@@ -289,9 +291,7 @@ export function patchElementPrototypeMethods (): void {
*/
function markElement (element: T): T {
const appName = getCurrentAppName()
- if (appName) {
- element.__MICRO_APP_NAME__ = appName
- }
+ appName && (element.__MICRO_APP_NAME__ = appName)
return element
}
@@ -304,8 +304,7 @@ function patchDocument () {
tagName: string,
options?: ElementCreationOptions,
): HTMLElement {
- const _this = this && rawDocument !== this ? this : rawDocument
- const element = globalEnv.rawCreateElement.call(_this, tagName, options)
+ const element = globalEnv.rawCreateElement.call(this, tagName, options)
return markElement(element)
}
@@ -314,38 +313,39 @@ function patchDocument () {
name: string,
options?: string | ElementCreationOptions,
): any {
- const _this = this && rawDocument !== this ? this : rawDocument
- const element = globalEnv.rawCreateElementNS.call(_this, namespaceURI, name, options)
+ const element = globalEnv.rawCreateElementNS.call(this, namespaceURI, name, options)
return markElement(element)
}
Document.prototype.createDocumentFragment = function createDocumentFragment (): DocumentFragment {
- const _this = this && rawDocument !== this ? this : rawDocument
- const element = globalEnv.rawCreateDocumentFragment.call(_this)
+ const element = globalEnv.rawCreateDocumentFragment.call(this)
return markElement(element)
}
// query element👇
function querySelector (this: Document, selectors: string): any {
- /**
- * The hijacking of queryselector should only occur on rawDocument, we should ignore document created by new DOMParser().parseFromString()
- * see https://github.com/micro-zoe/micro-app/issues/56
- */
- if (this && rawDocument !== this) return globalEnv.rawQuerySelector.call(this, selectors)
-
const appName = getCurrentAppName()
- if (!appName || selectors === 'head' || selectors === 'body' || selectors === 'html') {
- return globalEnv.rawQuerySelector.call(rawDocument, selectors)
+ if (
+ !appName ||
+ !selectors ||
+ isUniqueElement(selectors) ||
+ // see https://github.com/micro-zoe/micro-app/issues/56
+ rawDocument !== this
+ ) {
+ return globalEnv.rawQuerySelector.call(this, selectors)
}
return appInstanceMap.get(appName)?.container?.querySelector(selectors) ?? null
}
function querySelectorAll (this: Document, selectors: string): any {
- if (this && rawDocument !== this) return globalEnv.rawQuerySelectorAll.call(this, selectors)
-
const appName = getCurrentAppName()
- if (!appName || selectors === 'head' || selectors === 'body' || selectors === 'html') {
- return globalEnv.rawQuerySelectorAll.call(rawDocument, selectors)
+ if (
+ !appName ||
+ !selectors ||
+ isUniqueElement(selectors) ||
+ rawDocument !== this
+ ) {
+ return globalEnv.rawQuerySelectorAll.call(this, selectors)
}
return appInstanceMap.get(appName)?.container?.querySelectorAll(selectors) ?? []
}
@@ -353,47 +353,58 @@ function patchDocument () {
Document.prototype.querySelector = querySelector
Document.prototype.querySelectorAll = querySelectorAll
- // querySelector does not support the beginning of a number
Document.prototype.getElementById = function getElementById (key: string): HTMLElement | null {
- const appName = getCurrentAppName()
- if (!appName || /^\d/.test(key)) {
- const _this = this && rawDocument !== this ? this : rawDocument
- return globalEnv.rawGetElementById.call(_this, key)
+ if (!getCurrentAppName() || isInvalidQuerySelectorKey(key)) {
+ return globalEnv.rawGetElementById.call(this, key)
+ }
+
+ try {
+ return querySelector.call(this, `#${key}`)
+ } catch {
+ return globalEnv.rawGetElementById.call(this, key)
}
- return querySelector.call(this, `#${key}`)
}
Document.prototype.getElementsByClassName = function getElementsByClassName (key: string): HTMLCollectionOf {
- const appName = getCurrentAppName()
- if (!appName || /^\d/.test(key)) {
- const _this = this && rawDocument !== this ? this : rawDocument
- return globalEnv.rawGetElementsByClassName.call(_this, key)
+ if (!getCurrentAppName() || isInvalidQuerySelectorKey(key)) {
+ return globalEnv.rawGetElementsByClassName.call(this, key)
+ }
+
+ try {
+ return querySelectorAll.call(this, `.${key}`)
+ } catch {
+ return globalEnv.rawGetElementsByClassName.call(this, key)
}
- return querySelectorAll.call(this, `.${key}`)
}
Document.prototype.getElementsByTagName = function getElementsByTagName (key: string): HTMLCollectionOf {
const appName = getCurrentAppName()
if (
!appName ||
- /^body$/i.test(key) ||
- /^head$/i.test(key) ||
- /^html$/i.test(key) ||
+ isUniqueElement(key) ||
+ isInvalidQuerySelectorKey(key) ||
(!appInstanceMap.get(appName)?.inline && /^script$/i.test(key))
) {
- const _this = this && rawDocument !== this ? this : rawDocument
- return globalEnv.rawGetElementsByTagName.call(_this, key)
+ return globalEnv.rawGetElementsByTagName.call(this, key)
+ }
+
+ try {
+ return querySelectorAll.call(this, key)
+ } catch {
+ return globalEnv.rawGetElementsByTagName.call(this, key)
}
- return querySelectorAll.call(this, key)
}
Document.prototype.getElementsByName = function getElementsByName (key: string): NodeListOf {
- const appName = getCurrentAppName()
- if (!appName || /^\d/.test(key)) {
- const _this = this && rawDocument !== this ? this : rawDocument
- return globalEnv.rawGetElementsByName.call(_this, key)
+ if (!getCurrentAppName() || isInvalidQuerySelectorKey(key)) {
+ return globalEnv.rawGetElementsByName.call(this, key)
+ }
+
+ try {
+ return querySelectorAll.call(this, `[name=${key}]`)
+ } catch {
+ return globalEnv.rawGetElementsByName.call(this, key)
}
- return querySelectorAll.call(this, `[name=${key}]`)
}
}
diff --git a/typings/global.d.ts b/typings/global.d.ts
index dfbea916d..e9abdda68 100644
--- a/typings/global.d.ts
+++ b/typings/global.d.ts
@@ -191,3 +191,7 @@ declare namespace JSX {
}
declare module '@micro-zoe/micro-app/polyfill/jsx-custom-event'
+
+declare const __DEV__: boolean
+
+declare const __TEST__: boolean