如何在 Vue3 + Pinia + Typescript 上正确使用 pinia 商店
我在使用 Pinia 商店和 typescript 以及在基本 app.vue Vuejs3 选项 api 中使用商店时遇到了困难。
我有这个 app.js 文件
import {createApp} from 'vue'
import {createPinia} from "pinia";
import App from './App';
const pinia = createPinia()
const app = createApp(App);
app.use(pinia);
app.mount('#app');
这个 app.vue
<script>
import {useAuthStore} from "@app/store/auth.store";
import {useCountryStore} from "@app/store/country.store";
export default {
components: {SidebarMenu},
setup() {
return {
authStore: useAuthStore(),
countryStore: useCountryStore(),
}
},
computed: {
loggedIn: function () {
return this.authStore.status.loggedIn;
}
}
}
</script>
这个 authStore.js :
import {defineStore} from "pinia";
const user = JSON.parse(localStorage.getItem('user'));
export const useAuthStore = defineStore("auth", {
state: () => (
user ? {status: {loggedIn: true}, user} : {status: {loggedIn: false}, user: null}
),
});
还有这个 CountryStore.ts
import { defineStore } from "pinia";
import { Country } from "@app/interfaces/country";
export type CountryState = {
countries: Country[],
errors: any[],
}
export const useCountryStore = defineStore("country", {
state: () => ({
countries: [],
errors: []
} as CountryState)
})
就我而言,无论我做什么,我都会因为 countryStore 而不是 AuthStore 而收到此错误:
getActivePinia was called with no active Pinia. Did you forget to install pinia?
但无论出于什么原因。如果我将 countryStore.ts 转换为 .js(当然还要删除类型提示),它就会起作用!
我搜索了很多关于为什么会这样、我遗漏了什么或我做错了什么。
当然,我最终想保留 typescript,但我不知道如何让它工作。
感谢所有能帮助我的人。爱你们所有人。
因此,我通过尝试多种方法自己找到了答案。 Pinia 没有任何问题。
我的主要问题是,我在没有使用 typescript 的情况下启动了项目,然后在“某个文件”上开始实现它
如果要启用 typescript,请将
所有
.js 文件切换到 .ts
.vue 不需要这样做
然后,这里列出了我为使一切正常工作所做的各种操作:
使用此 tsconfig:
{
"compilerOptions": {
"target": "esnext",
"module": "esnext",
"strict": true,
"jsx": "preserve",
"importHelpers": true,
"moduleResolution": "node",
"experimentalDecorators": true,
"skipLibCheck": true,
"esModuleInterop": true,
"allowSyntheticDefaultImports": true,
"sourceMap": true,
"baseUrl": "./assets", //this is your working folder, usually ./ only, since i'm using webpack encore + symfony i adapted it
"types": [
"webpack-env"
],
"paths": { // very important to make your import @app work
"@app/*": [
"*"
]
},
"lib": [
"esnext",
"dom",
"dom.iterable",
"scripthost"
]
},
"include": [
"assets/**/*.ts",
"assets/**/*.tsx",
"assets/**/*.vue",
"tests/**/*.ts",
"tests/**/*.tsx"
],
"exclude": [
"node_modules"
]
}
在主文件夹(对我来说是 /assets)中添加 shims-vue.d.ts,我仍然不知道为什么需要这样做,但它拯救了我
declare module '*.vue' {
import type { DefineComponent } from 'vue'
const component: DefineComponent<{}, {}, any>
export default component
}
创建组件时不要忘记这一点
<script lang="ts">
不要忘记将 main.js 或 app.js 转换为 .ts 并调整 webpack.config.js再来一次
.addEntry('app', './assets/app.ts')
.addAliases({
'@app': path.resolve(__dirname, 'assets/') //usefull for @app/ in import, you can also only use @, adapt it on your desire
})
此后,您将收到大量与代码中需要适应的内容相关的编译错误。
一个技巧是 .vue 文件不会被导入并抛出“找不到模块”
例如,我必须从:
import App from './App';
切换到:
import App from './App.vue';
如果每个人都有更好的做法,请随时分享,我会调整我的答案
尝试将 defineStore 的名称作为第一个参数,然后将选项对象作为第二个参数。就像您在 authStore 上所做的一样。
来自:
export const useCountryStore = defineStore( {
id: "country",
state: () => ({
countries: [],
errors: []
} as CountryState)
})
至:
export const useCountryStore = defineStore("country", {
id: "country",
state: () => ({
countries: [],
errors: []
} as CountryState)
})