前端學習-vue影片學習013-pinia

ayubene發表於2024-03-24

尚矽谷影片教程

瞭解pinia

集中式狀態(資料)管理的工具,主要管理各元件之間的共享資料

準備一個效果

學到的幾個點

  • html下拉選擇框,可以使用v-model雙向繫結
  • v-modle獲取的值為字串,可以寫為v-model.number,會盡量轉為數字
<select name="num" v-model.number="n">
    <option value="1">1</option>
    <option value="2">2</option>
    <option value="3">3</option>
    <option value="4">4</option>
</select>
  • 隨機獲取id的方式有uuid和nanoid,需要npm i nanoid,import引入後使用
<script setup name="LoveTalk" lang="ts">
    import { reactive } from 'vue';
    import axios from 'axios';
    import { nanoid } from 'nanoid'

    let talkList = reactive([
        {id:'talk01',title:'asdfghjkl'},
        {id:'talk02',title:'awejdfaaff'},
        {id:'talk03',title:'irjeqirh'},
        {id:'talk04',title:'ljfdkjfdf'},
    ])
    async function getTalk() {
        // 連續解構賦值+重新命名
        let {data:{content:title}} = await axios.get('https://api.uomg.com/api/rand.qinghua?fomat=json')
        let obj = {id:nanoid(),title}
        talkList.unshift(obj)
    }
</script>

搭建pinia環境

  • 安裝pinia
npm i pinia
  • 引入、建立、安裝pinia
// 引入createApp建立應用
import { createApp } from "vue";
//  引入APP根元件
import App from './App.vue'

// 引入pinia
import { createPinia } from "pinia";
// 引入路由器
// import router from "./router";
// 建立一個應用
const app = createApp(App)
// 建立pinia
const pinia = createPinia()
// 使用路由器
// app.use(router)

// 安裝pinia-要在應用掛載前 否則報錯
app.use(pinia)
// 掛載應用到app容器
app.mount('#app')

讀取、儲存、修改資料

讀取+儲存

  • 在src中新建資料夾store,專門用於存放pinia資料
  • 新建ts文件,將要用到的資料存放在裡面
import { defineStore } from "pinia";

export const useCountStore = defineStore('count',{
    // state是真正儲存資料的地方
    state(){
        return {
            sum:6
        }
    }
})
  • 讀取/使用存放著pinia的資料
<template>
    <div class="count">
        <h2>求和:{{ countPinia.sum }}</h2>
    </div>
</template>
<script setup name="Count" lang="ts">
    import { ref } from 'vue';
    import { useCountStore } from '@/store/count'

    let countPinia = useCountStore()
</script>

修改資料的三種方式

方式1:直接運算元據
function add() {
    // 方式1
    CountStore.sum += n.value
    // sum.value += n.value
}
方式2:批次修改資料
function add() {
    // 方式1
    // CountStore.sum += n.value
    // 方式2
    CountStore.$patch({
        sum:888,
        title:'aaa'
    })
    // sum.value += n.value
}
方式3:使用actions,在其中放置方法,對應響應元件中的動作
  • 使用actios
    store/talk.ts
import { defineStore } from "pinia";
import axios from "axios";
import { nanoid } from 'nanoid'

export const useTalkStore = defineStore('talk',{
    actions:{
        async addList() {
            // 連續解構賦值+重新命名
            let {data:{content:title}} = await axios.get('https://api.uomg.com/api/rand.qinghua?fomat=json')
            let obj = {id:nanoid(),title}
            // talkStore.talkList.unshift(obj)
            this.talkList.unshift(obj)
        }
    },
    // state是真正儲存資料的地方
    state(){
        return {
            talkList:[
                {id:'talk01',title:'asdfghjkl'},
            ]
        }
    }
})
  • 使用actions定義的方法
    Talk.vue

<script setup name="LoveTalk" lang="ts">
    import { useTalkStore } from '@/store/talk'

    let talkStore = useTalkStore()
    // let talkList = reactive([
    //     {id:'talk01',title:'asdfghjkl'},
    // ])
    function getTalk() {
        talkStore.addList()
    }
</script>

storeToRefs

在解構資料時,會遇到失去響應式的情況
通常使用toRefs解決
但在pinia中,如果直接使用toRefs 會出現所有資料、方法都獲取到的情況
因此pinia提供storeToRefs,只會取到資料

<template>
    <div class="count">
        <h2>求和:{{ sum }}</h2>
    </div>
</template>

<script setup name="Count" lang="ts">
    import { useCountStore } from '@/store/count'
    import { storeToRefs } from 'pinia'

    let countStore = useCountStore()
    let { sum } = storeToRefs(countStore)
</script>

getters

export const useCountStore = defineStore('count',{
    actions:{
        increment(value) {
            this.sum += value
        },
        minus(value) {
            this.sum -= value
        }
    },
    // state是真正儲存資料的地方
    state(){
        return {
            sum:6
        }
    },
    getters:{
        // 寫法1
        // bigSum(state) {
        //     return state.sum*10
        // }
        // 寫法2
        // bigSum():number {
        //     return this.sum*10
        // }
        // 寫法3
        bigSum:state => state.sum*10
    }
})

$subscribe 監視修改

使用瀏覽器本地儲存作為例子
Talk.vue

<script setup name="LoveTalk" lang="ts">
    import { reactive } from 'vue';
    import axios from 'axios';
    import { nanoid } from 'nanoid'
    import { useTalkStore } from '@/store/talk'

    let talkStore = useTalkStore()

    talkStore.$subscribe((mutate,state)=>{
        // localStorage.setItem('talkList',state.talkList)
        localStorage.setItem('talkList',JSON.stringify(state.talkList))
    })
    function getTalk() {
        talkStore.addList()
    }
</script>

talk.ts

import { defineStore } from "pinia";
import axios from "axios";
import { nanoid } from 'nanoid'

export const useTalkStore = defineStore('talk',{
    actions:{
        async addList() {
            // 連續解構賦值+重新命名
            let {data:{content:title}} = await axios.get('https://api.uomg.com/api/rand.qinghua?fomat=json')
            let obj = {id:nanoid(),title}
            // talkStore.talkList.unshift(obj)
            this.talkList.unshift(obj)
        }
    },
    // state是真正儲存資料的地方
    state(){
        return {
            talkList:JSON.parse(localStorage.getItem('talkList')) || []
        }
    }
})

store的組合式寫法

import { defineStore } from "pinia";
import axios from "axios";
import { nanoid } from 'nanoid'

// export const useTalkStore = defineStore('talk',{
//     actions:{
//         async addList() {
//             // 連續解構賦值+重新命名
//             let {data:{content:title}} = await axios.get('https://api.uomg.com/api/rand.qinghua?fomat=json')
//             let obj = {id:nanoid(),title}
//             // talkStore.talkList.unshift(obj)
//             this.talkList.unshift(obj)
//         }
//     },
//     // state是真正儲存資料的地方
//     state(){
//         return {
//             talkList:JSON.parse(localStorage.getItem('talkList')) || []
//         }
//     }
// })
import { reactive } from "vue";
export const useTalkStore = defineStore('talk',()=>{
    let talkList = reactive(JSON.parse(localStorage.getItem('talkList') as string) || [])
    async function addList() {
        // 連續解構賦值+重新命名
        let {data:{content:title}} = await axios.get('https://api.uomg.com/api/rand.qinghua?fomat=json')
        let obj = {id:nanoid(),title}
        // talkStore.talkList.unshift(obj)
        talkList.unshift(obj)
    }
    return {talkList,addList}
})

相關文章