微信小程序基础

1、微信小程序介绍

微信小程序,简称[小程序, 英文名Mini Program, 是一种不需 要下载安装即 可使用的应 用,它实现了应用“触手可及”的梦想,用户在微信扫一扫或搜一下即可打开应用

1.1 微信小程序优势
  1. 微信有海量用户,而且用户粘性高,在微信里开发产品更容易触达用户
  2. 微信小程序具有无需安装,扫码即用的特性,相比App推广成本更低
  3. 低廉的开发成本,较好的体验
1.2 微信小程序历史
  1. 2016年1月11日,微信之父张小龙时隔多年的公开亮相,解读了微信的四大价值观。张小龙指出,越来越多产品通过公众号来做,因为这里开发、获取用户和传播成本更低。拆分出来的服务号并没有提供更好的服务,所以微信内部正在研究新的形态,叫**「微信小程序」** 需要注意的是,之前是叫做 应用号
  2. 2016年9月21日,微信小程序正式开启内测。在微信生态下,触手可及、用完即走的微信小程序引起广泛关注。腾讯云正式上线微信小程序解决方案,提供小程序在云端服务器的技术方案。
  3. 2017年1月9日,微信推出的“小程序”正式上线。“小程序”是一种无需安装,即可使用的手机“应用”。不需要像往常一样下载App,用户在微信中“用完即走”。
1.3 疯狂的微信小程序
  • 微信月活已经达到10.82亿。其中55岁以上的用户也达到6300万
  • 信息传达数达到450亿,较去年增长18%;视频通话4.1亿次,增长100%
  • 小程序覆盖超过200+行业,交易额增长超过6倍,服务1000亿+人次,创造出了5000亿+的商业价值

2、环境准备

2.1 注册账号

微信小程序有别于web应用,web应用通常由我们自己管理发布,但是微信小程序由微信统一管理,因此需要注册账号。

注册地址

2.2 获取AppID

AppID是微信小程序的身份标记,后期开发中需要调用开放接口,发布应用都需要用到AppID。

可登录微信公众平台 进入“开发” – “开发设置” 获取AppID

2.3 下载开发工具

下载地址

微信开发者工具集开发,预览,调试,发布于一身。

3、第一个微信小程序

3.1 登录微信开发者工具
3.2 新建小程序项目
3.3 填写项目信息
3.4 成功

4、微信开发者工具介绍

详细的使用,可以查看官网

5、小程序结构目录

小程序框架的目标是通过尽可能简单、高效的方式让开发者可以在微信中开发具有原生 APP 体验的服务。

小程序框架提供了自己的视图层描述语言 WXMLWXSS,以及 JavaScript,并在视图层与逻辑层间提供了数据传输和事件系统,让开发者能够专注于数据与逻辑。

5.1. 小程序文件结构和传统web对比
结构传统web微信小程序
结构HTMLWXML
样式CSSWXSS
逻辑JavascriptJavascript
配置JSON

通过以上对比得出,传统web 是三层结构。而微信小程序 是四层结构,多了一层 配置.json

6、小程序配置文件

6.1. 全局配置 app.json

app.json 是当前小程序的全局配置,包括了小程序的所有页面路径、界面表现、网络超时时间、底部 tab 等。普通快速启动项目里边的 app.json 配置

{
  "pages":[
    "pages/index/index",
    "pages/logs/logs"
  ],
  "window":{
    "backgroundTextStyle":"light",
    "navigationBarBackgroundColor": "#fff",
    "navigationBarTitleText": "WeChat",
    "navigationBarTextStyle":"black"
  }
}

字段的含义

  1. pages字段 —— 用于描述当前小程序所有页面路径,这是为了让微信客户端知道当前你的小程序页面定义在哪个目录。
  2. window字段 —— 定义小程序所有页面的顶部背景颜色,文字颜色定义等。
  3. 完整的配置信息请参考 app.json配置

img

6.1.1. tabbar
6.2. 页面配置 page.json

这里的 page.json 其实用来表示页面目录下的 page.json 这类和小程序页面相关的配置。

开发者可以独立定义每个页面的一些属性,如顶部颜色、是否允许下拉刷新等等。

页面的配置只能设置 app.json 中部分 window 配置项的内容,页面中配置项会覆盖 app.jsonwindow 中相同的配置项。

属性类型默认值描述
navigationBarBackgroundColorHexColor#000000导航栏背景颜色,如 #000000
navigationBarTextStyleStringwhite导航栏标题颜色,仅支持 black / white
navigationBarTitleTextString导航栏标题文字内容
backgroundColorHexColor#ffffff窗口的背景色
backgroundTextStyleStringdark下拉 loading 的样式,仅支持 dark / light
enablePullDownRefreshBooleanfalse是否全局开启下拉刷新。 详见 Page.onPullDownRefresh
onReachBottomDistanceNumber50页面上拉触底事件触发时距页面底部距离,单位为px。 详见 Page.onReachBottom
disableScrollBooleanfalse设置为 true 则页面整体不能上下滚动;只在页面配置中有效,无法在 app.json 中设置该项
6.3. sitemap 配置-了解即可

小程序根目录下的 sitemap.json 文件用于配置小程序及其页面是否允许被微信索引。

7、模板语法

WXML(WeiXin Markup Language)是框架设计的一套标签语言,结合基础组件事件系统,可以构建出页面的结构。

7.1. 数据绑定
7.1.1. 普通写法
<view> {{ message }} </view>
Page({
  data: {
    message: 'Hello MINA!'
  }
})
7.1.2. 组件属性
<view id="item-{{id}}"> </view>
Page({
  data: {
    id: 0
  }
})
7.1.3. bool类型

不要直接写 checked=“false”,其计算结果是一个字符串

<checkbox checked="{{false}}"> </checkbox>
7.2. 运算
7.2.1. 三元运算
<view hidden="{{flag ? true : false}}"> Hidden </view>
7.2.2. 算数运算
<view> {{a + b}} + {{c}} + d </view>
Page({
  data: {
    a: 1,
    b: 2,
    c: 3
  }
})
7.2.3. 逻辑判断
<view wx:if="{{length > 5}}"> </view>
7.2.4. 字符串运算
<view>{{"hello" + name}}</view>
Page({
  data:{
    name: 'MINA'
  }
})
7.2.5. 注意

花括号和引号之间如果有空格,将最终被解析成为字符串

7.3. 列表渲染
7.3.1. wx:for

项的变量名默认为 item wx:for-item 可以指定数组当前元素的变量名

下标变量名默认为 index wx:for-index 可以指定数组当前下标的变量名

wx:key 用来提高数组渲染的性能

wx:key 绑定的值 有如下选择

  1. string 类型,表示 循环项中的唯一属性 如

    list:[{id:0,name:"炒饭"},{id:1,name:"炒面"}]
    
    wx:key="id"
    
  2. 保留字 *this ,它的意思是 item 本身 ,*this 代表的必须是 唯一的字符串和数组。

    list:[1,2,3,4,5]
    
    wx:key="*this"
    

代码

<view wx:for="{{array}}" wx:key="id">
  {{index}}: {{item.message}}
</view>
Page({
  data: {
    array: [{
      id:0,
      message: 'foo',
    }, {
      id:1,
      message: 'bar'
    }]
  }
})
7.3.2. block

渲染一个包含多节点的结构块 block最终不会变成真正的dom元素

<block wx:for="{{[1, 2, 3]}}" wx:key="*this" >
  <view> {{index}}: </view>
  <view> {{item}} </view>
</block>
7.4. 条件渲染
7.4.1. wx:if

在框架中,使用 wx:if="{{condition}}" 来判断是否需要渲染该代码块:

  <view wx:if="{{false}}">1</view>
  <view wx:elif="{{true}}">2</view>
  <view wx:else>3</view>
7.4.2. hidden
<view hidden="{{condition}}"> True </view>

类似 wx:if

频繁切换 用 hidden

不常使用 用 wx:if

8、小程序事件绑定

小程序中绑定事件,通过bind关键字来实现。如 bindtap bindinput bindchange

不同的组件支持不同的事件,具体看组件的说明即可。

8.1. wxml
<input bindinput="handleInput" />
8.2. page
Page({
  // 绑定的事件
  handleInput: function(e) {
    console.log(e);
    console.log("值被改变了");
  }
})
8.3. 特别注意
  1. 绑定事件时不能带参数 不能带括号 以下为错误写法

    <input bindinput="handleInput(100)" />
    
  2. 事件传值 通过标签自定义属性的方式 和 value

    <input bindinput="handleInput" data-item="100" />
    
  3. 事件触发时获取数据

       handleInput: function(e) {
        // {item:100}
       console.log(e.currentTarget.dataset)
          
        // 输入框的值
       console.log(e.detail.value);
      }
    

9、样式 WXSS

WXSS(WeiXin Style Sheets)是一套样式语言,用于描述 WXML 的组件样式。

CSS 相比,WXSS 扩展的特性有:

  • 响应式长度单位 rpx
  • 样式导入
9.1. 尺寸单位

rpx(responsive pixel): 可以根据屏幕宽度进行自适应。规定屏幕宽为750rpx。如在 iPhone6 上,屏幕宽度为375px,共有750个物理像素,则750rpx = 375px = 750物理像素1rpx = 0.5px = 1物理像素

设备rpx换算px (屏幕宽度/750)px换算rpx (750/屏幕宽度)
iPhone51rpx = 0.42px1px = 2.34rpx
iPhone61rpx = 0.5px1px = 2rpx
iPhone6 Plus1rpx = 0.552px1px = 1.81rpx

建议: 开发微信小程序时设计师可以用 iPhone6 作为视觉稿的标准。

使用步骤:

  1. 确定设计稿宽度 pageWidth
  2. 计算比例 750rpx = pageWidth px ,因此 1px=750rpx/pageWidth
  3. 在less文件中,只要把设计稿中的 px => 750/pageWidth rpx 即可。
9.2. 样式导入

wxss中直接就支持,样式导入功能。

也可以和 less中的导入混用。

使用@import语句可以导入外联样式表,只支持相对路径

示例代码:

/** common.wxss **/
.small-p {
  padding:5px;
}
/** app.wxss **/
@import "common.wxss";
.middle-p {
  padding:15px;
}
9.3. 选择器

特别需要注意的是 小程序 不支持通配符 * 因此以下代码无效!

*{
    margin:0;
    padding:0;
    box-sizing:border-box;
}

目前支持的选择器有:

选择器样例样例描述
.class.intro选择所有拥有 class=“intro” 的组件
#id#firstname选择拥有 id=“firstname” 的组件
elementview选择所有 view 组件
element, elementview, checkbox选择所有文档的 view 组件和所有的 checkbox 组件
nth-child(n)view:nth-child(n)选择某个索引的标签
::afterview::after在 view 组件后边插入内容
::beforeview::before在 view 组件前边插入内容

10、常见组件

重点讲解小程序中常用的布局组件

view,text,rich-text,button,image,navigator,icon,swiper,radio,checkbox。

10.1. view

代替 原来的 div 标签

  <view hover-class="h-class">
  点击我试试
  </view>
10.2. text
  1. 文本标签
  2. 只能嵌套text
  3. 长按文字可以复制(只有该标签有这个功能)
  4. 可以对空格 回车 进行编码
属性名类型默认值说明
selectableBooleanfalse文本是否可选
decodeBooleanfalse是否解码
10.2.1. 代码
  <text selectable="{{ false }}" decode="{{ false }}">&nbsp;</text>
10.3. image
  1. 图片标签,image组件默认宽度320px、高度240px
  2. 支持懒加载
属性名类型默认值说明
srcString图片资源地址
modeString‘scaleToFill’图片裁剪、缩放的模式
lazy-loadBooleanfalse图片懒加载

mode 有效值:

mode 有 13 种模式,其中 4 种是缩放模式,9 种是裁剪模式。

模式说明
缩放scaleToFill不保持纵横比缩放图片,使图片的宽高完全拉伸至填满 image 元素
缩放aspectFit保持纵横比缩放图片,使图片的长边能完全显示出来。
缩放aspectFill保持纵横比缩放图片,只保证图片的短边能完全显示出来。
缩放widthFix宽度不变,高度自动变化,保持原图宽高比不变
裁剪top不缩放图片,只显示图片的顶部区域
裁剪bottom不缩放图片,只显示图片的底部区域
裁剪center不缩放图片,只显示图片的中间区域
裁剪left不缩放图片,只显示图片的左边区域
裁剪right不缩放图片,只显示图片的右边区域
裁剪top left不缩放图片,只显示图片的左上边区域
裁剪top right不缩放图片,只显示图片的右上边区域
裁剪bottom left不缩放图片,只显示图片的左下边区域
裁剪bottom right不缩放图片,只显示图片的右下边区域
10.4. swiper

微信内置滑动组件。

默认宽度 100% 高度 150px

属性名类型默认值说明
indicator-dotsBooleanfalse是否显示面板指示点
indicator-colorColorrgba(0, 0, 0, .3)指示点颜色
indicator-active-colorColor#000000当前选中的指示点颜色
autoplayBooleanfalse是否自动切换
intervalNumber5000自动切换时间间隔
circularBooleanfalse是否循环轮播
10.4.1. swiper

滑块视图容器。

10.4.2. swiper-item

滑块

默认宽度和高度都是100%

10.5. navigator

导航组件 类似超链接标签

属性名类型默认值说明
targetStringself在哪个目标上发生跳转,默认当前小程序,可选值self/miniProgram
urlString当前小程序内的跳转链接
open-typeStringnavigate跳转方式

open-type 有效值:

说明
navigate保留当前页面,跳转到应用内的某个页面,但是不能跳到 tabbar 页面
redirect关闭当前页面,跳转到应用内的某个页面,但是不允许跳转到 tabbar 页面。
switchTab跳转到 tabBar 页面,并关闭其他所有非 tabBar 页面
reLaunch关闭所有页面,打开到应用内的某个页面
navigateBack关闭当前页面,返回上一页面或多级页面。可通过 getCurrentPages() 获取当前的页面栈,决定需要返回几层
exit退出小程序,target="miniProgram"时生效
10.6. rich-text

富文本标签。

可以将字符串解析成 对应标签,类似 vuev-html功能
代码

// 1   index.wxml  加载 节点数组
<rich-text nodes="{{nodes}}" bindtap="tap"></rich-text>
// 2 加载 字符串
<rich-text nodes='<img src="https://developers.weixin.qq.com/miniprogram/assets/images/head_global_z_@all.png" alt="">'></rich-text> 
 
    
// index.js
    
Page({
  data: {
    nodes: [{
      name: 'div',
      attrs: {
        class: 'div_class',
        style: 'line-height: 60px; color: red;'
      },
      children: [{
        type: 'text',
        text: 'Hello&nbsp;World!'
      }]
    }]
  },
  tap() {
    console.log('tap')
  }
})

10.6.1. nodes属性

nodes属性支持 字符串标签节点数组

属性说明类型必填备注
name标签名string支持部分受信任的 HTML 节点
attrs属性object支持部分受信任的属性,遵循 Pascal 命名法
children子节点列表array结构和 nodes 一致

文本节点:type = text

属性说明类型必填备注
text文本string支持entities
  • nodes 不推荐使用 String 类型,性能会有所下降。
  • rich-text 组件内屏蔽所有节点的事件。
  • attrs 属性不支持 id ,支持 class 。
  • name 属性大小写不敏感。
  • 如果使用了不受信任的 HTML 节点,该节点及其所有子节点将会被移除。
  • img 标签仅支持网络图片。
10.7. button
<button
  type="default"
  size="{{defaultSize}}"
  loading="{{loading}}"
  plain="{{plain}}"
>
  default
</button>
属性类型默认值必填说明
sizestringdefault按钮的大小
typestringdefault按钮的样式类型
plainbooleanfalse按钮是否镂空,背景色透明
disabledbooleanfalse是否禁用
loadingbooleanfalse名称前是否带 loading 图标
form-typestring用于 ](https://developers.weixin.qq.com/miniprogram/dev/component/form.html) 组件,点击分别会触发 [ 组件的 submit/reset 事件
open-typestring微信开放能力

size 的合法值

说明
default默认大小
mini小尺寸

type 的合法值

说明
primary绿色
default白色
warn红色

form-type 的合法值

说明
submit提交表单
reset重置表单

open-type 的合法值

说明
contact打开客服会话,如果用户在会话中点击消息卡片后返回小程序,可以从 bindcontact 回调中获得具体信息,具体说明
share触发用户转发,使用前建议先阅读使用指引
getPhoneNumber获取用户手机号,可以从bindgetphonenumber回调中获取到用户信息,具体说明
getUserInfo获取用户信息,可以从bindgetuserinfo回调中获取到用户信息
launchApp打开APP,可以通过app-parameter属性设定向APP传的参数具体说明
openSetting打开授权设置页
feedback打开“意见反馈”页面,用户可提交反馈内容并上传日志,开发者可以登录小程序管理后台后进入左侧菜单“客服反馈”页面获取到反馈内容
open-type 的 contact的实现流程
  1. 将小程序 的appid 由测试号改为 自己的appid
  2. 登录微信小程序官网,添加 客服 - 微信
  3. 为了方便演示,老师自己准备了两个账号
    1. 普通用户 A
    2. 客服-微信 B
  4. 就是干!
10.8. icon
属性类型默认值必填说明
typestringicon的类型,有效值:success, success_no_circle, info, warn, waiting, cancel, download, search, clear
sizenumber/string23icon的大小
colorstringicon的颜色,同css的color

代码:

js

Page({
  data: {
    iconSize: [20, 30, 40, 50, 60, 70],
    iconType: [
      'success', 'success_no_circle', 'info', 'warn', 'waiting', 'cancel', 'download', 'search', 'clear'
    ],
    iconColor: [
      'red', 'orange', 'yellow', 'green', 'rgb(0,255,255)', 'blue', 'purple'
    ],
  }
})

wxml

<view class="group">
  <block wx:for="{{iconSize}}">
    <icon type="success" size="{{item}}"/>
  </block>
</view>

<view class="group">
  <block wx:for="{{iconType}}">
    <icon type="{{item}}" size="40"/>
  </block>
</view>

<view class="group">
  <block wx:for="{{iconColor}}">
    <icon type="success" size="40" color="{{item}}"/>
  </block>
</view>
10.9. radio

可以通过 color属性来修改颜色
需要搭配 radio-group 一起使用

10.10. checkbox

可以通过 color属性来修改颜色。

需要搭配 checkbox-group 一起使用

11. 自定义组件

类似 vue 或者 react 中的自定义组件

小程序允许我们使用自定义组件的方式来构建页面。

11.1. 创建自定义组件

类似于页面,一个自定义组件由 json wxml wxss js 4个文件组成

可以在微信开发者工具中快速创建组件的文件结构

11.1.1. 声明组件

首先需要在组件的 json 文件中进行自定义组件声明

myHeader.json

{
  "component": true
}

11.1.2. 编辑组件

同时,还要在组件的 wxml 文件中编写组件模板,在 wxss 文件中加入组件样式

slot表示插槽,类似vue中的slot

myHeader.wxml

<!-- 这是自定义组件的内部WXML结构 -->
<view class="inner">
  {{innerText}}
    <slot></slot>
</view>

在组件的 wxss文件中编写样式

注意:在组件wxss中不应使用ID选择器、属性选择器和标签名选择器。

myHeader.wxss

/* 这里的样式只应用于这个自定义组件 */
.inner {
  color: red;
}

11.1.3. 注册组件

在组件的 js 文件中,需要使用 Component() 来注册组件,并提供组件的属性定义、内部数据和自定义方法

myHeader.js

Component({
  properties: {
    // 这里定义了innerText属性,属性值可以在组件使用时指定
    innerText: {
      // 期望要的数据是 string类型
      type: String,
      value: 'default value',
    }
  },
  data: {
    // 这里是一些组件内部数据
    someData: {}
  },
  methods: {
    // 这里是一个自定义方法
    customMethod: function(){}
  }
})

11.2. 声明引入自定义组件

首先要在页面的 json 文件中进行引用声明。还要提供对应的组件名和组件路径

index.wxml

{
	// 引用声明
  "usingComponents": {
  	// 要使用的组件的名称     // 组件的路径
    "my-header":"/components/myHeader/myHeader"
  }
}

11.3. 页面中使用自定义组件

<view>
  <!-- 以下是对一个自定义组件的引用 -->
  <my-header inner-text="Some text">
    <view>用来替代slot的</view>
    </my-header>
</view>

11.4. 其他属性

11.5. 定义段与示例方法

Component构造器可用于定义组件,调用Component构造器时可以指定组件的属性、数据、方法等。

定义段类型是否必填描述
propertiesObject Map组件的对外属性,是属性名到属性设置的映射表,参见下文
dataObject组件的内部数据,和 properties 一同用于组件的模板渲染
observersObject组件数据字段监听器,用于监听 properties 和 data 的变化,参见 数据监听器
methodsObject组件的方法,包括事件响应函数和任意的自定义方法,关于事件响应函数的使用,参见 组件事件
createdFunction组件生命周期函数,在组件实例刚刚被创建时执行,注意此时不能调用 setData ,参见 组件生命周期
attachedFunction组件生命周期函数,在组件实例进入页面节点树时执行,参见 组件生命周期
readyFunction组件生命周期函数,在组件布局完成后执行,参见 组件生命周期
movedFunction组件生命周期函数,在组件实例被移动到节点树另一个位置时执行,参见 组件生命周期
detachedFunction组件生命周期函数,在组件实例被从页面节点树移除时执行,参见 组件生命周期

11.6. 组件-自定义组件传参

  1. 父组件通过属性的方式给子组件传递参数
  2. 子组件通过事件的方式向父组件传递参数

11.6.1. 过程

  1. 父组件 把数据 {{tabs}} 传递到 子组件的 tabItems 属性中
  2. **父组件 **监听 onMyTab 事件
  3. 子组件 触发 bindmytap 中的 mytap 事件
    1. 自定义组件触发事件时,需要使用 triggerEvent 方法,指定事件名detail对象
  4. 父 -> 子 动态传值 this.selectComponent("#tabs");

父组件代码

// page.wxml 

<tabs tabItems="{{tabs}}" bindmytap="onMyTab" >
  内容-这里可以放插槽
</tabs>

// page.js
  data: {
    tabs:[
      {name:"体验问题"},
      {name:"商品、商家投诉"}
    ]
  },
  onMyTab(e){
    console.log(e.detail);
  },

子组件代码

// com.wxml
<view class="tabs">
  <view class="tab_title"  >
    <block  wx:for="{{tabItems}}" wx:key="{{item}}">
      <view bindtap="handleItemActive" data-index="{{index}}">{{item.name}}</view>
    </block>
  </view>
  <view class="tab_content">
    <slot></slot>
  </view>
</view>

// com.js
Component({
  properties: {
    tabItems:{
      type:Array,
      value:[]
    }
  },
  /**
   * 组件的初始数据
   */
  data: {
  },

  /**
   * 组件的方法列表
   */
  methods: {
    handleItemActive(e){
      this.triggerEvent('mytap','haha');
    }
  }
})

11.7. 小结

  1. 标签名 是 中划线的方式
  2. 属性的方式 也是要中划线的方式
  3. 其他情况可以使用驼峰命名
    1. 组件的文件名如 myHeader.js 的等
    2. 组件内的要接收的属性名 如 innerText
  4. 更多。。

12. 小程序生命周期

分为应用生命周期页面生命周期

关于小程序前后台的定义和小程序的运行机制,请参考运行机制章节。

12.1. 应用生命周期

属性类型默认值必填说明
onLaunchfunction监听小程序初始化。
onShowfunction监听小程序启动或切前台。
onHidefunction监听小程序切后台。
onErrorfunction错误监听函数。
onPageNotFoundfunction页面不存在监听函数。

12.2. 页面生命周期

属性类型说明
dataObject页面的初始数据
onLoadfunction生命周期回调—监听页面加载
onShowfunction生命周期回调—监听页面显示
onReadyfunction生命周期回调—监听页面初次渲染完成
onHidefunction生命周期回调—监听页面隐藏
onUnloadfunction生命周期回调—监听页面卸载
onPullDownRefreshfunction监听用户下拉动作
onReachBottomfunction页面上拉触底事件的处理函数
onShareAppMessagefunction用户点击右上角转发
onPageScrollfunction页面滚动触发事件的处理函数
onResizefunction页面尺寸改变时触发,详见 响应显示区域变化
onTabItemTapfunction当前是 tab 页时,点击 tab 时触发

12.3. 页面生命周期图解

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值