vue3之pinia“全家桶”

124 阅读1分钟

前言

Vue2的时候,Vuex可以说是必备的,它作为一个状态管理工具,给我们带来了极大的 方便,Vue3推出后,虽然相对于Vue2很多东西都变了,但是核心的东西还是没有太大的变化。

优点

  • Vue2和Vue3都支持,这让我们同时使用Vue2和Vue3的前端同学都能很快上手。
  • pinia中只有state、getter、action,不需要用到Vuex中的Mutation。
  • pinia中action支持同步和异步,Vuex不支持。
  • 同时支持Typescript,毕竟我们Vue3都推荐使用TS来编写。
  • 无需创建各个模块嵌套,pinia中的每个store都是独立的,互相不影响

内容

安装依赖

yarn add pinia
# 或者使用 npm
npm install pinia

main.js

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

image.png

actiondemo.js

import { defineStore } from 'pinia'

export const useActionStore = defineStore('action', {
    state: () => ({
        counter: 3,
        count:0
    }),
    actions: {
        increment() {
            this.counter++;
        },
        incrementTrad(val) {
            this.count += val;
        },
        randomizeCounter() {
            this.counter = Math.round(100 * Math.random())
        },
    },
})

counter.js

import { ref, computed } from 'vue'
import { defineStore } from 'pinia'

export const useCounterStore = defineStore('counter', () => {
  const count = ref(0)
  const doubleCount = computed(() => count.value * 2)
  function increment() {
    count.value++
  }

  return { count, doubleCount, increment }
})

main.js

import { defineStore } from 'pinia';
import { useCounterStore } from './counter';

export const useStore = defineStore('main', {
    state: () => {
        return {
            counter: 0,
            users: [
                { id: 1, name1: "123+" ,active:true}, 
                { id: 2, name2: "456+" ,active:false}, 
                { id: 3, name3: "789+" ,active:true }]
        }
    },
    getters: {
        // 箭头函数
        doubleCount: (state) => state.counter * 2,
        // 普通函数
        doubleCountPlusOne() {
            // 自动完成 ✨
            return this.doubleCount + 1
        },
        getUserById: (state) => {
            return (userId) => state.users.find((user) => user.id === userId)
        },
        getActiveUserById(state) {
            const activeUsers = state.users.filter((user) => user.active)
            return (userId) => activeUsers.find((user) => user.id === userId)
        },
        otherGetter(state) {
            const cunterStore = useCounterStore()
            return state.counter + cunterStore.count
          },

    },
})

store.js

import { defineStore } from 'pinia'

export const useStore = defineStore('storeId', {
    // 推荐使用 完整类型推断的箭头函数
    state: () => {
        return {
            // 所有这些属性都将自动推断其类型
            counter: 0,
            name: 'Eduardo',
            isAdmin: false,
            items:['太','美']
        }
    },
})

2e7683f7d09d9b11b612c4fed70f552.png

demo.vue

<script setup>
import { storeToRefs } from "pinia";
import { useStore } from "../stores/store.js";
const store = useStore();
console.log(store);
let { counter, name, isAdmin ,items} = storeToRefs(store) ;

// 修改
const changeMyName = () => {
  name.value = "我替换了!!!";
};

// 重置
const resetStore=()=>{
    store.$reset()
}

const allChange=()=>{
    // 第一种
    store.$patch({
        // counter:counter.value+1+'我是修改1',
        counter:counter.value+1,
        name:'我是修改2'
    })
    // 第二种
//   store.$patch((state) => {
//     state.items.push('我是添加');
//     state.isAdmin = true;
//   });
}
// 通过赋值一个对象替换对应的属性
const stateChange = () => {
  store.$state = { counter: 666, name: "Paimon" };
};

store.$subscribe((mutation, state) => {
  console.log(state, "subscribe");
  // 每当它发生变化时,将整个状态持久化到本地存储
  localStorage.setItem("store", JSON.stringify(state));
});
</script>

<template>
    <div>
         <h1>pinia数据的调用</h1>
    <div>{{ counter }}</div>
    <div>{{ name }}</div>
    <div>{{ isAdmin }}</div>
     <button @click="changeMyName">修改name</button>
     <button @click="resetStore">重置所有内容</button>
     <button @click="allChange">批量修改</button>
      <button @click="stateChange">整体替换一个store</button>
     <div v-for="(i, index) in items" :key="index">{{ i }}</div>
    </div>
</template>

demo_two.vue

<script setup>
import { onMounted, getCurrentInstance } from "vue";
import { storeToRefs } from "pinia";
import { useStore } from "../stores/main";
import { useActionStore } from "../stores/actiondemo";


const store = useStore();
const actionStore = useActionStore();
let { counter, count } = storeToRefs(actionStore);

const requestChange = () => {
  getGroomList().then((res) => {
    console.log(res);
  });
};
const addOne = () => {
  actionStore.increment();
};
const addOneTradition = () => {
  actionStore.incrementTrad(2);
};

console.log(store.doubleCount, "doubleCount");
console.log(store.doubleCountPlusOne, "doubleCountPlusOne");
console.log(store.getUserById(2), "getUserById");
console.log(store.getUserById(1), "getactiveUsers");
console.log(store.getActiveUserById(1), "getActiveUserById");
console.log(store.otherGetter, "otherGetter");
</script>


<template>
  <div>
    <div>demo_two</div>
    <div>
      <button @click="requestChange">发起请求</button>
      <h1>action</h1>
      <div>{{ counter }}</div>
      <div>{{ count }}</div>
      <button
        @click="
          addOne();
          addOneTradition();
        "
      >
        加1
      </button>
    </div>
  </div>
</template>

这种组合式编程的思想更重要,pinia无非就是以下3个大点:

  • state
  • getters
  • actions