前端框架Vue(七)


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 useTabbarStore

recommend.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

文章作者: 老百
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 老百 !
 上一篇
前端框架Vue(总结) 前端框架Vue(总结)
Vue 是一款用于构建用户界面的 JavaScript 框架。本小节复习一遍之前所学的Vue知识,重新捋一遍,温故而知新。
2023-09-14
下一篇 
前端框架Vue(六) 前端框架Vue(六)
Vue 是一款用于构建用户界面的 JavaScript 框架。本小节介绍Vuex,是一个专为Vue.js应用程序开发的状态管理模式+库。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。
2023-08-29
  目录