Vue2 Vue3 组件传值的方式 --对比学习

Vue2 组件传值的方式(共12种)

  1. props
  2. $emit / v-on
  3. sync
  4. v-model
  5. ref
  6. $children / $parent
  7. $attrs / $listeners
  8. provide / inject
  9. EventBus
  10. Vuex
  11. $root
  12. slot

虽然 Vue2 组件通信方式虽然有很多,但是不同方式有不同的应用场景。

父子组件通信

  • props
  • $emit / v-on
  • $attrs / $listeners
  • ref
  • .sync
  • v-model
  • $children / $parent
  • slot

兄弟组件通信

  • EventBus
  • Vuex
  • $patent

跨层级组件通信

  • provide / inject
  • EventBus
  • Vuex
  • $attrs / $listeners
  • $root

具体使用

1. props

用于父组件向子组件传送数据。
子组件接收到数据之后,不能直接修改父组件的值,会报错。
当需要修改props的时候应该在父组件修改。父组件修改后子组件会同步渲染。
如果子组件一定要修改props的话推荐使用computed,计算一个新属性给子组件使用,而不是直接修改。

// 父组件
<template>
  <child :msg="msg"></child>
</template>

// 子组件
<template>
  <div>{{msg}}</div>
</template>
<script>
export default {
  // 写法一 用数组接收
  props:['msg'],
  // 写法二 用对象接收
  props: {
    msg: String
  },
  // 写法三 用对象接收,可以限定接收的数据类型、设置默认值、验证等
  props:{
    msg:{
      type:String,
      default:'这是默认数据',
      // 必传
      required: true
    }
  },
  props: {
    user:{
      type: Object,
      // 对象或数组默认值必须从一个工厂函数获取
      default: () => return {},
      // 自定义验证
      validator: () => {
        return true/false
      }
    } 
  }
}
</script>
2.$emit / v-on

我们知道Vue是单向数据流,父组件传递给子组件的值是不能直接修改的。
所以子组件想要修改父组件数据的时候需要先暴露事件并传递值给父组件,父组件监听该事件来完成值的修改。

// 子组件
<template>
  <div>
    <div>{{ msg }}</div>
    <button @click="handleClick">change</button>
  </div>
</template>
<script>
export default {
  props: ["msg"],
  methods: {
    handleClick() {
      const newMsg = "我被修改了";
      this.$emit("changeMsg", newMsg);
    },
  },
};
</script>

// 父组件
<template>
  <child :msg="msg" v-on:changeMsg="handleChangeMsg" ></child>
</template>
<script>
export default {
  data() {
    return {msg: "我会传递给子组件"}
  },
  methods:{
    handleChangeMsg(newMsg){
      this.msg = newMsg
    }
  }
}
</script>
3. .sync

需要修改父组件传递过来的属性的值,每次都需要暴露一个方法过去,然后在父组件监听然后再修改,是不是感觉特别麻烦。
.sync 就是来简化这一过程的。

// 子组件
<template>
  <div>
    <div>{{ msg }}</div>
    <button @click="handleClick">change</button>
  </div>
</template>
<script>
export default {
  props: ["msg"],
  methods: {
    handleClick() {
      const newMsg = "我被修改了";
      this.$emit("update:msg", newMsg);
    },
  },
};
</script>

// 父组件
<template>
  <child :msg.sync="msg"></child>
</template>
<script>
export default {
  data() {
    return {msg: "我会传递给子组件"}
  },
}
</script>

父组件不需要再监听事件然后修改值了。
父组件只需要在传递属性的时候加上.sync 修饰符,然后子组件再修改完值的时候暴露update: 属性名的事件就可以了。

4. v-model

.sync 我们知道,是用来简化数据修改的,那还有没有更简单的方法呢?有,那就是v-model
v-model 默认传递名为value的属性,并自动监听input事件。
我们来看个例子:

// 子组件
<template>
  <div>
    <input type="text" :value="value" @input="handleInput" />
  </div>
</template>
<script>
export default {
  props: {
    value: String,
  },
  methods: {
    handleInput(e) {
      this.$emit("input", e.target.value);
    },
  },
};
</script>

// 父组件
<template>
  <div>{{msg}}</div>
  <child v-model="msg"></child>
</template>
<script>
export default {
  data() {
    return {msg: "我会传递给子组件"}
  },
}

在上面的例子中,我们input框默认值是我会传递值给子组件,当我们修改input框值的时候,父组件的值也会改变。这其实就是双向绑定。
但有时候我们不可能就直接传递属性为value,然后监听input事件,这显然不满足我们的要求。
需要修改属性和事件怎么办呢?这就需要用到我们的model参数了。该属性定义在子组件。包含两个属性,prop用来定义属性名,event 用来定义事件名。
比如,我们想传递过来的属性名为customValue,监听的事件为customInput。

// 子组件
<template>
  <div>
    <button :url="url" @click="handleChange1">子组件的值:{{url}}</button>
  </div>
</template>
<script>
export default {
  model: {
	prop: 'url',
	event: 'change1'
  },
  props: {
    //value: String,
    // 使用url 代替 value 作为model 的prop
    url: {
        type: String,
        default: ''
    }
  },
  methods: {
    handleChange1(){
        const newUrl = '我被子修改了呀'
        this.$emit('change1',newUrl)
    }
  },
};
</script>

// 父组件
<template>
  <div>{{msg}}</div>
  <child v-model:url="msg"></child>
</template>
<script>
export default {
  data() {
    return {msg: "我会传递给子组件"}
  },
}

其他的事件和属性类似,但需要注意一个组件只能使用一个v-model。

5. ref

如果需要直接操作子组件我们就可以使用ref了。
ref 如果在普通的元素上,引用指向的就是该DOM元素;
如果在子组件上,引用的指向就是子组件实例。

// 子组件
<template>
  <div>
    <div>{{ msg }}</div>
  </div>
</template>
<script>
export default {
  props: ["msg"],
  data() {
    return {
      name: "child6",
    };
  },
  methods: {
    say() {
      console.log("say child6");
    },
  },
  computed: {
    title() {
      return this.name + "title";
    },
  },
};
</script>

// 父组件
<template>
  <child :msg="msg" ref="childRef"></child>
</template>
<script>
export default {
  data() {
    return {msg: "我会传递给子组件"}
  },
  mounted() {
    // 通过$refs获取子组件
    console.log(this.$refs.childRef)
    // 接下来我们就可以直接操作子组件了
    console.log(this.$refs.childRef.$data)
    console.log(this.$refs.childRef.$props)
    console.log(this.$refs.childRef.$el)
    this.$refs.childRef.say()
    console.log(this.$refs.childRef.name)
    console.log(this.$refs.childRef.title)
    // ...
  }
}

需要注意,如果ref定义在循环中,this.$refs.xxx 会是一个数组。

6. $children / $parent

类似ref,我们可以通过 $children / $parent 直接获取到子组件或父组件。
$children : 获取到一个包含所有子组件(不包含孙子组件)的VueComponent 对象数组,可以直接拿到子组件中所有数据和反方法。
$parent:获取到一个父节点的VueComponent对象,同样包含父节点中所有数据和方法。

// 父组件
export default{
  mounted(){
    this.$children[0].someMethod() // 调用第一个子组件的someMethod
    this.$children[0].name // 获取第一个子组件中的name属性
  }
}

// 子组件
export default{
  mounted(){
    this.$parent.someMethod() // 调用父组件的someMethod
    this.$parent.name // 获取父组件中的name属性
  }
}
7. $root

和$children / p a r e n t 相 似 , parent 相似, parentroot 可以获取到根实例里。
也就是我们main.js 创建的Vue实例。

new Vue({
  router,
  store,
  render: (h) => h(App),
  data: {
    name: "根组件",
  },
}).$mount("#app");
8. provide / inject

provide / inject 需要一起使用,以允许一个祖先组件向其所有子孙后代注入一个依赖,不论组件层次有多深,并在其上下游关系成立的时间里始终生效。如果你熟悉React,这与React 的context特性很相似。
provide选项应该是一个对象或返回一个对象的函数。该对象包含可注入其子孙的property。
inject 选项应该是:

  • 一个字符串数组,或
  • 一个对象,对象的key是本地绑定的域名,value是:
    • 在可用的注入内容中搜索用的key(字符串或Symbol),或
    • 一个对象,该对象的:
      • from property 是在可用的注入内容中搜索用的key(字符串或Symbol)
      • default property 是降级情况下使用的value。

提示:provide 和 inject 绑定并不是可响应的。这是刻意为之的。然而,如果你传入了一个可监听的对象,那么其对象的property还是可响应的。

// 父级组件提供 'foo'
var Provider = {
  provide: {
    foo: 'bar'
  },
  // ...
}

// 后代组件注入 'foo'
var Child = {
  inject: ['foo'],
  created () {
    console.log(this.foo) // => "bar"
  }
  // ...
}

在2.5.0+ 的注入中可以通过设置默认值使其变成可选项:

const Child = {
  inject: {
    foo: {
      from: 'bar',
      default: 'foo'
    }
  }
}

如果它需要从一个不同名字的property注入,则使用from来表示其源property:

const Child = {
  inject: {
    foo: {
      from: 'bar',
      default: 'foo'
    }
  }
}

与prop的默认值类似,你需要对非原始值使用一个工厂方法:

const Child = {
  inject: {
    foo: {
      from: 'bar',
      default: () => [1, 2, 3]
    }
  }
}
9.$attrs / $listeners

多层嵌套组件传递数据时,如果只是传递数据,而不做中间处理的话,就可以使用$attrs / $listeners,比如,父组件向孙子组件传递数据时。
$attrs 包含了父作用域中不作为prop被识别(且获取)的attribute绑定(class和style除外)。当一个组件没有声明任何prop时,这里会包含所有父作用域的绑定(class和style除外)。

$ listeners 包含了父作用域的(不含.native修饰器的)v-on事件监听器。

//子组件
props: ['msg'],
created() {
  // 获取没在props中定义的但是传递过来的属性,除去 class、style
  console.log(this.$attrs); // {id: 'childId', name: 'randy'}
  
  // 获取除.native修饰的原生事件
  console.log(this.$listeners); // {customChange(){}}
  
  // 如果单纯只传递属性给子组件,不需要处理,我们可以直接传递$attrs、$listeners
},

// 父组件
<template>
  <child :msg="msg" @click.native="handleClick" @customChange="handleChange" class="child" id="childId"></child>
</template>
<script>
export default {
  data() {
    return {msg: "我会传递给子组件", name: 'randy'}
  },
}
10. slot

slot 可以用在父组件直接向子组件传递内容,我们在子组件标签内的内容都可以传递过去。没命名的slot 默认名称是default。

// 父组件
<h3>默认插槽 default</h3>
<Slot1>
  <div>slot1</div>
  <div>哈哈</div>
</Slot1>

<h3>老具名插槽</h3>
<Slot1>
  <div>slot传递过来的 2.6已被废弃但是还能使用 vue3彻底移除</div>
  <div slot="header">header</div>
  <div slot="footer">footer</div>
  <div slot="content">content</div>
</Slot1>

<h3>新具名插槽</h3>
<Slot1>
  <template v-slot:header>header</template>
  <template v-slot:footer>footer</template>
  <template v-slot:content>content</template>
</Slot1>

<h3>新具名插槽缩写 #</h3>
<Slot1>
  <div>v-slot传递过来的</div>
  <template #header>header2</template>
  <template #footer>footer2</template>
  <template #content>content2</template>
</Slot1>

// 子组件 Slot1
<!-- 默认插槽 -->
<slot>我是后备内容,没有传递的时候展示</slot>

<slot name="header"></slot>
<slot name="content"></slot>
<slot name="footer"></slot>

不单父组件传递内容给子组件,子组件还可以通过作用域插槽传递数据给父组件。

// 父组件
<h3>老作用域插槽</h3>
<!-- scope 被 2.5.0 新增的 slot-scope 取代 -->
<!-- 除了 scope 只可以用于 <template> 元素,其它和 slot-scope 都相同。 -->
<Slot2>
  <template slot="main" slot-scope="slotProps">
    <div>user name: {{ slotProps.user.name }}</div>
    <div>user age: {{ slotProps.user.age }}</div>
    <div></div>
  </template>
  <template slot-scope="slotProps">
    <div>user name: {{ slotProps.user.name }}</div>
    <div>user age: {{ slotProps.user.age }}</div>
  </template>
  <template slot="footer" slot-scope="{ user: { name, age } }">
    <div>user name: {{ name }}</div>
    <div>user age: {{ age }}</div>
  </template>
</Slot2>

<h3>新作用域插槽</h3>
<Slot2>
  <template v-slot:main="slotProps">
    <div>user name: {{ slotProps.user.name }}</div>
    <div>user age: {{ slotProps.user.age }}</div>
    <div></div>
  </template>
  <template v-slot:default="slotProps">
    <div>user name: {{ slotProps.user.name }}</div>
    <div>user age: {{ slotProps.user.age }}</div>
  </template>
  <template v-slot:footer="{ user: { name, age } }">
    <div>user name: {{ name }}</div>
    <div>user age: {{ age }}</div>
  </template>
</Slot2>

// 子组件 Slot2
<template>
  <slot v-bind:user="user1"> </slot>
  <slot name="main" v-bind:user="user2"> </slot>
  <slot name="footer" :user="user3"> </slot>
</template>

export default {
  data() {
    return {
      user1: {
        name: "randy",
        age: 27,
      },
      user2: {
        name: "demi",
        age: 24,
      },
      user3: {
        name: "jack",
        age: 21,
      },
    };
  },
};

顺便说一说this. s l o t 和 t h i s . slot和this. slotthis.scopedSlots

this.$slot

this. s l o t 用 来 访 问 被 插 槽 分 发 的 内 容 。 每 个 具 名 插 槽 有 其 相 应 的 p r o p e r t y ( 例 如 : v − s l o t : f o o 中 的 内 容 将 会 在 v m . slot 用来访问被插槽分发的内容。每个具名插槽有其相应的property(例如:v-slot:foo中的内容将会在vm. slot访property:vslot:foovm.slots.foo中被找到)。default property 包括了所有没有被包含在具名插槽中的节点,或 v-slot:default 的内容。
每个属性包含一个VNode的数组。
请注意插槽不是响应性的。如果你需要一个组件可以在被传入的数据发生变化时重新渲染,我们建议改变策略,依赖诸如props或data等响应性实例选项。

this.$scopedSlots

this. S c o p e d S l o t s 用 来 访 问 作 用 域 插 槽 。 对 于 包 括 默 认 s l o t 在 内 的 每 一 个 插 槽 , 该 对 象 都 包 含 一 个 返 回 相 应 V N o d e 的 函 数 。 我 们 通 过 调 用 对 应 的 方 法 , 传 递 相 应 的 数 据 , 就 能 得 到 V N o d e 数 组 。 类 似 t h i s . ScopedSlots 用来访问作用域插槽。对于包括默认slot 在内的每一个插槽,该对象都包含一个返回相应VNode的函数。 我们通过调用对应的方法,传递相应的数据,就能得到VNode数组。类似this. ScopedSlots访slotVNodeVNodethis.slots的返回值。

console.log(
	this.$scopedSlots.default({
		user: this.user1,
	})
);

就类似于前面的,不过有$scopedSlots, $slots 就不会有值了。

this.$slots.default
11. EventBus

EventBus主要利用了Vue实例 o n 、 on、 ononce、 o f f 、 off、 offemit这四个方法来进行数据的传递。

首先我们定义一个EventBus

// Bus.js 
import Vue from "vue" 
export default new Vue()
import Bus from "./Bus.js"

// 暴露事件,传递数据
Bus.$emit("sendMsg", "这是要向外部发送的数据")

// 监听事件,进行处理
Bus.$on("sendMsg", data => {
  console.log("这是接收到的数据:", data) 
})

// 监听事件,进行处理,但是只监听一次,后面会自动取消监听
Bus.$once("sendMsg", data => {
  console.log("这是接收到的数据:", data) 
})

// 取消监听
Bus.$off("sendMsg")
12. Vuex

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

Vue3

Vue3组件通讯有9种:

  • props
  • emit
  • ref / expose
  • attrs
  • v-model
  • provide / inject
  • mitt
  • Vuex
  • Pinia

父子组件通信

  • props
  • emit
  • attrs
  • ref / expose
  • v-model

兄弟组件通信

  • mitt
  • Vuex
  • Pinia

跨层级组件通信

  • provide/inject
  • attrs
  • mitt
  • Vuex
  • Pinia

具体使用

1. props

props用于父组件向子组件传值,使用方式和vue2没什么差别。

2. emit

emit和vue2的$emit使用方式是一样的,但是需要注意:

vue3中,emit是在setup函数的第二个参数上。
vue3中,子组件暴露的方法需要在emits定义。

// 父组件
<template>
  <child :msg="msg" @changeMsg="handleChangeMsg"></child>
</template>
<script>
import { defineComponent, ref } from "vue";

export default defineComponent({
  
  setup(props, { emit }) {
    const msg = ref("message");
    const handleChangeMsg = (newValue) => {
      msg.value = newValue;
    };
    return { msg, handleChangeMsg };
  },
});
</script>

// 子组件
<template>
  <div class="">
    <div>{{ msg }}</div>
    <button @click="handelClick">changeMsg</button>
  </div>
</template>

<script>
import { defineComponent } from "vue";

export default defineComponent({
  props: {
    msg: String,
  },
  emits: { changeMsg: null },
  setup(props, { emit }) {
    const handelClick = () => {
      emit("changeMsg", "我被改变了");
    };
    return { handelClick };
  },
});
</script>
3. ref / expose

vue3中定义ref需要使用ref()定义。
使用的时候需要注意:

  1. 当组件没定义expose暴露内容的时候,通过ref获取到的就是组件自身的内容,也就是setup函数return的内容。

  2. 当定义了expose暴露内容的时候,通过ref获取到的就是组件expose暴露内容,并且setup函数return的内容会失效,也就是会被覆盖。

// 父组件
<template>
  <child :msg="msg" ref="ref1"></child>
</template>
<script>
import { defineComponent, ref, onMounted } from "vue";

export default defineComponent({
  
  setup(props, { emit }) {
    const msg = ref("message");
    const ref1 = ref(null)
    
    onMounted(() => {
      console.log(ref1.value)
      console.log(ref1.value.name)
      console.log(ref1.value.user)
      ref1.value.say()
    })
    
    return { msg, ref1 };
  },
});
</script>

// 子组件
<template>
  <div class="">{{ msg }}</div>
</template>

<script>
import { defineComponent, ref, reactive } from "vue";

export default defineComponent({
  props: ["msg"],
  emits: {},
  setup(props, { expose }) {
    const say = () => {
      console.log("RefChild say");
    };

    const name = ref("RefChild");
    const user = reactive({ name: "randy", age: 27 });

    //  如果定义了会覆盖return中的内容
    // expose({
    //   user,
    // });

    return {
      name,
      user,
      say,
    };
  },
});
</script>
4. attrs

在vue2中,我们知道this.$attrs包含了父作用域中不作为 prop 被识别 (且获取) 的 attribute 绑定 (class 和 style 除外)。
在vue3中有了更改,attrs被转移到setup的第二个参数context上,context.attrs。并且class 和 style也都不再忽略了。也就是说class 和 style也会在attrs里面。
使用方式和vue2还是一样的,多层嵌套组件传递数据时,如果只是传递数据,而不做中间处理的话就可以用attrs,比如父组件向孙子组件传递数据时。

//子组件
props: ['msg'],
setup(props, {attrs}) {
  // 获取没在props中定义的但是传递过来的属性,包括 class、style
  console.log(attrs); // {id: 'childId', name: 'randy', customChange(){}, class: 'child'}
  
  // 如果单纯只传递属性给子组件,不需要处理,我们可以直接传递attrs
},

// 父组件
<template>
  <child :msg="msg" @customChange="handleChange" class="child" id="childId"></child>
</template>
<script>
export default {
  data() {
    return {msg: "我会传递给子组件", name: 'randy'}
  },
}
5. v-model

vue3的v-model我们只需要注意两点:

在vue2中,一个组件只能绑定一个v-model,但是vue3中可以绑定多个。

在vue2中如果不指明model属性,那么它的值默认是value,事件默认是input事件。但是在vue3中不需要model属性了,并且它的值默认是modelValue,事件默认是update:modelValue事件。

// 父组件
<Child1 v-model="name1" />
<!--比使用默认名,自定义名字为name-->
<!-- <Child1 v-model:name="name1" /> -->

// 子组件
<template>
  <div class="child1">
    <button @click="changeName">改变值</button>
  </div>
</template>
<script>
import { defineComponent } from "vue";
export default defineComponent({
  props: {
    modelValue: String,
    // name: String,
  },
  setup(props, context) {
    
    const changeName = () => {
      context.emit("update:modelValue", "demi");
      // context.emit("update:name", "demi");
    };
    return {
      changeName,
    };
  },
});
</script>

如果不想用默认名,我们可以在v-model:后面加上自定义的名字。

6. provide / inject

provide / inject需要一起使用,以允许一个祖先组件向其所有子孙后代注入一个依赖,不论组件层次有多深,并在其上下游关系成立的时间里始终生效。

原理和vue2一样,可能就是方法有所改变。

// 父组件
<script setup>
  import { provide } from "vue"
  provide("name", "沐华")
</script>

// 子组件
<script setup>
  import { inject } from "vue"
  const name = inject("name")
  console.log(name) // 沐华
</script>

上面的写法是setup的语法糖写法,更简洁.

7. mitt

我们知道vue3去除了$on $once $off方法,所以没办法再使用 EventBus 跨组件通信了。但是现在有了一个替代的方案 mitt.js,原理还是 EventBus。

先安装 npm i mitt -S

然后像以前封装 bus 一样,封装一下

import mitt from 'mitt'
const mitt = mitt()
export default mitt

然后两个组件之间通信的使用

// 组件 A
<script setup>
import mitt from './mitt'
const handleClick = () => {
    mitt.emit('handleChange')
}
</script>

// 组件 B 
<script setup>
import mitt from './mitt'
import { onUnmounted } from 'vue'
const someMethed = () => { ... }
mitt.on('handleChange',someMethed)
onUnmounted(()=>{
    mitt.off('handleChange',someMethed)
})
</script>
8. Vuex

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

9. Pinia

如果你之前使用过 vuex 进行状态管理的话,那么 pinia 就是一个类似的插件。它是最新一代的轻量级状态管理插件。按照尤雨溪的说法,vuex 将不再接受新的功能,建议将 Pinia 用于新的项目。

  • 4
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
Vue 2和Vue 3中,组件传值方式有一些差异。下面我将介绍Vue 2和Vue 3中常用的几种组件传值方式Vue 2中的组件传值方式: 1. Props:通过在父组件中使用属性绑定的方式将数据传递给子组件。父组件通过在子组件标签上绑定属性,并在子组件中通过props选项声明接收该属性。父组件可以在模板中直接使用子组件的属性。 2. 自定义事件:父组件可以通过`$emit`方法触发自定义事件,并传递数据给子组件。子组件通过`$on`方法监听父组件触发的事件,并在事件处理函数中接收数据。 3. Vuex:Vuex是Vue的状态管理库,可以在全局共享数据。父组件可以将数据存储在Vuex的状态管理中,并在子组件中通过计算属性或直接从Vuex中获取数据。 Vue 3中的组件传值方式: 1. Props:与Vue 2相同,通过在父组件中使用属性绑定的方式将数据传递给子组件。但是在Vue 3中,子组件需要使用`defineProps`来声明接收属性。 2. 自定义事件:与Vue 2相同,父组件可以通过`$emit`方法触发自定义事件,并传递数据给子组件。子组件通过`$on`方法监听父组件触发的事件,并在事件处理函数中接收数据。 3. Provide/Inject:父组件通过provide选项提供数据,然后子组件通过inject选项注入数据。这样可以在整个组件树中共享数据,而不需要显式传递。 需要注意的是,Vue 3中还引入了Composition API,通过`setup`函数来组织组件的逻辑。在`setup`函数中,可以使用`ref`和`reactive`等函数来创建响应式数据,并通过`props`参数接收父组件传递的属性。 以上是Vue 2和Vue 3中常用的组件传值方式,根据具体需求和场景选择合适的方式

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

杉菜酱子

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值