【Vue3.x】整合Pinia(持久化)

155 阅读3分钟

1. Install

Official Website: pinia.web3doc.top/introductio…

npm install

npm install pinia
npm install pinia-plugin-persistedstate

main.ts

import './assets/main.css'

import { createApp } from 'vue'
import { createPinia, storeToRefs } from 'pinia'
import { createPersistedState } from 'pinia-plugin-persistedstate';
import ElementPlus from 'element-plus';
import 'element-plus/theme-chalk/index.css';
import * as ElementPlusIconsVue from '@element-plus/icons-vue'
import './assets/iconfont/iconfont.css'

import App from './App.vue'
import router from './router/index'
import i18n from './i18n';

const app = createApp(App)

//持久化
const pinia = createPinia()
pinia.use(
   createPersistedState({
      auto: true
   })
)
app.use(pinia)
   .use(router)
   .use(ElementPlus)
   .use(i18n)

//圖標
for (const [key, component] of Object.entries(ElementPlusIconsVue)) {
   app.component(key, component)
   }
app.mount('#app')

2. Technology

Vue3.x + Vite + Pinia + Router + ElementPlux +I18n + axios + TypeScript

  "dependencies": {
    "@element-plus/icons-vue": "^2.3.1",
    "axios": "^1.7.0",
    "element-plus": "^2.7.3",
    "moment": "^2.24.0",
    "pinia": "^2.1.7",
    "pinia-plugin-persist": "^1.0.0",
    "pinia-plugin-persistedstate": "^3.2.1",
    "vue": "^3.4.21",
    "vue-i18n": "^9.5.0",
    "vue-router": "^4.3.0"
  },

3. Pinia

3.1 Constructure

vue-demo
├── public/          # static files
│   └── favicon.ico  # title icon (可以多個,切換路由titile也切換) 
├── src/             # project root
│   ├── assets/      # images, icons, etc.靜態資源
│   ├── api/                    # 後端api
│   │   └── permission.ts       # 整理所有的後端方法
│   ├── components/             # common components - 客製化頁面
│   │   └── AppBreadcrumb.vue   # 麵包屑
│   ├── layouts/     # layout containers -header, footer,sidebar, etc.
│   │   ├── header              # 公共頭
│   │   ├── sidebar             # 導航欄
│   │   └── index.vue           # 導入公共頭和導航欄
│   ├── scss/        # scss styles
│   ├── config/                 # 封裝http
│   │   └── httpConfig.ts       # axios
│   ├── i18n/        # 多語言切換
│   │   ├── locales/        # 多語言切換
│   │   │   ├── en.ts       # 中文
│   │   │   ├── zh.ts       # 英文
│   │   │   └── xxx.ts      # 其他文
│   │   └── index.ts        # I18N切換
│   ├── router/           # routes config
│   │   └── index.ts      # I18N切換
│   ├── stores/           # pinia templage
│   │   └── user.ts       # pinia user
│   ├── views/pages       # Route apge,路由導航的頁面
│   │   ├── dashboard     # 儀錶盤頁面
│   │   ├── login         # 登錄頁面、註冊頁面
│   │   └── ....          # etc..
│   ├── App.vue      # 三個標籤 template /script  /style
│   └── main.ts      # 加載所有組件,掛載都index.html
│
├── .env.devlopment  # 多環境配置,在package.json啟動腳本中設定讀取
├── .env.production  # 多環境配置,在package.json啟動腳本中設定讀取
├── env.d.ts         # vue識別所有格式的文件
├── index.html       # 入口文件,main.ts
├── package.json     # dependency
└── vite.config.ts   # project config,install plugin,proxy

3.2 LocalStorage && SessionStorage

image.png

Notice:

  • localStorage: 瀏覽器打開創建,瀏覽器關閉消失
  • sessionStorage: 瀏覽器關閉後數據依然存在

Code

1.将value存储到key字段
    sessionStorage.setItem("key", "value");

2.getItem获取value
    var value = sessionStorage.getItem("key"); 

3.removeItem删除key
    sessionStorage.removeItem("key"); 

4.clear清除所有的key/value
    sessionStorage.clear(); 

5.json or array
    let arr = ['cat','dog','fish']
    let msg = {
        name: 'Tom',
        age: 10
    }
   sessionStorage.setItem("key", JSON.stringify(msg)); 
   sessionStorage.setItem("key", JSON.stringify(arr)); 
   
   var result = JSON.parse(sessionStorage.getItem("key")); 

3.3 Demo

store目錄下創建user.ts

import { reactive, ref } from "vue";
import { defineStore, acceptHMRUpdate } from "pinia";

export const useUserStore = defineStore('user',{
    state: ()=>({
      token: "",
      isAuthenticated: false,
    }),
    getters:{   
      getToken():string {
         return this.token
      },
      getAuthenticated():Boolean {
         return this.isAuthenticated
      }
    },
    actions:{
      setToken(str:string){
        this.token = str;
      },
      setAuthenticated (value:boolean){
        this.isAuthenticated = value;
      },
      clearStorage(){
        this.setToken("");
        this.setAuthenticated(false);
      }
    },
});
// 热更新 编辑你的 store,并直接在你的应用中与它们互动,
// 而不需要重新加载页面,允许你保持当前的 state、并添加甚至删除 state、action 和 getter。
if (import.meta.hot) {
  import.meta.hot.accept(acceptHMRUpdate(useUserStore, import.meta.hot));
}

<script setup lang="ts">沒用ts,部分不會轉???????

<script>
import { useUserStore } from '@/stores/user';
import { addRouter } from '../../router/addRouter'
import { loveTalk } from '../../api/permission'

export default {
    data() {
        const validateUsername = (rule, value, callback) => {
            if (value.length < 5) {
                callback(new Error('请输入正确的用户名'))
            } else {
                callback()
            }
        }
        const validatePass = (rule, value, callback) => {
            if (value.length < 5) {
                callback(new Error('密码不能小于5位'))
            } else {
                callback()
            }
        }
        return {
            loginForm: {
                username: 'admin',
                password: '123456'
            },
            loginRules: {
                username: [
                    {
                        required: true,
                        trigger: 'blur',
                        validator: validateUsername
                    }
                ],
                password: [
                    { required: true, trigger: 'blur', validator: validatePass }
                ]
            },
            loading: false,
            pwdType: 'password'
        }
    },
    methods: {
        showPwd() {
            if (this.pwdType === 'password') {
                this.pwdType = ''
            } else {
                this.pwdType = 'password'
            }
        },
        async login() {
            try {
                var loginMsg = {
                    username: this.loginForm.username,
                    password: this.loginForm.password
                }
                
                const userStore = useUserStore();
                userStore.setToken(loginMsg);
                userStore.setAuthenticated(true);

                sessionStorage.setItem('token',loginMsg);
                addRouter();
                this.$router.push('/')
            } catch (e) {
                console.log(e)
            }
        }
    }
}
</script>

3.4 批量修改

<script setup lang="ts">
    import { useUserStore } from './store'
    import { storeToRefs } from 'pinia'
    
    const msg = useUserStore();
    const { name } = storeToRefs(msg);
</script>

image.png

3.5 接收参数

store/nav.ts

import { reactive, ref } from "vue";
import { defineStore, acceptHMRUpdate } from "pinia";

export const useNavStore = defineStore('nav',{
    state: ()=>({
      collapse: false,
    }),
    getters:{
      getCollapse() {
        return this.collapse;
     }, 

    },
    actions:{
      changeCollapse(){
        if(this.collapse == false){
          this.collapse = true;
        }else{
          this.collapse = false;
        }
      }
    },
});

xxxx.vue获取

<template>
    <h2>{{collapse}}</h2>
</templage>
<script lang="ts" setup>
  import {
    Document,
    Menu as IconMenu,
    Location,
    Setting,
  } from '@element-plus/icons-vue'
  import { ref,reactive } from 'vue'
  import { useNavStore } from '@/stores/nav';

  const navStore = useNavStore();
  //可以拿多个
  const {sum,school,aaaa} =  reactive(navStore);
</script>