Pinia
Pinia简介
Pinia是Vue的专属状态管理库,它允许跨组件或页面共享状态。所谓状态管理,简单来说就是一个存储数据的地方。
Vue2的状态管理使用Vuex,Vue3在继续支持Vuex的同时,还支持新开发了Pinia,当然Pinia也支持Vue2。
Pinia起始于2019年11月,Pinia其实就是Vuex的升级版本。根据官网的描述,Pinia将取代Vuex,即Pinia=Vuex5。
Pinia与Vuex(<=4)的区别:
- mutation 已被弃用。它们经常被认为是极其冗余的。它们初衷是带来 devtools 的集成方案,但这已不再是一个问题了。
- 无需要创建自定义的复杂包装器来支持 TypeScript,一切都可标注类型,API 的设计方式是尽可能地利用 TS 类型推理。
- 无过多的魔法字符串注入,只需要导入函数并调用它们,然后享受自动补全的乐趣就好。
- 无需要动态添加 Store,它们默认都是动态的,甚至你可能都不会注意到这点。注意,你仍然可以在任何时候手动使用一个 Store 来注册它,但因为它是自动的,所以你不需要担心它。
- 不再有嵌套结构的模块。你仍然可以通过导入和使用另一个 Store 来隐含地嵌套 stores 空间。虽然 Pinia 从设计上提供的是一个扁平的结构,但仍然能够在 Store 之间进行交叉组合。你甚至可以让 Stores 有循环依赖关系。
- 不再有可命名的模块。考虑到 Store 的扁平架构,Store 的命名取决于它们的定义方式,你甚至可以说所有 Store 都应该命名。
安装Pinia
npm install pinia 在main.js中进行导入并注册使用
import { createApp } from 'vue'
import './style.css'
import App from './VueRouter/App.vue'
import router from './VueRouter/router' // 导入路由
import ElementPlus from 'element-plus'  // 引入element plus组件库
import 'element-plus/dist/index.css'  // 引入element plus样式表
import { createPinia } from 'pinia' // 导入pinia
const pinia = createPinia()
const app = createApp(App)
app.use(ElementPlus) // 加载Elementpuls
app.use(router) // 注册路由插件
app.use(pinia)  // 注册pinia状态插件
app.mount("#app")定义optionStore
新建src/VueRouter/store/tabbar.js
import { defineStore } from "pinia";
// 第一个参数是唯一的storeId
const useTabbarStore = defineStore("tabbar",{
  // option Store
  state:()=>({
    isTabbarShow:true
  }),
  // getters
  // actions
})
export default useTabbarStore修改App.vue
<template>
  <div>
    <!-- 通过插槽插入子组件路由 -->
    <router-view></router-view>
    <!-- 增加导航 -->
    <Tabbar v-show="store.isTabbarShow"></Tabbar>
  </div>
</template>
<script setup>
import Tabbar from './components/Tabbar.vue';
import useTabbarStore from './store/tabbar';
const store = useTabbarStore()
</script>
<style>
*{
  margin: 0;
  padding: 0;
}
ul{
  list-style: none;
}
</style>修改Detail.vue
<template>
  <div>
    <button @click="plBackClick">返回</button>
    detail
  </div>
</template>
<script setup>
import {onMounted,onBeforeMount,onBeforeUnmount} from 'vue'
import { useRoute,useRouter } from 'vue-router'
import useTabbarStore from '../store/tabbar';
const route = useRoute()
const router = useRouter()
const store = useTabbarStore()
onBeforeMount(()=>{
  store.isTabbarShow = false
})
onBeforeUnmount(()=>{
  store.isTabbarShow = true
})
onMounted(()=>{
  console.log('接收上一个页面传来的参数',route.params.plid)
})
const plBackClick = ()=>{
  router.back() // 返回  router.forward()
}
</script>Action
新建src/VueRouter/store/recommend.js
import { defineStore } from "pinia"
import axios from "axios"
const useRecommendStore = defineStore("recommend",{
  // options store
  state:()=>({
    recommendList:[]
  }),
  actions:{
    async getRecommendList(){
      let res = await axios({
        url:"https://m.maizuo.com/gateway?cityId=110100&ticketFlag=1&k=112132",
        headers:{
          'X-Client-Info':'{"a":"3000","ch":"1002","v":"5.2.1","e":"16931924276063063597842433"}',
          'X-Host':'mall.film-ticket.cinema.list'
        }
      })
      this.recommendList=res.data.data.cinemas
    }
  }
})
export default useRecommendStore修改Recommend.vue
<template>
  <div>
    <ul>
      <li v-for="data in store.recommendList" :key="data.cinemaId">
        {{data.name}}
      </li>
    </ul>
  </div>
</template>
<script setup>
import { onMounted, ref } from 'vue'
// import { useStore } from 'vuex'
import useRecommendStore from '../../store/recommend';
const type =ref(1)
// const store = useStore()
const store = useRecommendStore()
onMounted(()=>{
  if(store.recommendList.length===0){
      store.getRecommendList()
      // store.dispatch("RecommendModule/getRecommendList")
    }else{
      console.log("缓存")
    }
})
</script>
<style scoped lang="scss">
ul{
  li{
    padding:10px;
  }
}
</style>Getter
修改recommend.js,增加getters进行筛选
import { defineStore } from "pinia"
import axios from "axios"
const useRecommendStore = defineStore("recommend",{
  // options store
  state:()=>({
    recommendList:[]
  }),
  actions:{
    async getRecommendList(){
      let res = await axios({
        url:"https://m.maizuo.com/gateway?cityId=110100&ticketFlag=1&k=112132",
        headers:{
          'X-Client-Info':'{"a":"3000","ch":"1002","v":"5.2.1","e":"16931924276063063597842433"}',
          'X-Host':'mall.film-ticket.cinema.list'
        }
      })
      this.recommendList=res.data.data.cinemas
    }
  },
  getters:{
    filterRecommendList(state){
      return (type)=>{
        return state.recommendList.filter(item=>item.eTicketFlag===type)
      }
    }
  }
})
export default useRecommendStore修改Recommend.vue
<template>
  <div>
    <select v-model="type">
      <option :value="1">App订票</option>
      <option :value="0">前台兑换</option>
    </select>
    <ul>
      <li v-for="data in store.filterRecommendList(type)" :key="data.cinemaId">
        {{data.name}}
      </li>
    </ul>
  </div>
</template>
<script setup>
import { onMounted, ref } from 'vue'
// import { useStore } from 'vuex'
import useRecommendStore from '../../store/recommend';
const type =ref(1)
// const store = useStore()
const store = useRecommendStore()
onMounted(()=>{
  if(store.recommendList.length===0){
      store.getRecommendList()
      // store.dispatch("RecommendModule/getRecommendList")
    }else{
      console.log("缓存")
    }
})
</script>
<style scoped lang="scss">
ul{
  li{
    padding:10px;
  }
}
</style>定义Setup Store
在Setup Store中:
- ref()就是- state属性
- computed()就是- getters
- function()就是- actions
Setup Store比Option Store有更多的灵活性。
将tabbar.js和recommend.js由Option Store模式改为Setup Store模式
tabbar.js
import { defineStore } from "pinia";
import { ref } from "vue"
// 第一个参数是唯一的storeId
const useTabbarStore = defineStore("tabbar",()=>{
  // setup Store
  // ref包装定义的就是state
  const isTabbarShow = ref(true)
  const change = (value)=> {
    isTabbarShow.value = value
  }
  return {
    isTabbarShow,
    change
  }
})
export default useTabbarStorerecommend.js
import { defineStore } from "pinia"
import { ref,computed } from "vue"
import axios from "axios"
const useRecommendStore = defineStore("recommend",()=>{
  // setup store
  const recommendList = ref([])
  const getRecommendList = async()=>{
    let res = await axios({
      url:"https://m.maizuo.com/gateway?cityId=110100&ticketFlag=1&k=112132",
      headers:{
        'X-Client-Info':'{"a":"3000","ch":"1002","v":"5.2.1","e":"16931924276063063597842433"}',
        'X-Host':'mall.film-ticket.cinema.list'
      }
    })
    recommendList.value=res.data.data.cinemas
  }
  const filterRecommendList = computed(()=>
    (type)=>{
      return recommendList.value.filter(item=>item.eTicketFlag===type)
    }
  )
  return {
    recommendList,
    getRecommendList,
    filterRecommendList
  }
})
export default useRecommendStore 
                        
                        