vue基础

Vue基础

1. Vue版本

Vue2

Vue3

二. 第一个Vue示例

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>vue实例</title>
</head>
<body>
    <div id="app">
        {{ msg }}   <!-- 此处为用于渲染的代码 -->
    </div>
    <!-- 引入开发版本包:在全局环境就有了Vue构造函数 -->
    <script src="https://cdn.jsdelivr.net/npm/vue@2.7.14/dist/vue.js"></script>
    <script>
        const app = new Vue({
            el : '#app',             // 通过el配置选择器,指定Vue管理的是哪个盒子
            data : {
                msg : "hello, Vue"   // 通过data提供数据
            }
        })
    </script>
</body>
</html>

3. 插值表达式

插值表达式是一种Vue的模板语法(表达式是可以被求值的代码,JS引擎会将其计算出一个结果)

作用:利用表达式进行插值,渲染到页面中

语法:{{表达式}}

注意点:

  • 使用的数据必须在data内存在
  • 支持的是表达式,而不是语句,如if, for…
  • 不能在标签属性中使用{{ }}插值(如**<p title=“{{11}}”>这是p标签</p>**)

4. 响应式特性

响应式:数据改变,视图自动更新

修改或访问数据:

  • 访问:实例.属性名
  • 修改:实例.属性名 = 值

5. Vue指令

Vue.js指令

5.1 v-html

作用: 设置元素的innerHTML 语法:v-html=“表达式”

示例:

<body>
    <div id="app" v-html="url">   <!-- 更新标签的innerHTML -->
    </div>
    <script src="https://cdn.jsdelivr.net/npm/vue@2.7.14/dist/vue.js"></script>
    <script>
        const app = new Vue({
            el : '#app',         
            data : {
                url : '<a href="https://www.jd.com/">京东官网</a>'
            }
        })
    </script>
</body>
5.2 v-show和v-if
指令名v-showv-if
作用控制元素显示隐藏控制元素显示隐藏(条件渲染)
语法(表达式值为true 显示,false 隐藏)v-show=“表达式”v-if=“表达式”
区别切换display:none控制显示隐藏基于条件判断,是否创建或移除元素节点
场景频繁切换显示/隐藏的地方显示或隐藏,不频繁切换

示例:

<body>
    <div id="app">
        <div class="box" v-show="flag">v-show控制的盒子</div>
        <div class="box" v-if="flag">v-if控制的盒子</div>
    </div>
    
    <script src="https://cdn.jsdelivr.net/npm/vue@2.7.14/dist/vue.js"></script>
    <script>
        const app = new Vue({
            el : '#app',             // 通过el配置选择器,指定Vue管理的是哪个盒子
            data : {
                flag : false
            }
        })
    </script>
</body>
5.3 v-else和v-else-if

作用: 辅助v-if进行判断渲染(必须要与v-if一起使用)

语法: v-else/v-else-if=“表达式”

5.4 v-on

作用: 注册事件 = 添加监听 + 提供处理逻辑

语法( v-on:可以简写为@):

  • v-on:事件名 = “内联语句”
  • v-on:事件名 = “methods中的函数名”

v-on:事件名 = "内联语句"示例:

<body>
    <div id="app">
        <button @click="count--">-</button>
        <span>{{count}}</span>
        <button @click="count++">+</button>
    </div>
    
    <script src="https://cdn.jsdelivr.net/npm/vue@2.7.14/dist/vue.js"></script>
    <script>
        const app = new Vue({
            el : '#app',             // 通过el配置选择器,指定Vue管理的是哪个盒子
            data : {
                count : 100
            }
        })
    </script>
</body>

v-on:事件名 = "methods中的函数名"示例:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>v-on</title>
    <style>
        .box{
            width: 300px;
            height: 200px;
            line-height: 50px;
            border: 3px solid black;
            border-radius: 10px;
        }
        button{
            width: 100px;
            height: 30px;
            border: 1px solid black;
            border-radius: 5px;
            margin-left: 30px;
        }
        .title{
            text-align: center;
        }
    </style>
</head>
<body>
    <div id="app">
        <div class="box">
            <p class="title">饮料自动贩卖机</p>
            <button @click="buy(3)">可乐3元</button>     <!-- 内联语句 -->  
            <button @click="buy(6)">咖啡6元</button>
        </div>
        <p>余额{{count}}</p>
    </div>
    
    <script src="https://cdn.jsdelivr.net/npm/vue@2.7.14/dist/vue.js"></script>
    <script>
        const app = new Vue({
            el : '#app',             // 通过el配置选择器,指定Vue管理的是哪个盒子
            data : {
                count : 100
            },
            methods : {
                buy(price){
                    this.count -= price
                }
            }
        })
    </script>
</body>
</html>
5.5 v-bind

作用: 动态设置html的标签属性(如src,url,title等)

语法:v-bind:属性名=“表达式”(简写::属性名=“表达式”

示例:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>v-bind</title>
</head>
<body>
    <div id="app">
       <img :src="imgUrl" alt="">
    </div>
    
    <script src="https://cdn.jsdelivr.net/npm/vue@2.7.14/dist/vue.js"></script>
    <script>
        const app = new Vue({
            el : '#app',             // 通过el配置选择器,指定Vue管理的是哪个盒子
            data : {
                count : 100,
                imgUrl : '../imgs/10-01.png'
            },
            
        })
    </script>
</body>
</html>
5.6 v-for

作用: 基于数据循环,多次渲染整个元素(数据:数组、对象、数字等)

语法: v-for=“(item, index) in 数据” 其中item为每一项的具体值,index为下标

v-for中的key:给元素添加唯一的标识(不加keyv-for的默认行为会尝试原地修改元素

  • key只能是字符串或者数字类型
  • key的值必须具有唯一性
  • 一般使用id作为key

示例:

<body>
  <div id="app">
    <h3>小黑的书架</h3>
    <ul>
      <li v-for="item in booksList" :key="item.id">
        <span>{{item.name}}</span>
        <span>{{item.author}}</span>
        <button @click="del(item.id)">删除</button>
      </li>
    </ul>
  </div>
  <script src="https://cdn.jsdelivr.net/npm/vue@2.7.14/dist/vue.js"></script>
  <script>
    const app = new Vue({
      el: '#app',
      data: {
        booksList: [
          { id: 1, name: '《红楼梦》', author: '曹雪芹' },
          { id: 2, name: '《西游记》', author: '吴承恩' },
          { id: 3, name: '《水浒传》', author: '施耐庵' },
          { id: 4, name: '《三国演义》', author: '罗贯中' }
        ]
      },
      methods : {
        del(id){
          this.booksList = this.booksList.filter(item => {return item.id !== id})   // filter会得到一个新数组
        }
      }
    })
  </script>
</body>
5.7 v-model

作用: 给表单使用,双向数据绑定(快速获取或设置表单元素内容)

双向数据绑定

  • 数据变化—>视图自动更新
  • 视图变化—>数据自动更新

语法: v-model=‘变量’

示例:

<body>
    <div id="app">
        账号: <input type="text" v-model="username"> <br><br>
        密码: <input type="password" v-model="password"> <br><br>
        <button @click="login">登录</button>
        <button @click="reset">重置</button>
    </div>
    <script src="https://cdn.jsdelivr.net/npm/vue@2.7.14/dist/vue.js"></script>
    <script>
        const app = new Vue({
            el : '#app',
            data : {
                username : '',
                password : ''
            },
            methods : {
                login(){
                    console.log(this.username, this.password);
                },
                reset(){
                    this.username = '',
                    this.password = ''
                }
            }
        })
    </script>
</body>

6. 指令修饰符

通过 “.” 指明一些指令后缀,不同后缀封装了不同的操作(这样写可以简化代码)

  • 按键修饰符
    • @keyup.enter 键盘回车监听
  • v-model修饰符
    • v-model.trim 去除首位空格
    • v-model.number 转数字
  • 事件修饰符
    • @事件名.stop 阻止冒泡
    • @事件名.prevent 阻止默认行为

7. v-bind对于样式控制的增强

7.1 操作class

语法: v-bind:class=“对象/数组” 或 :class=“对象/数组”

  • 对象—>键就是类名,值是布尔值。若值为true,就有这个类,否则没有这个类(频繁切换类的场景)
<div class="box" :class="{类名1:布尔值, 类名2:布尔值}"></div>
  • 数组—>数组中所有的类,都会添加到盒子上,本质就是一个class列表(批量添加,删除类的场景)
<!-- 类名须为字符串  -->
<div class="box" :class="[类名1, 类名2]"></div>
7.2 操作style

语法: v-bind:style=“样式对象” 或 :style=“样式对象”

<!-- CSS属性值须为字符串  -->
<div class="box" :style="{CSS属性名1:CSS属性值, CSS属性名2:CSS属性值}"></div>

8.v-model应用于其他表单

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>v-model应用到其他表单元素</title>
</head>
<body>
    <div id="app">
        用户名:<input type="text" v-model="username">
        <br><br>
        是否单身:<input type="checkbox" v-model="isSingle">
        <br><br>
        性别:
        <!-- 给单选框加上name属性,可以分组,且同一组会相互互斥
            给单选框加上value属性,用于提交数据给后台
         -->
        <input type="radio" name="gender" value="1" v-model="gender"><input type="radio" name="gender" value="2" v-model="gender"><br><br>
        <!-- option需要设置value值,提交给后台 
             select的value值关联了选中的option的值 -->
        所在城市:
        <select v-model="cityID">
            <option value="101">北京</option>
            <option value="102">上海</option>
            <option value="103">重庆</option>
            <option value="104">广州</option>
        </select>
        <br><br>
        个人简介:
        <br>
        <textarea v-model="desc"></textarea>
        <button>立即注册</button>
    </div>
    <script src="https://cdn.jsdelivr.net/npm/vue@2.7.14/dist/vue.js"></script>
  <script>
    const app = new Vue({
      el: '#app',
      data: {
        username : '',
        isSingle : true,
        gender : '1',
        cityID : '101',
        desc : '我是小蓝'
      }
    })
  </script>
</body>
</html>

9. 计算属性

9.1 什么是计算属性

定义:基于现有的数据,计算出来新的属性。 依赖的数据变化,自动重新计算 \color{red}依赖的数据变化,自动重新计算 依赖的数据变化,自动重新计算

语法:

声明在computed配置项中,一个计算属性对应一个函数

使用起来和普通属性一样使用 {{ 计算属性名 \color{red}计算属性名 计算属性名}}

computed : {
	计算属性名(){
        基于现有数据,编写求值逻辑
        return 结果
    }
}
9.2 computed 计算属性 vs methods方法
computedmethods
作用封装了一段处理数据的函数,返回一个结果给实例提供一个方法,用以处理业务逻辑
语法1、写在computed配置项中
2、作为属性,直接使用(this.计算属性 {{计算属性}})
1、写在methods配置项中
2、作为方法,需要调用(this.方法名 {{方法名}} @事件名=‘方法名’)
备注计算属性具有缓存特性(对计算出的结果缓存,再次使用时直接读取)方法不具备缓存特性,调用一次,执行一次
9.3 计算属性的完整写法
computed : {
	计算属性名 : {
	get(){
	一段逻辑代码(计算逻辑)
	reutrn 结果
	}
	set(修改的值){
	一段代码逻辑(修改逻辑)
	}
	}
}

10. watch 侦听器(监听器)

作用: 监听数据变化,执行一些业务逻辑或异步操作 \color{red}监听数据变化,执行一些业务逻辑或异步操作 监听数据变化,执行一些业务逻辑或异步操作

10.1 简单写法

场景:简单数据类型,直接监听

data : {
	words : 'apple',
	obj : {
		words : 'apple'
	}
},
watch : {
    数据属性名 (newValue, oldValue){
        一些业务逻辑 或 异步操作
    }
    '对象.属性名' (newValue, oldValue){
        一些业务逻辑 或 异步操作
    }
}
10.2 完整写法

场景:添加额外配置项

  • deep : true 对复杂类型深度监视

  • immediate : true 初始化立刻执行一次handler方法

data : {
	obj : {
		words : 'apple',
        lang : 'italy'
	},
},
watch : {
    数据属性名(obj) : {   // 数据属性名
        deep : true, // 深度监视
        immediate : true, // 立刻执行,页面打开即执行一次handler方法
        handler(newValue){
            一些业务逻辑 或 异步操作
        }
    }
}

11. Vue的生命周期

Vue四个生命周期: 创建(create)、挂载(mount)、更新(update)、销毁(destroy)
在这里插入图片描述

示例:

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Vue四个生命周期</title>
</head>

<body>
  <div id="app">
    <h3>{{ title }}</h3>
    <div>
      <button @click="count--">-</button>
      <span>{{ count }}</span>
      <button @click="count++">+</button>
    </div>
  </div>
  <script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
  <script>
    const app = new Vue({
      el: '#app',
      data: {
        count: 100,
        title: '计数器'
      },
      beforeCreate(){
        console.log('创建数据之前');
      },
      created(){
        console.log('创建数据之后');
      },
      beforeMount(){
        console.log('模板渲染之前');
      },
      mounted(){
        console.log('模板渲染之后');
      },
      beforeUpdate(){
        console.log('数据更新之前');
      },
      updated(){
        console.log('数据更新之后');
      },
      beforeDestroy(){
        console.log('销毁实例之前');
      },
      destroy(){
        console.log('销毁实例之后');
      }
    })
  </script>
</body>

</html>

12. 工程化开发

12.1 脚手架Vue CLI搭建过程
  1. 全局安装(新设备安装一次即可): yarn global add @vue/cli 或 npm i @vue/cli -g
  2. 查看Vue版本: vue --version
  3. 创建项目架子: vue create project-name (项目名–不能是中文)
  4. 启动项目:yarn server 或 **npm run server **(找package.json)
12.2 脚手架文件目录

在这里插入图片描述

12.3 组件化&根组件

组件化: 一个页面可以拆分成一个个组件,每个组件有着自己独立的结构、样式、行为。(优点:便于维护、复用-----提升开发效率)

根组件: 整个应用最上层的组件,包裹所有其他组件。

12.4 普通组件的注册

局部注册: 只能在注册的组件内使用

  1. 在components文件夹中创建.vue文件
  2. 在使用的组件内导入并注册
  3. 示例:
<script>
import YouHeader from './components/YouHeader.vue';
export default {
  name: 'App',
  components: {
    YouHeader,
  }
}
</script>

使用:当成html标签使用 ‘<组件名></组件名>’

note:组件名通常采用大驼峰命名(如:YouHeader)

全局注册: 所有组件内都能使用

  1. 在components文件夹中创建.vue文件
  2. 然后在main.js中进行全局注册
  3. 示例:
import YouButton from './components/YouButton.vue'

// 调用 Vue.component 进行全局注册
Vue.component('YouButton', YouButton)

13. 解决组件间的样式冲突----scoped

默认情况下,写在组件中的样式会全局生效,因此很容易造成多个组件之间样式的冲突

  • 全局样式: 默认组件中的样式会作用到全局
  • 局部样式: 给组件的style加上scoped属性,可以让样式只作用于当前组件

scoped原理:

  • 当前组件内的标签都被添加上 data-v-hash值 的属性
  • CSS选择器都被添加上[ data-v-hash值] 的属性选择器
  • 因此必须是当前组件的元素,才会有这个自定义属性,才会被这个样式用到

14. 组件内的数据

一个组件的data选项必须是一个函数,这样的设计保证了每个组件实例维护独立的一份数据对象。

// 示例
export default {
  data() {
    return {
      count: 100,
    }
  },
}
14.1 组件内通信方案
14.1.1 父子关系

一、通过 props和$emit 进行通信

  • 父组件通过props将数据传递给子组件
  • 子组件利用$emit通知父组件,进行数据更新

子组件代码:

<template>
  <div class="son" style="border:3px solid #000;margin:10px">
    <!-- 3.直接使用props的值 -->
    我是Son组件 {{ title }}
    <button @click="changeTitle">修改</button>
  </div>
</template>
<script>
export default {
  name: 'Son-Child',
  // 2.通过props来接受
  props : ['title'],
  methods : {
    changeTitle(){
      this.$emit('changeT', '学JAVA更有趣')
    }
  }
}
</script>
<style>
</style>

父组件代码:

<template>
  <div class="app" style="border: 3px solid #000; margin: 10px">
    我是APP组件
    <!-- 1.给组件标签,添加属性方式 赋值 -->
    <Son :title="myTitle" @changeT="updateTitle"></Son>
  </div>
</template>
<script>
import Son from './components/Son.vue'
export default {
  name: 'App',
  data(){
    return {
      myTitle : '前端真有趣'
    }
  },
  components: {
    Son,
  },
  methods : {
    updateTitle(newTitle){
      this.myTitle = newTitle
    }
  }
}
</script>
<style>
</style>

二、什么是 prop?

定义: 组件上注册的一些自定义属性

作用: 向子组件传递数据

特点: 可以传递 任意数量和任意类型 \color{red}任意数量和任意类型 任意数量和任意类型的prop

三、props校验

为组件的prop指定校验要求,不符合要求,控制台就会有错误提示

// 只校验类型格式
props : {校验属性名 : 类型}   // Number,String,Boolean ...

// 完整校验格式
props : {
	校验属性名 : {
	type : 类型,     // Number,String,Boolean ...
    required : true, // 是否必填
    default : 默认值, // 默认值
    validator(value){
        // 自定义校验逻辑
        return 是否通过校验(true or false)
    }
	}
}

四、prop&data、单向数据流

共同点: prop&data都可以给组件提供数据流

区别:

  • data的数据是自身的,可以自己修改
  • prop的数据是外部的,不能直接修改,要遵循单向数据流

单向数据流: 父级的prop数据更新,会向下流动,影响子组件

14.1.2 非父子关系

(1) provide & inject

作用:用于跨层级之间的数据共享

  • 父组件使用 provide 提供数据
export default {
	provide(){
		return {
			userName : this.name,  // 普通类型数据,是非响应式的
			userInfo : {age : this.age, hobby : 'basketball'}  // 复杂类型数据,是响应式的
		}
	}
}
  • 子/孙组件使用 inject 取值使用
export default {
	inject : ['userName','userInfo']
}

(2) event bus
在这里插入图片描述
作用:非父子组件之间,进行简易消息传递

创建一个都能访问到的事件总线(空 Vue 实例)----utils/EventBus.js

import Vue from 'vue'
const Bus = new Vue()
export default Bus

A 组件(接收方),监听 Bus 实例 的事件

import Bus from '../utils/EventBus.js'
created(){
    Bus.$on('sendMsg', (msg) => {
        this.msg = msg
    })
}

B 组件(发送方),触发 Bus 实例 的事件

import Bus from '../utils/EventBus.js'
Bus.$emit('sendMsg', '这是B组价发送的信息')

通用方案:Vuex(适合复杂业务场景)

15 V-model详解

v-model本质上是一个语法糖,用于提供数据的双向绑定。如应用在输入框上,就是 value属性input事件 的合写

  • 数据变,视图跟着变 :value
  • 视图变,数据跟着变 @input
<!-- 如下两个标签的功能一样 -->
<input type="text" v-model="msg">
<input type="text" :value="msg" @input="msg = $event.target.value">

note: $event 用于在模板中,获取事件的形参

1、封装表单类基础组件(实现子组件与父组件之间数据的双向绑定)

  • 父传子: 父组件动态传递prop数据,拆解v-model,绑定数据
  • 子传父: 监听输入,子组件传值给父组件修改

2、v-model简化代码步骤

  • 子组件中: props 通过 value 接收,事件触发input
  • 父组件: v-model 给组件直接绑数据

示例:

<!-- 父组件 -->
<template>
  <div id="app">
    <SonCom v-model="CityId"></SonCom>
  </div>
</template>
<script>
import SonCom from './components/SonCom.vue'
export default {
  components: {
    SonCom
  },
  data () {
    return {
      CityId : '102'
    }
  },
}
</script>
<style>
</style>
<!-- 子组件 -->
<template>
    <select :value="value" @change="handleC">
      <option value="101">北京</option>
      <option value="102">上海</option>
      <option value="103">广州</option>
      <option value="104">深圳</option>
    </select>
</template>

<script>
export default {
    name: 'SonCom',
    props : {value : String},
    components: {},
    methods : {
      handleC(e) {
        this.$emit('input', e.target.value)
      }
    }
}
</script>
<style scoped>
</style>

16. 其他知识点补充

16.1 .sync修饰符

作用: 可以实现子组件与父组件的双向数据绑定,简化代码

特点: 可以自定义prop属性名,不用固定为value

使用场景: 封装弹框类的基础组件:visible属性—true显示 ,false隐藏

本质: 属性名 和 @update:属性名的合写

note:子组件向父组件传值时必须使用如下格式

this.$emit('update:属性名',false)
16.2 ref 和 refs

作用:用于获取 DOM元素组件实例

特点:查找范围只限于 当前组件内

获取DOM元素:

  1. 给目标标签添加ref属性

    <div ref="chartRef"> 渲染图表的容器 </div>
    
  2. 恰当时机,通过this.$refs.xxx,获取目标标签

    mounted(){
        console.log(this.$refs.chartRef)
    }
    

获取组件实例:

  1. 给目标组件添加ref属性

    <BaseDialog ref="baseDialog"></BaseDialog>
    
  2. 恰当时机,通过this.$refs.xxx,获取目标组件,调用组件对象内的方法

    this.$refs.baseDialog.组件方法()
    
16.3 $nextTick

Vue是异步更新DOM的:即数据更新之后,DOM(视图)不会立即更新

如果想要在DOM更新完成后做某件事,则需要使用$nextTick

this.$nextTick(() => {
 // 业务逻辑   
})

17. 自定义指令

自定义指令可以 封装一些DOM操作 ,扩展额外的功能。

全局注册:

Vue.directive('focus',{   // 自定义指令全局注册
  inserted (el){        // el是指令绑定的DOM元素
    // 自定义逻辑操作
  }
})

局部注册:

directives : {   // 自定义指令局部注册
   "focus" : {
     inserted (el) {  // el是指令绑定的DOM元素
       // 自定义逻辑操作
     }
   }
}

指令的值:

语法:在绑定指令时,通过"="为指令绑定 具体的参数值

<p v-color="color1">指令的值1测试</p>

通过binding.value可以拿到指令值,指令修改会触发 update函数

<!-- 示例 -->
<template>
  <div>
    <p v-color="color1">指令的值111</p>
    <p v-color="color2">指令的值222</p>
  </div>
</template>
<script>
export default {
  data () {
    return {
      color1 : 'blue',
      color2 : 'green'
    }
  },
  directives : {
    "color" : {
      inserted(el, binding) {
        el.style.color = binding.value
      },
      update(el, binding) {
        el.style.color = binding.value
      },
    }
  }
}
</script>
<style>
</style>

18. 插槽

18.1 默认插槽

语法:

  1. 组件内需要定制的结构位置,改用 <slot> </slot> 占位
  2. 使用组件时,<MyBody> ( 内部 ) </MyBody> 标签内部传入结构替换slot

插槽后备内容( 默认值 ):在 <slot> </slot> 标签内放置内容,作为默认显示内容

18.2 具名插槽

语法:

  1. 多个slot使用name属性区分名字

    <div class="Header">
    	<slot name="head"></slot>
    </div>
    <div class="Body">
    	<slot name="body"></slot>
    </div>
    
  2. template配合v-slot:名字来分发对应的标签(v-slot:也可以简写为#)

    <template v-slot:head>Header</template>  <!-- v-slot:head相当于#head -->
    <template v-slot:body>Body</template>
    
18.3 作用域插槽

使用步骤:

  • 以添加属性的方式给slot标签 传值

  • 所有添加的属性都会被收集到一个对象中

  • 在template中,通过’ #插槽名=“obj” '接收,默认插槽名为 default

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值