diff --git a/packages/uni-core/src/view/plugin/appConfig.ts b/packages/uni-core/src/view/plugin/appConfig.ts
index 05ceaf9b3cba773cd05944d4aabd5969399c7bb2..7b7c073948e1bc596cb9306a468d9a058973a873 100644
--- a/packages/uni-core/src/view/plugin/appConfig.ts
+++ b/packages/uni-core/src/view/plugin/appConfig.ts
@@ -9,12 +9,13 @@ export function initAppConfig(appConfig: AppConfig) {
const globalProperties = appConfig.globalProperties
extend(globalProperties, instance)
if (__UNI_FEATURE_WXS__) {
- globalProperties.getComponentDescriptor = getComponentDescriptor
- Object.defineProperty(globalProperties, '$ownerInstance', {
- get() {
- return this.$getComponentDescriptor(this)
- },
- })
+ //$getComponentDescriptor
+ globalProperties.$gcd = getComponentDescriptor
+ // Object.defineProperty(globalProperties, '$ownerInstance', {
+ // get() {
+ // return getComponentDescriptor(this)
+ // },
+ // })
// globalProperties.$handleWxsEvent = handleWxsEvent
}
}
diff --git a/packages/uni-core/src/view/plugin/componentWxs.ts b/packages/uni-core/src/view/plugin/componentWxs.ts
index 40d48d35960ccce88e13fc8bf69280eaa380d986..ab44ea3535c04158d7dc651b734c4f5c60b5f13c 100644
--- a/packages/uni-core/src/view/plugin/componentWxs.ts
+++ b/packages/uni-core/src/view/plugin/componentWxs.ts
@@ -1,5 +1,6 @@
import { ComponentPublicInstance } from 'vue'
-import { isFunction, isPlainObject } from '@vue/shared'
+import { hyphenate, isFunction, isPlainObject } from '@vue/shared'
+import { isBuiltInComponent } from '@dcloudio/uni-shared'
// import { normalizeEvent, findUniTarget } from './componentEvents'
interface WxsElement extends HTMLElement {
@@ -192,7 +193,7 @@ function createComponentDescriptor(
isOwnerInstance &&
vm &&
vm.$options.name &&
- vm.$options.name.indexOf('VUni') === 0
+ isBuiltInComponent(hyphenate(vm.$options.name))
) {
// ownerInstance 内置组件需要使用父 vm
vm = vm.$parent!
@@ -206,11 +207,10 @@ function createComponentDescriptor(
}
export function getComponentDescriptor(
- this: ComponentPublicInstance,
instance: ComponentPublicInstance,
isOwnerInstance: boolean
) {
- return createComponentDescriptor(instance || this, isOwnerInstance)
+ return createComponentDescriptor(instance, isOwnerInstance)
}
// export function handleWxsEvent(this: ComponentPublicInstance, $event: Event) {
diff --git a/packages/uni-h5-vue/dist/vue.runtime.esm.js b/packages/uni-h5-vue/dist/vue.runtime.esm.js
index bf0db7cbeb45f5dd9b52a862ec505b35493c8c0d..edcc810e7f453e2fa29f96c3e38a0a51d3c0f158 100644
--- a/packages/uni-h5-vue/dist/vue.runtime.esm.js
+++ b/packages/uni-h5-vue/dist/vue.runtime.esm.js
@@ -8424,9 +8424,32 @@ function patchStopImmediatePropagation(e, value) {
}
}
+function patchWxs(el, rawName, nextValue, instance = null) {
+ if (!el.__wxsWatches) {
+ el.__wxsWatches = {};
+ }
+ if (!nextValue) {
+ return el.__wxsWatches[rawName] && el.__wxsWatches[rawName]();
+ }
+ if (!el.__wxsWatches[rawName] && instance && instance.proxy) {
+ const proxy = instance.proxy;
+ const name = rawName.split(':')[1];
+ el.__wxsWatches[rawName] = proxy.$watch(() => instance.attrs[name], (value, oldValue) => {
+ // TODO ownerInstance,instance
+ nextValue(value, oldValue, proxy.$gcd(proxy, true), proxy.$gcd(proxy, true));
+ }, {
+ deep: true
+ });
+ }
+}
+
const nativeOnRE = /^on[a-z]/;
const forcePatchProp = (_, key) => key === 'value';
const patchProp = (el, key, prevValue, nextValue, isSVG = false, prevChildren, parentComponent, parentSuspense, unmountChildren) => {
+ // @ts-expect-error fixed by xxxxxx
+ if (__UNI_FEATURE_WXS__ && key.indexOf('change:') === 0) {
+ patchWxs(el, key, nextValue, parentComponent);
+ }
switch (key) {
// special
case 'class':
diff --git a/packages/uni-h5-vue/lib/vue.runtime.esm.js b/packages/uni-h5-vue/lib/vue.runtime.esm.js
index 4298b6cdaae38e4ce7c242d61ca56275c419437d..3b31283c3a18cf4a8f0000487bd9d70d78c7db8a 100644
--- a/packages/uni-h5-vue/lib/vue.runtime.esm.js
+++ b/packages/uni-h5-vue/lib/vue.runtime.esm.js
@@ -8424,9 +8424,32 @@ function patchStopImmediatePropagation(e, value) {
}
}
+function patchWxs(el, rawName, nextValue, instance = null) {
+ if (!el.__wxsWatches) {
+ el.__wxsWatches = {};
+ }
+ if (!nextValue) {
+ return el.__wxsWatches[rawName] && el.__wxsWatches[rawName]();
+ }
+ if (!el.__wxsWatches[rawName] && instance && instance.proxy) {
+ const proxy = instance.proxy;
+ const name = rawName.split(':')[1];
+ el.__wxsWatches[rawName] = proxy.$watch(() => instance.attrs[name], (value, oldValue) => {
+ // TODO ownerInstance,instance
+ nextValue(value, oldValue, proxy.$gcd(proxy, true), proxy.$gcd(proxy, true));
+ }, {
+ deep: true
+ });
+ }
+}
+
const nativeOnRE = /^on[a-z]/;
const forcePatchProp = (_, key) => key === 'value';
const patchProp = (el, key, prevValue, nextValue, isSVG = false, prevChildren, parentComponent, parentSuspense, unmountChildren) => {
+ // @ts-expect-error fixed by xxxxxx
+ if (__UNI_FEATURE_WXS__ && key.indexOf('change:') === 0) {
+ patchWxs(el, key, nextValue, parentComponent);
+ }
switch (key) {
// special
case 'class':
diff --git a/packages/uni-h5/dist/uni-h5.esm.js b/packages/uni-h5/dist/uni-h5.esm.js
index 06b8c4a2612f2151bc7cdb37f559b9660ae55b41..856f9f491d6781c9cb72546328adf991c5fdfa1e 100644
--- a/packages/uni-h5/dist/uni-h5.esm.js
+++ b/packages/uni-h5/dist/uni-h5.esm.js
@@ -1,6 +1,6 @@
-import {isFunction, extend, isPlainObject, isString, isArray, hasOwn as hasOwn$1, isObject as isObject$1, capitalize, toRawType, makeMap as makeMap$1, isPromise, invokeArrayFns as invokeArrayFns$1, hyphenate} from "@vue/shared";
+import {isFunction, extend, hyphenate, isPlainObject, isString, isArray, hasOwn as hasOwn$1, isObject as isObject$1, capitalize, toRawType, makeMap as makeMap$1, isPromise, invokeArrayFns as invokeArrayFns$1} from "@vue/shared";
import {injectHook, withModifiers, createVNode, inject, provide, reactive, computed, nextTick, getCurrentInstance, onBeforeMount, onMounted, onBeforeActivate, onBeforeDeactivate, openBlock, createBlock, mergeProps, toDisplayString, ref, defineComponent, resolveComponent, toHandlers, renderSlot, watch, onUnmounted, onBeforeUnmount, onActivated, withDirectives, vShow, createTextVNode, createCommentVNode, renderList, onDeactivated, createApp, watchEffect, Transition, withCtx, KeepAlive, resolveDynamicComponent, Fragment} from "vue";
-import {once, passive, normalizeTarget, invokeArrayFns, NAVBAR_HEIGHT, parseQuery, PRIMARY_COLOR, removeLeadingSlash, getLen, ON_REACH_BOTTOM_DISTANCE, decodedQuery, debounce, updateElementStyle, addFont, scrollTo} from "@dcloudio/uni-shared";
+import {once, passive, normalizeTarget, isBuiltInComponent, invokeArrayFns, NAVBAR_HEIGHT, parseQuery, PRIMARY_COLOR, removeLeadingSlash, getLen, ON_REACH_BOTTOM_DISTANCE, decodedQuery, debounce, updateElementStyle, addFont, scrollTo} from "@dcloudio/uni-shared";
import {useRoute, createRouter, createWebHistory, createWebHashHistory, useRouter, isNavigationFailure, RouterView} from "vue-router";
function applyOptions(options, instance2, publicThis) {
Object.keys(options).forEach((name) => {
@@ -1087,7 +1087,7 @@ class ComponentDescriptor {
}
}
function createComponentDescriptor(vm, isOwnerInstance = true) {
- if (isOwnerInstance && vm && vm.$options.name && vm.$options.name.indexOf("VUni") === 0) {
+ if (isOwnerInstance && vm && vm.$options.name && isBuiltInComponent(hyphenate(vm.$options.name))) {
vm = vm.$parent;
}
if (vm && vm.$el) {
@@ -1098,18 +1098,13 @@ function createComponentDescriptor(vm, isOwnerInstance = true) {
}
}
function getComponentDescriptor(instance2, isOwnerInstance) {
- return createComponentDescriptor(instance2 || this, isOwnerInstance);
+ return createComponentDescriptor(instance2, isOwnerInstance);
}
function initAppConfig$1(appConfig) {
const globalProperties = appConfig.globalProperties;
extend(globalProperties, instance);
if (__UNI_FEATURE_WXS__) {
- globalProperties.getComponentDescriptor = getComponentDescriptor;
- Object.defineProperty(globalProperties, "$ownerInstance", {
- get() {
- return this.$getComponentDescriptor(this);
- }
- });
+ globalProperties.$gcd = getComponentDescriptor;
}
}
function initView(app) {
@@ -13144,7 +13139,7 @@ function useToastIcon(props2) {
let showToastState;
let showType = "";
let timeoutId;
-const onHidePopupOnce = once(() => {
+const onHidePopupOnce = /* @__PURE__ */ once(() => {
UniServiceJSBridge.on("onHidePopup", () => hidePopup("onHidePopup"));
});
function createToast(args) {
diff --git a/packages/uni-h5/src/service/api/ui/popup/showToast.ts b/packages/uni-h5/src/service/api/ui/popup/showToast.ts
index 395a874153e84ac21cd717303be8111702634fe8..77d0b8f19fb85a6291ed5c3fe6254eb2a1b9080e 100644
--- a/packages/uni-h5/src/service/api/ui/popup/showToast.ts
+++ b/packages/uni-h5/src/service/api/ui/popup/showToast.ts
@@ -30,7 +30,7 @@ import { once } from '@dcloudio/uni-shared'
let showToastState: ToastProps
let showType: 'onShowToast' | 'onShowLoading' | '' = ''
let timeoutId: number
-const onHidePopupOnce = once(() => {
+const onHidePopupOnce = /*#__PURE__*/ once(() => {
UniServiceJSBridge.on('onHidePopup', () => hidePopup('onHidePopup'))
})
diff --git a/packages/vite-plugin-uni/__tests__/__snapshots__/wxs.spec.ts.snap b/packages/vite-plugin-uni/__tests__/__snapshots__/wxs.spec.ts.snap
new file mode 100644
index 0000000000000000000000000000000000000000..aa0141698860fd9b1c763970a600b3de331e4aea
--- /dev/null
+++ b/packages/vite-plugin-uni/__tests__/__snapshots__/wxs.spec.ts.snap
@@ -0,0 +1,53 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`wxs normalizeWxsCode 1`] = `
+Array [
+ Array [],
+ "
+
+
+ export default{
+ mounted(){
+ console.log('mounted')
+ }
+ }
+
+
+ ",
+]
+`;
+
+exports[`wxs normalizeWxsCode 2`] = `
+Array [
+ Array [],
+ "
+
+
+ export default{
+ mounted(){
+ console.log('mounted')
+ }
+ }
+
+
+ ",
+]
+`;
diff --git a/packages/vite-plugin-uni/__tests__/wxs.spec.ts b/packages/vite-plugin-uni/__tests__/wxs.spec.ts
new file mode 100644
index 0000000000000000000000000000000000000000..0c18f8505dd8b42fe6268d5b66aac4f0783fde0e
--- /dev/null
+++ b/packages/vite-plugin-uni/__tests__/wxs.spec.ts
@@ -0,0 +1,50 @@
+import { normalizeWxsCode } from '../src/configResolved/plugins/preVue'
+
+describe('wxs', () => {
+ test('normalizeWxsCode', () => {
+ expect(
+ normalizeWxsCode(`
+
+
+
+ `)
+ ).toMatchSnapshot()
+ expect(
+ normalizeWxsCode(`
+
+
+
+ `)
+ ).toMatchSnapshot()
+ })
+})
diff --git a/packages/vite-plugin-uni/src/configResolved/plugins/easycom.ts b/packages/vite-plugin-uni/src/configResolved/plugins/easycom.ts
index 060fcb85c9ba279ee29a8434c51c633f5b71e4b8..4cf7a2a2e29bb3971d7fd93314d67817c4d37277 100644
--- a/packages/vite-plugin-uni/src/configResolved/plugins/easycom.ts
+++ b/packages/vite-plugin-uni/src/configResolved/plugins/easycom.ts
@@ -68,7 +68,10 @@ export function uniEasycomPlugin(options: UniPluginFilterOptions): Plugin {
return
}
const { filename, query } = parseVueRequest(id)
- if (query.vue || !EXTNAME_VUE.includes(path.extname(filename))) {
+ if (
+ query.type !== 'template' &&
+ (query.vue || !EXTNAME_VUE.includes(path.extname(filename)))
+ ) {
return
}
debugEasycom(id)
diff --git a/packages/vite-plugin-uni/src/configResolved/plugins/index.ts b/packages/vite-plugin-uni/src/configResolved/plugins/index.ts
index 0662f4a384fed79c76644d6312b2a75ab13736b8..04692ad2b12f7d07a14024cfd57147a41ca32d34 100644
--- a/packages/vite-plugin-uni/src/configResolved/plugins/index.ts
+++ b/packages/vite-plugin-uni/src/configResolved/plugins/index.ts
@@ -15,6 +15,8 @@ import { uniPageVuePlugin } from './pageVue'
import { uniCopyPlugin } from './copy'
import { uniStaticPlugin } from './static'
import { uniCssScopedPlugin } from './cssScoped'
+import { uniRenderjsPlugin } from './renderjs'
+import { uniPreVuePlugin } from './preVue'
const debugPlugin = debug('uni:plugin')
@@ -28,14 +30,13 @@ const UNI_H5_RE = /@dcloudio\/uni-h5/
const COMMON_EXCLUDE = [
/pages\.json\.js$/,
/manifest\.json\.js$/,
- /vue&type=/,
/vite\//,
/\/@vue\//,
/\/vue-router\//,
/\/vuex\//,
/@dcloudio\/uni-h5-vue/,
/@dcloudio\/uni-shared/,
- /\.html$/,
+ /@dcloudio\/uni-components\/style/,
]
const APP_VUE_RE = /App.vue$/
@@ -112,6 +113,9 @@ export function initPlugins(
uniPreCssPlugin(Object.assign(uniPreCssPluginOptions, options)),
'vite:css'
)
+ addPlugin(plugins, uniPreVuePlugin(), 'vite:vue', 'pre')
+ addPlugin(plugins, uniRenderjsPlugin(), 'vite:vue')
+
if (command === 'build') {
addPlugin(
plugins,
diff --git a/packages/vite-plugin-uni/src/configResolved/plugins/pre.ts b/packages/vite-plugin-uni/src/configResolved/plugins/pre.ts
index 174f924cfc4359999f3157403fced04c3ad25a48..6d9a4b8934c8a97bab5a786abb92d8aaea81ad8f 100644
--- a/packages/vite-plugin-uni/src/configResolved/plugins/pre.ts
+++ b/packages/vite-plugin-uni/src/configResolved/plugins/pre.ts
@@ -26,11 +26,12 @@ export function uniPrePlugin(options: UniPluginFilterOptions): Plugin {
return code
}
const { filename, query } = parseVueRequest(id)
- if (query.vue) {
+ if (query.vue && query.type !== 'template') {
return code
}
const extname = path.extname(filename)
- const isHtml = PRE_HTML_EXTNAME.includes(extname)
+ const isHtml =
+ query.type === 'template' || PRE_HTML_EXTNAME.includes(extname)
const isJs = PRE_JS_EXTNAME.includes(extname)
const isPre = isHtml || isJs
if (isPre) {
@@ -49,8 +50,8 @@ export function uniPrePlugin(options: UniPluginFilterOptions): Plugin {
// 读取sourcemap时,需要移除?mpType=page等参数,否则读取不到提示文件不存在
const map = this.getCombinedSourcemap()
if (map) {
- map.sources = map.sources.map((source) =>
- source.replace('?mpType=page', '')
+ map.sources = map.sources.map(
+ (source) => parseVueRequest(source).filename
)
}
return {
diff --git a/packages/vite-plugin-uni/src/configResolved/plugins/preVue.ts b/packages/vite-plugin-uni/src/configResolved/plugins/preVue.ts
new file mode 100644
index 0000000000000000000000000000000000000000..93a6a75e6de2329c968dddad57f452b13a4c3b4b
--- /dev/null
+++ b/packages/vite-plugin-uni/src/configResolved/plugins/preVue.ts
@@ -0,0 +1,115 @@
+import path from 'path'
+import debug from 'debug'
+import { Plugin } from 'vite'
+import {
+ TextModes,
+ NodeTypes,
+ ElementNode,
+ AttributeNode,
+} from '@vue/compiler-core'
+import { parse } from '@vue/compiler-dom'
+import { MagicString } from '@vue/compiler-sfc'
+import { EXTNAME_VUE, parseVueRequest } from '@dcloudio/uni-cli-shared'
+
+const debugPreVue = debug('uni:pre-vue')
+
+const WXS_LANG_RE = /lang=["|'](renderjs|wxs)["|']/
+
+const WXS_ATTRS = ['wxs', 'renderjs']
+
+const sourceToSFC = new Map()
+
+export function uniPreVuePlugin(): Plugin {
+ return {
+ name: 'vite:uni-pre-vue',
+ transform(code, id) {
+ const { filename, query } = parseVueRequest(id)
+ if (query.vue) {
+ return
+ }
+ if (!EXTNAME_VUE.includes(path.extname(filename))) {
+ return
+ }
+ if (!WXS_LANG_RE.test(code)) {
+ return
+ }
+ const sourceKey = code + filename
+ const cache = sourceToSFC.get(sourceKey)
+ if (cache) {
+ debugPreVue('cache', id)
+ return cache
+ }
+ debugPreVue(id)
+ const [errors, wxsCode] = normalizeWxsCode(code)
+ if (errors.length) {
+ this.error(errors.join('\n'))
+ }
+ sourceToSFC.set(sourceKey, wxsCode)
+ return wxsCode
+ },
+ }
+}
+
+export function normalizeWxsCode(code: string): [SyntaxError[], string] {
+ const errors: SyntaxError[] = []
+ const ast = parse(code, {
+ isNativeTag: () => true,
+ isPreTag: () => true,
+ getTextMode: () => TextModes.DATA,
+ onError: (e) => {
+ errors.push(e)
+ },
+ })
+ const wxsNode = ast.children.find(
+ (node) =>
+ node.type === NodeTypes.ELEMENT &&
+ node.tag === 'script' &&
+ node.props.find(
+ (prop) =>
+ prop.name === 'lang' &&
+ prop.type === NodeTypes.ATTRIBUTE &&
+ prop.value &&
+ WXS_ATTRS.includes(prop.value.content)
+ )
+ )
+ if (wxsNode) {
+ code = normalizeWxsNode(code, wxsNode as ElementNode)
+ }
+ return [errors, code]
+}
+
+const SCRIPT_END_LEN = ''.length
+const SCRIPT_START_LEN = '`
+ )
+ }
+ return `${rewriteDefault(code, '_sfc_' + type)}
+export default Comp => {
+ if(!Comp.mixins){Comp.mixins = []}
+ Comp.mixins.push({beforeCreate(){ this['${(query as any).name}'] = this }})
+ Comp.mixins.push(_sfc_${type})
+}`
+ },
+ }
+}
diff --git a/packages/vite-plugin-uni/src/vue/compilerOptions.ts b/packages/vite-plugin-uni/src/vue/compilerOptions.ts
index 4b91493562aca1782c2660f0376298cb271afdcf..e39aa0a422e11c3bff0c2c736b9dfe3ad0131ee3 100644
--- a/packages/vite-plugin-uni/src/vue/compilerOptions.ts
+++ b/packages/vite-plugin-uni/src/vue/compilerOptions.ts
@@ -1,21 +1,12 @@
-import { ElementNode, NodeTransform } from '@vue/compiler-core'
-
import { CompilerOptions, SFCTemplateCompileOptions } from '@vue/compiler-sfc'
import { isNativeTag } from '@dcloudio/uni-shared'
-const transform: NodeTransform = (node, ctx) => {
- if (
- process.env.UNI_PLATFORM !== 'mp-weixin' &&
- (node as ElementNode).tag === 'match-media'
- ) {
- ;(node as ElementNode).tag = 'uni-match-media'
- }
-}
+import { matchMedia } from './transforms/matchMedia'
export const uniVueCompilerOptions: CompilerOptions = {
isNativeTag,
- nodeTransforms: [transform],
+ nodeTransforms: [matchMedia],
}
export const uniVueTransformAssetUrls: SFCTemplateCompileOptions['transformAssetUrls'] = {
diff --git a/packages/vite-plugin-uni/src/vue/transforms/matchMedia.ts b/packages/vite-plugin-uni/src/vue/transforms/matchMedia.ts
new file mode 100644
index 0000000000000000000000000000000000000000..99a9f872e0851604e7d438eae4c04ae13dad40dd
--- /dev/null
+++ b/packages/vite-plugin-uni/src/vue/transforms/matchMedia.ts
@@ -0,0 +1,10 @@
+import { ElementNode, NodeTransform } from '@vue/compiler-core'
+
+export const matchMedia: NodeTransform = (node) => {
+ if (
+ process.env.UNI_PLATFORM !== 'mp-weixin' &&
+ (node as ElementNode).tag === 'match-media'
+ ) {
+ ;(node as ElementNode).tag = 'uni-match-media'
+ }
+}