pinia2入门使用

作者: 天气不不错 | 来源:发表于2022-01-26 15:02 被阅读0次

    pinia是一个状态管理工具,使用起来和vuex非常类似,是vuex5的设计的思路。

    和vuex4相比,它使用起来更简单;将actions和mutations进行了合并,不论是同步还是异步操作都在actions中进行。对Ts支持更好,不需要定义太多的类型,能够自己进行类型推断。

    安装

    npm install pinia
    

    在main.js中引入使用

    import { createPinia } from 'pinia'
    
    app.use(createPinia())
    

    创建stores/main.js文件

    import { defineStore } from 'pinia'
    // 'main' 是storeId,自己随便取,保证唯一
    export const useMainStore = defineStore('main', {
      // 定义state的一种方式
      state: () => {
        return {
          // 所有这些属性的类型都将被自动推断出来  
          counter: 0,
          name: 'Eduardo',
          isAdmin: true,
        }
      },
    })
    

    在组件中使用

    import { useMainStore } from './stores/main.js'
    const store = useMainStore()
    // console.log(store.$state);
    console.log(store.name);
    
    //在template中
     <h1>{{ store.name }}</h1>
    

    State

    创建state

    创建state的第一种方法

     state: () => {
        return {
          // 所有这些属性的类型都将被自动推断出来  
          counter: 0,
          name: 'Eduardo',
          isAdmin: true,
        }
      },
    

    创建state的第二种方法

      state: () => ({
        counter: 0,
        name: 'Eduardo',
        isAdmin: true
      }),
    
    使用state

    一般使用

    import { useMainStore } from './stores/main.js'
    const store = useMainStore()
    console.log(store.name);
    // 模板中
    // <h1>{{ store.counter }}</h1> 
    

    如果要使导出的数据具有响应式

    import { storeToRefs } from 'pinia'
    import { useMainStore } from './stores/main.js'
    // 如果要将数据导出也具有响应式
    const { name } = storeToRefs(useMainStore())
    // 这时,store中的数据也会变成'xiaoyan'
    name.value = 'xiaoyan'
    

    Getters

    定义getter
    getters: {
        doubleCount: (state) => state.counter * 2,
        // 在getter属性中访问其他的getter属性数据
        doubleCountPlusOne() {
          // autocompletion ✨
          return this.doubleCount + 1
        },
        // 可以在里面使用this,在ts中要定义返回值类型,但如果接收了state参数,是不是还要定义返回值类型没有测试
        // doublePlusOne(): number {
        //   return this.counter * 2 + 1
        // },
      },
    
    • 可以在getter属性中访问其他getter属性数据

    • 可以在getter中通过this访问到state

    • 在ts中要定义返回值类型,但如果接收了state参数,是不是还要定义返回值类型没有测试

    使用getter
    <script setup>
    import { useMainStore } from './stores/main.js'
    const store = useMainStore()
    </script>
    <template>
      <h1>{{ store.doubleCount }}</h1>
    </template>
    
    将参数传递给 getter

    可以从getter返回一个函数来接受任何参数

    export const useStore = defineStore('main', {
      getters: {
        getActiveUserById(state) {
          const activeUsers = state.users.filter((user) => user.active)
          return (userId) => activeUsers.find((user) => user.id === userId)
        },
      },
    })
    

    在组件中使用

    <script>
       import { useStore } from './stores/main.js'
       const store = useStore()
    </script>
    
    <template>
    User 2: {{ store.getUserById(2) }}
    </template>
    

    Actions

    同步
      actions: {
        addCount(num) {
          this.counter += num
        }
      }
    
    <script setup>
        import { useMainStore } from './stores/main.js'
        const store = useMainStore()
    </script>
    <template>
      <button @click="store.addCount(2)">增加</button>
      <h1>{{ store.counter }}</h1>
    </template>
    
    
    异步
    import { mande } from 'mande'
    
    const api = mande('/api/users')
    
    export const useUsers = defineStore('users', {
      state: () => ({
        userData: null,
        // ...
      }),
    
      actions: {
        async registerUser(login, password) {
          try {
            this.userData = await api.post({ login, password })
            showTooltip(`Welcome back ${this.userData.name}!`)
          } catch (error) {
            showTooltip(error)
            // let the form component display the error
            return error
          }
        },
      },
    })
    

    持久化

    使用subscribe

    可以使用订阅机制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挂载后再调用,这里可以将它封装成方法导出,在挂载后调用

    export 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);
      }
    
    }
    

    在main.js后面调用

    使用插件

    安装

    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中开启

    import { defineStore } from 'pinia'
    // 'main' 是storeId,自己随便取,保证唯一
    export const useMainStore = defineStore('main', {
      state: () => ({
        counter: 2,
        name: 'Eduardo',
        isAdmin: true
      }),
      // ……
      // 开启数据缓存
      persist: {
        enabled: true
      }
    
    })
    

    数据默认存在 sessionStorage 里,并且会以 storeId 作为 key

    自定义key和存储位置

    persist: {
      enabled: true,
      strategies: [
        {
          key: 'user',
          storage: localStorage,
        }
      ]
    }
    

    持久化部分 state

    state: () => {
      return {
        counter: 2,
        name: 'Eduardo',
        isAdmin: true
      }  
    },
    
    persist: {
      enabled: true,
      strategies: [
        {
          storage: localStorage,
          paths: ['name', 'counter']
        }
      ]
    }
    

    只会存储paths中指定的satae字段

    相关文章

      网友评论

        本文标题:pinia2入门使用

        本文链接:https://www.haomeiwen.com/subject/hcynhrtx.html