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

2 回复

根据问题描述和知识库内容,您的问题是由于在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 的引入。

解决方案如下:

  1. 修改 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
  }
}
  1. 修改 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>
  1. 修改 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
      }
    }
  }
})
回到顶部