diff --git a/packages/uni-app-plus/dist/uni.runtime.esm.js b/packages/uni-app-plus/dist/uni.runtime.esm.js index af2eb58c7a0d467d35567148824c062b6a95d257..5559d3f1f333f0fdcdd74a18e965e3795c2fa5eb 100644 --- a/packages/uni-app-plus/dist/uni.runtime.esm.js +++ b/packages/uni-app-plus/dist/uni.runtime.esm.js @@ -18247,7 +18247,7 @@ function initPageOptions({ meta }) { } function initNVuePage(id, nvuePageVm, pageInstance) { initPageVm(nvuePageVm, pageInstance); - addCurrentPage(nvuePageVm); + addCurrentPage(initScope(id, nvuePageVm, pageInstance)); if (id === 1) { // 首页是 nvue 时,在 registerPage 时,执行路由堆栈 if (__uniConfig.splashscreen && diff --git a/packages/uni-app-plus/src/service/framework/page/register.ts b/packages/uni-app-plus/src/service/framework/page/register.ts index 4e3819aa8b08e1edb90bedb3a0cd7a3bb69fdccc..355d8e5f201a7a025f37956bda30425c9bbfcbc1 100644 --- a/packages/uni-app-plus/src/service/framework/page/register.ts +++ b/packages/uni-app-plus/src/service/framework/page/register.ts @@ -19,6 +19,7 @@ import { addCurrentPage, getAllPages } from './getCurrentPages' import { getBaseSystemInfo } from '../../api/base/getBaseSystemInfo' import { preloadWebviews, PreloadWebviewObject } from './preLoad' import { navigateFinish } from '../../api/route/utils' +import { initScope } from './setup' interface RegisterPageOptions { url: string @@ -154,7 +155,7 @@ function initNVuePage( pageInstance: Page.PageInstance['$page'] ) { initPageVm(nvuePageVm, pageInstance) - addCurrentPage(nvuePageVm) + addCurrentPage(initScope(id, nvuePageVm, pageInstance)) if (id === 1) { // 首页是 nvue 时,在 registerPage 时,执行路由堆栈 if ( diff --git a/packages/uni-app-plus/src/service/framework/page/setup.ts b/packages/uni-app-plus/src/service/framework/page/setup.ts index bf581c118645d6e984f4f016599659ede0acc4a3..1101e3a7b43a37bcc5578000b1c45f1042cb9b45 100644 --- a/packages/uni-app-plus/src/service/framework/page/setup.ts +++ b/packages/uni-app-plus/src/service/framework/page/setup.ts @@ -52,7 +52,7 @@ export function setupPage(component: VuePageComponent) { return component } -function initScope( +export function initScope( pageId: number, vm: ComponentPublicInstance, pageInstance: Page.PageInstance['$page'] diff --git a/packages/uni-app-vite/package.json b/packages/uni-app-vite/package.json index d8d4f7ea0a60e884d192fd45d6ea33eb21d83349..0ebdc10ce18dbdd40a3b6504cb2b256988f97dfd 100644 --- a/packages/uni-app-vite/package.json +++ b/packages/uni-app-vite/package.json @@ -25,6 +25,7 @@ "@dcloudio/uni-shared": "0.0.1-nvue3.3040020220221001", "@rollup/pluginutils": "^4.1.2", "@vitejs/plugin-vue": "^2.2.2", + "@vue/compiler-dom": "3.2.31", "@vue/compiler-sfc": "3.2.31", "debug": "^4.3.3", "fs-extra": "^10.0.0", diff --git a/packages/uni-app-vite/src/nvue/plugin/index.ts b/packages/uni-app-vite/src/nvue/plugin/index.ts index 5973c6084844a01d3acf360257fe951ae71699d1..bbdaaa224ceadaf62ec1b4388fe27721aa7fd9d1 100644 --- a/packages/uni-app-vite/src/nvue/plugin/index.ts +++ b/packages/uni-app-vite/src/nvue/plugin/index.ts @@ -25,6 +25,7 @@ import { createConfigResolved } from '../../plugin/configResolved' import { defaultNVueRpx2Unit } from '@dcloudio/uni-shared' import { external, globals } from '../utils' import { transformRootNode } from './transforms/transformRootNode' +import { transformModel } from './transforms/vModel' const uTags = { text: 'u-text', @@ -48,6 +49,12 @@ export function initNVueNodeTransforms() { ] } +export function initNVueDirectiveTransforms() { + return { + model: transformModel, + } +} + export function uniAppNVuePlugin({ appService, }: { diff --git a/packages/uni-app-vite/src/nvue/plugin/transforms/vModel.ts b/packages/uni-app-vite/src/nvue/plugin/transforms/vModel.ts new file mode 100644 index 0000000000000000000000000000000000000000..21b922c689426f3c19ab7a2de451d4e4f544e43e --- /dev/null +++ b/packages/uni-app-vite/src/nvue/plugin/transforms/vModel.ts @@ -0,0 +1,98 @@ +import { + transformModel as baseTransform, + DirectiveTransform, + ElementTypes, + findProp, + NodeTypes, + hasDynamicKeyVBind, +} from '@vue/compiler-core' +import { createDOMCompilerError, DOMErrorCodes } from '@vue/compiler-dom' +import { V_MODEL_TEXT, V_MODEL_DYNAMIC } from '@vue/compiler-dom' + +export const transformModel: DirectiveTransform = (dir, node, context) => { + const baseResult = baseTransform(dir, node, context) + // base transform has errors OR component v-model (only need props) + if (!baseResult.props.length || node.tagType === ElementTypes.COMPONENT) { + return baseResult + } + + if (dir.arg) { + context.onError( + createDOMCompilerError( + DOMErrorCodes.X_V_MODEL_ARG_ON_ELEMENT, + dir.arg.loc + ) + ) + } + + function checkDuplicatedValue() { + const value = findProp(node, 'value') + if (value) { + context.onError( + createDOMCompilerError( + DOMErrorCodes.X_V_MODEL_UNNECESSARY_VALUE, + value.loc + ) + ) + } + } + + const { tag } = node + const isCustomElement = context.isCustomElement(tag) + if ( + tag === 'input' || + tag === 'u-input' || + tag === 'textarea' || + tag === 'u-textarea' || + isCustomElement + ) { + let directiveToUse = V_MODEL_TEXT + let isInvalidType = false + if (tag === 'input' || tag === 'u-input' || isCustomElement) { + const type = findProp(node, `type`) + if (type) { + if (type.type === NodeTypes.DIRECTIVE) { + // :type="foo" + directiveToUse = V_MODEL_DYNAMIC + } else if (type.value) { + checkDuplicatedValue() + } + } else if (hasDynamicKeyVBind(node)) { + // element has bindings with dynamic keys, which can possibly contain + // "type". + directiveToUse = V_MODEL_DYNAMIC + } else { + // text type + checkDuplicatedValue() + } + } else { + // textarea + checkDuplicatedValue() + } + // inject runtime directive + // by returning the helper symbol via needRuntime + // the import will replaced a resolveDirective call. + if (!isInvalidType) { + baseResult.needRuntime = context.helper(directiveToUse) + } + } else { + context.onError( + createDOMCompilerError( + DOMErrorCodes.X_V_MODEL_ON_INVALID_ELEMENT, + dir.loc + ) + ) + } + + // native vmodel doesn't need the `modelValue` props since they are also + // passed to the runtime as `binding.value`. removing it reduces code size. + baseResult.props = baseResult.props.filter( + (p) => + !( + p.key.type === NodeTypes.SIMPLE_EXPRESSION && + p.key.content === 'modelValue' + ) + ) + + return baseResult +} diff --git a/packages/uni-app-vite/src/nvue/plugins/esbuild.ts b/packages/uni-app-vite/src/nvue/plugins/esbuild.ts index b920a0f3047aa0c422120f69b9fb5d03a11f31a6..9b12914d0859700cbe2b71ac8d6be4c25d857e1a 100644 --- a/packages/uni-app-vite/src/nvue/plugins/esbuild.ts +++ b/packages/uni-app-vite/src/nvue/plugins/esbuild.ts @@ -109,7 +109,7 @@ const __pagePath = '${removeExt(filename)}' let __pageQuery = {} try{ __pageQuery = JSON.parse(webview.__query__) }catch(e){} App.mpType = 'page' -const app = Vue.createPageApp(App,{$store:getApp().$store,__pageId,__pagePath,__pageQuery}) +const app = Vue.createPageApp(App,{$store:getApp({allowDefault:true}).$store,__pageId,__pagePath,__pageQuery}) app.provide('__globalStyles', Vue.useCssStyles([...__uniConfig.styles, ...(App.styles||[])])) app.mount('#root')`, path.join(nvueOutDir(), 'main.js'), diff --git a/packages/uni-app-vite/src/plugin/uni/index.ts b/packages/uni-app-vite/src/plugin/uni/index.ts index 45ad6ad5b14797172c3f0eefcb2d15ca4795cc89..0532d3bcfb1f04b2ac8e9dabecac86502428712a 100644 --- a/packages/uni-app-vite/src/plugin/uni/index.ts +++ b/packages/uni-app-vite/src/plugin/uni/index.ts @@ -12,6 +12,7 @@ import { } from '@dcloudio/uni-cli-shared' import { initNVueNodeTransforms } from '../../nvue' +import { initNVueDirectiveTransforms } from '../../nvue/plugin' export function uniOptions(): UniVitePlugin['uni'] { const isNVueCompiler = process.env.UNI_COMPILER === 'nvue' @@ -53,6 +54,9 @@ export function uniOptions(): UniVitePlugin['uni'] { transformMatchMedia, transformPageHead, ], + directiveTransforms: { + ...(isNVueCompiler ? initNVueDirectiveTransforms() : {}), + }, }, } } diff --git a/packages/uni-app-vite/src/vue/plugins/mainJs.ts b/packages/uni-app-vite/src/vue/plugins/mainJs.ts index dda49efca02eb2bc411ee490c8a8a2392623d51d..d453977326a2f701d09b6da8518d59f3b6aca184 100644 --- a/packages/uni-app-vite/src/vue/plugins/mainJs.ts +++ b/packages/uni-app-vite/src/vue/plugins/mainJs.ts @@ -24,11 +24,11 @@ function createApp(code: string) { return `${code.replace( 'createSSRApp', 'createVueApp as createSSRApp' - )};const {app:__app__,Vuex:__Vuex__,Pinia:__Pinia__}=createApp();uni.Vuex=__Vuex__;uni.Pinia=__Pinia__;__app__._component.mpType='app';__app__._component.render=()=>{};__app__.mount("#app");` + )};const {app:__app__,Vuex:__Vuex__,Pinia:__Pinia__}=createApp();uni.Vuex=__Vuex__;uni.Pinia=__Pinia__;__app__.provide('__globalStyles', __uniConfig.styles);__app__._component.mpType='app';__app__._component.render=()=>{};__app__.mount("#app");` } function createLegacyApp(code: string) { - return `function createApp(rootComponent,rootProps){rootComponent.mpTye='app';rootComponent.render=()=>{};const app=createVueApp(rootComponent,rootProps);const oldMount=app.mount;app.mount=(container)=>{const appVm=oldMount.call(app,container);return appVm;};return app;};${code.replace( + return `function createApp(rootComponent,rootProps){rootComponent.mpTye='app';rootComponent.render=()=>{};const app=createVueApp(rootComponent,rootProps);app.provide('__globalStyles', __uniConfig.styles);const oldMount=app.mount;app.mount=(container)=>{const appVm=oldMount.call(app,container);return appVm;};return app;};${code.replace( 'createApp', 'createVueApp' )}` diff --git a/packages/uni-app-vue/dist/nvue.runtime.esm.dev.js b/packages/uni-app-vue/dist/nvue.runtime.esm.dev.js index 50e66400ddea455dc1f78e908b4f6d5722743bb7..92db52e8721b01c921f8cef0255d67defaf7b6d4 100644 --- a/packages/uni-app-vue/dist/nvue.runtime.esm.dev.js +++ b/packages/uni-app-vue/dist/nvue.runtime.esm.dev.js @@ -9433,6 +9433,11 @@ function parseStyleSheet(_ref22) { var component = type; if (!component.__styles) { + // nvue 和 vue 混合开发时,__globalStyles注入的是未处理过的 + if (appContext && isArray(appContext.provides.__globalStyles)) { + appContext.provides.__globalStyles = useCssStyles(appContext.provides.__globalStyles); + } + if (component.mpType === 'page' && appContext) { // 如果是页面组件,则直接使用全局样式 component.__styles = appContext.provides.__globalStyles; diff --git a/packages/uni-app-vue/dist/nvue.runtime.esm.prod.js b/packages/uni-app-vue/dist/nvue.runtime.esm.prod.js index fb65e2eb2e832732772cc38fd2be6bac1e2abb4c..1b84cfa3ec6cc006116a0cf808f82fd79371ae19 100644 --- a/packages/uni-app-vue/dist/nvue.runtime.esm.prod.js +++ b/packages/uni-app-vue/dist/nvue.runtime.esm.prod.js @@ -7700,6 +7700,11 @@ function parseStyleSheet(_ref22) { var component = type; if (!component.__styles) { + // nvue 和 vue 混合开发时,__globalStyles注入的是未处理过的 + if (appContext && isArray(appContext.provides.__globalStyles)) { + appContext.provides.__globalStyles = useCssStyles(appContext.provides.__globalStyles); + } + if (component.mpType === 'page' && appContext) { // 如果是页面组件,则直接使用全局样式 component.__styles = appContext.provides.__globalStyles; diff --git a/packages/uni-app-vue/lib/nvue.runtime.esm.js b/packages/uni-app-vue/lib/nvue.runtime.esm.js index 48340f238356829af13eee50f4e01ac206ff6f21..358592e2b867255d3e11345296f026eb651b02e0 100644 --- a/packages/uni-app-vue/lib/nvue.runtime.esm.js +++ b/packages/uni-app-vue/lib/nvue.runtime.esm.js @@ -7892,6 +7892,10 @@ function parseClassList(classList, instance, el = null) { function parseStyleSheet({ type, appContext }) { const component = type; if (!component.__styles) { + // nvue 和 vue 混合开发时,__globalStyles注入的是未处理过的 + if (appContext && isArray(appContext.provides.__globalStyles)) { + appContext.provides.__globalStyles = useCssStyles(appContext.provides.__globalStyles); + } if (component.mpType === 'page' && appContext) { // 如果是页面组件,则直接使用全局样式 component.__styles = appContext.provides.__globalStyles; diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index ef96609342602b64248fe1863404e1cb472b1aaa..c760f05c39cc7b573cda0fbc0ef22b5a233617c7 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -207,6 +207,7 @@ importers: '@types/fs-extra': ^9.0.13 '@vitejs/plugin-vue': ^2.2.2 '@vue/compiler-core': 3.2.31 + '@vue/compiler-dom': 3.2.31 '@vue/compiler-sfc': 3.2.31 debug: ^4.3.3 esbuild: ^0.14.14 @@ -221,6 +222,7 @@ importers: '@dcloudio/uni-shared': link:../uni-shared '@rollup/pluginutils': 4.1.2 '@vitejs/plugin-vue': 2.2.2_vite@2.8.4+vue@3.2.31 + '@vue/compiler-dom': 3.2.31 '@vue/compiler-sfc': 3.2.31 debug: 4.3.3 fs-extra: 10.0.0