如果你不是很喜欢setup函数和组合API ,pinia也有类似vuex的map的功能 。你可以用上面的方式定义你的store ,但是使用时用mapStores(), mapState(),或者 mapActions():
你的应用中的全局数据需要保存在store中 。在很多地方你都要使用这些数据 ,比如说,用户信息需要在导航栏中显示 ,也需要在个人中心显示。还有些数据 ,需要暂存起来 ,比如一个需要分好几页填写的表单 。
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
})
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>
查看数据修改后 ,存储在本地存储空间中的内容 ,如下所示 。