微信小程序开发基础入门

微信小程序概念

微信小程序概述

运行在微信app内部的轻量级应用,无需安装,只需要有微信,在微信中下拉,即可使用。

大前端包括:浏览器中访问的页面(web页面),安装,iso的app,微信小程序,桌面端。

开发安卓,要java,开发iso要objectc,微信小程序开发用wxml,wxss,js,桌面端,用qt。

uni-app 有国人推出,使用html,css,js并且配合vue的语法,在uni-app平台上开发,就可以打包到 安卓,ios,微笑小程序,web端,可谓是一次开发,多端使用。

谷歌也有一个flutter,可以造成一处编译,就可以编译到is,安卓,桌面等多平台。

微信小程序账号注册

1.首先访问微信公众平台官网

2.其次注册账号的注意事项:

注册使用邮箱注册

未被微信公众平台注册

未被微信开发平台注册

未被个人微信号绑定过

如果被绑定了,需要解绑或使用其他邮箱

3.访问到官网页面后,点击右上角的立即注册,然后选择小程序,然后点击前往注册,然后按照要求填写账号信息,邮箱激活,信息登记。在信息登记中的主体类型这栏,由于学习阶段,所以选择个人就好,如果说要涉及到上线进行商业化,就要用到企业类型了,这就涉及到一些企业的各种资料了。

以上流程的信息都填好了,就算注册成功了。

微信小程序配置

注册完成之后,就可以进入到 微信小程序的后台管理页面了。

然后在后台管理页面中的小程序发布流程这一栏,依次配置好 小程序信息,小程序类名,小程序备案,以及微信认证。

小程序备案了才能发布上线。但是备案流程复杂,时间长,最快也要半个月。

微信小程序开发流程

小程序只是一个前端页面,需要后端来做支持。

前端页面需要些wxml 和wxss 和javascript。其中wxml就相当于html,wxss相当于css,注意,只是相当于。

扩展:支付宝的app需要用到java和xml。

前端会向后端发起http请求,来接受后端的响应。

微信小程序开发 需要用到微信小程序开发工具

微信开发,是先在本地开发,再上线到线上环境

​ 本地开发:需要微信开发工具,和 后端接口;

​ 线上开发:体验版只能选择几个人用,正式发布需要备案,所有人都可以用。都需要用到公网ip,将后端接口部署服务器上,可以选择阿里云,腾讯云之类的厂商。

微信小程序成员

微信小程序分为两种:

​ 项目成员:开发者,运营人员,数据分析人员

​ 体验成员:在微信中体验小程序

访问到微信小程序后端管理页面。选择左侧的菜单栏的管理选择,选择成员管理。在项目成员这一栏中,添加开发人员,最多添加15人,还有体验成员这一栏,可以添加体验成员的微信号,然后选择该体验成员的权限,确认添加即可。需要管理员的认证。

微信小程序的项目创建

创建项目流程

1.需要获取小程序id,在小程序后端,选择左侧的菜单栏,点击开发管理,开发设置中的AppID就是小程序的id了。

2.下载微信开发者工具,该工具必须联网才能使用。还是在后台管理页面,左侧菜单栏中,点击开发,开发工具,开发者工具,然后点击下载即可。也可以直接访问下载地址,微信开发者工具下载

选择稳定版,然后选择对应的系统下载即可。

创建项目

打开微信开发者工具,扫码登录。就进入到创建项目的页面了。

点击主页面的+号,开始创建项目,项目名称,项目目录,AppId,选择小程序开发模式,选择不使用云服务,不使用模板创建,然后点击创建,就可以创建一个项目了。

配置小程序支持http请求

在本地开发,假设用到的后端运行的地址是:0.0.0.0:8000地址

微信小程序才能通过ip地址访问到我们的后端项目的接口。

微信小程序默认不支持http,所以这里就需要配置了,让小程序支持http请求。

配置方式:在微信开发者工具的界面中,打开右上角的详情,然后点击本地设置,然后勾选不校验合法域名、web-view(业务域名)、TLS版本以及HTTPS证书

自此,微信小程序就支持了http请求。

项目目录结构

目录介绍

1.项目的主配置文件,在项目根路径下,控制整个项目的,主配置文件分别是:

app.js:小程序入口文件,小程序启动,会执行这个js文件

app.json: 小程序的全局配置,可以配置顶部的颜色,标题等

app.wxss:小程序的全局样式:所有样式,全局生效

其中 app.js 和app.json文件必须存在,没有不行。

2.页面文件

pages文件下,有许多文件,比如说indx,login,register等文件,而每个文件夹都有4个文件,分是是

xx.js:页面逻辑,js代码控制

xx.wxml:页面的结构,布局,采用xwml标签布局

xx.json:页面配置,当前页面顶部颜色,标题

xx.wxss:当前页面的样式,如果全局样式也有,以当前页面为准

其中xx跟文件夹同名。xx.js和xx.wxml文件必须存在。

3.其他文件

components:页面中会用到的组件,比如轮播图组件,按钮组件等,每个组件放一个文件夹,而每个文件也会有4个文件

pages:微信小程序有一个个页面,一个页面就是一个文件夹

.eslintrc.js:作用是做语法错误检测的,对于语法要求严格,一般不用。

project.config.json和 project.private.config.json:项目配置 等同于pycharm中的idea文件

sitemap.json:爬虫页面抓取相关,搜索优化。

以上的几个文件,一般开发阶段,不太需要触碰。

配置文件app.json

1.app.json文件是 小程序全局配置文件,用于配置小程序的一些全局属性和页面路由,以及默认标题,顶部颜色,是否有下拉刷新。

2.查看参考文档进行配置。

3.部分参数介绍

entryPagePath:小程序默认启动页面

pages:小程序总共有多个页面

window:全局默认窗口表现,顶部颜色,是否有下拉,它控制很多东西,这个经常用

页面配置xx.json

参考文档

xx.json文件 是小程序页面配置文件,也称局部配置文件,用于配置当前页面的窗口样式、页面标题等。虽然说app.json文件中的部分配置,也支持对单个页面进行配置,但是xx.json会替换到app.json文件中的部分配置。

常用的配置属性:

navigationBarBackgroundColor:导航栏背景颜色

navigationBarTextStyle:导航栏标题,状态栏颜色,仅支持black/white

navigationBarTitleText:导航栏标题文字内容

工程配置

参考文档

project.config.json 和 project.private.config.json:

小程序项目的配置文件,用于保存项目的一些配置信息和开发者的个人设置,其中project.private.config.json文件是项目的私有配置文件,此文件中的内容将覆盖project.config.json文件中的相同字段。

其中project.config.json文件与右侧的详情菜单中的本地设置是联动的。

SEO搜索相关配置

参考文档

通过sitemap.json的配置,可以方便被搜索引擎搜索到。

// sitemap.json文件
{
    "desc": "关于本文件的更多信息,请参考文档 https://developers.weixin.qq.com/miniprogram/dev/framework/sitemap.html",
    "rules": [{ // 允许微信爬取*页面,*表示所有页面
    "action": "allow",
    "page": "*"
    }]
}
// 这段配置,以后用户搜索小程序,任意页面有关键字,都会被搜索到

webview渲染

webview和skyline渲染模式

webview,老一点,比较稳定,支持老版本和新版本

skyline,新一点,不太稳定,不支持老版本

调成webview模式

修改app.json文件,删除以下配置代码

  "renderer": "skyline",
  "rendererOptions": {
    "skyline": {
      "defaultDisplayBlock": true,
      "disableABTest": true,
      "sdkVersionBegin": "3.0.0",
      "sdkVersionEnd": "15.255.255"
    }
  },
  "componentFramework": "glass-easel",

然后保存文件,就变成了webview模式。

新建页面

app.json中只有一个页面,需要后期增加页面。

增加方式一:

​ 1.在pages上右键》新建文件夹,名字就命名login把

​ 2.在新建的文件上右键》新建Page》输入login(与新建的文件夹同名) ,就发现多出4个文件,并且在app.json的page中会多一行"pages/login/login" 表示的是pages文件夹下的login文件夹下的四个文件。

增加方式二:

在app.json中,pages中,新增一行,就会自动创建文件夹页面

    "pages": [
        "pages/index/index",
        "pages/login/login",
        "pages/register/register" // 新增的一行
    ],

然后保存,就会发现,在pages文件夹中创建register文件,以及在该文件下创建以register为名的四个文件。

启动页面调整

小程序默认启动的页面是pages下的index下的index.xtml文件

修改小程序一启动,显示的页面:

方式一:

​ 在app.json文件中的pages修改顺序,第一个的配置页面会被默认启动。

    "pages": [
        "pages/index/index", // 默认启动第一行页面
        "pages/login/login",
        "pages/register/register"
    ],

如果想要默认启动register页面,就可以将"pages/register/register"提到最前面

    "pages": [
        // 将register页面放在最前面,默认启动页面
        "pages/register/register",
        "pages/index/index",
        "pages/login/login"
       
    ],

方式二:

通过entryPagePath属性配置。

在app.json文件中的第一行,但不要加到{}之外,添加以下配置:

{
    // 其中pages/index/index就是想要设置的启动页面
	"entryPagePath": "pages/index/index",
     // 省略以下代码
}

方式二用的比较多

方式三:

临时用,写了个页面,想要临时看一下,比如说想看login页面。

在微信开发者工具界面的中间部分,点击普通编译》添加编译模式》启动页面改成login页面的路径:pages/login/login 》点击确定,就可以看到页面,这种方式只是临时用。

调试小程序

调试小程序基础库

参考文档

微信小程序的基础库,一直不停的在做版本升级。

微信中的转发功能,发送朋友圈功能等都是在不同版本中加入的。

假设我们基于老版本的基础开发的,有的功能可能没有,在开发的时候,做功能如果发现写了没有效果,确认以下这个基础库是否支持这个功能。

右侧详情》本地设置》调整基础库:选择版本

调试窗口

在下半部分有个调试器

wxml显示页面布局的代码,console打印输出结果,Network表示网络请求,AppData存放着当前页面的变量,Storage存放着本地存储。

真机调试

在微信开发者工具的界面的中间部分,点击真机调试按钮,然后会提示手机扫描二维码,手机微信扫描之后,就会出现调试窗口。

纯净项目

把项目不要的东西都删除,只留核心做开发。

可以将 components文件夹删除,然后将pages/indx/index.json文件中以下代码删除

"navigation-bar": "/components/navigation-bar/navigation-bar"

然后在pages/index/index.wxml文件中将以下代码删除

<navigation-bar title="Weixin" back="{{false}}" color="black" background="#FFF"></navigation-bar>
<scroll-view class="scrollarea" scroll-y type="list">
</scroll-view>

然后将pages/indx/index.wxss中的内容可以清空。

然后可以将.eslintrc.js 文件也删除。

然后将app.wxss中的内容也清空。

然后将project.config.json 和 project.private.config.json和sitemap.json都删除。

然后在app.json文件中进行添加代码:

{
  "pages": [  
    "pages/index/index"
    
  ],
  "window": {
    "navigationBarTitleText": "顶部标题名字",   # 顶部标题
    "navigationBarBackgroundColor": "#0000FF", # 顶部颜色
    "enablePullDownRefresh": true,  # 是否带下拉刷新
    "backgroundColor": "#00FFFF",    # 下拉刷新颜色
    "backgroundTextStyle": "dark"    # light ,下拉刷新的点点什么颜色
  },
  "style": "v2",
}

app.wxss保持空

app.js文件中就一行代码

App({})

page/index文件中

// 1.index.js
Page({})

// 2.index.json 注意json文件不能有注释,这里的//只是解释说明用,不要真的在项目文件中写注释
	 {
          "usingComponents": {

          },
          "navigationBarTitleText": "登录页面", //当前页面名字
          "navigationBarBackgroundColor": "#FFFF00", // 当前页面顶部颜色
          "enablePullDownRefresh": true,    // 当前页面是否带刷新
          "backgroundTextStyle": "light"  // 当前页面刷新的点点点是什么颜色
        }

// 3.index.wxml
  <view class="container">
    index页面
   </view>
  </scroll-view>

// 4.index.wxss保持空

自此,以上配置就是纯净模式。

入门小程序

tabbar配置

在底部或在顶部的tab,几乎所有的小程序都会这个

设计tabbar

1.在app.json文件中配置,必须按照以下方式写:

"tabBar": {
    "selectedColor": "#b4282d", // 选中tabbar的颜色
    "position": "bottom", //tabbar的位置:顶部/底部
    // tabbar列表 只少包含两项
     "list": [
        {
            "pagePath": "pages/index/index", // tabbar链接的页面
            "text": "首页", // tabbar的文本
            "iconPath": "images/home.png",//未被选中的tabbar图标
            "selectedIconPath": "images/home_select.png" //被选中的tabbar图标
        },
        {
            "pagePath": "pages/my/my", 
            "text": "我的", 
            "iconPath": "images/my.png",
            "selectedIconPath": "images/my_select.png"
        }
    ]
},

完整的app.json文件案例

{
    "pages": [
      "pages/index/index",
      "pages/my/my"
    ],
    "window": {
        "navigationBarTitleText": "顶部标题",
        "navigationBarTextStyle": "black",
        "navigationBarBackgroundColor": "#FFFF00",
        "enablePullDownRefresh": true,
        "backgroundColor": "#00ffff",
        "backgroundTextStyle":"light"
    },
    "tabBar": {
      "selectedColor": "#b4282d", 
      "position": "bottom", 
       "list": [
          {
              "pagePath": "pages/index/index", 
              "text": "首页", 
              "iconPath": "images/home.png",
              "selectedIconPath": "images/home_select.png"
          },
          {
            "pagePath": "pages/my/my", 
            "text": "我的", 
            "iconPath": "images/my.png",
            "selectedIconPath": "images/my_select.png"
        }
      ]
  },

    "style": "v2",
    "sitemapLocation": "sitemap.json",
    "lazyCodeLoading": "requiredComponents"
}

小程序常用组件

参考文档

web版前端,用到的标签有 a标签,div标签,span标签,img标签等。而小程序没有这些标签,只有自己封装的组件。

部分组件介绍

text标签

text 等同于 span;表示不换行,放文字。

<text>我是首页</text>
<!-- 会发现以下文字都不换行,相当于span -->
<text>我是首页</text>
<text>我是首页1</text>
<text>我是首页2</text>

view标签

view等同于div;表示换行

<view>我是view</view>
<!-- 会发现以下文字换行,相当于div -->
<view>我是view</view>
<view>我是view2</view>
<view><text>view嵌套view</text></view>

image标签

image等同于img;展示图片

<image src="/images/b.jpg" mode=""/>

icon标签

type对应着不同的图标,这里只展示对勾和下载,其他样式可参考官方文档。

<icon type="success" color="red"></icon> <!-- 对勾图标 -->
<icon type="download" color="#ddd"></icon> <!-- 下载图标 -->

小程序开发核心

尺寸单位

在微信小程序中,尺寸单位统一用rpx

<view style="height:300rpx;width:750rpx;background-color: pink;"></view>

小程序中手机屏幕大小可能不一样,使用像素就会有问题,小程序中统一了,整个宽度就是750rpx,这样无论在什么手机上都能等比例缩放。

样式

全局样式

app.wxss 文件中写的是css样式。这里写的样式在整个小程序都生效。

案例

index.wxml

<view class="myview">我是个view</view>

app.wxss

/**app.wxss**/
.myview{
  height: 500rpx;
  width: 300rpx;
  background-color: aquamarine;
  font-size: 16rpx;
}

这样,局部页面就使用了全局样式,也就是其他页面也可以引入myview的class样式,能达到与index页面相同的效果。

局部样式

pages文件夹中的 xxx.wxss文件中写的也是css样式,这里的写样式只作用于当前页面。

案例

my.wxml

<!--pages/my/my.wxml-->
<text>个人中心</text>

<view class="myview"></view>

my.wxss

/* pages/my/my.wxss */
.myview{
  background-color: purple;
}

以上代码,my是局部组件,它使用全局样式(app.wxsss),并且在全局样式的基础上,重写或者说覆盖了background-color的样式。这样一来,my组件和index组件,除了背景色不一样,其他样式都一致。

按钮组件

按钮组件,button

<button>按钮</button>

button中的属性介绍

size:“”,表示尺寸样式

type: “” ,表示按钮的样式,比如default,warn,primary

plain ,表示镂空按钮(布尔类型)

如果一个属性是布尔类型,就不需要 属性='布尔值' ,直接写上就是默认true,不写就默认false。

<button size:"mini" type="default" plain>按钮</button>

也可以给button设置一些盒子样式,例如:

/* 标签选择器 */
button{
    /* 距离顶部300rpx */
	margin-top:300rpx;
    /* 距离底部30rpx */
	margin-botton:30rpx;
    /* 按钮本身就是有样式,如果想修改,记得添加!important */
    background-color:red !important;
}

轮播图组件

轮播图组件有 swiper 和 swiper-item 这两个组件来实现轮播图

案例

<!-- autoplay表示自动轮播 indicator-dots表示显示指示点 indicator-color表示指示点的颜色 interval="毫秒"表示自动轮播的间隔时间 circular表示衔接轮播-->

<!-- mode表示图片的裁剪属性,例如:mode="widthFix"表示图片自适应宽度 -->
<!-- 轮播图效果 -->
<swiper autoplay indicator-dots indicator-color="#00F00"
 interval="3000" circular>
  <swiper-item>
    <image src="/images/banner1.jpg" mode="widthFix"/>
  </swiper-item>
  <swiper-item>
    <image src="/images/banner2.png" mode="widthFix"/>
  </swiper-item>
  <swiper-item>
    <image src="/images/banner3.jpg" mode="widthFix"/>
  </swiper-item>
</swiper>

引入矢量图标库

这里介绍 使用阿里的矢量图标

1.登录成功后,搜索自己想要的图标,

2.然后点击图标上的购物车图标,然后点击右上角的购物车图标,然后添加至项目(没有项目就点击加入新项目),项目名称自定义,然后点击确定。然后会自动跳转到我的项目页面

3.然后选择Font class,然后点击项目设置选项,在弹出窗口中项目设置里勾选base64,点击保存。点击暂无代码,点此生成,会看到一段地址,访问该链接,会访问到代码,将代码复制下来

4.然后再项目里新建一个static文件夹,再在该目录下新建css文件夹,在/static/css/下新建一个文件font.wxss,将刚刚的代码粘贴进去,然后再app.wxss文件中写入:

@import "/static/css/font.wxss";

5.在我的项目页面中,复制图标下的图标名称,比如icon-anquan

6.在页面中引入阿里矢量图

<!-- icon-anquan是图标的名称 -->
<text class="iconfont icon-anquan"></text>

tips效果

<view class="tips">
    <!--  -->
    <!-- icon-anquan是图标的名称 -->
    <text class="iconfont icon-anquan"></text>
    <text>欢迎使用我们的系统,谢谢</text>
</view>
.tips{
    /* 背景色 */
    background-color:#f5eedf;
    /* 字大小 */
    font-size:40rpx;
    /* 字颜色 */
    color:#e9ab4a;
    /* 圆角效果 */
    border-radius:50rpx;
    /* 上右下左的距离 */
    margin:30rpx 10rpx 30rpx 10rpx;
    /*  */
    padding-left:20rpx;
}

flex布局

index.wxml

<view class="menu">
  <view class="item">
    <image src="/images/menu/ht.png" class="img" />
    <text class="title">物业合同</text>
  </view>
  <view class="item">
    <image src="/images/menu/wyf.png" class="img" />
    <text class="title">物业费</text>
  </view>
  <view class="item">
    <image src="/images/menu/wygl.png" class="img" />
    <text class="title">物业管理</text>
  </view>
  <view class="item">
    <image src="/images/menu/wylx.png" class="img" />
    <text class="title">物业维修</text>
  </view>
  <view class="item">
    <image src="/images/menu/ht.png" class="img" />
    <text class="title">物业合同</text>
  </view>
  <view class="item">
    <image src="/images/menu/wyf.png" class="img" />
    <text class="title">物业费</text>
  </view>
  <view class="item">
    <image src="/images/menu/wygl.png" class="img" />
    <text class="title">物业管理</text>
  </view>
  <view class="item">
    <image src="/images/menu/wylx.png" class="img" />
    <text class="title">物业维修</text>
  </view>
</view>

inedx.wxss

/* flex布局 */
.menu{
    display:flex;
    justify-content:space-between;
    padding:16rpx;
    border-radius:10rpx;
    /* 元素自动换行 */
    flex-wrap:wrap;
    background-color:powderblue;
}

.item{
    display:flex;
    flex-direction:column;
    justify-content:center;
    align-items:center;
    width:150rpx;
    height:200rpx;
    border:rgb(192,251,255) solid 1rpx;
    margin:1rpx;
    background-color:powderblue;
}

.img{
	width:88rpx;
    height:88rpx;
    border-radius:10rpx;
}

.title{
    margin-top:12rpx;
    font-size:24rpx;
}

通知布局

index.wxml

<view class="notice">
	<image src="/images/home/board.png" mode="aspectFit" style="width:200rpx;height:100rpx">
        <text>通知公告</text>
</view>

index.wxss

.notice{
    display:flex;
    justify-content:flex-start;
    margin-top:20rpx;
    margin-bottom:20rpx;
}
.notice > text{
    flex-grow:1;
    font-size:40rpx
}

底部布局

index.wxml

<view class="bottom">
    <view>
    	<image src="/images/home/cute_1.jpg" mode="scaleToFill" />
    </view>
    <view>
    	<image src="/images/home/cute_2.jpg" mode="scaleToFill" />
    </view>
    <view>
    	<image src="/images/home/cute_3.jpg" mode="scaleToFill" />
    </view>
    <view>
    	<image src="/images/home/cute_4.jpg" mode="scaleToFill" />
    </view>
</view>

index.wxss

.bottom{
    display:flex;
    justify-content:space-between;
    flex-wrap:wrap;
}
.bootm>view>image{
    width:345rpx;
    padding:10rpx;
    height:200rpx;
}

事件

事件绑定

按钮或者某些组件,点击会触发事件执行,比如打印数据,向后端发起请求。

bind:tap=“函数方法” :给组件添加点击事件

也可以bindtap=“” 这种写法

最简单的事件绑定案例

my.wxml

<view>====事件绑定====</view>
<button type="warn" plain size="mini" bind:tap="handleConsole">点击控制台打印</button>

my.js

// 所有代码,都要放在Page对象中
Page({
    handleConsole(){
      console.log('我被点了');  
    },
})

当打开my的页面,点击按钮,调试器中的Console就会打印:我被点了。

阻止事件冒泡

父组件套了子组件,子组件上有事件,父组件上也有事件,点击子组件,子组件的事件会触发,父组件的事件也会触发。为了防止这种现象发生,就要阻止事件冒泡。

使用catch:tap="方法名" 绑定点击事件 就可以阻止事件冒泡

my.wxml

<view style="height:400rpx;width:750rpx;background-color:pink; display:flex;justify-content:center;align-items:center;"  bind:tap="handleParent">
    <!-- 阻止事件冒泡:catch:tap="函数方法名" -->
    <button type="primary" plain catch:tap="handleChildren">按钮</button>
</view>

my.wxss

Page({
    handleParent(){
        console.log("父亲被点了");
    },
    handleChildren(){
        console.log("孩纸被点了");
    },
})

事件对象的传参

当绑定了事件后,函数都可以接受一个参数,事件对象(evnet)

在标签中添加属性:data-xxx=“数据”;

例如:

my.wxml

<!-- 传参方式一 -->
<view bind:tap="handleClick" data-id="1001" data-name="justin">点我</view>
<!-- 将data-xxx="" 传递给js中的event -->
<!-- 传参方式二 -->
<view bind:tap="handleClick" mark:name="justin1">点我</view>

my.js

event.currentTarget : 事件绑定者

event.target:事件触发者

一般情况下,上面这两个值是一样的,如果有事件冒泡,这两个值就不一样了

event.target.dataset: 获取标签传来的对象 data,里面有data-xxx的值 {id:1001,name:justin}

<!-- 获取参数方式一 -->
Page({
    handleClick(event){
        // event.currentTarget:事件绑定者
        // event.target:事件触发者
        // event.target.dataset 获取标签传来的对象 data,里面有data-xxx的值
        console.log(event.target.dataset.name);//获取data-name的值
    }
})
<!-- 获取参数方式二 -->
Page({
    handleClick(event){
        // event.mark.xxx 获取标签中mark:xxx传来的值
        console.log('event.mark.name');
    }
})

页面跳转

组件跳转

组件跳转又称为声明式导航

需要使用navigator组件,加属性来实现跳转

<navigator url="/pages/login/login">
	<view> type="primary" plain>跳转登录页面</view>
</navigator>

这样,当点击按钮,就会调转到login页面。

更多跳转方式

navigator标签中的open-type属性

navigate(默认):保留当前页面,跳转到应用内的某个页面。但是不能跳到 tabbar 页面
redirect: 关闭当前页面,跳转到应用内的某个页面。但不能跳转到 tabbar 页面
switchTab:跳转到 tabBar 页面,并关闭其他所有非 tabBar 页面
reLaunch:关闭所有页面,打开到应用内的某个页面
navigateBack:关闭当前页面,返回上一页面或多级页面

<!--  open-type="navigate"案例  -->
<navigator url="/pages/login/login" open-type="navigate">
  <button type="primary" plain="true">跳转到登录页面</button>
</navigator>
<!-- open-type="navigateBack":表示回退上一页 -->
<!-- delta="数字" 表示回退到前面第几个页面 -->
<navigator open-type="navigateBack">
    <button>回退</button>
</navigator>

跳转携带参数

url=“/pages/login/login?name=justin&age=19”

<navigator url="/pages/login/login?name=justin&age=19">
  <button type="primary" plain>携带参数的跳转</button>
</navigator>

跳转到的另一个页面获取 跳转来的数据,要在另一个页面的js文件中的onLoad(options){console.log("options")} 获取

js跳转

js跳转又称为编程式导航

有5个方法进行跳转

wx.navigateTo({

​ url:‘url’;

})

wx.redirectTo({

​ url:‘url’;

})

wx.switchTab({

​ url:‘url’;

})

wx.reLaunch({

​ url:‘url’;

})

wx.navigateBack({

​ url:‘url’;

})

js跳转案例

my.wxml

<button type="default"  bind:tap="handlenavigateTo">navigateTo</button>
<button type="warn" bind:tap="handleredirectTo">redirectTo</button>
<button type="primary" bind:tap="handleswitchTab">switchTab</button>
<button type="default" bind:tap="handlereLaunch">reLaunch</button>
<button type="warn" bind:tap="handlenavigateBack">navigateBack</button>

my.js

// 跳转的时候也可以携带参数
handlenavigateTo(){
    wx.navigateTo({
      url: '/pages/login/login?name=xxx&hobby=fly',
    })
  },
  handleredirectTo(){
    wx.redirectTo({
      url: '/pages/login/login',
    })
  },
  handleswitchTab(){
    wx.switchTab({
      url: '/pages/index/index',
    })
  },
  handlereLaunch(){
    wx.reLaunch({
      url: '/pages/login/login',
    })

  },
  handlenavigateBack(){
    // 关闭当前页面,返回上一页或上某一页,传入数字
    wx.navigateBack()
      
     wx.navigateBack({
      delta:2
    })
  },

wxml语法

模板语法

页面的js中定义一些变量,在wxml使用 {{js中的data中的变量}}。

注意:{{}} 中不能写js语句和js方法。

login.wxml

<view>
    <view>名字是:{{name}}</view>
    <view>年龄是:{{age}}</view>
    <view>爱好是:{{hobby}}</view>
</view>

<view>
    <view>对象数据类型显示</view>
    <view>名字是:{{userinfo.name}}</view>
    <view>年龄是:{{userinfo.gender}}</view>
    <view>爱好是:{{userinfo.age}}</view>
</view>

<view>
    <view>列表数据类型显示</view>
    <view>animals[0]</view>
    <view>animals[1]</view>
    <view>animals[2]</view>
</view>

<view>算术运算:{{99+1}}</view>
<view>三目运算符:{{num>999?"真":"假"}}</view>
<view>逻辑运算:{{num>999}}</view>

<!-- {{}} 中不能写js语句和js方法 -->

login.js

Page({
    // wxml中使用的变量,必须放在data中
    data:{
        name:'justin',
        age:99,
        hobby:'喝酒',
        userinfo:{
            name:'lyf',
            gender:'女',
            age:38
        },
        animals:['狗','猫','大象'],
        num:99
    }
})

数据更新

修改变量值

如果在js中,改了变量的值,想让页面也发生变化,需要使用this.setData({key: 变化后的值})

index.wxml

<view>姓名是:{{name}}</view>
<view>年龄是:{{age}}</view>
<button bind:tap="handleAddAge">点我年龄+1</button>

index.js

Page({
    data:{
        name:'justin',
        age:19
    },
    handleAddAge(){
        //1.取到data中的age
        console.log(this.data.age);//19
        this.data.age+=1;
        console.log(this.data.age);//20
        // 默认数据,不是响应式,js变化,页面不变
        // 2.想要页面也变化,借助微信提供的setData方法,也就是直接给数据赋值
        this.setData({
            age:this.data.age + 1;
        })
    }
})

修改对象

使用 this.setData({‘对象.属性’=属性值}) 修改data中对象的属性值

另一种方式:this.data.对象.属性 = 属性值

this.setData({

​ ‘对象.属性’ :this.data.对象.属性 = 属性值

})

index.js

Page({
    data:{
        name:'justin',
        age:19,
        userinfo:{name:'lqz',hobby:'烫头'}
    },
    handleChangeHobby(){
        // 修改对象中值
        this.setData({
            // 修改userinfo对象中的hobby属性
            'userinfo.hobby':'篮球'
        })
    }
})

index.wxml

<!-- 显示对象 -->
<view>{{userinfo.name}}</view>
<view>{{userinfo.hobby}}</view>
<button type="primary" bindtap="handleChangeHobby">变换爱好</button>

修改多个对象

思路:直接定义一个新的对象,将data中原有的对象,直接整个替换掉。

<!-- 显示对象 -->
<view>{{userinfo.name}}</view>
<view>{{userinfo.hobby}}</view>
<view>{{userinfo.age}}</view>
<button type="primary" bindtap="handleChangeHobby">变换爱好和增加年龄</button>
Page({
    data:{
        userinfo:{name:'lqz',hobby:'烫头'}
    },
    handleChangeHobby(){
        // 解压赋值
        const user = {...this.data.userinfo,age:19};
        // ..this.data.userinfo是解压赋值,后面的全都是替换对象原有的值
        // 简写:const userinfo = {...this.data.userinfo,age:19,hobby:'乒乓球'};
        this.setData({
            // 简写直接用:
            // userinfo
            userinfo:user
        })
    }
})

修改数组

思路:先把数组修改完,再用setData赋值

index.wxml

<!-- 循环数组打印名字 -->
<view wx:for="{{names}}" wx:key="{{index}}">{{item}}</view>
<button type="primary" bindtap="handleAddName">增加人名</button>

index.js

Page({
    data:{
        names:['lyf','dlrb','glnz','mezh']
    },
    handleAddName(){
        // 1.先追加,再setData
        // 增加亚瑟王
        this.data.names.push('亚瑟王');
        // 让页面数据变化
        this.setData({
            names:this.data.names
        })
        
        // 2.通过数组的拼接
        // concat不会在原数据上增加
        const newName = this.data.names.concat('甄姬');
        this.setData({
            names:newName
        })
        
        // 3.通过解构赋值
        const newName = [...this.data.names,'李白'];
        this.setData({
            names:newName
        })
        
        // 4.修改数组中的值
        // 修改方式:'数组[索引]' = '新值'
        this.setData({
            'names[0]': 'alyf'
        })
        
        // 5.删除数据中的值
        this.setData({
            // 删除数组中的第一个元素
            names:this.data.names.slice(1)
        })
    }
    
})

列表渲染

for循环

<view wx:for={{}} wx:key="index"> </view>

item只要循环数据,在循环里面,就会有两个值,一个是index,索引值,另一个是item,数组循环的值。

修改item: wx:for-item =‘info’

修改index: wx:for-index=‘i’

index.wxml

<!-- 列表渲染 -->
<view>循环显示商品信息</view>
<view wx:for="{{goodsList}}" wx:key="index">
    <text>商品id:{{item.id}}--商品名字:{{item.name}}--商品价格:{{item.price}}</text>
</view>

index.js

Page({
    data:{
         goodsList:[{id:1001,name:'钢笔',price:9},{id:1002,name:'铅笔',price:6},{id:1003,name:'脸盆',price:99}]
    }
})

条件渲染

if语句

wx:if wx:elif wx:else

<!-- if语句格式 -->
<view wx:if="{{}}"></view>
<view wx:elif="{{}}"></view>
<view wx:else></view>

index.wxml

<!-- 条件渲染 -->
<!-- model:变量名 表示双向数据绑定 -->
<input type="text" model:value="{{score}}" style="border:1rpx solid red;">
<view wx:elif="{{score>=90&&score<=100}}">优秀</view>
<view wx:elif="{{score>=80&&score<=90}}">良好</view>
<view wx:elif="{{score>=60&&score<=80}}">及格</view>
<view wx:else>不及格</view>

index.js

Page({
    data:{
        score:70
    }
})

扩展

<!-- wx:if 和 hidden 的区别 -->
wx:if 为false的时候,元素隐藏,但元素不占据位置
hiden 为false的时候,,元素隐藏,但元素会占据位置
<!-- 部分代码案例 -->
<view wx:if="{{false}}">元素</view>
<view hidden="{{false}}">元素</view>

网络请求

需要在微信小程序端,发送网络请求,获取数据,显示在小程序上。

注意:发送网络请求的域名,必须在微信公众平台配置。

微信访问后端地址,必须有域名,https的,需要在服务器域名中配置才能访问

配置方式

1.登录到微信小程序后端管理,

2.点击左侧菜单栏中的开发

3.然后在右侧的开发设置中,鼠标向下滑动,找到服务器域名

4.点击开始配置,然后扫描验证身份,在request合法域名对应的输入框中输入https://www/xxx/com (自己备案的域名),然后点击保存并提按钮。

当然了,以上方式是项目上线阶段。如果只是测试,只需要在微信开发者工具中的 详情》本地配置》勾选不校验合法域名、web-view(业务域名)、TLS版本以及HTTPS证书 即可。就可以本地接受和发送网络请求了。

具体案例

django后端部分代码

子应用的views.py

from django.http import JsonResponse
def index(request):
    return JsonResponse({"name":"pyy","hobby":"抽烟","age":38})

根目录下 urls.py

from 子应用.view import index
urlpatterns = [
	path('index/'index)
]

然后启动django程序。

微信小程序部分代码

index.wxml

<!-- 发送网络请求 -->
<view>用户名:{{user.name}}</view>
<view>爱好:{{user.hobby}}</view>
<view>年龄:{{user.age}}</view>
<button type="primary" bindtap="handleLoadUser">加载用户信息</button>

index.js

Page({
    data:{
        user:{}
    },
    handleLoadUser(){
        // 发送请求之前,展示loading效果
        wx.showLoading({
            title:'加载中~',
            mark:true,//显示透明蒙层,设置后,框后的按钮都不能点击了。
        })
        
        // 发起网路请求
        wx.request({
            url:'http://127.0.0.1:8000/index/',
            method:'GET',
            data:{},//如果是POST请求,这里就写请求参数,GET请求为空就好
            header:{},
            success:(res)=>{
                // 如果请求成功
                // 获取后端返回的数据 res.data
                console.log(res.data);
                // 渲染数据到页面
                this.setData({
                    user:res.data
                })
            },
            fail:(error)=>{
                // 如果请求失败
                console.log(error)
            },
            complete:(res)=>{
                // 请求无论是成功 还是失败都会走到这里
                // 关闭加载loading 必须手动关闭
                wx.hideLoading();
            }
        })
    }
})

显示电影案例

小程序端样式

my.wxml

<view class="item" wx:for="{{film_list}}" wx:key="*this">
	<image src="{{item.poster}}" mode="aspectFit" class="photo" />
    <view>
        <view class="name">{{item.name}}</view>
        <text>
        	<text class="grade">观众评分 </text>
            <text class="grade2">{{item.grade}} </text>
            <text class="label">
            	{{item.nation}} | {{item.runtime}} 分钟
            </text>
        </text>
    </view>
    
</view>

my.js

Page({
    data:{
        film_list:[]
    },
    /**
   * 生命周期函数--监听页面加载
   */
     // 当页面一进来,页面加载成功,就发送请求获取数据
    onLoad: function (options) {
        // 发送网络请求,加载数据
        wx.request({
            url:'http://127.0.0.1:8000/app01/films/',
            method:'GET',
            success:(res)=>{
                console.log(res.data);
                if(res.data.code==100){
                    // 后端返回的,赋值给film_list
                    this.setData({
                        film_list:res.data.results
                    })
                }
            }
        })
    }
})

my.wxss

page{
    background-color:pink;
}

.item{
    display:flex;
    flex-direction:row;
    justify-content:flex-start;
    margin:10rpx;
    background-color:#FFFFFF;
    border-radius:20rpx;
}

.photo{
    height:250rpx;
    width:200rpx;
    padding:5rpx;
}

.name{
    color:#191a1b;
    font-size:40rpx;
    height:22px;
    line-height:22px;
    margin-right:5px
    
}

.grade{
    font-size:30rpx;
    margin-top:4px;
    color:#797d82;
}

.grade2{
    color:#ffb232;
    font-size:30rpx;
}

.label{
    font-size:30rpx;
    margin-top:4px;
    color:#797d82;
}

django后端接口

film.json文件中的数据

{
    "code": 100,
    "msg": "ok",
    "results": [
            {
                "filmId": 6821,
                "name": "你想活出怎样的人生",
                "poster": "https://pic.maizuo.com/usr/movie/57116f984c95f7e0abe768550bd78ef9.jpg",
                "actors": [
                    {
                        "name": "宫崎骏",
                        "role": "导演",
                        "avatarAddress": "https://pic.maizuo.com/usr/movie/589bd0777f174e554b866cbc61145422.jpg"
                    },
                    {
                        "name": "山时聪真",
                        "role": "真人",
                        "avatarAddress": "https://pic.maizuo.com/usr/movie/ed862a087874582813cf62ff331be69d.jpg"
                    },
                    {
                        "name": "刘昊然",
                        "role": "真人(中文配音)",
                        "avatarAddress": "https://pic.maizuo.com/usr/movie/a7b242f9b8167e42c460d3b96d28a721.jpg"
                    },
                    {
                        "name": "菅田将晖",
                        "role": "苍鹭",
                        "avatarAddress": "https://pic.maizuo.com/usr/movie/06eae5dd0a6a705ae6eb1f2c625fc1e0.jpg"
                    },
                    {
                        "name": "大鹏",
                        "role": "苍鹭\u0026苍鹭男(中文配音)",
                        "avatarAddress": "https://pic.maizuo.com/usr/movie/3125ea2b699584e68cb3c3b9ae586217.png"
                    }
                ],
                "director": "宫崎骏",
                "category": "动画|奇幻|冒险",
                "synopsis": "电影讲述了少年牧真人的母亲葬身火海后,他随父亲与继母组成新家庭。深陷悲伤的真人阴郁孤僻,难以融入新环境。一次意外,他跟随一只会说话的苍鹭闯入废弃的神秘塔楼,却不料进入了奇幻的“亡灵世界”,开始了一场不可思议的冒险……",
                "filmType": {
                    "name": "2D",
                    "value": 1
                },
                "nation": "日本",
                "language": "",
                "videoId": "",
                "premiereAt": 1712102400,
                "timeType": 3,
                "runtime": 124,
                "grade": "7.4",
                "item": {
                    "name": "2D",
                    "type": 1
                },
                "isPresale": true,
                "isSale": false
            },
            {
                "filmId": 6753,
                "name": "哥斯拉大战金刚2:帝国崛起",
                "poster": "https://pic.maizuo.com/usr/movie/be17f0784f8a83fbe6be79df1ce1914b.jpg",
                "actors": [
                    {
                        "name": "亚当·温加德",
                        "role": "导演",
                        "avatarAddress": "https://pic.maizuo.com/usr/movie/de782ff4f69db74eb031ff33a035f8c8.jpg"
                    },
                    {
                        "name": "金刚",
                        "role": "演员",
                        "avatarAddress": "https://pic.maizuo.com/usr/movie/cab8709e5703861909485b45abae59c0.jpg"
                    },
                    {
                        "name": "哥斯拉",
                        "role": "演员",
                        "avatarAddress": "https://pic.maizuo.com/usr/movie/f7b2715cecfc4365ff749a5a9e6b025c.jpg"
                    },
                    {
                        "name": "丽贝卡·豪尔",
                        "role": " 艾琳 Ilene Andrews",
                        "avatarAddress": "https://pic.maizuo.com/usr/movie/467d85cafb939c0285ab69ae887fce84.jpg"
                    },
                    {
                        "name": "布莱恩·泰里·亨利",
                        "role": " 伯尼 Bernie Hayes",
                        "avatarAddress": "https://pic.maizuo.com/usr/movie/c10d99a613d070ce83c60e25d169cb64.jpg"
                    }
                ],
                "director": "亚当·温加德",
                "category": "动作|冒险|科幻",
                "synopsis": "继上一次的怪兽高燃对战之后,金刚和哥斯拉将再度联手对抗一个潜伏在世界中的巨大威胁,并逐步探索这些巨兽们的起源以及骷髅岛等地的奥秘。同时,上古之战的面纱也将会被揭晓,而正是那场战斗创造出了这些超凡的生物,并深刻影响了人类世界的命运。",
                "filmType": {
                    "name": "3D",
                    "value": 2
                },
                "nation": "美国",
                "language": "",
                "videoId": "",
                "premiereAt": 1711670400,
                "timeType": 3,
                "runtime": 115,
                "grade": "7.2",
                "item": {
                    "name": "3D",
                    "type": 2
                },
                "isPresale": true,
                "isSale": false
            },
            {
                "filmId": 6812,
                "name": "草木人间",
                "poster": "https://pic.maizuo.com/usr/movie/7a4e3daddbe3a35aa4247cb4ae6273cd.jpg",
                "actors": [
                    {
                        "name": "陈建斌",
                        "role": "老钱",
                        "avatarAddress": "https://pic.maizuo.com/usr/movie/7fc8f50b79675adaeb37a83833696652.jpg"
                    },
                    {
                        "name": "王佳佳",
                        "role": "万晴",
                        "avatarAddress": "https://pic.maizuo.com/usr/movie/655d3d188544bec01ebab82c5adaee3e.jpg"
                    },
                    {
                        "name": "顾晓刚",
                        "role": "导演",
                        "avatarAddress": "https://pic.maizuo.com/usr/movie/83acc483e3d165bf99083da374aaec20.jpg"
                    },
                    {
                        "name": "吴磊",
                        "role": "何目莲",
                        "avatarAddress": "https://pic.maizuo.com/usr/movie/42ab0462b8b3bc7c2203713320ab9c8e.jpg"
                    },
                    {
                        "name": "蒋勤勤",
                        "role": "吴苔花",
                        "avatarAddress": "https://pic.maizuo.com/usr/movie/529786e75f23f5d5b45ddf3f2d32c652.jpg"
                    }
                ],
                "director": "顾晓刚",
                "category": "剧情|犯罪",
                "synopsis": "丈夫何山凭空消失了十年后,苔花(蒋勤勤饰)正要迈进新生,但命运却把她推向了另一重绝境——她前脚被情人(陈建斌饰)母亲从采茶园赶走,后脚就被最亲近的好姐妹金兰骗进了传销组织“蝴蝶国际”。母亲沉迷其中,让一边寻父一边救母的儿子目莲(吴磊饰)身心疲惫,而蝴蝶国际却如藤蔓疯长一般,将恶魔的种子根植在无数百姓心中。苔花也摇身一变,从衣着打扮到言行举止都宛如“新生”,疯癫的举动让目莲感到诧异。母亲如蝴蝶一般翩翩于梦中之际,儿子想尽一切办法奋力解救……这座人间炼狱究竟该怎样逃脱?现代版“目连救母”能否成功?",
                "filmType": {
                    "name": "2D",
                    "value": 1
                },
                "nation": "中国大陆",
                "language": "",
                "videoId": "",
                "premiereAt": 1712102400,
                "timeType": 3,
                "runtime": 118,
                "grade": "7.7",
                "item": {
                    "name": "2D",
                    "type": 1
                },
                "isPresale": true,
                "isSale": false
            },
            {
                "filmId": 6801,
                "name": "白日之下",
                "poster": "https://pic.maizuo.com/usr/movie/11bf63b107d048357e8ca630fc39ae35.jpg",
                "actors": [
                    {
                        "name": "姜大卫",
                        "role": " 周健通(通伯)",
                        "avatarAddress": "https://pic.maizuo.com/usr/movie/542a5a0e25aed5c3bae6ea68f1d63600.jpg"
                    },
                    {
                        "name": "余香凝",
                        "role": " 凌晓琪",
                        "avatarAddress": "https://pic.maizuo.com/usr/movie/496d1fed33ad248efb3ceea0b408d0cf.jpeg"
                    },
                    {
                        "name": "林保怡",
                        "role": " 章剑华",
                        "avatarAddress": "https://pic.maizuo.com/usr/movie/4b1c4459cc5b00ec4588482ce997f3db.jpg"
                    },
                    {
                        "name": "梁仲恒",
                        "role": " 阿亮",
                        "avatarAddress": "https://pic.maizuo.com/usr/movie/8d0e65025c7e9a51caf5eeeb4d92b344.jpg"
                    },
                    {
                        "name": "简君晋",
                        "role": "导演",
                        "avatarAddress": "https://pic.maizuo.com/usr/movie/f6705ea1b27e72a8c93a06d7b2649153.jpg"
                    }
                ],
                "director": "简君晋",
                "category": "剧情|犯罪",
                "synopsis": "故事改编自真实事件,揭露隐藏在新闻背后、鲜为人知的残疾院舍真相。新闻社接获一宗有关残疾院舍“彩桥之家”虐待院友的线报,侦查小组为揭露残疾院舍监管问题,记者晓琪(余香凝 饰)潜入院舍,揭发内里的非人道生活,寻找日光之下的残酷真相。",
                "filmType": {
                    "name": "2D",
                    "value": 1
                },
                "nation": "中国香港",
                "language": "",
                "videoId": "",
                "premiereAt": 1712880000,
                "timeType": 3,
                "runtime": 106,
                "item": {
                    "name": "2D",
                    "type": 1
                },
                "isPresale": true,
                "isSale": false
            },
            {
                "filmId": 6816,
                "name": "黄雀在后!",
                "poster": "https://pic.maizuo.com/usr/movie/adc91ba9d7505d7352260f9d4a6fcff2.jpg",
                "actors": [
                    {
                        "name": "徐伟",
                        "role": "导演",
                        "avatarAddress": "https://pic.maizuo.com/usr/movie/b8566f83d0af556ec66e67fde7e91f89.jpg"
                    },
                    {
                        "name": "何文超",
                        "role": "导演",
                        "avatarAddress": "https://pic.maizuo.com/usr/movie/cafb44fa22a10eb809ace85b89291d3b.jpg"
                    },
                    {
                        "name": "冯绍峰",
                        "role": "演员",
                        "avatarAddress": "https://pic.maizuo.com/usr/movie/63cd6726f250c6788cc8d8f4caab1509.jpg"
                    },
                    {
                        "name": "陶虹",
                        "role": "演员",
                        "avatarAddress": "https://pic.maizuo.com/usr/movie/87e31cded6c44462755aa44eed9b0be2.jpg"
                    },
                    {
                        "name": "黄觉",
                        "role": "演员",
                        "avatarAddress": "https://pic.maizuo.com/usr/movie/793afc2b277346f51375d06f84d732ff.jpg"
                    }
                ],
                "director": "徐伟|何文超",
                "category": "犯罪|悬疑|剧情",
                "synopsis": "10年前的一个夏夜,警官袁文山(冯绍峰 饰)接到一起抢劫杀人案,在逐渐深入的调查过程中,当晚在场的嫌疑人们逐一浮出水面,然而案情的真相远非表面那般简单,三案并行,一场利益和正义的较量愈演愈烈,卷入其中的人们都是所图为何?究竟是情法之争,还是欲望驱使?在案件稍有眉目之时,袁文山却发现了一个被自己忽略的重要线索... ...",
                "filmType": {
                    "name": "2D",
                    "value": 1
                },
                "nation": "中国大陆",
                "language": "",
                "videoId": "",
                "premiereAt": 1712102400,
                "timeType": 3,
                "runtime": 99,
                "grade": "7.6",
                "item": {
                    "name": "2D",
                    "type": 1
                },
                "isPresale": true,
                "isSale": false
            },
            {
                "filmId": 6795,
                "name": "功夫熊猫4",
                "poster": "https://pic.maizuo.com/usr/movie/89d7a3bbd98d0ffab74da50cd03641e2.jpg",
                "actors": [
                    {
                        "name": "迈克·米歇尔",
                        "role": "导演",
                        "avatarAddress": "https://pic.maizuo.com/usr/movie/9f40bb3aaf9ef967b67b4bc3123a03e8.jpg"
                    },
                    {
                        "name": "杰克·布莱克",
                        "role": "阿宝 Po",
                        "avatarAddress": "https://pic.maizuo.com/usr/movie/0e4b06db0fb7f08fd309cf872b994cce.jpg"
                    },
                    {
                        "name": "黄渤",
                        "role": "阿宝 Po(中文配音)",
                        "avatarAddress": "https://pic.maizuo.com/usr/movie/f2a4a18bf8cf420b09c0a19d20a4a0fc.jpg"
                    },
                    {
                        "name": "奥卡菲娜",
                        "role": "小真 Zhen",
                        "avatarAddress": "https://pic.maizuo.com/usr/movie/1b7f719c81114df25dc2688ea39f6e18.jpeg"
                    },
                    {
                        "name": "关继威",
                        "role": "Han",
                        "avatarAddress": "https://pic.maizuo.com/usr/movie/b008f921bda277caae91823cffb4a4e6.jpg"
                    }
                ],
                "director": "迈克·米歇尔",
                "category": "动画|动作|冒险",
                "synopsis": "爷青回!《功夫熊猫》新作来袭!阿宝“升职”同时,新仇旧敌集结现身,大龙竟起死回生?狐狸小真身份神秘,到底有何心机?阿宝被师傅要求选出下一任神龙大侠,正苦恼如何应对时,阿宝昔日的手下败将们却纷纷重出江湖!身世神秘的狐狸小真告诉阿宝,这一切的幕后黑手正是邪恶女巫魅影妖后!阿宝能否打败魅影妖后,昔日敌人又为何再次现身?这次又会发生怎样的搞笑趣事?赶快带上亲朋好友,一起到影院寻找真相吧~",
                "filmType": {
                    "name": "3D",
                    "value": 2
                },
                "nation": "美国",
                "language": "",
                "videoId": "",
                "premiereAt": 1711065600,
                "timeType": 3,
                "runtime": 94,
                "grade": "7.3",
                "item": {
                    "name": "3D",
                    "type": 2
                },
                "isPresale": true,
                "isSale": false
            },
            {
                "filmId": 6834,
                "name": "来自汪星的你",
                "poster": "https://pic.maizuo.com/usr/movie/4de0b4ddb98abe9fa45d6b31da07cb53.jpg",
                "actors": [
                    {
                        "name": "陆可",
                        "role": "导演",
                        "avatarAddress": "https://pic.maizuo.com/usr/movie/edf5c22c4394c5b2844d241ddb95378d.jpg"
                    },
                    {
                        "name": "郭富城",
                        "role": "江斯旺",
                        "avatarAddress": "https://pic.maizuo.com/usr/movie/bcb5b34461bff36771f7f7201090f057.jpg"
                    },
                    {
                        "name": "蓝盈莹",
                        "role": "江露",
                        "avatarAddress": "https://pic.maizuo.com/usr/movie/8fbfa4d3e0b988f796220f545dd0c683.jpg"
                    },
                    {
                        "name": "黄龄",
                        "role": "C姐",
                        "avatarAddress": "https://pic.maizuo.com/usr/movie/cab1fa62536f8bb52e38904f40a3bd74.jpg"
                    },
                    {
                        "name": "王大陆",
                        "role": "秦天",
                        "avatarAddress": "https://pic.maizuo.com/usr/movie/1d416e6ceb5529dc890c91236231e227.jpg"
                    }
                ],
                "director": "陆可",
                "category": "奇幻|喜剧|家庭",
                "synopsis": "糖厂工人江斯旺(郭富城 饰)独自抚养女儿江露(蓝盈莹 饰)成长,不料在阴差阳错中变成一条小狗。狗爸阿旺费尽力气找到女儿,发现此时江露已长大成人,并成为了一位创作歌手,但看似光鲜亮丽的背后却另有隐情。老爸决定以小狗阿旺的身份开启一段“守护之旅”……",
                "filmType": {
                    "name": "2D",
                    "value": 1
                },
                "nation": "中国大陆",
                "language": "",
                "videoId": "",
                "premiereAt": 1712880000,
                "timeType": 3,
                "runtime": 105,
                "item": {
                    "name": "2D",
                    "type": 1
                },
                "isPresale": true,
                "isSale": false
            },
            {
                "filmId": 6767,
                "name": "我们一起摇太阳",
                "poster": "https://pic.maizuo.com/usr/movie/a8ecf5fcbeeddb7488876f042bf7baa4.jpg",
                "actors": [
                    {
                        "name": "彭昱畅",
                        "role": "吕途",
                        "avatarAddress": "https://pic.maizuo.com/usr/movie/91590c0fb4e9e895503796203ed14489.jpg"
                    },
                    {
                        "name": "李庚希",
                        "role": "凌敏",
                        "avatarAddress": "https://pic.maizuo.com/usr/movie/e0d8d70d6a267dc4563806bc4b522b7b.jpg"
                    },
                    {
                        "name": "韩延",
                        "role": "导演",
                        "avatarAddress": "https://pic.maizuo.com/usr/movie/cfa40371868495071b1c97b72c55ab8f.jpg"
                    },
                    {
                        "name": "徐帆",
                        "role": "陶怡",
                        "avatarAddress": "https://pic.maizuo.com/usr/movie/4bc8d78d21b4e6c6eeeeedc143ca5b83.jpg"
                    },
                    {
                        "name": "高亚麟",
                        "role": "凌父",
                        "avatarAddress": "https://pic.maizuo.com/usr/movie/28c233165445e3079756d3c52f8cbb83.jpg"
                    }
                ],
                "director": "韩延",
                "category": "爱情|剧情|家庭",
                "synopsis": "春节档温暖现实主义题材电影,挥别旧年的阴霾,迎接新年的爱与阳光!韩延导演“生命三部曲”终章,当“没头脑”吕途遇上“不高兴”凌敏,两个身患重症却性格迥异的年轻人,因为“生命接力”的约定,阴差阳错地踏上了一段充满爱与力量的治愈之旅。",
                "filmType": {
                    "name": "2D",
                    "value": 1
                },
                "nation": "中国大陆",
                "language": "",
                "videoId": "",
                "premiereAt": 1707523200,
                "timeType": 3,
                "runtime": 129,
                "grade": "7.9",
                "item": {
                    "name": "2D",
                    "type": 1
                },
                "isPresale": true,
                "isSale": false
            },
            {
                "filmId": 6786,
                "name": "坠落的审判",
                "poster": "https://pic.maizuo.com/usr/movie/a1cfca3e8ac6d12ac07cdbd9fc7a0697.jpg",
                "actors": [
                    {
                        "name": "茹斯汀·特里耶",
                        "role": "导演",
                        "avatarAddress": "https://pic.maizuo.com/usr/movie/69178dbbc98aee3ab2fa12a4f21952c1.jpg"
                    },
                    {
                        "name": "桑德拉·惠勒",
                        "role": " Sandra Voyter",
                        "avatarAddress": "https://pic.maizuo.com/usr/movie/38c134c4bdac10d2d8dcf10c059cfd1f.jpg"
                    },
                    {
                        "name": "斯万·阿劳德",
                        "role": " Maître Vincent Renzi",
                        "avatarAddress": "https://pic.maizuo.com/usr/movie/dbfdb35a687980af2e6591931e363f16.jpg"
                    },
                    {
                        "name": "安托万·赖纳茨",
                        "role": " L'avocat général",
                        "avatarAddress": "https://pic.maizuo.com/usr/movie/08405bf7416d13af4aeea42e01b94e4b.jpg"
                    },
                    {
                        "name": "萨穆埃尔·泰斯",
                        "role": " Samuel Maleski",
                        "avatarAddress": "https://pic.maizuo.com/usr/movie/644bd98b7a230279f393f2e3a8ed09cf.jpg"
                    }
                ],
                "director": "茹斯汀·特里耶",
                "category": "剧情|家庭",
                "synopsis": "2023戛纳金棕榈最佳影片!2024奥斯卡最佳原创剧本大奖!狂揽全球280+项大奖及提名!继是枝裕和的《小偷家族》后,时隔六年,再度登陆内地大银幕的金棕榈最佳影片!国内外各大平台口碑爆棚,影片以女性视角细腻地呈现了夫妻关系中的隐痛,丈夫的死亡真相唤起观众对亲密关系的深入思考和共鸣,没有谁的生活经得起这样的审判!但人性中不肯投降的、微弱的美好和希望,最终将指引着每个人继续前行!3月29日,大银幕探寻家庭与婚姻的真相!",
                "filmType": {
                    "name": "2D",
                    "value": 1
                },
                "nation": "法国",
                "language": "",
                "videoId": "",
                "premiereAt": 1711670400,
                "timeType": 3,
                "runtime": 152,
                "grade": "7.5",
                "item": {
                    "name": "2D",
                    "type": 1
                },
                "isPresale": true,
                "isSale": false
            },
            {
                "filmId": 6756,
                "name": "沙丘2",
                "poster": "https://pic.maizuo.com/usr/movie/ed94ed416641c374e55e16162692019c.jpg",
                "actors": [
                    {
                        "name": "丹尼斯·维伦纽瓦",
                        "role": "导演",
                        "avatarAddress": "https://pic.maizuo.com/usr/movie/967cff2206d0325dfaa865fb613224a5.jpg"
                    },
                    {
                        "name": "提莫西·查拉梅",
                        "role": "保罗",
                        "avatarAddress": "https://pic.maizuo.com/usr/movie/5697b464e40ed22bec1a9e1952d3adb9.jpg"
                    },
                    {
                        "name": "赞达亚·科尔曼",
                        "role": "契妮",
                        "avatarAddress": "https://pic.maizuo.com/usr/movie/0599bb29ab6f328cce7a0ff7d6cb4f1b.jpg"
                    },
                    {
                        "name": "丽贝卡·弗格森",
                        "role": "杰西卡夫人",
                        "avatarAddress": "https://pic.maizuo.com/usr/movie/d5fa927d7101db694815d4b60fad0926.jpg"
                    },
                    {
                        "name": "乔什·布洛林",
                        "role": "哥尼",
                        "avatarAddress": "https://pic.maizuo.com/usr/movie/1d90154f6fb5ad98a6c5497184e50526.jpg"
                    }
                ],
                "director": "丹尼斯·维伦纽瓦",
                "category": "科幻|动作|冒险|剧情",
                "synopsis": "《沙丘2》将会探索保罗·厄崔迪的传奇之旅,他与契妮和弗雷曼人联手,踏上对致其家毁人亡的阴谋者的复仇之路。当面对一生挚爱和已知宇宙命运之间的抉择时,他必须努力阻止只有他能预见的可怕的未来。",
                "filmType": {
                    "name": "4D",
                    "value": 13
                },
                "nation": "美国,加拿大",
                "language": "",
                "videoId": "",
                "premiereAt": 1709856000,
                "timeType": 3,
                "runtime": 166,
                "grade": "7.2",
                "item": {
                    "name": "4D",
                    "type": 13
                },
                "isPresale": true,
                "isSale": false
            }
        ]

}

1.创建django项目 wx_backend

2.创建app文件夹,在该文件夹下创建子应用app01

3.路由分发,app01下的urls.py

4.总路由分发

urlpatterns =  [
	# ...省略以上代码
	path('app01/',include('app01.urls')),
]

5.app01包下的urls.py

from django.urls import path,include
form .views import films
urlpatterns = [
	path('films/',films),
]

6.视图函数

import json 
from django.http import JsonResponse
def films(request):
    with open('./film.json','r',encoding="utf-8") as f:
        res_dic = json.load(f)
        return JsonResponse(res_dic,safe=False)

7.前端访问:http://127.0.0.1:8000/app01/films/ 就可以看到json数据。

对话框

模态框

index.wxml

<button type="primary" plain bind:tap="handleShowModel">点我弹出模态框</button>

index.js

Page({
    data:{
        
    },
    handleShowModel(){
        wx.showModal({
            title:'您确定要xx吗',
            content:'这里是内容部分',
            complete:(res)=>{
                if(res.cancel){
                    // 用户取消操作
                    console.log('用户取消了');
                }
                if(res.confirm){
                    // 用户确认操作
                    console.log('用户确认了');
                }
            }
        })
    }
})

消息对话框

index.wxml

<button type="primary" plain bind:tap="handleShowTost">点我弹出消息对话框</button>

index.js

Page({
    handleShowTost(){
        wx.showToast({
            title:'恭喜你,秒杀成功',
            icon:'success', // 也可以eroor
            duration:2000,// 2000毫秒之后消失
        })
    }
})

本地存储

比如说登录成功,后端返回token串[用户登录信息],把token存到小程序端,后续发送请求,要携带token,后端才能校验通过。

小程序端本地如何存储数据

index.wxml

<button type="default" plain bind:tap="handleSave">存储数据</button>
<button type="primary" plain bind:tap="handleGet">获取数据</button>
<button type="default" plain bind:tap="handleDelete">删除数据</button>
<button type="primary" plain bind:tap="handleClear">清空数据</button>

index.js

Page({
    // 后期可以使用同步或异步,但是感官上差不多,但是写法不一样
    // 同步保存
    handleSave(){
        wx.setStorageSync('name','justin')
        wx.setStorageSync('age',19)
        // 微信小程序,直接存对象即可,最终它被转成json格式字符串存到 本地存储中
        wx.setStorageSync('wife',{name:'lyf',age:'37',hobby:'高尔夫'})
    },
    handleGet(){
        // 获取本地存储
        const name = wx.getStorageSync("name")
        const age = wx.getStorageSync("age")
        const wife = wx.getStorageSync("wife")
        console.log(name)
        console.log(age)
        console.log(wife)
    },
    handleDelete(){
        // 清除微信缓存或者删除小程序或者用代码删除
        wx.removeStorageSync('wife')
    },
    handleClear(){
        // 清空本地存储
        wx.clearStorageSync()
    }
})
Page({
    // 异步保存
    handleSave(){
        wx.setStorage({
            // 必须是key和data
            key:'name',
            data:'lqz'
        })
        wx.setStorage({
            key:'boyfirend',
            data:{name:'pyy',age:67}
        })
    },
    // 异步获取,函数定义成async 内部获取的时候,前面写await
    async handleGet(){
        // 获取
        const boyfriend = await wx.getStorage({key:'boyfirend'})
        console.log(boyfriend.data)
        
    },
    handleDelete(){
        // 删除
        wx.removeStorage({
            key:'name'
        })
    },
    handleClear(){
        // 清空
        wx.clearStorage()
    }
})

上拉下拉加载

上拉加载更多

goods.wxml

<view wx:for="{{good_list}}" wx:key:'*this'>{{item}}</view>

goods.js

onReachBottom(){} 是固定内置函数,必须这么写

Page({
    data:{
        good_list:[1,2,3]
    },
    // (配合goods.json中的配置)当滑动到底部还有50rpx时,就会触发整个函数执行
    // 可以发送请求获取数据
    onReachBottom(){
        // console.log('上拉了')
        wx.request({
            url:"http://127.0.0.1:8000/app01/random/",
            method:"GET",
            success:(res)=>{
                this.setData({
                    good_list:this.data.good_list.concat(res.data)
                })
            }
        })
        
    }
})

goods.wxss

view{
    height:400rpx;
    dispaly:flex;
    justify-content:center;
    align-items:center;
}

// 奇数背景色是粉色
view:nth-child(odd){
    background-color:pink;
}

// 偶数背景色绿色
view:nth-child(even){
    background-color:rgb(17,133,88);
}

goods.json

“onReachBottomDistance”:50 表示当页面距离底部50rpx的时候,触发js文件中的onReachBottom函数

{
    "usingComponents":{},
    "onReachBottomDistance":50,
}

后端接口

子应用的urls.py

from django.urls import path
from .views import random_view
urlpatterns =[
    path('random/',random_view)
]

子应用的views.py

import json 
from django.http import JsonResponse
def random_view(request):
    l = []
    for i in range(3):
        l.append(random.randint(0.99999))
    return JsonResponse(l,safe=False) #返回json格式,如果里面有列表,必须加safe=False

下拉刷新

goods.json

“enablePullDownRefresh”:true 表示开启下拉刷新

“backgroundColor”:“#efefef” 表示下拉刷新的背景颜色

“backgroundTextStyle”:“dark” 表示下拉刷新的小白点

{
    "usingComponents":{},
    "enablePullDownRefresh":true,
    "backgroundColor":"#efefef",
    "backgroundTextStyle":"dark"
}

goods.wxml

<view wx:for="{{good_list}}" wx:key:'*this'>{{item}}</view>

goods.js

onPullDownRefresh(){} 表示下拉刷新,是内置函数,必须这样写

Page({
    data:{
        good_list:[1,2,3]
    }
    
    // 下拉刷新
    onPullDownRefresh(){
    	// ......下拉刷新之后要做的事情.......
    	console.log('下拉了,刷新')
    	// 只要下拉,把数据恢复
    	this.setData({
            good_list:[1,2,3]
        })
    	// 下拉刷新后.loading效果回弹
    	if(this.data.good_list.length==3){
            wx.stopPullDownRefresh();
        }
	}
	
	
})

scroll-view实现上拉下拉

<scroll-view></scroll-view> 标签,使用该标签,必须要给该标签设置css样式:height:100vh;

该标签内的属性介绍:

scroll-y: 允许上下滑动

lower-threshold=“50” :距离底部50rpx的时候,触发滑动

bindscrolltolower=“handleGetData” :给滑动绑定事件处理函数


refresher-enabled=“true” 表示开启上拉

refresher-default-style=“black” 表示上拉刷新的颜色

refresher-background=“#f0f0f0” 表示上拉刷新的背景颜色

bindrefresherrefresh = “handleReloadData” 表示给上拉操作绑定事件处理函数

refresher-triggered=“{{isRefresh}}” 配合在js中的data定义isRefresh:false 以及在 下拉操作的方法最后设置this.setData({isRefresh:false}) 来实现下拉回弹


enable-back-to-top=“true” 表示: 在真机上,快速双击顶部标题,立即回到最顶上

goods2.wxml

<scroll-view class="scroll" scroll-y lower-threshold="50" bindscrolltolower="handleGetData" refresher-enabled="true" refresher-default-style="black" refresher-background="#f0f0f0" bindrefresherrefresh = "handleReloadData">
    <view wx:for="{{good_list}}" wx:key:'*this'>{{item}}</view>
</scroll-view>

goods2.js

Page({
    data:{
        good_list:[1,2,3],
        isRefresh:false
    },
    // 
    handleGetData(){
        // 上拉 的事件处理逻辑
        console.log('上拉了');
        wx.request({
            url:"http://127.0.0.1:8000/app01/random/",
            method:"GET",
            success:(res)=>{
                this.setData({
                    good_list:this.data.good_list.concat(res.data)
                })
            }
        })
    },
    // 下拉的操作
    handleReloadData(){
        Wx.showToast({
            title:'下拉刷新了'
        })
        this.setData({
            good_list:[1,2,3]
        })
        //隐藏掉下拉刷新
        this.setData({
            isRefresh:false
        })
    }
})

goods2.wxss

.scroll{
    /* 100vh就是指元素的高度等于当前浏览器的视窗高度,即浏览器内部的可视区域的高度大小 */
    height:100vh;
    background-color:gray;
}

view{
    height:400rpx;
    dispaly:flex;
    justify-content:center;
    align-items:center;
}

// 奇数背景色是粉色
view:nth-child(odd){
    background-color:pink;
}

// 偶数背景色绿色
view:nth-child(even){
    background-color:rgb(17,133,88);
}

小程序强制更新

后续我们代码更新了,如果我们在微信端使用过小程序,微信会把小程序代码拉到微信本地,下次打开,会优先使用本地的代码,咱们代码更新了,需要强制更新到我们最新的代码

在app.js 加入如下代码,即可实现强制更新

App({
  // 生命周期函数,启动小程序就会执行
  onLaunch(){
    const update=wx.getUpdateManager()
    update.onUpdateReady(function(){
      wx.showModal({
        title: '发现新版本',
        content: '重启应用,更新版本新版本?',
        success:(res)=>{
          if(res.confirm){
            update.applyUpdate()
          }
        }
      })
    })
  }
})

小程序的生命周期

整个应用的生命周期

app.js

// app.js
App({

  /**
   * 当小程序初始化完成时,会触发 onLaunch(全局只触发一次)
   */
  onLaunch: function () {
    console.log('小程序启动了')
    
  },

  /**
   * 当小程序启动,或从后台进入前台显示,会触发 onShow
   */
  onShow: function (options) {
    console.log('后台切前台了')
  },

  /**
   * 当小程序从前台进入后台,会触发 onHide
   */
  onHide: function () {
    console.log('进后台了')
  },

})

某个页面的生命周期

index.js

Page({

  /**
   * 生命周期函数--监听页面加载
   */
  onLoad(options) {
    console.log('1 页面加载了')

  },

  /**
   * 生命周期函数--监听页面初次渲染完成
   */
  onReady() {
    console.log('3 初次渲染完成')
  },

  /**
   * 生命周期函数--监听页面显示
   */
  onShow() {
    console.log('2 页面显示')
  },

  /**
   * 生命周期函数--监听页面隐藏
   */
  onHide() {
    console.log('4 页面隐藏')
  },

  /**
   * 生命周期函数--监听页面卸载
   */
  onUnload() {
    console.log('5 页面卸载')
  },


})

分享到朋友圈

假设想要将my页面分享到朋友圈

my.js

Page({
    // 允许分享到朋友圈 onShareTimeline(){}固定内置函数
    onShareTimeline(){
        return {
            title:'这是一个神奇的页面',
            query:'name=justin&age=19',//带参数访问过来
            inageUrl="/images/b.jpg"
        }
    }
})
Page({
    // 允许分享到朋友 onShareAppMessage(){}固定内置函数
    onShareAppMessage(){
        return {
            title:'是朋友就帮我点一下',
            path:'/pages/my/my.json',//带参数访问过来
            imageUrl:'/images/b.jpg'
        }
    }
})

另外一种转发方式

<button open-type="share">转发</button>

获取头像

index.wxml

open-type="chooseAvatar 固定属性写法

bindchooseavatar=“choosePhoto” :绑定获取头像事件

<!-- 获取用户头像 -->
<button class="btn" open-type="chooseAvatar" bindchooseavatar="choosePhoto">
	<image src="{{photo}}" class="photo" />
</button>

index.js

Page({
    data:{
        photo:'/images/b.jpg'
    },
    // 获取头像
    choosePhoto(event){
        console.log(event);
        this.setData({
            photo:event.detail.avatarUrl
        })
        // 同时要把图片传到后端保存
    }
})

index.wxss

.btn{
    background-color:transparent;
}
.btn:after{
    border:none;
}
.photo{
    height:250rpx;
    width:250rpx;
    border-radius:50%
}

获取昵称

index.wxml

<!-- 获取昵称 -->
<!-- type必须是nickname -->
<input type="nickname" placeholder="输入或获取昵称" model:value="{{username}}" />
<button type="primary" plain bind:tap="showName">提交</button>

index.js

Page({
    data:{
      username:""  
    },
    // 获取用户名
    showName(){
        // 获取输入框中的值
        console.log(this.data.username)
    }
})

index.wxss

input{
    border:1rpx solid pink;
    border-radius:10rpx;
    padding:10rpx;
    margin:10rpx;
}

获取手机号

快速登录,需要前后端配合,前端配合获取手机号带着code到后端,后端实现注册+登录接口,后端通过code去微信开发平台换取真正的手机号。后端检测用户表,这个用户有没有注册过,如果注册过,直接签发token登录成功,如果没有注册过,先注册,再签发token登录成功。

获取手机号,有两种方式。

手机号快速验证

就是小程序登录界面 有手机号快速登录的按钮

手机号实时验证

给用户手机发送验证码,输入验证码后,才能获取到手机号码

# 前提
# 1 手机号接口,必须是非个人开发者,并且完成了认证的小程序
# 2 两种验证方式需要付费使用,每个小程序账号有1000次体验额度

# 3 小程序端
# https://developers.weixin.qq.com/miniprogram/dev/framework/open-ability/getPhoneNumber.html

代码案例

快速获取手机号,必须添加这两个属性:open-type="getPhoneNumber"bindgetphonenumber="getPhoneNumber"

实时获取手机号,必须添加这两个属性:open-type="getRealtimePhoneNumber"bindgetrealtimephonenumber="getRealPhoneNumber"

index.wxml

<button  type="warn" open-type="getPhoneNumber" 
bindgetphonenumber="getPhoneNumber">快速手机号</button>
<button  type="default" plain open-type="getRealtimePhoneNumber"
bindgetrealtimephonenumber="getRealPhoneNumber"
>实时手机号</button>

index.js

Page({
    getPhoneNumber(event){
        console.log(event.detail.code);
        wx.request({
            url:'后端地址',
            method:'POST',
            data:{
                code:event.detail.code
            }
        })
    },
    getRealPhoneNumber(event){
        console.log(event);
    }
})

客服功能

微信为小程序提供客服消息能力,以便小程序用户可以方便快捷地与小程序服务提供方进行沟通
https://developers.weixin.qq.com/miniprogram/introduction/custom.html

先在微信小程序的后台,添加客服人员

index.wxml

<!-- 客服 -->
<button type="default" plain open-type="contact">联系客服</button>

当用户点击该按钮,并且发送信息,微信小程序的后台的客服管理界面就会收到用户的信息,并且可以回复。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值