Vue3.0下,如何在组件的setup()中监听vuex里某个state的变化? - 知乎

简介:本文介绍了Vue的管理工具Vuex、Provide/Inject、Pinia的基本使用。

一、Vue的Vuex状态管理

1、Vuex状态管理的应用(state、mutations、actions、getters)

npm install vuex@next --save   //安装
import store from './store/index.js'  //在main.js引入
createApp(App).use(store).mount('#app')

index.js的代码:

import {createStore} from 'vuex';
export default createStore({
  state(){return{count:0,  dzList:[]}},
  getters:{
    totalPrice(state){return state.count * 50}
  },
  mutations:{
    setCount(state){state.count++},
    setCountAdd(state,num){state.count += num},
    setdzList(state,arr){state.dzList = arr},
  },
  actions:{
    getDz(context){
      let api = 'https://api.apiopen.top/getJoke?page=1&count=2&type=video'
         fetch(api).then(res=>res.json()).then(result=>{
           context.commit('setdzList',result.result)})
    },
  },
  modules:{},
})

2、映射状态数据与方法

1)不借用映射状态数据获取Vuex的getters、state、mutations、actions的方法:

{{$store.state.count}}  //state正常访问方式
{{$store.getters.totalPrice}}  //getters正常访问方式
this.$store.commit('setCountAdd',10)  //mutations正常访问方式,写在对应的方法里面,用commit去触发mutations对应的方法
this.$store.dispatch("getDz")  //actions正常访问方式,需要用dispatch去触发actions对应的方法

2)使用映射状态数据,访问更方便:

注:mapState和mapGetters放入computed中;mapMutations和mapActions放在methods中。

import {mapState,mapMutations,mapActions,mapGetters} from 'vuex'
 export default {
   name: "home",
   computed:{
     ...mapState(['count']),
     ...mapState({productCount:state=>state.count,}),   //对state的状态名进行修改
     ...mapGetters(['totalPrice']),   //
   },
   methods:{
     ...mapMutations(['setCountAdd']), //Mutation仅支持同步
     ...mapActions(['getDz']),   //Action支持同步与异步
   },
   mounted(){
     this.getDz()
     // this.$store.dispatch("getDz")  //Action正常访问方式
   }
 }  
{{count}}  //state      //视图中的使用
{{totalPrice}}  //getter

3、模块化管理Vuex

1)一个vuex模块

import user from './user'   //书写对应的模块化vuex
import user1 from './user1'
modules:{     //在index.js中的modules引入
  user,   user1,
},
const user = {    //其中的user.js文件
  state:()=>({
    username:'wl', age:20
  }),
  mutations:{
    setUsername(state){state.username = 'hello'},
    setAge(state,val){ state.age = val}
  },
  actions:{
    asyncsetAge(context,num=50){
      setTimeout(()=>{ context.commit('setAge',num)},1000)
    }
  },
  getters:{
    descrption(state){ return state.username + '!' + '年龄是'  + state.age + '岁!'}
  },
}
export default user

在视图中的使用:

{{$store.state.user.username}}  //模块user的state正常访问方式
{{$store.getters.descrption}}  //模块user的getters正常访问方式
this.$store.commit('setUsername')  //模块user的mutations正常访问方式
this.$store.dispatch("asyncsetAge")  //模块user的actions正常访问方式

2)如果两个模块的state及方法名同名,可开启命名空间的写法

const user = {     //内容和userjs文件内容一致
  namespaced:true,    //state的名称一样,开启命名空间
  state:()=>({}),
  mutations:{},
  actions:{},
  getters:{},
}
export default user

在视图中写法:

//不使用辅助函数,正常访问方式
{{$store.state.user1.username}}            //模块user1的state正常访问方式
{{$store.getters['user1/descrption']}}     //模块user1的getters正常访问方式
this.$store.dispatch('user1/asyncsetAge')   //模块user1的actions正常访问方式
this.$store.commit('user1/setUsername')    //模块user1的mutations正常访问方式
//通过辅助函数(mapState,mapMutations,mapActions,mapGetters)访问
...mapState(['user1']),       //模块user1的state
...mapGetters('user1',['descrption'])   //传入命名空间的名字,再把getters解构出来
...mapActions('user1',['asyncsetAge']),
//使用辅助函数的视图写法
{{user1.username}}  //user1的state
{{descrption}}  //user1的getter

二、使用Prpvide/Inject

Vue2.x在后期就提供了Provide / Inject实现跨级组件间通信,Vue3.x的Provide / Inject,相比全局共享,可实现基础的状态管理。

const store = {        //在store/index.js中
    state:reactive({
        message:'hello-wl',
        duanziList:[]}),
    setMessage(value){this.state.message = value},
    setdzList(list){this.state.duanziList = list}
}
export default store
provide:{store}   //组件中注入数据
inject:['store'],   //其他组件使用全局数据

三、Pinina基础

1、Pinia具有以下几点特性:

  • 直观,像定义components一样地定义store
  • 完整的Typescrip支持
  • 去除mutations,只有state、getters、actions
  • actions支持同步和异步
  • Vue Devtools支持Pinia,提供更好的开发体验
  • 能够构建多个stores,并实现自动地代码拆分
  • 极其轻量(1kb),甚至感觉不到它的存在

注:官网地址:https://pinia.vuejs.org/introduction.html,目前已经合并到vue的官网文档里。

Pinia从2019年11月左右,开始尝试重新使用Composition APl设计Vue Store,是 Vuex4 的升级版,也就是 Vuex5。

2、Pina的使用

1)安装与导入

npm install pinia   //"pinia": "^2.0.13"    //安装
import {createPinia} from 'pinia'          //main.js导入
createApp(App).use(createPinia()).mount('#app')  //createPinia()得加上括号

2)store/index.js的写法

import {defineStore} from "pinia";
export default  defineStore('main',{    //定义一个仓库id名
  state:()=>{
    return{count:10}
  }
})

3)在组件中使用

import useMainStore from "./store/index.js"
const store = useMainStore()
{{store.count}}    //使用stroe中的数据

3、Vuex 与 Pinia 对比

1)Vuex 中核心部分:State、Getters、Mutations(同步) 和Actions(异步)

2)Pinia 中核心部分:State、Getters和Actions(同步异步均支持)

State:类似于组件中data,用于存储全局状态。

Getters:类似于组件中的computed,根据已有的State封装派生数据,也具有缓存的特性。

Actions:类似于组件中的methods,用于封装业务逻辑,同步异步均可以。

四、Vue3与axios实现前后端交互

方法1:使用fetch

setup(){
    let api = 'https://api.apiopen.top/getJoke?page=l&count=2&type=video'
    fetch(api).then(res=>res.json()).then(result=>{
        store.setdzList(result.message)
    })
    return{ store}
}

方法2:使用axios

install axios --save   //安装
import axios form 'axios'
setup(){
    let api = 'https://api.apiopen.top/getJoke?page=l&count=2&type=video'
   axios.get(api).then(res=>{
    store.setdzList(res.data.message)}) 
}

五、Vite配置跨域请求

添加vite.config.js文件,类似于vue2.x的vue.config.js,Vue3.x不需要写devServer。

module.exports = {
    proxy:{
        '/api':{
            target:'https://pvp.qq.com',
            changeOrigin:true,//是否允许跨域
            rewrite:path => path.replace(/^\/api/,'')
        }
    }
}
let api = '/api/web201605/js/herolist.json'    //使用

六、mockjs模拟数据

作用:生成随机数据,拦截Ajax请求,模拟后端返回数据。

npm install mockjs --save   //安装
import  './mock/index.js'   //main.js中引入
import Mock from 'mockjs'    //mock/index.js
Mock.setup({
    timeout:'200-600',
})
 Mock.mock(
    "/user/userinfo",
    'get',
    (req,res)=>{
        return{ username:'wl',type:'math',}
    }
)
Mock.mock(
    /\/account.*/,
    'get',
    (req,res)=>{
        console.log(req,res)
        return{ info:'登录成功', }
    }
)
setup(){                //调接口使用
    let api = '/user/userinfo'
   axios.get(api).then(res=>{store.setdzList(res.data) })
   axios.get('/account?username=wl&password=12').then(res=>{
        store.setMessage(res.data)
    })
    return{store}
}

原网址: 访问
创建于: 2023-10-08 11:27:37
目录: default
标签: 无

请先后发表评论
  • 最新评论
  • 总共0条评论