学习vue——vue.js入门(五)

vue组件通信

组件通信:组件实例的作用域是相互独立的,这就意味着不同组件之间的数据无法相互引用,而组件间相互传递数据,就是组件通信
在这里插入图片描述
vue组件通信方案
1.父传子 2.子传父 3.兄弟组件 4.任何组件通信(bus中央事件总线)
5.vuex插件

父传子

父组件像子组件传值,子组件接收值是使用props处理的
第一步:创建子组件和父组件
子组件 bagSon.vue 父组件 father.vue
第二步: 配置子组件和父组件的路由
第三步:在父组件里面引入子组件

import bagSon from '@/components/bagSon'

第四步:在父组件里面注册子组件

 //注册组件
        components:{
            bagSon
        },

第五步:在父组件里面使用注册的子组件,也就是使用子组件标签

<bagSon></bagSon>

第六步 :把父组件的数据绑定到子组件的注册的子组件标签里面

<bagSon :msg="msg" :msgArray="msgArray"></bagSon>

第七步:在子组件标签里面使用propos接收父组件的传过来的值

props : [“msg”,“msgArray”]

在子组件里面接收父组件的传值有两种方式,上面的是第一种数组的方式,还有一种对象的方式,例如下面的这种方式

//第二种书写的方式 对象书写方式
        props :{
            msg :{
                //设置传入类型
                type : String,
                //如果不传值的话,会显示默认设置的值
                default : "默认消息"
            },
            msgArray :{
                //传值的类型
                type :Array,
                //如果不传值的话,会显示默认设置的值
                default :[
                    {
                         id : "1",
                         msg : "成绩单拿出来我看看!!!!!!"
                    }
                   
                ]
            }
        }

完整代码
父组件 father.vue

<template>
    <div class = "father">
        <h1>我是老子!!!!!!</h1>
        <!-- 使用组件 :msg="msg" 等同于v-bind:msg="msg" 给子组件绑定父组件的数据
        第一个msg代表着我们传入的数据起了一个名字,第二msg代表父组件里面传入的数据的名字,在子组件使用的
        时第一个msg -->
        <bagSon :msg="msg" :msgArray="msgArray"></bagSon>
    </div>
</template>

<script>
//引入组件
import bagSon from '@/components/bagSon'
    export default {
        //注册组件
        components:{
            bagSon
        },
        data(){
            return {
                msg :"儿子,我是你爸爸!!!!!!",
                msgArray :[
                    {
                        id : "1",
                        msg : "数学考了多少?"
                    },{
                        id : "2",
                        msg : "语文考了多少?"
                    },{
                        id : "3",
                        msg : "英语考了多少?"
                    }
                ]
            }
        }
    }
</script>

<style scoped>
.father{
  height: 1000px;
  border: blue solid 1px;
}
</style>

子组件bagSon.vue代码

<template>
    <div class="bagSon">
        <h1>我是老大尼古拉斯赵四!!!!</h1>
        <h1>{{msg}}</h1>
        <ul>
            <li v-for = "item in msgArray" :key ="item.id">
                {{item.id}} ============={{item.msg}}
            </li>
        </ul>
        
    </div>
</template>

<script>
    export default {
        //第一种接收的书写方式,数组的方式
        //props : ["msg","msgArray"]
        //第二种书写的方式 对象书写方式
        props :{
            msg :{
                //设置传入类型
                type : String,
                //如果不传值的话,会显示默认设置的值
                default : "默认消息"
            },
            msgArray :{
                //传值的类型
                type :Array,
                //如果不传值的话,会显示默认设置的值
                default :[
                    {
                         id : "1",
                         msg : "成绩单拿出来我看看!!!!!!"
                    }
                   
                ]
            }
        }
    }
</script>

<style  scoped>
.bagSon{
  height: 300px;
  border:red solid 1px;
}
</style>

子传父

第一步:在子组件里面发送数据到父组件

 //第一个参数是自定义的事件类型   第二个参数是需要发送的数据
                this.$emit("toSendFather",this.toFatherMsg)

第二步:在父组件里面的子组件标签里面绑定子组件的自定义事件,并且给事件定义一个方法

  <!-- 接收儿子传过来的数据,需要绑定儿子的自定义事件toSendFather  getSonMsg方法 -->
        <bagSon :msg="msg" :msgArray="msgArray" @toSendFather="getSonMsg" ></bagSon>

第三步:写方法 处理数据

methods:{
            getSonMsg(sonMsg){
                this.sonMsg = sonMsg;
            }
        }

全部代码
子组件 bagSon.vue

<template>
    <div class="bagSon">
        <h1>我是老大尼古拉斯赵四!!!!</h1>
        <h1>{{msg}}</h1>
        <ul>
            <li v-for = "item in msgArray" :key ="item.id">
                {{item.id}} ============={{item.msg}}
            </li>
        </ul>
        <button  @click = "toSendFather">给父组件发送数据</button>
    </div>
</template>

<script>
    export default {
        //第一种接收的书写方式,数组的方式
        //props : ["msg","msgArray"]
        //第二种书写的方式 对象书写方式
        props :{
            msg :{
                //设置传入类型
                type : String,
                //如果不传值的话,会显示默认设置的值
                default : "默认消息"
            },
            msgArray :{
                //传值的类型
                type :Array,
                //如果不传值的话,会显示默认设置的值
                default :[
                    {
                         id : "1",
                         msg : "成绩单拿出来我看看!!!!!!"
                    }
                   
                ]
            }
        },
        data(){
            return {
                toFatherMsg : "爸,全是满分!!!!!!!!!!"
            }
        },
        methods:{
            toSendFather(){
                //第一个参数是自定义的事件类型   第二个参数是需要发送的数据
                this.$emit("toSendFather",this.toFatherMsg)
            }
        }
    }
</script>

<style  scoped>
.bagSon{
  height: 300px;
  border:red solid 1px;
}
</style>

父组件 father.vue

<template>
    <div class = "father">
        <h1>我是老子!!!!!!</h1>
        <!-- 使用组件 :msg="msg" 等同于v-bind:msg="msg" 给子组件绑定父组件的数据
        第一个msg代表着我们传入的数据起了一个名字,第二msg代表父组件里面传入的数据的名字,在子组件使用的
        时第一个msg -->

        <!-- 接收儿子传过来的数据,需要绑定儿子的自定义事件toSendFather  getSonMsg方法 -->
        <bagSon :msg="msg" :msgArray="msgArray" @toSendFather="getSonMsg" ></bagSon>
        <h1>{{sonMsg}}</h1>
    </div>
</template>

<script>
//引入组件
import bagSon from '@/components/bagSon'
    export default {
        //注册组件
        components:{
            bagSon
        },
        data(){
            return {
                msg :"儿子,我是你爸爸!!!!!!",
                msgArray :[
                    {
                        id : "1",
                        msg : "数学考了多少?"
                    },{
                        id : "2",
                        msg : "语文考了多少?"
                    },{
                        id : "3",
                        msg : "英语考了多少?"
                    }
                ],
                sonMsg : ""
            }
        },
        methods:{
            getSonMsg(sonMsg){
                this.sonMsg = sonMsg;
            }
        }
    }
</script>

<style scoped>
.father{
  height: 1000px;
  border: blue solid 1px;
}
</style>

兄弟组件

兄弟组件之间通信,在vue里面,兄弟组件指的是拥有同一个父亲的组件,一个兄弟把数据传递到父组件,然后这个父组件在传递给另外一个子组件

bus中央事件总线

公共事件总线eventBus的实质就是创建一个vue实例,通过一个空的vue实例作为桥梁实现vue组件间的通信。它是实现非父子组件通信的一种解决方案。
第一步:创建爷爷father_bus.vue,大儿子bagSon_bus.vue,大儿子的儿子bagSon_son_bus.vue,小儿子smallSon_bus.vue,小儿子的儿子smallSon_son_bus.vue,现在我们要两个孙在之间传递数据的话
第二步,创建一个vue实例,并且把这个实例挂在vue原型上
main.js里面的

//创建一个新的vue实例
let bus = new Vue();
//把创建的这个vue实例挂在vue的原型上
//只要挂在vue原型上,在任何的vue组件上,通过this就可以获取bus
Vue.prototype.bus = bus;

第三步:传递数据

//第一个参数自定义事件fnSendMsg
                //第二个参数传递的数据
                this.bus.$emit("fnSendMsg",this.msg)

第四步:
接收数据

 //第一个参数fnSendMsg自定义事件
            //第二个参数 方法对象
            this.bus.$on("fnSendMsg",msg =>{
                this.msg = msg
            })

完整代码
father_bus.vue`

<template>
  <div class="bagSon_bus">
    <h1>我是大儿子</h1>
    <bagSon_son_bus />
  </div>
</template>

<script>
import bagSon_son_bus from "../busVue/bagSon_son_bus";

export default {
  components: {
    bagSon_son_bus
  }
};
</script>

<style  scoped>
.bagSon_bus {
  border: seagreen 2px solid;
  height: 300px;
}
</style>

bagSon_son_bus.vue

<template>
    <div class= "bagSon_son_bus">
        <h1>我是大儿子的儿子</h1>
        <h1>传递过来的数据{{msg}}</h1>
    </div>
</template>

<script>
    export default {
        data(){
            return{
                msg:""
            }
        },
        created(){
            //第一个参数fnSendMsg自定义事件
            //第二个参数 方法对象
            this.bus.$on("fnSendMsg",msg =>{
                this.msg = msg
            })
        }
    }
</script>

<style  scoped>
.bagSon_son_bus{
    border: rgb(105, 46, 139) 2px solid;
     height: 150px;
}
</style>

smallSon_bus.vue

<template>
    <div class="smallSon_bus">
        <h1>我是小儿子</h1>
        <smallSon_son_bus/>
    </div>
</template>

<script>
import smallSon_son_bus from "../busVue/smallSon_son_bus";

    export default {
        components:{
            smallSon_son_bus
        }

    }
</script>

<style  scoped>
.smallSon_bus{
    border: solid 2px coral;
     height: 300px;
}
</style>

smallSon_son_bus.vue

<template>
    <div class="smallSon_son_bus">
        <h1>我是小儿子的儿子</h1>
        <button @click="fnSendMsg">传递数据</button>
    </div>
</template>

<script>
    export default {
        data(){
            return {
                msg : "我是小儿子的儿子,我想对大儿子的儿子说:哥哥,我是通过bus传递的!!!!!"
            };
        },
        methods :{
            fnSendMsg(){
                //第一个参数自定义事件fnSendMsg
                //第二个参数传递的数据
                this.bus.$emit("fnSendMsg",this.msg)
            }
        }

    }
</script>

<style  scoped>
.smallSon_son_bus{
    border: solid 2px rgb(144, 255, 80);
     height: 300px;
}
</style>

vuex

vuex主要应用于vue里面管理数据状态的一个库,通过创建一个集中的数据存储,供应用中的所有组件使用。
vuex包含state,getter,mutation,action,module五个核心概念 ,5个api

state状态

state状态 组件中需要共享和使用的数据
使用state的数据
第一步:安装

npm install vuex --save

第二步:
在src下新建store文件夹,文件夹下新建一个index.js
在index.js里面初始化vuex

//引入vue
import Vue from 'vue'
//引入vuex
import Vuex from 'vuex'
//注册vuex
Vue.use(Vuex);


//创建仓库,并把仓库暴漏出去
export default new Vuex.Store({
    //state状态 组件中需要共享和使用的数据
    state: {
        num: 110
    },
    //Vuex 允许我们在 store 中定义“getter”(可以认为是 store 的计算属性)。
    //就像计算属性一样,getter 的返回值会根据它的依赖被缓存起来,且只有当它的依赖值发生了改变才会被重新计算。
    getters: {

    },
    //更改 Vuex 的 store 中的状态的唯一方法是提交 mutation。Vuex 中的 mutation 非常类似于事件:
    //每个 mutation 都有一个字符串的 事件类型 (type) 和 一个 回调函数 (handler)。
    //这个回调函数就是我们实际进行状态更改的地方,并且它会接受 state 作为第一个参数
    mutations: {

    },
    //Action 类似于 mutation,不同在于:
    //Action 提交的是 mutation,而不是直接变更状态。
    //Action 可以包含任意异步操作。
    actions: {

    },
    //由于使用单一状态树,应用的所有状态会集中到一个比较大的对象。
    //当应用变得非常复杂时,store 对象就有可能变得相当臃肿。
    //为了解决以上问题,Vuex 允许我们将 store 分割成模块(module)。
    //每个模块拥有自己的 state、mutation、action、getter、甚至是嵌套子模块——从上至下进行同样方式的分割:
    modules: {

    }
})

第三步:把仓库传入vue实例对象里面渲染
main.js里面 引入仓库

import store from './store' //引入仓库

把仓库传入vue实例对象里面渲染

new Vue({ //创建vue实例
    el: '#app', //挂载dom
    router, //传入路由渲染
    store, //把仓库传入vue实例对象里面渲染
    components: { App }, //传入顶级组件渲染  
    template: '<App/>'
})

第四步:新建一个vue组件use_vuex_state并配置路由
因为已经在把仓库注册到vue实例对象里面渲染了,所以使用
this.$store就可以获取到state,从而可以获取state里面的对象数据

this.$store.state.num

完整的代码

<template>
    <div>
        <h1>使用vuex的state</h1>
        <h1>{{num}}</h1>
    </div>
</template>

<script>
    export default {
        //计算属性
        computed:{
            num(){
                return this.$store.state.num;
            }
        }
    }
</script>

<style  scoped>

</style>

其实vuex给我们提供了一个辅助函数,专门用来获取state里面的数据
在需要获取state的页面里面引入辅助函数

//引入vuex的辅助函数
import {mapState} from  'vuex'

使用

//计算属性
        computed:{
            // num(){
            //     return this.$store.state.num;
            // }
            //直接通过state里面定义的名字就可以获取到,如果多个,那就在数组里面多谢几个,用逗号隔开
            ...mapState(['num'])
        }

上面这种使用是数组用法,下面的这个是对象用法

//计算属性
        computed:{
            // num(){
            //     return this.$store.state.num;
            // }
            //直接通过state里面定义的名字就可以获取到,如果多个,那就在数组里面多谢几个,用逗号隔开
            //...mapState(['num'])数组写法
            ...mapState({//对象写法  第一个参数是你自定义的对象名字,第二个参数是state里面的对象名字
                num : "num"
            })
            
        }

getters仓库里面的计算属性

如果我有一份学生的单,放在了state里面了,但是我现在只需要成绩高于90份的,如果不使用getters的话,我需要先取出来,在页面里面判断后,获取高于90分的学生。
现在有了getters,我可以直接在getters里面计算完,直接取出来就可以了,就算多个组件都需要这份数据,我也只需要在getters里面判断一次就可以了。

//引入vue
import Vue from 'vue'
//引入vuex
import Vuex from 'vuex'
//注册vuex
Vue.use(Vuex);


//创建仓库,并把仓库暴漏出去
export default new Vuex.Store({
    //state状态 组件中需要共享和使用的数据
    state: {
        num: 110,
        users: [{
            id: "1",
            name: "张三",
            scores: 99
        }, {
            id: "2",
            name: "李四",
            scores: 98
        }, {
            id: "3",
            name: "王五",
            scores: 97
        }, {
            id: "4",
            name: "赵六",
            scores: 59
        }]
    },
    //Vuex 允许我们在 store 中定义“getter”(可以认为是 store 的计算属性)。
    //就像计算属性一样,getter 的返回值会根据它的依赖被缓存起来,且只有当它的依赖值发生了改变才会被重新计算。
    getters: {
        //传入的参数是整个state的数据
        toGetUserDone(state) {
            return state.users.filter(v => (v.scores > 90));
        }
    },
    //更改 Vuex 的 store 中的状态的唯一方法是提交 mutation。Vuex 中的 mutation 非常类似于事件:
    //每个 mutation 都有一个字符串的 事件类型 (type) 和 一个 回调函数 (handler)。
    //这个回调函数就是我们实际进行状态更改的地方,并且它会接受 state 作为第一个参数
    mutations: {

    },
    //Action 类似于 mutation,不同在于:
    //Action 提交的是 mutation,而不是直接变更状态。
    //Action 可以包含任意异步操作。
    actions: {

    },
    //由于使用单一状态树,应用的所有状态会集中到一个比较大的对象。
    //当应用变得非常复杂时,store 对象就有可能变得相当臃肿。
    //为了解决以上问题,Vuex 允许我们将 store 分割成模块(module)。
    //每个模块拥有自己的 state、mutation、action、getter、甚至是嵌套子模块——从上至下进行同样方式的分割:
    modules: {

    }
})
<template>
  <div>
    <h1>使用vuex的getters</h1>
    <ul>
      <li v-for="item in users" :key="item.id">{{item.name}}</li>
    </ul>
  </div>
</template>

<script>
//引入vuex的辅助函数
import { mapGetters } from "vuex";
export default {
  //计算属性
  computed: {
    //     users(){  直接获取
    //          return this.$store.getters.toGetUserDone;
    //  }
    //使用辅助对象mapGetters  对象获取方式
    ...mapGetters({
      users: "toGetUserDone"
    })
  }
};
</script>

<style  scoped>
</style>

mutation唯一改变state的方式(同步)

当我们需要修改 仓库里面的数据时,就要用到mutation。
第一步 在store文件夹下的index里面的mutations里面定义对state修改的方法
方法里面存在两个参数,第一个参数是vuex里面定义的state,第二个参数是传进来的值

  //更改 Vuex 的 store 中的状态的唯一方法是提交 mutation。Vuex 中的 mutation 非常类似于事件:
    //每个 mutation 都有一个字符串的 事件类型 (type) 和 一个 回调函数 (handler)。
    //这个回调函数就是我们实际进行状态更改的地方,并且它会接受 state 作为第一个参数
    mutations: {
        updateNum(state, payload) {
            this.state.num += payload.num;
        },
    },

第二步创建一个vue组件,并配置路由

<template>
  <div>
    <h1>使用vuex的mutation</h1>
    <h1>{{num}}</h1>
    <button @click="fnAdd(num)">num++</button>
    <button @click="fnDel(num)"> num--</button>

    <button @click="updateNum({num : 10})">辅助函数数组方式num++</button>
    <button @click="updateNum({num : -10})">辅助函数数组方式num--</button>
     <button @click="fnAddObj({num : 10})">辅助函数对象方式num++</button>
    <button @click="fnDelObj({num : -10})">辅助函数对象方式num--</button>
  </div>
</template>

<script>
//引入vuex的辅助函数
import { mapState ,mapMutations} from "vuex";
export default {
  //计算属性
  computed: {
    ...mapState({
      num : "num"
    })
  },
  methods:{
    fnAdd(num){
      //第一种方式
      //this.$store.commit("updateNum",{num:10});
      //第二种方式,对象方式
      this.$store.commit({type : "updateNum",num:10});
    },
    fnDel(num){
      this.$store.commit("updateNum",{num:-10});
    },
    //辅助函数数组方式
    ...mapMutations(
      ["updateNum"]
    ),
    //辅助函数对象方式
    ...mapMutations({
       fnAddObj : "updateNum",
       fnDelObj : "updateNum"
    })
  }
};
</script>

<style  scoped>
</style>

第三步引入vuex的辅助函数

//引入vuex的辅助函数
import { mapState ,mapMutations} from "vuex";

第四步在计算属性里面获取需要修改的数据

//计算属性
  computed: {
    ...mapState({
      num : "num"
    })
  },

第五步修改数据
修改数据的第一种方式
第一个参数是在vuex里面的mutation定义的方法名字,第二个参数是修改的参数值,是一个对象,对象里面可以有多个属性

//第一种方式
this.$store.commit("updateNum",{num:10});

第二种方式 第一个参数的key是type,固定写法,参数值是mutations里面定义的方法名,第二个参数是修改的参数,可以多个,用逗号隔开

//第二种方式,对象方式
      this.$store.commit({type : "updateNum",num:10});

第三种方式,辅助对象数组方式
这个只有一个参数,这个参数就是mutations的方法名字,并且调用的时候也必须使用这个名字,也就是说如果我们添加点击事件来调用mutations里面的方法修改state的话,定义的click的方法名也必须是updateNum,那么我们要传参数怎么办,我们只需要在方法里面添加参数对象就可以,就像这样
@click=“updateNum({num : 10})”

//辅助函数数组方式
    ...mapMutations(
      ["updateNum"]
    ),

第四种:辅助函数的对象方式
对象里面的key是我们定义的别名,value是我们在mutations里面定义的方法名,传参数和数组模式传参一样@click=“fnDelObj({num : -10})”,只是点击事件的方法名这次是我们自己定义的别名。

//辅助函数对象方式
    ...mapMutations({
       fnAddObj : "updateNum",
       fnDelObj : "updateNum"
    })

actions异步修改state

actions自己不处理需要修改的数据,他需要调用vuex里面mutations里面的方法进行修改,那么为什么还要引入这个东西呢,因为actions是异步的,好多需要异步处理的地方需要用到。
第一步:在store文件夹下的index里面的actions里面定义对state修改的方法
方法里面存在两个参数,第一个参数是vuex里面commit,用来调用mutations里面的方法,进行数据修改,第二个参数是传进来的值

 //Action 类似于 mutation,不同在于:
    //Action 提交的是 mutation,而不是直接变更状态。
    //Action 可以包含任意异步操作。
    actions: {
        updateActionNum({ commit }, payload) {
            commit("updateNum", payload)
        },
    },

第二步,定义一个vue的组件,并配置路由

<template>
  <div>
    <h1>使用vuex的action</h1>
    <h1>{{num}}</h1>
    <button @click="fnAdd(num)">num++</button>
    <button @click="fnDel(num)"> num--</button>

    <button @click="updateActionNum({num : 10})">辅助函数数组方式num++</button>
    <button @click="updateActionNum({num : -10})">辅助函数数组方式num--</button>
     <button @click="fnAddObj({num : 10})">辅助函数对象方式num++</button>
    <button @click="fnDelObj({num : -10})">辅助函数对象方式num--</button>
  </div>
</template>

<script>
//引入vuex的辅助函数
import { mapState ,mapActions} from "vuex";
export default {
  //计算属性
  computed: {
    ...mapState({
      num : "num"
    })
  },
  methods:{
    fnAdd(num){
      //第一种方式
     // this.$store.dispatch("updateActionNum",{num:10});
      //第二种方式,对象方式
      this.$store.dispatch({type : "updateActionNum",num:10});
    },
    fnDel(num){
      this.$store.dispatch("updateActionNum",{num:-10});
    },
    //辅助函数数组方式
    ...mapActions(
      ["updateActionNum"]
    ),
    //辅助函数对象方式
    ...mapActions({
       fnAddObj : "updateActionNum",
       fnDelObj : "updateActionNum"
    })
  }
};
</script>

<style  scoped>
</style>

第三步引入vuex的辅助函数

//引入vuex的辅助函数
import { mapState ,mapActions} from "vuex";

第四步获取需要修改的参数

 //计算属性
  computed: {
    ...mapState({
      num : "num"
    })
  },

第五步修改数据
修改的方式和mutations的方式基本类似

methods:{
    fnAdd(num){
      //第一种方式
     // this.$store.dispatch("updateActionNum",{num:10});
      //第二种方式,对象方式
      this.$store.dispatch({type : "updateActionNum",num:10});
    },
    fnDel(num){
      this.$store.dispatch("updateActionNum",{num:-10});
    },
    //辅助函数数组方式
    ...mapActions(
      ["updateActionNum"]
    ),
    //辅助函数对象方式
    ...mapActions({
       fnAddObj : "updateActionNum",
       fnDelObj : "updateActionNum"
    })
  }

modules

由于使用单一状态树,应用的所有状态会集中到一个比较大的对象。
当应用变得非常复杂时,store 对象就有可能变得相当臃肿。
为了解决以上问题,Vuex 允许我们将 store 分割成模块(module)。
每个模块拥有自己的 state、mutation、action、getter

现在相当于我一个vuex仓库里面分割成了好多的小格子,每个格子都拥有自己的存储空间,和之前一个大仓库相比,一切都没改变,只是取值的时候,之前是this. s t o r e 处 理 的 , 现 在 需 要 加 上 t h i s . store处理的,现在需要加上this. storethis.store.storeA或者其他的小格子的store名字
代码如下:

//引入vue
import Vue from 'vue'
//引入vuex
import Vuex from 'vuex'
//注册vuex
Vue.use(Vuex);


//模块A
const modelA = {
    state: {

    },
    getters: {

    },
    mutations: {

    },
    actions: {

    }
}


//模块B
const modelB = {
    state: {

    },
    getters: {

    },
    mutations: {

    },
    actions: {

    }
}

//创建仓库,并把仓库暴漏出去
export default new Vuex.Store({
    modules: {
        storeA: modelA,
        storeB: modelB
    }

})
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值