uni-app CLI 运行APP首屏是 nvue时,引入 pinia插件时报错
uni-app CLI 运行APP首屏是 nvue时,引入 pinia插件时报错
| 开发环境 | 版本号 | 项目创建方式 |
|---|---|---|
| Mac | 15.7.2 | CLI |
产品分类:uniapp/App
PC开发环境操作系统:Mac
手机系统:Android
手机系统版本号:Android 12
手机厂商:华为
手机机型:urovo
页面类型:nvue
vue版本:vue3
打包方式:云端
CLI版本号:3.0.0-alpha-4080720251125001
示例代码:
// # index.nvue
<template>
<view class="content">
<image class="logo" src="/static/logo.png"></image>
<view class="text-area">
<text class="title">{{title}}</text>
</view>
<view class="box">
<input v-model="username" class="box-input" type="text" placeholder="账号">
</view>
<view class="box">
<input v-model="password" class="box-input" type="text" placeholder="密码">
</view>
<text class="login-btn" @click="login">登录</text>
</view>
</template>
<script lang="ts" setup>
import { ref, computed } from 'vue'
import { onLoad } from "@dcloudio/uni-app";
import type { User } from '@/types/index';
import { useAuthStore } from '@/store/auth';
const authStore = useAuthStore();
const title = ref('Hello');
const username = ref(''); // 登录账号
const password = ref(''); // 登录密码
onLoad(() => {
let loginInfo = authStore.userInfo as User;
if (loginInfo?.account && loginInfo?.pwd) {
username.value = loginInfo.account;
password.value = loginInfo.pwd;
}
let hasLogin = !!uni.getStorageSync('hasLogin');
uni.removeStorageSync('hasLogin');
// #ifdef H5
hasLogin = true;
// #endif
})
// 登录
const login = () => {
authStore.login(username.value, password.value)
}
</script>
<style scoped>
.content {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
}
.logo {
height: 200rpx;
width: 200rpx;
margin: 200rpx 0 20rpx;
}
.text-area {
line-height: 40rpx;
text-align: center;
justify-content: center;
padding: 4rpx 40rpx 20rpx;
margin-bottom: 20rpx;
}
.title {
font-size: 36rpx;
color: #8f8f94;
}
.box {
background: #f1f2f3;
margin: 12rpx;
width: 450rpx;
}
.box-input {
flex: 1;
padding: 12rpx 18rpx;
border-radius: 8rpx;
height: 76rpx;
font-size: 32rpx;
}
</style>
// # auth.ts
import { defineStore } from 'pinia';
import type { User } from '../types';
interface AuthState {
token: string | null;
userInfo: User | null;
isLoading: boolean;
}
// 登录状态管理
export const useAuthStore = defineStore('auth', {
state: (): AuthState => {
const token = uni.getStorageSync('token');
const userInfo = token ? uni.getStorageSync('userinfo') : {} as User;
return {
token,
userInfo,
isLoading: false
};
},
actions: {
async login(account: string, password: string) {
this.isLoading = true;
try {
const res = { token: '123456', user: {} as User }
this.token = data.data.token;
this.userInfo = data.data.user;
uni.reLaunch({ url: '/pages/home/home' })
} catch (error) {
console.error(`登录失败:${error}`);
uni.showToast({
icon: 'none',
title: '登录失败'
})
} finally {
this.isLoading = false;
}
}
}
});
操作步骤:
定义一个首屏index.nvue 引入 pinia注入模块 auth.ts ,调用即可
预期结果:
能够正常的使用
实际结果:
reportJSException >>>> exception function:createInstanceContext, exception:white screen cause create instanceContext failed,check js stack -> Uncaught TypeError: (0 , import_pinia.defineStore) is not a function at (pages/index/index.js.nvue:849:51) at (pages/index/index.js.nvue:1329:3)
bug描述:
CLI 运行APP首屏是 nvue时,引入 pinia插件模块时报错
更多关于uni-app CLI 运行APP首屏是 nvue时,引入 pinia插件时报错的实战教程也可以访问 https://www.itying.com/category-93-b0.html
根据问题描述和知识库内容,您的问题是由于在nvue页面中直接引入Pinia导致的。nvue页面基于Weex引擎,对某些Vue生态插件的支持有限。
关键原因:
知识库明确指出:“nvue 暂不支持在 main.js 注册全局组件” 和 “uni-app x 暂不支持 i18n、vuex、pinia等插件”
虽然uni-app内置了Pinia,但主要针对Vue页面优化,nvue页面存在兼容性问题
错误信息 (0 , import_pinia.defineStore) is not a function 表明Pinia未被正确加载
解决方案:
升级HBuilderX:确保使用最新正式版(至少4.71+),知识库中4.71.2025061206-alpha修复了App平台 修复 vue3 cli 项目 nvue 页面可能编译失败的Bug
架构调整建议:
将首屏改为Vue页面(非nvue),Pinia在Vue页面中能正常工作
若必须使用nvue首屏,建议在Vue页面中管理状态,通过uni-app通信机制与nvue页面交互
替代方案:
使用uni-app的globalData进行简单状态管理
通过自定义事件总线实现跨页面通信
注意事项:
CLI项目需在main.js中正确初始化Pinia:app.use(createPinia())
不要在nvue页面中直接import Pinia store
参考文档:Pinia状态管理 和 nvue注意事项 内容为 AI 生成,仅供参考
更多关于uni-app CLI 运行APP首屏是 nvue时,引入 pinia插件时报错的实战教程也可以访问 https://www.itying.com/category-93-b0.html
这个问题是由于在 nvue 页面中,Pinia 的初始化时机与普通 vue 页面不同导致的。nvue 页面在 App 端运行在独立的 JavaScript 环境中,需要特殊处理 Pinia 的引入。
解决方案如下:
- 修改 main.js/ts 中的 Pinia 初始化:
确保在 App 启动时正确初始化 Pinia,并在 nvue 页面中通过
getApp()获取 store 实例。
// main.js/ts
import { createSSRApp } from 'vue'
import { createPinia } from 'pinia'
import App from './App.vue'
export function createApp() {
const app = createSSRApp(App)
const pinia = createPinia()
app.use(pinia)
// 将 pinia 挂载到全局,供 nvue 页面使用
if (typeof global !== 'undefined') {
global.$pinia = pinia
}
return {
app,
pinia
}
}
- 修改 nvue 页面中的 store 引入方式:
在 nvue 页面中,不能直接使用
useAuthStore(),需要通过getApp()获取 pinia 实例。
// index.nvue
<script lang="ts" setup>
import { ref } from 'vue'
import { onLoad } from "@dcloudio/uni-app"
import { storeToRefs } from 'pinia'
// 获取全局的 pinia 实例
const pinia = getApp().$pinia
// 动态导入 store 定义
import { useAuthStore } from '@/store/auth'
// 使用 pinia 实例创建 store
const authStore = useAuthStore(pinia)
const title = ref('Hello')
const username = ref('')
const password = ref('')
onLoad(() => {
// 使用 storeToRefs 保持响应式
const { userInfo } = storeToRefs(authStore)
if (userInfo.value?.account && userInfo.value?.pwd) {
username.value = userInfo.value.account
password.value = userInfo.value.pwd
}
})
const login = () => {
authStore.login(username.value, password.value)
}
</script>
- 修改 store 定义: 确保 store 可以被正确传递 pinia 实例。
// store/auth.ts
import { defineStore } from 'pinia'
import type { User } from '../types'
interface AuthState {
token: string | null
userInfo: User | null
isLoading: boolean
}
export const useAuthStore = defineStore('auth', {
state: (): AuthState => ({
token: uni.getStorageSync('token'),
userInfo: uni.getStorageSync('userinfo') || null,
isLoading: false
}),
actions: {
async login(account: string, password: string) {
this.isLoading = true
try {
// 模拟登录请求
const res = { token: '123456', user: {} as User }
this.token = res.token
this.userInfo = res.user
uni.setStorageSync('token', res.token)
uni.setStorageSync('userinfo', res.user)
uni.reLaunch({ url: '/pages/home/home' })
} catch (error) {
console.error(`登录失败:${error}`)
uni.showToast({
icon: 'none',
title: '登录失败'
})
} finally {
this.isLoading = false
}
}
}
})

