首页IT科技vue能用js吗(在Vue3项目中使用pinia代替Vuex进行数据存储)

vue能用js吗(在Vue3项目中使用pinia代替Vuex进行数据存储)

时间2025-05-01 17:29:09分类IT科技浏览4924
导读:pinia是一个vue的状态存储库,你可以使用它来存储、共享一些跨组件或者页面的数据,使用起来和vuex非常类似。pina相对Vuex来说,更好的ts支持和代码自动补全功能。本篇随笔介绍pinia的基础用法以及持久化存储的一些用法,供参考学习。...

pinia是一个vue的状态存储库             ,你可以使用它来存储             、共享一些跨组件或者页面的数据                    ,使用起来和vuex非常类似             。pina相对Vuex来说       ,更好的ts支持和代码自动补全功能                    。本篇随笔介绍pinia的基础用法以及持久化存储的一些用法             ,供参考学习       。

1                    、pinia的安装和使用

安装pinia(https://pinia.vuejs.org/)

npm install pinia

在main.j或者main.ts中引入使用

import { createPinia } from pinia app.use(createPinia())

下面就是使用pinia的一个例子             。这样你就创建了一个状态存储                   。

// stores/counter.js import { defineStore } from pinia export const useCounterStore = defineStore(counter, { state: () => { return { count: 0 } }, // 也可以这样定义状态 // state: () => ({ count: 0 }) actions: { increment() { this.count++ }, }, })

在组件中使用:

import { useCounterStore } from @/stores/counter export default { setup() { const counter = useCounterStore() counter.count++ // 编辑器会有代码提示 counter.$patch({ count: counter.count + 1 }) // 也可以使用action来代替 counter.increment() }, }
如果你不是很喜欢setup函数和组合API                   ,pinia也有类似vuex的map的功能       。你可以用上面的方式定义你的store       ,但是使用时用mapStores(), mapState(),或者 mapActions():
const useCounterStore = defineStore(counter, { state: () => ({ count: 0 }), getters: { double: (state) => state.count * 2, }, actions: { increment() { this.count++ } } }) const useUserStore = defineStore(user, { // ... }) export default { computed: { // 其他计算属性 // ... // 可以使用 this.counterStore 和 this.userStore获取 ...mapStores(useCounterStore, useUserStore) // 可以使用 this.count 和this.double获取 ...mapState(useCounterStore, [count, double]), }, methods: { // 可以使用 this.increment()调用 ...mapActions(useCounterStore, [increment]), }, }

与vue4之前的版本相比       ,pinia的API是有很多不同的                   ,即:

去掉了mutation       。因为好多人认为mutation是多余的                   。以前它方便devtools集成             ,现在这不是个问题了             。 不用在写复杂的ts类型包装       ,所有的都是有类型的                    ,API设计的都是尽量符合ts的类型推断 不再使用一个莫名其妙的字符串了             ,只需要导入一个函数,调用他们就行了                    ,同时还有代码自动补全 不需要动态添加store了                    ,因为它们现在本来就是动态       。如果你想,你随时可以手动去写一个store                    。 没有复杂的嵌套模块了             。你仍然可以在一个store中导入其他的store来实现嵌套模块             ,但是pinia还是推荐使用一个扁平的结构。但是即使你使用循环依赖也没关系                    。 不再需要命名空间了                    。因为现在store本来就是扁平结构了。你也可以理解为所有的store本来就有命名空间了             。
你的应用中的全局数据需要保存在store中                    。在很多地方你都要使用这些数据                    ,比如说       ,用户信息需要在导航栏中显示             ,也需要在个人中心显示       。还有些数据                   ,需要暂存起来       ,比如一个需要分好几页填写的表单             。
在pinia中       ,store是通过defineStore()方法定义的                   ,它的第一个参数就是一个唯一的名字:
import { defineStore } from pinia export const useStore = defineStore(main, { // other options... })

上面只是定义了store             ,在setup函数中调用了useStore()时       ,才会创建store:

import { useStore } from @/stores/counter export default { setup() { const store = useStore() return { // 你可以返回store这个对象                    ,然后就可以在template中使用了 store, } }, }

在store实例化以后             ,你就可以调用到store中定义的state       、getters和actions了                   。为了让解构的值还保持响应式,你需要用到storeToRefs()方法       。它会给响应式的数据创建ref       。

import { storeToRefs } from pinia export default defineComponent({ setup() { const store = useStore() // `name` 和 `doubleCount` 是响应式的 // 插件增加的属性也会创建ref // 但是会自动跳过action或者不是响应性的属性 const { name, doubleCount } = storeToRefs(store) return { name, doubleCount } }, })

默认情况下                    ,你可以在store实例上直接获取或者修改state:

const store = useStore() store.counter++

也可以调用$reset()方法来把state恢复为初始值:

const store = useStore() store.$reset()

除了直接修改store里的值store.counter++                    ,你也可以是用$patch方法                   。你可以同时修改多个值:

store.$patch({ counter: store.counter + 1, name: Abalam, })

或者$patch接收一个函数作为参数,来简化改变数组的写法:

store.$patch((state) => { state.items.push({ name: shoes, quantity: 1 }) state.hasChanged = true })

2             、pinia的持久化存储处理

你可以用$subscribe()来侦听state的改变             ,持久化一般存储在localStorage和sessionStorage             。

localStorage和sessionStorage差别

localStorage和sessionStorage一样都是用来存储客户端临时信息的对象       。

他们均只能存储字符串类型的对象(虽然规范中可以存储其他原生类型的对象                    ,但是目前为止没有浏览器对其进行实现)                    。

localStorage生命周期是永久       ,这意味着除非用户显示在浏览器提供的UI上清除localStorage信息             ,否则这些信息将永远存在             。

sessionStorage生命周期为当前窗口或标签页                   ,一旦窗口或标签页被永久关闭了       ,那么所有通过sessionStorage存储的数据也就被清空了。

不同浏览器无法共享localStorage或sessionStorage中的信息                    。相同浏览器的不同页面间可以共享相同的 localStorage(页面属于相同域名和端口)       ,但是不同页面或标签页间无法共享sessionStorage的信息                    。这里需要注意的是                   ,页面及标 签页仅指顶级窗口             ,如果一个标签页包含多个iframe标签且他们属于同源页面       ,那么他们之间是可以共享sessionStorage的。

JSON对象提供的parse和stringify将其他数据类型转化成字符串                    ,再存储到storage中就可以了             ,操作的方式:

存:

var obj = {"name":"xiaoming","age":"16"}

localStorage.setItem("userInfo",JSON.stringify(obj));

取:

var user = JSON.parse(localStorage.getItem("userInfo"))

删除:

localStorage.remove("userInfo);

清空:

localStorage.clear();

pnia 使用订阅机制subscribe来实现数据的持久化存储的代码如下所示             。

const instance = useMainStore(); // 订阅数据变化,变化时存储 instance.$id 这是storeId instance.$subscribe((mutation, state) => { localStorage.setItem(instance.$id, JSON.stringify(state)); }); //init 初始的时候获取 const val = localStorage.getItem(instance.$id); if (val) { instance.$state = JSON.parse(val); }

也可以通过watch实现

watch( pinia.state, (state) => { // persist the whole state to the local storage whenever it changes localStorage.setItem(piniaState, JSON.stringify(state)) }, { deep: true } )

但是需要注意                    ,这种方式持久化会提示pinia未安装挂载                    ,所以需要在pinia挂载后再调用,这里可以将它封装成方法导出             ,在挂载后调用

xport const initStore = () => { const instance = useMainStore(); // 订阅数据变化                    ,变化时存储 instance.$id 这是storeId instance.$subscribe((mutation, state) => { localStorage.setItem(instance.$id, JSON.stringify(state)); }); //init 初始的时候获取 const val = localStorage.getItem(instance.$id); if (val) { instance.$state = JSON.parse(val); } }
默认情况下       ,state侦听会和组件绑定在一起(如果store是在组件的setup中)                    。这意味着             ,当组件卸载时                   ,侦听会自动被移除       。如果你需要在组件被卸载时       ,侦听仍然保持       ,需要给$subscribe()方法传递第二个参数true:
export default { setup() { const someStore = useSomeStore() // 组件卸载后                   ,侦听也会有 someStore.$subscribe(callback, true) // ... }, }

或者watch状态的变化

watch( pinia.state, (state) => { // 在state改变时             ,保存在localStorage中 localStorage.setItem(piniaState, JSON.stringify(state)) }, { deep: true } )

3                   、使用pinia插件持久化存储

pinia plugin persist官方网站:pinia-plugin-persist

持久化存储也可以通过安装插件的方式       ,安装 pinia-plugin-persist 来实现             。

npm i pinia-plugin-persist --save

使用main.js

import { createPinia } from pinia import piniaPluginPersist from pinia-plugin-persist const store = createPinia() store.use(piniaPluginPersist) createApp(App).use(store).mount(#app)

在对应的store中开启                    ,数据默认存在 sessionStorage 里             ,并且会以 storeId 作为 key

import { defineStore } from pinia // main 是storeId export const useMainStore = defineStore(main, { state: () => ({ counter: 2, name: Eduardo, isAdmin: true }), // …… // 开启数据缓存 persist: { enabled: true } })

如果需要自定义key和存储位置,则修改参数即可                   。

persist: { enabled: true, strategies: [ //使用插件自定义存储 { key: settings, // key可以自己定义                    ,不填的话默认就是这个store的ID storage: localStorage, } ] },

4       、在实际项目中使用pinia

一般项目开发                    ,实际上存储的内容会比较多,可能根据不同的键值模块进行区分             ,因此把它们放在一个store/modules里面                    ,方便的使用引用它来存取设置数据即可       。

我们这里简单以一个settings的配置信息进行介绍       ,其中index.ts是一个统一的创建pinia的对象并挂接到全局App上的       。

其中index.ts的代码如下所示                   。

import type { App } from "vue"; import { createPinia } from "pinia"; import piniaPluginPersist from pinia-plugin-persist;//使用插件持久化 const store = createPinia(); store.use(piniaPluginPersist) //使用插件持久化 export function setupStore(app: App<Element>) { app.use(store); } export { store };

因此在main.js里面引入并挂接pinia即可             。

import { createApp } from vue import ElementPlus from element-plus import element-plus/dist/index.css import normalize.css // css初始化 import App from ./App.vue import { setupStore } from "/@/store"; const app = createApp(App) setupStore(app) app.use(ElementPlus) app.mount(#app)

这样我们就可以再次定义一个模块化的配置信息             ,以便于管理存储各种不同类型的内容       。

如下面我们定义一个程序配置信息setttings.ts

import { defineStore } from "pinia"; import { store } from "/@/store"; export type settingType = { title: string; fixedHeader: boolean; hiddenSideBar: boolean; }; export const useSettingStore = defineStore({ id: "settings", state: (): settingType => ({ title: "Vue3 + TypeScript + Element", fixedHeader: false, hiddenSideBar: false }), persist: { enabled: true, strategies: [ //使用插件自定义存储 { key: settings, // key可以自己定义                   ,不填的话默认就是这个store的ID storage: localStorage, } ] }, getters: { getTitle() { return this.title; }, getFixedHeader() { return this.fixedHeader; }, getHiddenSideBar() { return this.HiddenSideBar; } }, actions: { CHANGE_SETTING({ key, value }) { // eslint-disable-next-line no-prototype-builtins if (this.hasOwnProperty(key)) { this[key] = value; } }, changeSetting(data) { this.CHANGE_SETTING(data); } } }); export function useSettingStoreHook() { return useSettingStore(store); }

然后在组件视图vue或者app.vue中使用即可

<script lang="ts"> import { defineComponent } from "vue"; import { useSettingStoreHook } from "/@/store/modules/settings"; import { storeToRefs } from "pinia"; export default defineComponent({ name: "app", components: { }, setup() { const store = useSettingStoreHook(); const { fixedHeader, title } = storeToRefs(store); return { fixedHeader, title, }; }, methods: { setTitle() { this.title = "Vue3 + TypeScript + Element + Edit"; console.log(this.title); }, }, }); </script>

查看数据修改后       ,存储在本地存储空间中的内容       ,如下所示                    。

声明:本站所有文章                   ,如无特殊说明或标注             ,均为本站原创发布             。任何个人或组织       ,在未征得本站同意时                    ,禁止复制       、盗用                   、采集             、发布本站内容到任何网站       、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益             ,可联系我们进行处理                    。

创心域SEO版权声明:以上内容作者已申请原创保护,未经允许不得转载,侵权必究!授权事宜、对本内容有异议或投诉,敬请联系网站管理员,我们将尽快回复您,谢谢合作!

展开全文READ MORE
python怎么断点运行(Python中pdb设置断点) ubuntu编译c程序(ubuntu下编译安装boost库 longcpp 博客园)