20230422----重返学习-vue数据集中管理vuex

Vuex是一个专为Vue.js设计的状态管理模式,用于集中管理应用的所有组件状态。它提供了state、getters、mutations、actions和modules等核心概念,支持数据持久化和日志插件,便于调试和维护。Vuex通过计算属性和辅助函数如mapState、mapGetters、mapMutations和mapActions简化了组件与全局状态的交互,实现了数据通信和状态缓存功能。
摘要由CSDN通过智能技术生成

day-055-fifty-five-20230422-vue数据集中管理vuex

vuex

vuex的说明

  • vuex是专门为vue提供的大仓库,采用状态管理的大仓库
  • Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。
    • 它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。

vuex与vue版本的关联

  • 一般vuex要比vue的版本多1
    • vue2 —> vuex3
    • vue3 —> vuex4

vuedevtools安装

  1. 解压vuedevtools文件夹
  2. 打开谷歌浏览器进行安装
    • 网页右上角没有的V可以点开这个拼图图标,然后把V置顶就出现了
  3. 安装完成后,需要重新启动vue项目

安装vuex

  • 方法1. 创建项目的时候,直接选vuex

    1. src目录先多一个文件夹 store —> index.js(写好的模板)导出仓库
      • 多一个文件/src/store/index.js,里面会让vue使用vuex这个插件,同时初始化一个Vuex实例对象,并导出。

        import Vue from 'vue'
        import Vuex from 'vuex'
        Vue.use(Vuex)//让Vue构造函数使用了Vuex这个vue插件
        const store=new Vuex.Store({})// 创建一个Vuex实例对象
        export default store;// 导出Vuex实例对象
        
      • /src/main.js中会导入Vuex实例对象,并将其挂载到根Vue实例对象上。

        import store from './store'
        let vm=new Vue({
          store,
          render: h => h(App)
        }).$mount('#app')
        
  • 方法2. 创建项目的,没有选择vuex

    1. 重新安装vuex这个vue插件的npm依赖

      npm install vuex --save//使用npm方式,个人推荐,最基础的方式
      //yarn add vuex//yarn方式,npm方式因网络不好时再用
      
    2. 安装好vuex之后,项目中关于vuex的什么基础操作都没有,需要自己手动编写和操作

      • 安装依赖的作用,主要是可以通过import Vuex from 'vuex'在项目中可以导入Vuex这个vue插件。
    3. src目录先多一个文件夹 store —> index.js(写好的模板)导出仓库

      • 多一个文件/src/store/index.js,里面会让vue使用vuex这个插件,同时初始化一个Vuex实例对象,并导出。

        import Vue from 'vue'
        import Vuex from 'vuex'
        Vue.use(Vuex)//让Vue构造函数使用了Vuex这个vue插件
        const store=new Vuex.Store({})// 创建一个Vuex实例对象
        export default store;// 导出Vuex实例对象
        
      • /src/main.js中会导入Vuex实例对象,并将其挂载到根Vue实例对象上。

        import store from './store'
        let vm=new Vue({
          store,
          render: h => h(App)
        }).$mount('#app')
        

vue五大模块

  • state: {} 相当于vue中的data

    • 设置值:

      export default new Vuex.Store({
        state: {
          num:100,
          str:"hello"
        }
      })
      
    • 获取值:

      • 通过this.$store.state拿到state对象里的数据

        1. 直接取

          <template>
            <div>{{ $store.state.num }}</div>
          </template>
          
          <script>
          export default {
            mounted() {
              this.$store.state.num
            }
          };
          </script>
          
        2. 通过data取

          <script>
          export default {
            data(){
              return {
                dataNum:this.$store.state.num
              }
            }
          };
          </script>
          
        3. 通过computed

          • 推荐
          <script>
          export default {
            computed:{//推荐
              dataNum(){
                return this.$store.state.num
              }
            }
          };
          </script>
          
      • 通过mapState()辅助函数拿到state对象里的数据

        1. mapState()辅助函数

          • 推荐
          <template>
            <div>{{ num }}--{{ str }}</div>
          </template>
          <script>
          import { mapState } from 'vuex';
          export default {
            computed:mapState(["num","str"])
          };
          </script>
          
          • 步骤

            1. 引入

              import { mapState } from 'vuex';
              
            2. 配合计算属性使用

              computed:mapState(["num","str"])
              
              computed:{...mapState(["num","str"])}
              
          • 使用类型

            • 数组:直接接收,直接使用

              <template>
                <div>{{ num }}--{{ str }}</div>
              </template>
              <script>
              import { mapState } from 'vuex';
              export default {
                computed:mapState(["num","str"])
              };
              </script>
              
            • 对象:接收后,换一个名称

              <template>
                <div>{{ nn }}---{{ ss }}---{{ mm }}</div>
              </template>
              <script>
              import { mapState } from 'vuex';
              export default {
                computed:mapState({
                  nn:state=>state.num,//使用函数的方式
                  ss:"str",//使用字符串的方式
              
                  //使用函数ES6简写的方式
                  mm(state){
                    return state.num+200
                  }
                })
              };
              </script>
              
          • 辅助函数 与 计算属性的其他属性共存

            <template>
              <div>{{ nn }}---{{ fullName }}---{{ str }}</div>
            </template>
            <script>
            import { mapState } from 'vuex';
            export default {
              computed:{
                  ...mapState({
                    nn:state=>state.num
                  }),
                  fullName(){
                    return 5555
                  },
                  ...mapState(['str'])
              }
            };
            </script>
            
  • getters: {}: 相当于vue中的计算属性,对state的数据二次处理

    • 函数的写法,属性的用法。

    • 设置值:

      export default new Vuex.Store({
        state: {
          arr:[10,20,30,40,50,60]
        },
        getters:{
          //函数的写法,属性的用法
          //作用 state里面的数据进行二次处理返回
          //箭头函数写法
          newarr:(state)=>{
            return state.arr.filter((item)=>item>30)
          }
          
          //ES6写法
          //newarr(state) {
          //  return state.arr.filter((item) => item > 30);
          //},
        }
      })
      
      export default new Vuex.Store({
        state: {
          arr:[10,20,30,40,50,60]
        },
        getters:{
          //ES6写法
          newarr(state) {
            return state.arr.filter((item) => item > 30);
          },
        }
      })
      
    • 获取值:

      • 通过this.$store.state拿到getters对象里的数据

        1. 直接取

          <template>
            <div>{{ $store.getters.newarr }}</div>
          </template>
          
          <script>
          export default {
            mounted() {
              this.$store.getters.newarr
            }
          };
          </script>
          
        2. 通过data取

          <script>
          export default {
            mounted() {
              this.dataNum
            },
            data(){
              return {
                dataNum:this.$store.getters.newarr
              }
            }
          };
          </script>
          
        3. 通过computed

          • 推荐
          <script>
          export default {
            mounted() {
              this.computedNum
            },
            computed:{//推荐
              computedNum(){
                return this.$store.getters.newarr
              }
            }
          };
          </script>
          
      • 通过mapGetters()辅助函数拿到getters对象里的数据

        1. mapGetters()辅助函数

          • 推荐
          <template>
            <div>{{ newarr }}</div>
          </template>
          <script>
          import { mapGetters } from 'vuex';
          export default {
            computed:mapGetters(["newarr"])
          };
          </script>
          
          • 步骤

            1. 引入

              import { mapGetters } from 'vuex';
              
            2. 配合计算属性使用

              computed:mapGetters(["newarr"])
              
              computed:{...mapGetters(["newarr"])}
              
          • 使用类型

            • 数组:直接接收,直接使用

              <template>
                <div>{{ newarr }}</div>
              </template>
              <script>
              import { mapGetters } from 'vuex';
              export default {
                computed:mapGetters(["newarr"])
              };
              </script>
              
            • 对象:接收后,换一个名称

              <template>
                <div>{{ arr }}</div>
              </template>
              <script>
              import { mapGetters } from 'vuex';
              export default {
                computed:mapGetters({arr:"newarr"})
              };
              </script>
              
          • 辅助函数 与 计算属性的其他属性共存

            <template>
              <div>{{ newarr }}---{{ arr }}</div>
            </template>
            <script>
            import { mapGetters } from 'vuex';
            export default {
              computed:{
                  ...mapGetters(["newarr"]),
                  fullName(){
                    return 5555
                  },
                  ...mapGetters({arr:"newarr"})
              }
            };
            </script>
            
  • mutations: {} 同步方法(仓库管理员)

    • vuex是单向数据流,state只能通过Mutation来修改

    • 设置方法:

      export default new Vuex.Store({
        state: {
          num:100
        },
        mutations: {
          //箭头函数写法
          //无入参
          addNum:(state)=>{
            state.num++
          },
        }
      })
      
      export default new Vuex.Store({
        state: {
          num:100
        },
        mutations: {
          //箭头函数写法
          //有入参
          addNum:(state,payload)=>{
            //console.log(payload);
            //state.num++
            state.num+=payload.n;
          }
        }
      })
      
      export default new Vuex.Store({
        state: {
          num:100
        },
        mutations: {
          //ES6简写写法
          //无入参
          addNum(state){
            state.num++
          },
        }
      })
      
      export default new Vuex.Store({
        state: {
          num:100
        },
        mutations: {
          //ES6简写写法
          //有入参
          addNum(state,payload){
            console.log(payload);
            state.num+=payload.n;
          }
        }
      })
      
    • 使用方法:

      • 通过this.$store.commit()使用mutations对象里的同步方法

        • 要想执行 mutations里面的方法,必须通过 commit()

          • commit(函数名,参数) 只有两个值
            • 如果第二个参数那里,想要传递多个内容,可以使用数组,对象
          <template>
            <div>
              {{ $store.state.num }}
              <button @click="add">add</button>
            </div>
          </template>
          
          <script>
          export default {
            methods:{
              //  add(){//页面数据可以修改,仓库数据无法修改
              //     this.$store.state.num++;
              //  }
              add(){//要想执行 mutations里面的方法,必须通过 commit()
                //commit(函数名,参数) 只有两个值  
                //如果第二个“参数”,想要传递多个内容,数组,对象
                this.$store.commit("addNum",{n:10,m:20})
              }
            }
          }
          </script>
          
      • 通过mapMutations()辅助函数使用mutations对象里的同步方法

        1. mapMutations()辅助函数

          <template>
            <div>
              {{ $store.state.num }}
              <button @click="add({n:10,m:20})">add</button>
            </div>
          </template>
          <script>
          import { mapMutations } from 'vuex';
          export default {
            methods:{
              ...mapMutations({
                add:"addNum"
              })
            }
          };
          </script>
          
          • 步骤

            1. 引入

              import { mapMutations } from 'vuex';
              
            2. 配合methods属性使用

              methods:mapMutations({add:"addNum"})
              
              methods:{...mapMutations({add:"addNum"})}
              
          • 使用类型

            • 数组:直接接收,直接使用

              <template>
                <div>
                  {{ $store.state.num }}
                  <button @click="addNum({n:10,m:20})">addNum</button>
                </div>
              </template>
              <script>
              import { mapMutations } from 'vuex';
              export default {
                methods:mapMutations(["addNum"]),
              };
              </script>
              
            • 对象:接收后,换一个名称

              <template>
                <div>
                  {{ $store.state.num }}
                  <button @click="add({n:10,m:20})">add</button>
                </div>
              </template>
              <script>
              import { mapMutations } from 'vuex';
              export default {
                methods:mapMutations({add:"addNum"}),
              };
              </script>
              
          • 辅助函数 与 methods的其他方法共存

            <template>
              <div>
                {{ $store.state.num }}
                <button @click="addNum({n:10,m:20})">addNum</button>
                <button @click="add({n:10,m:20})">add</button>
              </div>
            </template>
            <script>
            import { mapMutations } from 'vuex';
            export default {
              methods:{
                ...mapMutations(["addNum"]),
                ...mapMutations({add:"addNum"})
              }
            };
            </script>
            
  • actions: {}

    • 设置异步方法

      export default new Vuex.Store({
        state: {
          n:10
        }
        mutations: {
          addN(state,payload){//通过mutations做异步操作效果实现的不对
              state.n+=payload;
          }
        },
        actions: {
          AsyncAddN(context,payload){
            //console.log(context);//{commit,...}
            setTimeout(() => {
                context.commit("addN",payload);
            }, 1000);
          }
        }
      })
      
    • 使用异步方法

      <template>
        <div>
          {{ $store.state.n }}
          <button @click="addN()">addN</button>
        </div>
      </template>
      
      <script>
      export default {
        methods:{
          addN(){
            //this.$store.commit("addN")
            //通过dispatch来调用 actions
            this.$store.dispatch("AsyncAddN",10)
          }
        }
      }
      </script>
      
    • 使用辅助函数-对象可改名

      <template>
        <div>
          {{ $store.state.n }}
          <button @click="add(10)">add</button>
        </div>
      </template>
      
      <script>
      import { mapActions } from 'vuex';
      export default {
        methods:{
          ...mapActions({
            add:"AsyncAddN"
          })
        }
      }
      </script>
      
    • 使用辅助函数-数组不可改名

      <template>
        <div>
          {{ $store.state.n }}
          <button @click="AsyncAddN(10)">add</button>
        </div>
      </template>
      
      <script>
      import { mapActions } from 'vuex';
      export default {
        methods:{
          ...mapActions(["AsyncAddN"])
        }
      }
      </script>
      
  • modules: {} 模块,将仓库进行划分,每个模块仍然具有五部分

    • 模式一: 不区别getters与mutations等

      • 设置

        const ModelA={
          state:{
            arra:[1,2,3,4,5]
          },
          getters:{
            newarra(store){
              return store.arra.filter((item)=>{
                  return item>3
              })
            }
          }
        }
        
        const ModelB={
          state:{
            numb:200
          },
          mutations:{
            changeNum(state){
                state.numb+=10;
            }
          }
        }
        
        
        export default new Vuex.Store({
          modules: {
            a:ModelA,
            b:ModelB
          }
        })
        
      • 使用

        <template>
          <div>
            {{ $store.state.b.numb }}
            {{ $store.getters.newarra }}
            <button @click="changeNum()">changeNum</button>
          </div>
        </template>
        
        <script>
        import { mapMutations } from 'vuex';
        export default {
          methods:{
            ...mapMutations(["changeNum"])
          }
        }
        </script>
        
    • 模式二:使用命名空间,区别getters与mutations等

      namespaced: true,//添加命名空间
      
      • 设置

        const ModelC = {
          namespaced: true,
          state: {
            arra: [1, 2, 3, 4, 5],
          },
          getters: {
            newarra(state) {
              return state.arra.filter((item) => item > 3);
            },
          },
        };
        
        const ModelD = {
          namespaced: true,
          state: {
            numd: 5,
          },
          mutations: {
            changeNumd(state, payload = 10) {
              state.numd += payload;
            },
          },
          actions: {
            asyncChangeNumd(context, payload = 100) {
              setTimeout(() => {
                context.commit("changeNumd", payload);
              }, 1000);
            },
          },
        };
        
        
        export default new Vuex.Store({
          modules: {
            c: ModelC,
            d: ModelD,
          }
        })
        
      • 使用

        • 方法一,使用命名空间直接访问

          <template>
            <div>
              <h1>ModulesView01</h1>
              <div>$store.getters["c/newarra"] --- {{ $store.getters["c/newarra"] }}</div>
              <div>mapGetters('c',['newarra']) --- {{ newarra }}</div>
              <div>{{ $store.state.d.numd }}</div>
              <div>
                <button @click="changeNumd()">
                  同步改变值-辅助函数-数组-mapMutations("d", ["changeNumd"])
                </button>
                <button @click="asyncChangeNumd()">
                  异步改变值-辅助函数-数组-mapActions("d", ["asyncChangeNumd"])
                </button>
              </div>
          
              <div>
                <button @click="handleChange01()">
                  同步改变值-commit-对象-mapMutations({ handleChange01: "d/changeNumd" })
                </button>
                <button @click="handleChange02()">
                  异步改变值-dispatch-对象-mapActions({ handleChange02:
                  "d/asyncChangeNumd" })
                </button>
              </div>
              <div>
                <button @click="handleChange03()">
                  同步改变值-辅助函数-对象-mapMutations("d", { handleChange03:
                  "changeNumd" })
                </button>
                <button @click="handleChange04()">
                  异步改变值-辅助函数-对象-mapActions("d", { handleChange04:
                  "asyncChangeNumd" })
                </button>
              </div>
              <div>
                <button @click="handleChange05()">同步改变值-commit-this.$store.commit("d/changeNumd", num)</button>
                <button @click="handleChange06()">异步改变值-dispatch-this.$store.dispatch("d/asyncChangeNumd", num)</button>
              </div>
            </div>
          </template>
          
          <script>
          import { mapGetters } from "vuex";
          import { mapMutations } from "vuex";
          import { mapActions } from "vuex";
          export default {
            computed: {
              ...mapGetters("c", ["newarra"]),
            },
            methods: {
              ...mapMutations("d", ["changeNumd"]), //常用,推荐使用方式
              ...mapActions("d", ["asyncChangeNumd"]), //常用,推荐使用方式
          
              ...mapMutations({ handleChange01: "d/changeNumd" }),
              ...mapActions({ handleChange02: "d/asyncChangeNumd" }),
          
              ...mapMutations("d", { handleChange03: "changeNumd" }),
              ...mapActions("d", { handleChange04: "asyncChangeNumd" }),
          
              handleChange05() {
                this.$store.commit("d/changeNumd"); //常用,推荐使用方式
              },
              handleChange06() {
                this.$store.dispatch("d/asyncChangeNumd"); //常用,推荐使用方式
              },
            },
          };
          </script>
          
          • 简洁

            <template>
              <div>
                <h1>ModulesView01</h1>
                <div>$store.getters["c/newarra"] --- {{ $store.getters["c/newarra"] }}</div>
                <div>mapGetters('c',['newarra']) --- {{ newarra }}</div>
                <div>{{ $store.state.d.numd }}</div>
                <div>
                  <button @click="changeNumd()">
                    同步改变值-辅助函数-数组-mapMutations("d", ["changeNumd"])
                  </button>
                </div>
              </div>
            </template>
            
            <script>
            import { mapGetters } from "vuex";
            import { mapMutations } from "vuex";
            export default {
              computed: {
                ...mapGetters("c", ["newarra"]),
              },
              methods: {
                ...mapMutations("d", ["changeNumd"]), //常用,推荐使用方式
              },
            };
            </script>
            
        • 方法二:使用import { createNamespacedHelpers } from "vuex";

          <template>
            <div>
              <h1>ModulesView01</h1>
              <div>$store.getters["c/newarra"] --- {{ $store.getters["c/newarra"] }}</div>
              <div>mapGetters(['newarra']) --- {{ newarra }}</div>
              <div>{{ $store.state.d.numd }}</div>
              <div>
                <button @click="changeNumd()">
                  同步改变值-辅助函数-数组-mapMutations(["changeNumd"])
                </button>
                <button @click="asyncChangeNumd()">
                  异步改变值-辅助函数-数组-mapActions(["asyncChangeNumd"])
                </button>
              </div>
          
              <div>
                <button @click="handleChange01()">
                  同步改变值-commit-对象-mapMutations({ handleChange01: "changeNumd" })
                </button>
                <button @click="handleChange02()">
                  异步改变值-dispatch-对象-mapActions({ handleChange02:
                  "asyncChangeNumd" })
                </button>
              </div>
              <div>
                <button @click="handleChange05()">
                  同步改变值-commit-this.$store.commit("d/changeNumd", num)
                </button>
                <button @click="handleChange06()">
                  异步改变值-dispatch-this.$store.dispatch("d/asyncChangeNumd", num)
                </button>
              </div>
            </div>
          </template>
          
          <script>
          import { createNamespacedHelpers } from "vuex";
          const { mapGetters } = createNamespacedHelpers("c");
          const { mapMutations } = createNamespacedHelpers("d");
          const { mapActions } = createNamespacedHelpers("d");
          export default {
            computed: {
              ...mapGetters(["newarra"]),
            },
            methods: {
              ...mapMutations(["changeNumd"]),
              ...mapActions(["asyncChangeNumd"]),
          
              ...mapMutations({ handleChange01: "changeNumd" }),
              ...mapActions({ handleChange02: "asyncChangeNumd" }),
          
              handleChange05() {
                this.$store.commit("d/changeNumd"); //常用,推荐使用方式
              },
              handleChange06() {
                this.$store.dispatch("d/asyncChangeNumd"); //常用,推荐使用方式
              },
            },
          };
          </script>
          
          • 简洁

            <template>
              <div>
                <h1>ModulesView01</h1>
                <div>$store.getters["c/newarra"] --- {{ $store.getters["c/newarra"] }}</div>
                <div>mapGetters(['newarra']) --- {{ newarra }}</div>
                <div>{{ $store.state.d.numd }}</div>
                <div>
                  <button @click="changeNumd()">
                    同步改变值-辅助函数-数组-mapMutations(["changeNumd"])
                  </button>
                </div>
                <div>
                  <button @click="handleChange05()">
                    同步改变值-commit-this.$store.commit("d/changeNumd", num)
                  </button>
                </div>
              </div>
            </template>
            
            <script>
            import { createNamespacedHelpers } from "vuex";
            const { mapGetters } = createNamespacedHelpers("c");
            const { mapMutations } = createNamespacedHelpers("d");
            export default {
              computed: {
                ...mapGetters(["newarra"]),
              },
              methods: {
                ...mapMutations(["changeNumd"]),
            
                handleChange05() {
                  this.$store.commit("d/changeNumd"); //常用,推荐使用方式
                },
              },
            };
            </script>
            

vuex插件

  1. 日志插件

    • vuex自带一个日志插件用于一般的调试

      import createLogger from 'vuex/dist/logger'
      const store = new Vuex.Store({
        plugins: [createLogger()]
      })
      
  2. vuex数据持久化插件

辅助函数

  • vuex有五大重要特性,有四个都有对应的辅助函数

    • 所有的辅助函数大多是一样的使用方式
  • State 相当于vue中的data

    • 辅助函数为mapState()

      import { mapState } from "vuex";
      
  • Getter 相当于vue中的计算属性,对State的数据二次处理

    • 辅助函数为mapGetters()

      import { mapGetters } from "vuex";
      
  • Mutation 管理同步方法,专门用来直接修改State中的数据的

    • 辅助函数为mapMutations()

      import { mapMutations } from "vuex";
      
  • Action 管理异步方法,专门用来调用的Mutation中的同步方法的

    • 辅助函数为mapActions()

      import { mapActions } from "vuex";
      
  • Module 管理模块的

vuex的作用

  • vuex一般有两个作用
    • 作用一: 实现数据通信
    • 作用二: 数据缓存 切换页面(前进后退),数据不变(缓存); 除非刷新或者关闭

配置一个路由

  1. 在/src/views/新建一个vue文件,例如叫MutationView.vue

    <template>
      <div>
        <h1>MutationView</h1>
      </div>
    </template>
    
    <script>
    export default {
    
    }
    </script>
    
  2. 在/src/router/index.js上进行修改,新添加一个动态路由

      //一个动态路由
      {
        path: '/mutationView',//这个是页面URL路径
        name: 'MutationView',//这个是路由页面名称
        component: () => import('../views/MutationView.vue')//这个路径是之前新建文件的文件名。
      }
    
    import Vue from 'vue'
    import VueRouter from 'vue-router'
    import HomeView from '../views/HomeView.vue'
    
    Vue.use(VueRouter)
    
    const routes = [
      {
        path: '/',
        name: 'home',
        component: HomeView
      },
      {
        path: '/about',
        name: 'about',
        component: () => import(/* webpackChunkName: "about" */ '../views/AboutView.vue')
      },
      {
        path: '/mutationView',//这个是页面URL路径
        name: 'MutationView',//这个是路由页面名称,也是webpack的chunk名称
        component: () => import('../views/MutationView.vue')//这个路径是之前新建文件的文件名。
      }
    ]
    
    const router = new VueRouter({
      routes
    })
    
    export default router
    
  3. 在根组件上,写一个router-link标签,用于跳转到新建的路由页面。

    • router-link标签的to属性与新建路由的页面URL路径保持一致
    <template>
      <div id="app">
          <router-link to="/mutationView">MutationView</router-link>
        <router-view/>
      </div>
    </template>
    

进阶参考

  1. Vue2配合使用的Vuex3官方中文文档
  2. Vue3配合使用的Vuex4官方中文文档
  3. Vuex官方中文文档–一般照着这个来就行了-这个一般都是最新版最主流的
  4. vuedevtools-官方git仓库
  5. vuex内置-logger-插件
  6. vuex数据持久化插件
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值