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
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>
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>