Vue3 --- 集中式状态 (数据) 管理工具 pinia (类似 vuex)
1. 下载模块
npm i pinia
2. 配置 pinia 环境
src/main.ts
import {createApp} from 'vue'
import App from './App.vue'
import {createPinia} from 'pinia'
const app = createApp(App)
app.use(createPinia())   // 使用 pinia
app.mount('#app')
3. 存储
src/store/count.ts
import {defineStore} from "pinia";
export const useCountStore = defineStore('count', {
    // 用来储存公共数据
    state() {
        return {
            sum: 0
        }
    },
})
4. 读取
1. .属性 读取数据
src/components/Count.vue
<template>
<div class="count">
  <!-- 4. 页面中使用 sum -->
  <h2>当前求和结果: {{ countStore.sum }}</h2>
  <select v-model.number="v">
    <option value="1">1</option>
    <option value="2">2</option>
    <option value="3">3</option>
  </select>
  <button @click="add">加</button>
  <button @click="minus">减</button>
</div>
</template>
<script setup lang="ts" name="Count">
import {ref} from "vue";
// 1. 导入 count 的 pinia
import {useCountStore} from "@/store/count";
// 2. 使用这个 pinia
const countStore = useCountStore();
// 3. 获取 state 中的数据
// countStore.sum
// countStore.$store.sum
let v = ref(1)
function add() {
  countStore.sum += v.value
}
function minus() {
  countStore.sum -= v.value
}
</script>
<style scoped>
.count{
  width: 1200px;
  height: 120px;
  border-radius: 20px;
  background-color: aqua;
}
select,button{
  margin:0 5px;
  height: 28px;
}
select{
  margin-top: 57px;
}
</style>
2. 解构赋值读取数据
<template>
<div class="count">
  <!-- 4. 页面中使用 sum -->
  <h2>当前求和结果: {{ sum }}</h2>
  <select v-model.number="v">
    <option value="1">1</option>
    <option value="2">2</option>
    <option value="3">3</option>
  </select>
  <button @click="add">加</button>
  <button @click="minus">减</button>
</div>
</template>
<script setup lang="ts" name="Count">
import {ref} from "vue";
// 1. 导入 count 的 pinia
import {useCountStore} from "@/store/count";
import {storeToRefs} from "pinia";
// 2. 使用这个 pinia
const countStore = useCountStore();
// 3. 解构赋值, storeToRefs 只会将数据变成响应式, 方法不会变成响应式
const {sum} = storeToRefs(countStore);
let v = ref(1)
function add() {
  countStore.add(v.value);
}
function minus() {
  countStore.minus(v.value);
}
</script>
<style scoped>
.count{
  width: 1200px;
  height: 120px;
  border-radius: 20px;
  background-color: aqua;
}
select,button{
  margin:0 5px;
  height: 28px;
}
select{
  margin-top: 57px;
}
</style>
5. 修改
1. 直接修改
<template>
<div class="count">
  <h2>当前求和结果: {{ countStore.sum }}</h2>
  <select v-model.number="v">
    <option value="1">1</option>
    <option value="2">2</option>
    <option value="3">3</option>
  </select>
  <button @click="add">加</button>
  <button @click="minus">减</button>
</div>
</template>
<script setup lang="ts" name="Count">
import {ref} from "vue";
import {useCountStore} from "@/store/count";
const countStore = useCountStore();
let v = ref(1)
function add() {
  // 直接读取到pinia 中的 sum 修改即可
  countStore.sum += v.value
}
function minus() {
  countStore.sum -= v.value
}
</script>
<style scoped>
.count{
  width: 1200px;
  height: 120px;
  border-radius: 20px;
  background-color: aqua;
}
select,button{
  margin:0 5px;
  height: 28px;
}
select{
  margin-top: 57px;
}
</style>
2. 批量修改, 适用于需要同时修改 pinia 中 的很多条数据
<template>
<div class="count">
  <h2>当前求和结果: {{ countStore.sum }}</h2>
  <select v-model.number="v">
    <option value="1">1</option>
    <option value="2">2</option>
    <option value="3">3</option>
  </select>
  <button @click="add">加</button>
  <button @click="minus">减</button>
</div>
</template>
<script setup lang="ts" name="Count">
import {ref} from "vue";
import {useCountStore} from "@/store/count";
const countStore = useCountStore();
let v = ref(1)
function add() {
  // 直接读取到pinia 中的 sum 修改即可
  countStore.$patch({
    sum: 100
  })
}
function minus() {
  countStore.sum -= v.value
}
</script>
<style scoped>
.count{
  width: 1200px;
  height: 120px;
  border-radius: 20px;
  background-color: aqua;
}
select,button{
  margin:0 5px;
  height: 28px;
}
select{
  margin-top: 57px;
}
</style>
3. 将方法定义在 pinia 中, 组件中直接调用
src/store/count.ts
import {defineStore} from "pinia";
export const useCountStore = defineStore('count', {
    // 用来储存公共数据
    state() {
        return {
            sum: 0
        }
    },
    // 用来存放修改数据的方法
    actions: {
        add(value: number) {
            this.sum += value
        }
    }
})
src/components/Count.vue
<template>
<div class="count">
  <h2>当前求和结果: {{ countStore.sum }}</h2>
  <select v-model.number="v">
    <option value="1">1</option>
    <option value="2">2</option>
    <option value="3">3</option>
  </select>
  <button @click="add">加</button>
  <button @click="minus">减</button>
</div>
</template>
<script setup lang="ts" name="Count">
import {ref} from "vue";
// 1. 导入 count 的 pinia
import {useCountStore} from "@/store/count";
// 2. 使用这个 pinia
const countStore = useCountStore();
let v = ref(1)
function add() {
  // 3. 直接调用 pinia 中定义的 add 函数
  countStore.add(v.value);
}
function minus() {
  countStore.sum -= v.value
}
</script>
<style scoped>
.count{
  width: 1200px;
  height: 120px;
  border-radius: 20px;
  background-color: aqua;
}
select,button{
  margin:0 5px;
  height: 28px;
}
select{
  margin-top: 57px;
}
</style>
6. 计算属性
src/store/count.ts
import {defineStore} from "pinia";
export const useCountStore = defineStore('count', {
    // 用来储存公共数据
    state() {
        return {
            sum: 0
        }
    },
    // 用来存放修改数据的方法
    actions: {
        add(value: number) {
            this.sum += value
        },
        minus(value: number) {
            this.sum -= value
        }
    },
    // 用来返回处理过的数据
    getters: {
        // 接收参数, 读取 sum 方式
        bigSum: (state) => state.sum * 10,
        // 使用 this 读取 sum 方式
        bigSumTwo(): number {
            return this.sum * 50
        }
    }
})
src/components/Count.vue
<template>
  <div class="count">
    <h2>当前求和结果: {{ sum }}</h2>
    <!-- 4. 页面中使用 bigSum  -->
    <h2>放大十倍后的结果: {{ bigSum }}</h2>
    <select v-model.number="v">
      <option value="1">1</option>
      <option value="2">2</option>
      <option value="3">3</option>
    </select>
    <button @click="add">加</button>
    <button @click="minus">减</button>
  </div>
</template>
<script setup lang="ts" name="Count">
import {ref} from "vue";
// 1. 导入 count 的 pinia
import {useCountStore} from "@/store/count";
import {storeToRefs} from "pinia";
// 2. 使用这个 pinia
const countStore = useCountStore();
// 3. 取出定义在 getters 中的  bigSUm
const {sum, bigSum} = storeToRefs(countStore);
let v = ref(1)
function add() {
  countStore.add(v.value);
}
function minus() {
  countStore.minus(v.value);
}
</script>
<style scoped>
.count {
  width: 1200px;
  height: 120px;
  border-radius: 20px;
  background-color: aqua;
}
select, button {
  margin: 0 5px;
  height: 28px;
}
select {
  margin-top: 57px;
}
</style>
7. 订阅 ( 监视 )
**监视 talkList 是否发生变化, 如果变化了, 就将新的数据存储到 LocalStorage **
src/store/loveTalk.ts
import {defineStore} from "pinia";
import axios from "axios";
import {nanoid} from "nanoid";
export const useLoveTalkStore = defineStore('loveTalk', {
    // 用来储存公共数据
    state() {
        return {
            // 从 LocalStorage 中读取 talks
            talks: JSON.parse(localStorage.getItem("talks") as string) || [],
        }
    },
    actions: {
        async reqTalk() {
            const {data: {content: title}} = await axios.get("https://api.uomg.com/api/rand.qinghua?format=json")
            const newItem = {
                id: nanoid(),
                title
            }
            this.talks.unshift(newItem);
        }
    }
})
src/components/LoveTalk.vue
<template>
  <div class="talk">
    <button @click="getLoveTalk">获取一段土味情话</button>
    <ul>
      <li v-for="t in talks" :key="t.id">{{ t.title }}</li>
    </ul>
  </div>
</template>
<script setup lang="ts">
import {useLoveTalkStore} from "@/store/loveTalk";
import {storeToRefs} from "pinia";
const loveTalkStore = useLoveTalkStore();
const {talks} = storeToRefs(loveTalkStore);
loveTalkStore.$subscribe((mutate, state) => {
  // console.log("loveTalkStore中保存的数据 发生了变化", mutate, state)
  // 当监视到 loveTalkStore 中的数据发生变化时, 将变化后的 talks 存入 LocalStorage
  localStorage.setItem("talks", JSON.stringify(state.talks))
})
async function getLoveTalk() {
  loveTalkStore.reqTalk()
}
</script>
<style scoped>
.talk {
  width: 1200px;
  height: 250px;
  border-radius: 20px;
  background-color: orange;
}
button {
  margin-bottom: 15px;
}
</style>
8. 组合式写法
import {defineStore} from "pinia";
import axios from "axios";
import {nanoid} from "nanoid";
import {reactive} from "vue";
export const useLoveTalkStore2 = defineStore('loveTalk',()=>{
    // 定义数据, 相当于 state
    const talks = reactive(JSON.parse(localStorage.getItem("talks") as string) || [])
    // 定义方法, 相当于 actions
    async function reqTalk() {
        // 连续结构, 将 content 解构出来, 并将 content 重命名为 title
        const {data: {content: title}} = await axios.get("https://api.uomg.com/api/rand.qinghua?format=json")
        const newItem = {
            id: nanoid(),
            title
        }
        talks.unshift(newItem);
    }
    
    // 注意: 必须将需要使用到的数据和方法 return 回去
    return {
        talks, 
        reqTalk
    }
})
    python防脱发技巧

                
            
        
浙公网安备 33010602011771号