微信小程序

微信开放者平台和微信公众号平台区别

开放平台:

  • 是微信对外开放API接口的平台
  • 开放的API接口,供第三方网站和App调用
  • 后端程序员是开放平台开发的主力军

公众平台:

  • 是基于微信公众号,为微信用户提供服务的平台
  • 所有公众号,都属于微信内开发
  • 前端程序员是公众平台开发的主力军

app 与 小程序之间的区别

开发原理不同

  • App:基于手机操作系统提供的API进行开发;
  • 小程序:基于微信提供的API进行开发;

运行方式不同

  • App:直接安装并运行在手机操作系统之上;
  • 小程序:必须基于手机微信才能安装和运行;

小程序默认的项目结构

在这里插入图片描述
注意:

  • 对于小程序来说:
    • app.js 和 app.json 文件是必须的
  • 对于小程序的页面来说:
    • .js 和 .wxml 文件是必须的

小程序页面中每个组成部分的作用

  • .wxml 用来描述当前这个页面的结构,同时提供了类似于Vue中指令的语法
  • .js 用来定义当前页面中用到的数据,交互逻辑和响应用户的操作
  • .json 用来定义当前页面的个性化配置,例如,为每个页面单独配置顶部颜色,是否允许下拉刷新等
  • .wxss 用来定义样式来美化当前的页面

设置小程序项目的默认首页

  • 打开 app.json 全局配置文件,找到 pages 节点。这个 pages 节点是一个数组,存储了项目中所有页面的访问路径。其中,pages 数组中第一个页面路径,就是小程序项目的默认首页
  • 修改 pages 数组中路径的顺序,即可修改小程序的默认首页

小程序常用的UI组件

text文本

text是一个行内组件,一行显示多个
在这里插入图片描述

view视图容器

view 是一个块级组件,每个view独自占据一行
在这里插入图片描述

button按钮

在这里插入图片描述

input输入框

在这里插入图片描述

image图片

常见的属性:

小程序的 wxss文件

WXSS(WeiXin Style Sheets)是一套样式语言,用来决定 WXML 的组件应该怎么显示;

WXSS 具有 CSS 大部分特性;

WXSS 对 CSS 进行了扩充以及修改,以适应微信小程序的开发;

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

  • 尺寸单位
  • 样式导入

rpx尺寸单位

rpx(responsive pixel): 是微信小程序独有的、解决屏幕自适应的尺寸单位

  • 可以根据屏幕宽度进行自适应。不论大小屏幕,规定屏幕宽为750rpx。
  • 通过rpx设置元素和字体的大小,小程序在不同尺寸的屏幕上,可以实现自动适配

@import 样式导入

  • 使用 @import 语句可以导入外联样式表
  • 语法格式为:
    • @import “wxss样式表的相对路径”;
      导入的好处可以提高复用性。我们可以把公共的样式抽取出来,然后通过 @import来进行导入

全局样式与局部样式

全局样式

定义在 app.wxss 中的样式为全局样式,作用于每一个页面。

局部样式

在 page 的 wxss 文件中定义的样式为局部样式,只作用在对应的页面,并会覆盖 app.wxss 中相同的选择器。

注意:当局部样式的权重大于或等于全局样式的权重时,才会覆盖全局的样式效果!

全局配置文件

app.json配置文件的作用

小程序根目录下的 app.json 文件用来对微信小程序进行全局配置,它决定了页面文件的路径、窗口表现、设置网络超时时间、设置多 tab 等。

在app.json配置文件中,最主要的配置节点是:

  • pages 数组:配置小程序的页面路径
  • window 对象:用于设置小程序的状态栏、导航条、标题、窗口背景色
  • tabBar 对象:配置小程序的tab栏效果
pages – 配置小程序的页面路径
  • pages 用于指定小程序由哪些页面组成,每一项都对应一个页面的 路径+文件名 信息
  • 文件名不需要写文件后缀,框架会自动去寻找对应位置的 .json、 .js、 .wxml 和 .wxss 四个文件进行处理
window节点常用的配置项
  • navigationBarTitleText:导航栏标题文字内容—字符串
  • navigationBarBackgroundColor:导航栏背景颜色—#000000只能是16进制的颜色值,不可以使用英文单词
  • navigatonBarTextStyle:导航栏标题颜色—black/white
  • backgroundColor:窗口的背景色
  • backgroundTextStyle:下拉loading的样式—dark/light
  • enablePullDownRefresh:是否全局开启下拉刷新—true/false
  • onReachBottomDistance:页面上拉触底事件触发时距离页面底部的距离—默认50,不需要带单位
 "window": {
    "backgroundTextStyle": "dark",
    "backgroundColor": "#000000",
    "navigationBarBackgroundColor": "#124231",
    "navigationBarTitleText": "鲜果时蔬",
    "navigationBarTextStyle": "black",
    "enablePullDownRefresh": true,
    "onReachBottomDistance": 100
  },
tabBar - 配置Tab栏

tabBar 是移动端应用常见的页面效果,用于实现多页面的快速切换;

小程序中通常将其分为底部tabBar和顶部tabBar

注意:tabBar中,只能配置最少2个、最多5个 tab 页签,当渲染顶部tabBar的时候,不显示icon,只显示文本

  • backgroundColor:导航条背景色
  • color:tab上的文字颜色
  • selectedColor:tab上的文字被选择中时的颜色
  • borderStyle:tabBar上边框的颜色
  • position:tabBar的位置,仅支持 bottom / top
  • list:ab 的列表,详见 list 属性说明,最少2个、最多5个 tab
    list的配置项
  • pagePath:页面路径,必须先在pages数组中配置【必填】
  • text:tab上按钮文字【必填】
  • iconPath:图片路径;icon 大小限制为40kb,建议尺寸为 81px * 81px,不支持网络图。当 postion 为 top 时,不显示 icon。【可选】
  • selectedIconPath:选中时的图片路径;icon 大小限制为40kb,建议尺寸为 81px * 81px,不支持网络图片。当 postion 为 top 时,不显示 icon。【可选】

页面级别和全局级别配置的关系

小程序中,app.json 中的 window节点,可以全局配置小程序中每个页面的窗口表现;

如果某些小程序页面,想要拥有特殊的窗口表现,此时,“页面级别的.json配置文件”就可以实现这种需求;

总结:页面级别配置优先于全局配置生效。

页面配置文件中可选的配置项列表

在这里插入图片描述
注意:页面的.json只能设置 window 相关的配置项,以决定本页面的窗口表现

小程序中的生命周期

在小程序中,包含两种类型的生命周期:

  • 应用生命周期:特指小程序从启动 -> 运行 -> 销毁的过程;
  • 页面生命周期:特指小程序中,每个页面的加载 -> 渲染 -> 销毁的过程;

其中,页面的生命周期范围较小,应用程序的生命周期范围较大,如图所示:
在这里插入图片描述

生命周期函数

生命周期函数:是由小程序框架提供的内置函数,会伴随着生命周期,自动按次序执行;

生命周期函数的作用:允许程序员在特定的生命周期时间点上,执行某些特定的操作。例如,页面刚加载的时候,在生命周期函数中自动发起数据请求,获取当前页面的数据;

注意:生命周期强调的是时间段,生命周期函数强调的是时间点。

应用生命周期函数

app.js 是小程序执行的入口文件,在 app.js 中必须调用 App() 函数,且只能调用一次。其中,App() 函数是用来注册并执行小程序的。

App(Object) 函数接收一个Object参数,可以通过这个Object参数,指定小程序的生命周期函数。

App({
  // 小程序初始化完成时,执行此函数,可以做一些初始化的工作。
  onLaunch: function(options) {},
  // 小程序显示到屏幕上的时候,执行此函数。
  onShow  : function(options) {},
  // 小程序被最小化的时候,执行此函数。
  onHide  : function() {},
  //小程序报错的时候触发
  onError : function(){}
})

在这里插入图片描述

页面生命周期函数

每个小程序页面,必须拥有自己的 .js 文件,且必须调用 Page() 函数,否则报错。其中Page() 函数用来注册小程序页面。

Page(Object) 函数接收一个Object参数,可以通过这个Object参数,指定页面的生命周期函数。

Page({
  onLoad  : function(options) {}, // 监听页面加载
  onShow  : function() {},        // 监听页面显示
  onReady : function() {},        // 监听页面初次渲染完成
  onHide  : function() {},        // 监听页面隐藏
  onUnload: function() {}         // 监听页面卸载
})

在这里插入图片描述

数据绑定与事件绑定

数据绑定

小程序中每个页面,由4部分组成,其中 .js 文件内可以定义页面的数据、生命周期函数、其它业务逻辑;

如果要在.js文件内定义页面的数据,只需把数据定义到 data 节点下即可

Page({
  data: {
    info: 'init data', // 字符串类型的数据
    array: [{msg: '1'}, {msg: '2'}] // 数组类型的数据
  }
})

Mustache 语法格式

把data中的数据绑定到页面中渲染,使用 Mustache 语法(双大括号)将变量包起来即可;

<view>{{要绑定数据名称}}</view>

绑定属性

Page({
  data: {
    id: 0
  }
})
<view id="item-{{id}}"> </view>

事件

  • 事件是视图层到逻辑层的通讯方式
  • 事件可以将用户的行为反馈到逻辑层进行处理
  • 事件可以绑定在组件上,当组件触发事件,就会执行逻辑层中对应的事件处理函数
  • 事件对象可以携带额外信息,如 id, dataset, touches

事件的使用方式

在组件中绑定一个事件处理函数。如bindtap,当用户点击该组件的时候会在该页面对应的Page中找到相应的事件处理函数。

<view id="tapTest" data-hi="WeChat" bindtap="tapName"> Click me! </view>

在相应的Page定义中写上相应的事件处理函数,参数是event。

Page({
  tapName: function(event) {
    console.log(event)
  }
})

data和文本框之间的数据同步

监听文本框的数据变化

在文本框的 input 事件处理函数中,通过事件参数 event,能够访问到文本框的最新值

event.detail.value

修改data中的数据
通过 this.setData(dataObject) 方法,可以给页面中的 data 数据重新赋值

inputName: function (event) {
    this.setData({
    	msg: event.detail.value // 为 data 中的 msg 重新赋值
    })
}

事件传参

小程序中的事件传参比较特殊,不能在为组件绑定事件的同时,为事件处理函数传递参数
因为小程序会把 bindtap 后指定的值,统一当作事件名称来处理;
通过 data- * 自定义属性传参
如果要在组件触发事件处理函数的时候,传递参数,可以为组件提供 data-* 自定义属性传参。

<button bindtap='btnHandler’ data-info=“{{123}}”>事件传参</button>

通过事件参数 event.target.dataset.参数名,能够获取 data-* 自定义属性传递到事件处理函数中的参数

btnHandler: function(event){
	console.log(event.target.dataset.info)
}

wxs脚本

WXS(WeiXin Script)是小程序的一套脚本语言,结合 WXML,可以构建出页面的结构。

WXS 与 JavaScript 是不同的语言,有自己的语法,并不和 JavaScript 一致。

wxs 的注意点

  • 没有兼容性:wxs 不依赖于运行时的基础库版本,可以在所有版本的小程序中运行
  • 与 javascript 不同:wxs 与 javascript 是不同的语言,有自己的语法,并不和 javascript 一致
  • 不支持高阶的js语法,ES6语法
  • 隔离性:wxs 的运行环境和其他 javascript 代码是隔离的,wxs 中不能调用其他 javascript 文件中定义的函数,也不能调用小程序提供的API
  • 不能作为事件回调:wxs 函数不能作为组件的事件回调
  • iOS设备上比 javascript 运行快:由于运行环境的差异,在 iOS 设备上小程序内的 wxs 会比 javascript 代码快 2 ~ 20 倍。在 android 设备上二者运行效率无差异
  • wxs属于单例的设计模式,wxs 模块在第一次被引用时,会自动初始化为单例对象。多个页面,多个地方,多次引用,使用的都是同一个 wxs 模块对象。
WXS 代码可以编写在 wxml 文件中的 < wxs> 标签内,或以 .wxs 为后缀名的文件内。

每一个 .wxs 文件和 标签都是一个单独的模块。
每个模块都有自己独立的作用域。即在一个模块里面定义的变量与函数,默认为私有的,对其他模块不可见。

一个模块要想对外暴露其内部的私有变量与函数,只能通过 module.exports 实现。

.wxs 文件

在微信开发者工具里面,右键可以直接创建 .wxs 文件,在其中直接编写 WXS 脚本。该 .wxs 文件可以被其他的 .wxs 文件 或 WXML 中的 标签引用。

module 对象

每个 wxs 模块均有一个内置的 module 对象。

属性

exports: 通过该属性,可以对外共享本模块的私有变量与函数。

// /pages/tools.wxs

var foo = "'hello world' from tools.wxs";
var bar = function (d) {
  return d;
}
module.exports = {
  FOO: foo,
  bar: bar,
};
module.exports.msg = "some msg";
<wxs src="./../tools.wxs" module="tools" />
<view> {{tools.msg}} </view>
<view> {{tools.bar(tools.FOO)}} </view>
require函数

在.wxs模块中引用其他 wxs 文件模块,可以使用 require 函数。

引用的时候,要注意如下几点:

只能引用 .wxs 文件模块,且必须使用相对路径。
wxs 模块均为单例,wxs 模块在第一次被引用时,会自动初始化为单例对象。多个页面,多个地方,多次引用,使用的都是同一个 wxs 模块对象。
如果一个 wxs 模块在定义之后,一直没有被引用,则该模块不会被解析与运行。

< wxs> 标签
在这里插入图片描述
module 属性
module 属性是当前 标签的模块名。在单个 wxml 文件内,建议其值唯一。有重复模块名则按照先后顺序覆盖(后者覆盖前者)。不同文件之间的 wxs 模块名不会相互覆盖。

module 属性值的命名必须符合下面两个规则:

  • 首字符必须是:字母(a-zA-Z),下划线(_)
  • 剩余字符可以是:字母(a-zA-Z),下划线(_), 数字(0-9)

src 属性
src 属性可以用来引用其他的 wxs 文件模块。

引用的时候,要注意如下几点:

  • 只能引用 .wxs 文件模块,且必须使用相对路径。
  • wxs 模块均为单例,wxs 模块在第一次被引用时,会自动初始化为单例对象。多个页面,多个地方,多次引用,使用的都是同一个 wxs 模块对象。
  • 如果一个 wxs 模块在定义之后,一直没有被引用,则该模块不会被解析与运行。

注意

  • < wxs> 模块只能在定义模块的 WXML 文件中被访问到。使用 < include> 或 < import> 时,< wxs> 模块不会被引入到对应的 WXML 文件中。
  • < template> 标签中,只能使用定义该 < template> 的 WXML 文件中定义的 < wxs> 模块。

页面渲染

条件渲染

wx:if 单独设置在元素身上

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

<view wx:if="{{condition}}"> True </view>

也可以用 wx:elif 和 wx:else 来添加一个 else 块:

<view wx:if="length > 5">1</view>
<view wx:elif="length > 6">2</view>
<view wx:else>3</view>
block wx:if 可以包裹在多个元素身上

因为 wx:if 是一个控制属性,需要将它添加到一个标签上。如果要一次性判断多个组件标签,可以使用一个 标签将多个组件包装起来,并在上边使用 wx:if 控制属性

<block wx:if="{{true}}">
  <view> view1 </view>
  <view> view2 </view>
</block>

注意: 并不是一个组件,它仅仅是一个包装元素,不会在页面中做任何渲染,只接受控制属性

hidden 控制隐藏

在小程序中,直接使用 hidden="{{condition}}" 也能控制元素的显示与隐藏

<view hidden="{{condition}}"> 条件为 true 隐藏,条件为 false 显示 </view>
wx:if 与 hidden 的对比
  • 被 wx:if 控制的区域,框架有一个局部渲染的过程,会根据控制条件的改变,动态创建或销毁对应的UI结构
  • 同时, wx:if 也是惰性的,如果在初始渲染条件为 false,框架什么也不做,在条件第一次变成真的时候才开始局部渲染
  • 相比之下,hidden 就简单的多,组件始终会被渲染,只是简单的控制显示与隐藏
  • 总结:wx:if 有更高的切换消耗而 hidden 有更高的初始渲染消耗。因此,如果需要频繁切换的情景下,用 hidden 更好,如果在运行时条件不大可能改变则 wx:if 较好

列表渲染

wx:for 渲染单个节点

在组件上使用 wx:for 控制属性绑定一个数组,即可使用数组中各项的数据重复渲染该组件

默认数组的当前项的下标变量名默认为 index,数组当前项的变量名默认为 item

<view wx:for="{{array}}" wx:key="index">
  索引是:{{index}} 当前项是:{{item}}
</view>
data: {
    array:['红楼梦','三国演义','西游记','水浒传']
}
手动指定索引和当前项的变量名
  • 使用 wx:for-item 可以指定数组当前元素的变量名
  • 使用 wx:for-index 可以指定数组当前下标的变量名
<view wx:for="{{array}}" wx:key="index" wx:for-index="idx" wx:for-item="itemName">
  索引是:{{idx}} 当前项是:{{itemName}}
</view>
block wx:for 渲染多个节点

类似 block wx:if,也可以将 wx:for 用在标签上,以渲染一个包含多节点的结构块

<block wx:for="{{[1, 2, 3]}}">
  <view> {{index}}: </view>
  <view> {{item}} </view>
</block>
列表渲染中的 key

key 在列表循环中的作用

如果列表中项目的位置会动态改变或者有新的项目添加到列表中,并且希望列表中的项目保持自己的特征和状态(如 < input/> 中的输入内容,< checkbox/>的选中状态),需要使用 wx:key 来指定列表中项目的唯一的标识符

当数据改变触发渲染层重新渲染的时候,会校正带有 key 的组件,框架会确保他们被重新排序,而不是重新创建,以确保使组件保持自身的状态,并且提高列表渲染时的效率

key 值的注意点
  • key 值必须具有唯一性,且不能动态改变
  • key 的值必须是数字或字符串
  • 保留关键字 *this 代表在 for 循环中的 item 本身,它也可以充当 key 值,但是有以下限制:需要 item 本身是一个唯一的字符串或者数字
  • 如不提供 wx:key,会报一个 warning, 如果明确知道该列表是静态,或者不必关注其顺序,可以选择忽略

页面事件

下拉刷新

概念:下拉刷新是移动端更新列表数据的交互行为,用户通过手指在屏幕上自上而下的滑动,可以触发页面的下拉刷新,更新列表数据。

应用场景:在移动端,数据列表是常见的页面效果,更新列表数据是最基本的页面需求,相比于按钮刷新、定时刷新来说,下拉刷新的用户体验方便友好,已经成为移动端刷新列表数据的最佳解决方案。

启用下拉刷新

两种方式:

  • 需要在 app.json 的 window 选项中或页面配置中开启 enablePullDownRefresh。但是,一般情况下,推荐在页面配置中为需要的页面单独开启下拉刷新行为
  • 可以通过 wx.startPullDownRefresh() 触发下拉刷新,调用后触发下拉刷新动画,效果与用户手动下拉刷新一致

配置下拉刷新窗口的样式

需要在 app.json 的 window 选项中或页面配置中修改 backgroundColor 和 backgroundTextStyle 选项

  • backgroundColor 用来配置下拉刷新窗口的背景颜色,仅支持16进制颜色值
  • backgroundTextStyle 用来配置下拉刷新 loading 的样式,仅支持 dark 和 light

监听页面的下拉刷新事件

为页面添加 onPullDownRefresh() 函数,可以监听用户在当前页面的下拉刷新事件,这个函数在对应的 .js 里面

停止下拉刷新效果

当处理完下拉刷新后,下拉刷新的 loading 效果会一直显示,不会主动消失,所以需要手动隐藏下拉刷新的 loading 效果。此时,调用
wx.stopPullDownRefresh() 可以停止当前页面的下拉刷新

上拉加载

概念:在移动端,随着手指不断向上滑动,当内容将要到达屏幕底部的时候,页面会随之不断的加载后续内容,直到没有新内容为止,我们称之为上拉加载更多。上拉加载更多的本质就是数据的分页加载。

应用场景:在移动端,列表数据的分页加载,首选的实现方式就是上拉加载更多。

配置上拉触底的距离

可以在 app.json 的 window 选项中或页面配置中设置触底距离 onReachBottomDistance。单位为px,默认触底距离为 50px

onPageScroll(Object) 页面滚动

监听用户滑动页面事件。其中 Object 参数说明如下
在这里插入图片描述

Page({
    onPageScroll(scroll){
        console.log(scroll.scrollTop)
    }
})

onShareAppMessage(Object) 分享

监听用户点击页面内转发按钮( 组件 open-type=“share”)或右上角菜单“转发”按钮的行为,并自定义转发内容。其中 Object 参数说明如下
在这里插入图片描述

Page({
   /**
   * 用户点击右上角分享
   */
  onShareAppMessage: function (share) {
     console.log(share.from);//获取用户是以哪种方式进行分享 menu:右上角菜单,button:页面按钮
     console.log(share.target);//如果是右上角菜单触发,那么这个值就是undefined,如果是button触发,那么这个值就是触发的button
  },
})

如果是button触发分享,需要定义button组件

<button open-type='share'>分享</button>

同时,此转发事件需要 return 一个 Object,用于自定义转发内容,返回内容如下
在这里插入图片描述

Page({
    onShareAppMessage: function (res) {
        ...
        return {
            title: '自定义转发标题',
            path: '/page/user?id=123',
            imageUrl: '转发的图片地址'
        }
    }
})

onTabItemTap(Object)

点击 tab 时触发,其中 Object 参数说明如下
在这里插入图片描述
在对应的页面的js文件中注册 onTabItemTap 监听

page({
    ...
    onTabItemTap(obj){
        //每次点击对应的页面就能调用对应页面的这个监听
    }
})

页面导航

页面导航就是页面之间的跳转,小程序中页面之间的导航有两种方式:

  • 声明式导航:通过点击 navigator 组件实现页面跳转的方式
  • 编程式导航:通过调用小程序的 API 接口实现跳转的方式

声明式导航

导航到非 tabBar 页面

非 tabBar 页面指的是没有被当作 tabBar 进行切换的页面

<navigator url='/pages/info/info'>去info页面</navigator>

注意:上述代码使用 url 属性指定要跳转到的页面路径;其中,页面路径应该以 / 开头,且路径必须提前在 app.json 的 pages 节点下声明,才能实现正常的跳转

导航到 tabBar 页面

tabBar 页面指的是被当作 tabBar 进行切换的页面(配置在"tabBar"中的list中的页面)。如果 navigator 组件单纯使用 url 属性,无法导航到 tabBar 页面,需要结合open-type 属性进行导航

<navigator url="/pages/list/lists" open-type='switchTab'>去tabBar页面</navigator>

关于 navigator 组件的更多用法,请翻阅官方文档
https://developers.weixin.qq.com/miniprogram/dev/component/navigator.html

后退导航

如果要后退到上一页面或多级页面,需要把 open-type 设置为 navigateBack,同时使用 delta 属性指定后退的层数

<navigator open-type='navigateBack' delta='1'>
    返回上一页
</navigator>

编程式导航

导航到非 tabBar 页面

通过 wx.navigateTo(Object object) 方法,可以跳转到应用内的某个页面。但是不能跳到 tabbar 页面
Object 参数对象的属性列表如下:

在这里插入图片描述

<view bindtap='tapHandler'>前进</view>
tapHandler:function(){
    wx.navigateTo({
      url: '/pages/list/lists',//跳转的路径
      success:function(){//成功后的回调
        console.log('success')
      },
      fail:function(){//失败后的回调
        console.log('fail')
      },
      complete:function(){//不管成功还是失败都会回调
        console.log('complete')
      }
    })
  }
导航到 tabBar 页面

通过 wx.switchTab(Object object) 方法,可以跳转到 tabBar 页面,并关闭其他所有非 tabBar 页面。其中 Object 参数对象的属性列表如下
在这里插入图片描述

<view bindtap='tapHandler'>前进</view>
tapHandler:function(){
    wx.switchTab({
      url: '/pages/list/lists',//跳转的路径
      success:function(){//成功后的回调
        console.log('success')
      },
      fail:function(){//失败后的回调
        console.log('fail')
      },
      complete:function(){//不管成功还是失败都会回调
        console.log('complete')
      }
    })
  }
后退导航

通过 wx.navigateBack(Object object) 方法,关闭当前页面,返回上一页面或多级页面。其中 Object 参数对象的属性列表如下:
在这里插入图片描述

<view bindtap='tapHandler'>前进</view>
tapHandler:function(){
    wx.navigateBack({
      delta: 1,//返回的页面数
      success:function(){//成功后的回调
        console.log('success')
      },
      fail:function(){//失败后的回调
        console.log('fail')
      },
      complete:function(){//不管成功还是失败都会回调
        console.log('complete')
      }
    })
  }

导航传参

声明式导航传参

navigator 组件的 url 属性用来指定导航到的页面路径,同时路径后面还可以携带参数,参数与路径之间使用 ?分隔,参数键与参数值用 = 相连,不同参数用 & 分隔

<navigator url=‘/pages/logs/logs?name=zs&age=20’>去logs页面</navigator>
编程式导航传参

wx.navigateTo(Object object) 方法的 object 参数中,url 属性用来指定需要跳转的应用内非 tabBar 的页面的路径, 路径后可以带参数。参数与路径之间使用 ? 分隔,参数键与参数值用 = 相连,不同参数用 & 分隔

wx.navigateTo({
  url: '/pages/logs/logs?name=zs&age=20',
})
页面接收导航传递过来的参数

不论是声明式导航还是编程式导航,最终导航到的页面可以在 onLoad 生命周期函数中接收传递过来的参数。

onLoad: function(options) {
   console.log(options) // options 就是导航传递过来的参数
}

注意: 导航栏的页面不支持此参数传递

自定义编译模式快速传参

小程序每次修改代码并编译后,会默认从首页进入,但是在开发阶段,我们经常会针对特定的页面进行开发,为了方便编译后直接进入对应的页面,可以配置自定义编译模式,步骤如下

  • 单击工具栏上的“普通编译”下拉菜单;
  • 单击下拉菜单中的“添加编译模式”选项;
  • 在弹出的“自定义编译条件窗口”,按需添加模式名称、启用页面、启动参数、进入场景等。

配置服务器域名

每个微信小程序需要事先设置一个通讯域名,小程序只可以跟指定的域名进行网络通信

服务器域名请在 「小程序后台-开发-开发设置-服务器域名」 中进行配置,配置时需要注意:

  • 域名只支持 https (request、uploadFile、downloadFile) 和 wss (connectSocket) 协议
  • 域名不能使用 IP 地址或 localhost
  • 域名必须经过 ICP 备案
    • 网络内容[服务商]英文为 Internet Content Provider 简写为ICP,即向广大用户综合提供互联网信息业务和增值业务的电信运营商。其必须具备的证书即为[ICP证]。ICP证是指各地通信管理部门核发的《[中华人民共和国电信与信息服务业务经营许可证]》。

跳过域名校验

在微信开发者工具中,可以临时开启 「开发环境不校验请求域名、TLS 版本及 HTTPS 证书」 选项,跳过服务器域名的校验。此时,在微信开发者工具中及手机

开启调试模式时,不会进行服务器域名的校验

注意:在服务器域名配置成功后,建议开发者关闭此选项进行开发,并在各平台下进行测试,以确认服务器域名配置正确

网络数据请求

在这里插入图片描述

发起 get 请求

调用 wx.request(Object object) 方法发起 get 请求

wx.request({// 请求的URL地址,必须基于 HTTPS 协议
    url: 'https://www.liulongbin.top:8082/api/get',
    // 发送到服务器的数据
    data: { name: 'zs', age: 20 },
    method: 'GET'// 成功之后的回调函数
    success: function(result) {
        //result.data 就能获取服务器返回的数据
        console.log(result)
    }
})

发起 post 请求

调用 wx.request(Object object) 方法发起 post 请求

wx.request({// 请求的URL地址,必须基于 HTTPS 协议
    url: 'https://www.liulongbin.top:8082/api/post',
    // 发送到服务器的数据
    data: { name: 'zs', age: 20 },
    method: 'POST'// 成功之后的回调函数
    success: function(result) {
        //result.data 就能获取服务器返回的数据
        console.log(result)
    }
})

小程序中没有跨域限制
在普通网站开发中,由于浏览器的同源策略限制,存在数据的跨域请求问题,从而衍生出了 JSONP 和 CORS 两种主流的跨域问题解决方案。但是,小程序的内部运行机制与网页不同,小程序中的代码并不运行在浏览器中,因此小程序开发中,不存在数据的跨域请求限制问题

关于微信小程序更多的数据请求内容,请翻阅 wx.request() 的相关文档:
https://developers.weixin.qq.com/miniprogram/dev/api/network/request/wx.request.html

自定义组件

创建组件

  • 在项目的根目录中,鼠标右键,创建 components -> test 文件夹
  • 在新建的 components -> test 文件夹上,鼠标右键,点击“新建 Component”
  • 为新建的组件命名之后,会自动生成组件对应的 4 个文件,后缀名分别为 .js,.json, .wxml 和 .wxss
    注意:尽量将不同的组件,存放到单独的文件夹中,从而保证清晰的目录结构

引用组件

  • 在需要引用组件的页面中,找到页面的 .json 配置文件,新增 usingComponents 节点
  • 在 usingComponents 中,通过键值对的形式,注册组件;键为注册的组件名称,值为组件的相对引用路径
  • 在页面的 .wxml 文件中,把注册的组件名称,以标签形式在页面上使用,即可把组件展示到页面上
    注意:注册组件名称时,建议把名称注册为短横线连接的形式,例如 vant-button 或 custom-button

使用样式美化组件
组件对应 wxss 文件的样式,只对组件 wxml 内的节点生效。编写组件样式时,需要注意以下几点:

  • 组件和引用组件的页面不能使用id选择器(#a)、属性选择器([a])和标签名选择器,请改用class选择器。
  • 组件和引用组件的页面中使用后代选择器(.a .b)在一些极端情况下会有非预期的表现,如遇,请避免使用
  • 子元素选择器(.a>.b)只能用于 view 组件与其子节点之间,用于其他组件可能导致非预期的情况
  • 继承样式,如 font 、 color ,会从组件外继承到组件内
  • 除继承样式外, app.wxss 中的样式、组件所在页面的样式对自定义组件无效

在自定义组件外界定义组件样式
默认外界是不能修改自定义组件内部的样式
在自定义组件中的js中设置向外暴露的属性externalClasses

/* 组件 custom-component.js */
Component({
  externalClasses: ['my-class']
})
<!-- 组件 custom-component.wxml -->
<custom-component class="my-class">这段文本的颜色由组件外的 class 决定</custom-component>

在外界page页面使用的时候,把暴露出去的类名当作当前组件的属性,然后来设置 类选择器

<!-- 页面的 WXML -->
<custom-component my-class="red-text" />
<custom-component my-class="large-text" />
<!-- 以下写法需要基础库版本 2.7.1 以上 -->
<custom-component my-class="red-text large-text" />
.red-text {
  color: red;
}
.large-text {
  font-size: 1.5em;
}

组件的 data 与 methods

小程序组件中的 data,和小程序页面中的 data 用法一致,只不过:

  • 页面的 data 定义在 Page() 函数中
  • 组件的 data 定义在 Component() 函数中
  • 如果要访问 data 中的数据,直接使用 this.data.数据名称 即可
  • 如果要为data 中的数据重新赋值,调用 this.setData({ 数据名称: 新值 }) 即可
  • 如果要渲染 data 中的数据,直接使用 {{ 数据名称 }} 即可

使用 methods 定义组件的事件处理函数

和页面不同,组件的事件处理函数,必须定义在 methods 节点中。

Component({
    methods: {
        // 按钮的点击事件处理函数
        btnHandler: function() {}
    }
})

组件的 properties

properties 的作用

  • 类似于 vue 组件中的 props, 小程序组件中的 properties,是组件的对外属性,用来接收外界传递到组件中的数据
  • 在小程序中,组件的 properties 和 data 的用法类似,它们都是可读可写的,只不过:
    • data 更倾向于存储组件的私有数据
    • properties 更倾向于存储外界传递到组件中的数据
声明 properties 的两种方式
Component({
    properties: {
        // 完整的定义方式
        propA: {          // 属性名
            type: String, // 属性类型
            value: ''     // 属性默认值
        },
        propB: String     // 简化的定义方式
    }
})

注意:type 的可选值为 Number,String、Boolean、Object、Array、null(表示不限制类型)

为组件传递 properties 的值

可以使用数据绑定的形式,向子组件的属性传递动态数据

<!-- 引用组件的页面模板 -->
<view>
  <component-tag-name prop-a="{{dataFieldA}}" prop-b="{{dataFieldB}}">
  </component-tag-name>
</view>

在以上例子中,组件的属性 propA 和 propB 将收到页面传递的数据。页面可以通过 setData 来改变绑定的数据字段。

注意:在定义 properties 时,属性名采用驼峰写法(propertyName);在 wxml 中,指定属性值时,则对应使用连字符写法(property-name=“attr value”),应用于数据绑定时,采用驼峰写法(attr="{{propertyName}}")。

在组件内修改 properties 的值

小程序中,properties 的值是可读可写的,它的用法与 data 几乎一致,因此可以通过 setData 修改 properties 中任何属性的值,不会影响父组件中的值

properties: {
  count: Number
},
methods: {
  add: function() {
    this.setData({ count: this.properties.count + 1 })
  }
}

数据监听器

数据监听器可以用于监听和响应任何属性和数据字段的变化,从而执行特定的操作。作用类似于 vue 中的 watch
数据监听器从小程序基础库版本 2.6.1 开始支持。
数据监听器的基本语法格式如下:

Component({
  observers: {
    '字段A, 字段B': function(字段A的新值,字段B的新值) {
      // do something 只要字段被修改,就会调用这个监听
    }
  }
})
监听子数据字段的变化

数据结构

Component({
  /**
   * 组件的属性列表
   */
  properties: {
     product:{
       type:Object,
       value:{
          imgUrl:{
             type: String,
             value:''
          },
          title:{
            type:String,
            value:''
          }
       }
     }
  }

点击按钮修改product里面的属性值

methods: {
    updateImgHandler:function(){
      this.setData({
        'product.title': "程序员"
      });
    },
    updateTitleHandler:function(){
      this.setData({
        'product.imgUrl': 'www.itcast.cn'
      });
    }
  }

监听的代码

observers:{
    'product.**': function (newPro){
      console.log(newPro)
    }
}

注意:虽然product对象可以通过 . 的方式去进行设置(例如:this.properties.product.title=“程序员”😉,但是这种方式不会触发监听,我们需要通过setData的方式才能触发监听

组件的生命周期

组件的生命周期,指的是组件自身的一些函数,这些函数在特殊的时间点或遇到一些特殊的框架事件时被自动触发
其中,最重要的生命周期是 created, attached, detached ,包含一个组件实例生命流程的最主要时间点

  • 组件实例刚刚被创建好时, created 生命周期被触发。此时还不能调用 setData 。 通常情况下,这个生命周期只应该用于给组件 this 添加一些自定义属性字段
  • 在组件完全初始化完毕、进入页面节点树后, attached 生命周期被触发。此时, this.data 已被初始化完毕。这个生命周期很有用,绝大多数初始化工作可以在这个时机进行
  • 在组件离开页面节点树后, detached 生命周期被触发。退出一个页面时,如果组件还在页面节点树中,则 detached 会被触发

组件可用的全部生命周期函数

在这里插入图片描述

Component({
  /**
   * 生命周期--创建时候
   */
  created:function(){
    console.log('自定义组件被创建了');
    console.log(arguments);
  },
   /**
   * 生命周期--被加载完毕
   */
  attached:function(){
    console.log('自定义组件被加载完毕了,在这里可以做一些初始化工作');
    console.log(arguments);
  },
   /**
   * 生命周期--页面布局完成
   */
  ready:function(){
    console.log('自定义组件页面布局完成');
    console.log(arguments);
  },
  /**
   * 生命周期--页面布局完成
   */
  detached:function(){
    console.log('自定义组件在页面节点移除');
    console.log(arguments);
  },
  /**
  * 生命周期--页面加载错误
  */
  detached: function () {
    console.log('自定义组件页面加载错误');
    console.log(arguments);
  }
})

生命周期方法可以直接定义在 Component 构造器的第一级参数中。
自小程序基础库版本 2.2.3 起,组件的的生命周期也可以在 lifetimes 字段内进行声明(这是推荐的方式,其优先级最高)

Component({
  lifetimes: {
    attached() {}, // 在组件实例进入页面节点树时执行
    detached() {}, // 在组件实例被从页面节点树移除时执行
  },
  // 以下是旧式的定义方式,可以保持对 <2.2.3 版本基础库的兼容
  attached() {}, // 在组件实例进入页面节点树时执行
  detached() {}, // 在组件实例被从页面节点树移除时执行
  // ...
})

组件所在页面的生命周期

有一些特殊的声明周期,它们并非与组件有很强的关联,但有时组件需要获知,以便组件内部处理,这样的生命周期称为 ‘组件所在页面的生命周期’ ,在 pageLifetimes 定义字段中,其中可用的声明周期包含:
在这里插入图片描述

Component({
  /**
   * 定义组件所在页面生命周期函数
   */
  pageLifetimes:{
    /**
     * 组件所在的页面被展示时执行
     */
       show:function(){
          console.log('组件所在页面展示了');
       },
     /**
      * 组件所在的页面被隐藏时执行
      */
      hide:function(){
        console.log('组件所在页面隐藏了');
      },
      /**
       * 组件所在的页面尺寸变化时执行
       */
      resize:function(){
        console.log('组件所在页面尺寸变化了');
      }
  }
})

组件插槽

默认插槽

在组件的 wxml 中可以包含 slot 节点,用于承载组件使用者提供的 wxml 结构

默认情况下,一个组件的 wxml 中只能有一个slot。需要使用多 slot 时,可以在组件 js 中声明启用

注意:小程序中目前只有默认插槽和多个插槽,暂不支持作用域插槽
引用组件的页面结构

 <btn-zidingyi >
   <view>插入到模板中的代码</view> 
   <view><input type="password"></input></view> 
 </btn-zidingyi>

组件的页面结构

<view>
  <!-- 组件插槽,能把组页面的内容显示在自定义组件的插槽内 -->
  <slot></slot>
</view>

这样的话,< btn-zidingyi> 里面的内容就会被插入到 组件页面的< slot>内

多个插槽使用

启用多个插槽
在组件中,需要使用多 slot 时,可以在组件 js 中声明启用。示例代码如下:

Component({
    options:{
        multipleSlots: true
    }
})

定义多个插槽
可以在组件的 wxml 中使用多个 slot 标签,以不同的 name 来区分不同的插槽。示例代码如下:

//组件被引用的页面
<view>
  <list-zidingyi>
      <view slot="one">插入到list模板中第一个view</view>
      <view slot="two">插入到list模板中第二个view</view>
  </list-zidingyi>
</view>
//组件的页面
<view>
  <slot name="one"></slot>
</view>
<view>
  <slot name="two"></slot>
</view>

组件间的通信

组件之间的三种基本通信方式

  • WXML 数据绑定:用于父组件向子组件的指定属性传递数据,仅能设置 JSON 兼容数据(自基础库版本 2.0.9 开始,还可以在数据中包含函数)
  • 事件:用于子组件向父组件传递数据,可以传递任意数据
  • 如果以上两种方式不足以满足需要,父组件还可以通过 this.selectComponent 方法获取子组件实例对象,这样就可以直接访问组件的任意数据和方法

this.selectComponent(string)
在小程序的组件中,调用 this.selectComponent(string),可以返回指定组件的实例对象。示例代码如下:

<!-- wxml -->
<component-a class="customA" id= "cA" ></component-a>
//父组件的 .js 文件中,可以调用 selectComponent 函数并指定 id 或 class 选择器,获取子组件对象
Page({
  onLoad(){
    // 切记下面参数不能传递标签选择器(component-a),不然返回的是 null
    var component = this.selectComponent('.customA'); // 也可以传递 id 选择器 #cA
    console.log(component);
  }
})
通过事件监听实现子向父传值

1.在引用组件的页面,给组件绑定事件名称

<user bind:userTapHandler="userTapHandler"></user>

这里是由子组件触发,通过triggerEvent去触发这个事件,我们需要用bind:开头
2.在引用组件的js里面,定义userTapHandler函数

Page({
  userTapHandler:function(e){
    console.log(e);//e就是传递过来的事件对象,可以通过e.detail来获取传递过来的值
  }
})

3.给组件 user 绑定点击事件

<image id='imgId' src='../../assets/images/home-active.png' bindtap='getImageUrlHandler' data-url="home-active.png"></image>

4.在组件的js文件中的 methods 里面定义tap事件

Component({
   /**
   * 组件的方法列表
   */
  methods: {
    getImageUrlHandler:function(e){
      var dataUrl = e.currentTarget.dataset.url;
      //通过 this.triggerEvent 来触发父组件的自定义事件,第一个参数是事件名称,第二个参数是传递的值,第三个是配置项,是否冒泡|是否捕获
      this.triggerEvent('userTapHandler', { url: dataUrl});
    }
  }
})

WePY框架

WePY 是腾讯官方出品的一个小程序快速开发框架,对原生小程序的开发模式进行了再次封装,更贴近于 MVVM 架构模式,并支持ES6/7的一些新特性,同时语法

风格更接近于 Vue.js,使用 WePY 框架能够提高小程序的开发效率

注意:WePY 只是小程序的快速开发框架之一,市面上还有诸如 mpvue 之类的小程序开发框架也比较流行
WePY 相比于原生小程序开发,拥有众多的开发特性和优化方案,例如:

  • 开发风格接近于 Vue.js,支持很多vue中的语法特性
  • 通过 polyfill 让小程序完美支持 Promise
  • 可以使用ES6等诸多高级语法特性,简化代码,提高开发效率
  • 对小程序本身的性能做出了进一步的优化
  • 支持第三方的 npm 资源
  • 支持多种插件处理和编译器
  • etc

创建WePY项目

1.安装 WePY 框架

npm install wepy-cli -g

2.初始化 WePY 项目

wepy init standard myProject

”wepy init” 是固定写法,代表要初始化 wepy 项目;”standard” 代表模板类型为标准模板,可以运行 ”wepy list” 命令查看所有可用的项目模板; ”myproject” 为自定义的项目名称。
3.安装 WePY 项目依赖项

npm install

4.编译

wepy build --watch

自动编译生成小程序项目,生成的小程序项目默认被存放于 dist 目录中

WePY 项目的目录结构

  • dist 小程序运行代码目录(该目录由WePY的build指令自动编译生成,不要直接修改该目录下的文件)
  • node_modules 相关的一些第三方库
  • src 代码编写的目录 (该目录为使用WePY后的开发目录)
    • components WePY组件目录(组件不属于完整页面,仅供完整页面或其他组件引用)
      • com_a.wpy 可复用的WePY组件a
      • com_b.wpy 可复用的WePY组件b
    • pages WePY页面目录(属于完整页面)
      • index.wpy index页面(经build后,会在dist目录下的pages目录生成index.js、index.json、index.wxml和index.wxss文件)
      • other.wpy other页面(经build后,会在dist目录下的pages目录生成other.js、other.json、other.wxml和other.wxss文件)
    • app.wpy 小程序配置项(全局数据、样式、声明钩子等;经build后,会在dist目录下生成app.js、app.json和app.wxss文件)
  • package.json 项目的package配置

.wpy 文件的组成部分

一个 .wpy 文件可分为三大部分,各自对应于一个标签:

  • 脚本部分,即 标签中的内容,又可分为两个部分:
    • 逻辑部分,除了 config 对象之外的部分,对应于原生的 .js 文件
    • 配置部分,即 config 对象,对应于原生的 .json 文件
  • 结构部分,即 模板部分,对应于原生的 .wxml 文件
  • 样式部分,即样式部分,对应于原生的 .wxss 文件。
    • 其中,小程序入口文件 app.wpy 不需要 template,所以编译时会被忽略。

lang 和 src 属性

.wpy 文件中的 script、template、style 这三个标签都支持 lang 和 src 属性,lang 决定了其代码编译过程,src 决定是否外联代码,存在 src 属性且有效时,会忽略内联代码。
在这里插入图片描述
文件后缀为.wpy,可共用 Vue 的高亮规则,但需要手动设置。如下是 VS Code 中实现代码高亮的相关设置步骤:

  • 在 Code 里先安装 Vue 的语法高亮插件 Vetur。
  • 打开任意 .wpy 文件。
  • 点击右下角的选择语言模式,默认为纯文本。
  • 在弹出的窗口中选择 .wpy 的配置文件关联…。
  • 在选择要与 .wpy 关联的语言模式 中选择 Vue。
  • 在 VS Code 编辑器设置中设置。// 文件-首选项-设置-settings.json 中,添加 “files.associations”: { “*.wpy”: “vue” }
    注意:其它常见 IDE 或编辑器中设置代码高亮,可以参考:https://tencent.github.io/wepy/document.html#/?id=%e4%bb%a3%e7%a0%81%e9%ab%98%e4%ba%ae

小程序入口 app.wpy

入口文件 app.wpy 中所声明的小程序实例继承自 wepy.app 类,包含一个 config 属性和其它全局属性、方法、事件。在 build 编译期间:

  • config 属性会被编译为小程序的 app.json 全局配置文件
  • config 属性之外的其它节点,会被编译为小程序的 app.js 文件
  • style 标签会被编译为小程序的 app.wxss 全局样式
<script>
import wepy from 'wepy';
export default class extends wepy.app {
    config = {
        "pages":[
            "pages/index/index"
        ],
        "window":{
            "backgroundTextStyle": "light",
            "navigationBarBackgroundColor": "#fff",
            "navigationBarTitleText": "WeChat",
            "navigationBarTextStyle": "black"
        }
    };
    onLaunch() {
        console.log(this);
    }
}
</script>

页面page.wpy

<script>
import wepy from 'wepy';
import Counter from '../components/counter';

export default class Page extends wepy.page {
    config = {};
    components = {counter1: Counter};

    data = {};
    methods = {};

    events = {};
    onLoad() {};
    // Other properties
}
</script>

<template lang="wxml">
    <view>
    </view>
    <counter1></counter1>
</template>

<style lang="less">
/** less **/
</style>

页面文件page.wpy中所声明的页面实例继承自wepy.page类,该类的主要属性介绍如下:
在这里插入图片描述

组件com.wpy

<template lang="wxml">
    <view>  </view>
</template>

<script>
import wepy from 'wepy';
export default class Com extends wepy.component {
    components = {};

    data = {};
    methods = {};

    events = {};
    // Other properties
}
</script>

<style lang="less">
/** less **/
</style>

组件文件com.wpy中所声明的组件实例继承自wepy.component类,除了不需要config配置以及页面特有的一些生命周期函数之外,其属性与页面属性大致相同。

自定义默认首页

创建 home 首页
在 src -> pages 目录下,创建 home.wpy 页面,并创建页面的基本代码结构,示例代码如下:

<template></template>
<script>
import wepy from 'wepy'
export default class Home extends wepy.page {
    config = {}
    methods = {}
}
</script>
<style></style>

设置默认首页
如果要把刚创建的 home.wpy 设置为默认首页,需要打开 src -> app.wpy 入口文件,将 home.wpy 的页面路径,注册到 config -> pages 数组中,并调整为数组的第一项即可,示例代码如下:

<script>
import wepy from 'wepy'
import 'wepy-async-function'
export default class extends wepy.app {
  config = {
    pages: ['pages/home', 'pages/index’]
  }
}
</script>

创建 .wpy 页面的注意事项

在创建 .wpy 页面的时候,要注意以下事项:

  • 每个页面的 script 标签中,必须导入 wepy 模块,并创建继承自 wepy.page 的页面类;否则会报错
  • 每个页面的路径,必须记录到 app.wpy 的 config -> pages 数组中
  • 页面路径记录完毕之后,必须再回到页面文件中,摁下 Ctrl + S 快捷键重新编译生成页面,否则会报错

为 WePY 页面绑定事件并传参

使用 @ 绑定事件处理函数

原生小程序使用 bindtap、bindinput 等绑定事件处理函数,在 wepy 框架中,优化了事件绑定机制,支持类似于 Vue.js 的事件绑定语法,绑定事件可以采用如下

  • 原 bindtap=“clickHandler” 替换为 @tap=“clickHandler”
  • 原 bindinput=“inputHandler” 替换为 @input=“inputHandler”
  • 可以利用 @tap.stop=“clickHandler” 来阻止事件冒泡
<template>
    <view @tap="tapHandler">点我</view>
</template>
<script>
import wepy from 'wepy'
export default class Home extends wepy.page{
     config={}
     methods={
         tapHandler:function(){
             console.log('点击了');
         }
     }
}
</script>
事件传参的优化写法

如果 @ 符号绑定的事件处理函数需要传参,可以采用优化的写法

原 bindtap="clickHandler" data-index={{index}} 替换为 @tap="click({{index}})"
<template>
    <view @tap="tapHandler({{2}})">点我</view>
</template>
<script>
import wepy from 'wepy'
export default class Home extends wepy.page{
     config={}
     methods={
         tapHandler:function(data,event){
             console.log(data);
         }
     }
}
</script>
定义事件处理函数的注意点
  • 通过 @ 符号绑定的事件处理函数,必须定义到页面的 methods 节点下
  • 注意:对于 WePY 中的 methods 属性,因为与 Vue 中的使用习惯不一致,非常容易造成误解,这里需要特别强调一下:WePY 中的 methods 属性只能声明页面 wxml 标签的事件处理函数,不能声明自定义方法,自定义方法需要声明到和 methods 平级的节点位置,这与 Vue 中的用法是不一致的

WePY 页面的数据绑定

使用 data 定义私有数据

.wpy 页面中的私有数据,需要定义到 data 节点中,页面上可以使用双大括号语法 {{ }} 渲染 data 中的数据

<template>
    <view @tap="tapHandler({{msg}})">{{msg}}</view>
</template>
<script>
import wepy from 'wepy'
export default class Home extends wepy.page{
     ...
     data={
         msg: 'hello world'
     }
}
</script>
将文本框与 data 做双向数据绑定

实现步骤如下:

  • 为 input 输入框绑定数据和事件处理函数,代码为:<input value="{{msg}}" @input=“inputHandler” />
  • 在 methods 中定义事件处理函数,函数名称为 inputHandler
  • 在事件处理函数中,通过事件参数 e.detail.value 获取到最新的文本框内容
  • 通过 this.msg = e.detail.value 为 data 中的 msg 重新赋值
<template>
    <view>
        <input type="text" value="{{msg}}" @input="inputHandler">
    </view>
    </view>
</template>
<script>
import wepy from 'wepy'
export default class Home extends wepy.page{
     config={}
     data={
         msg: 'hello world'
     }
     methods={
        inputHandler:function(e){
            //通过e.detail.value 可以获取到用户输入的值
            this.data.msg = e.detail.value;
            console.log(this.data.msg);
        }
     }
}
</script>
使用 wxs 脚本

在 WePY 中使用 wxs 脚本的方式如下:

  • 将 wxs 脚本定义为外联文件,并且后缀名为 .wxs
  • 在 标签内,通过 import 导入相对路径的 wxs 模块
  • 在当前页面的 class 类中,通过 wxs = { } 注册刚才导入的 wxs 模块
  • 注意:被注册的 wxs 模块,只能在当前页面的 template 中使用,不能在script中使用
<template>
    <view>{{homeWxs.random(10,20)}}</view>
</template>
<script>
import wepy from 'wepy'
//需要模块导入
import homeWxs from '../wxs/home.wxs'
export default class Home extends wepy.page{
     ...
     //需要在class类中进行注册
     wxs={
         homeWxs: homeWxs
     }
}
</script>

WePY 页面中发起数据请求

配置 promisify 启用 async 和 await

默认使用 wepy-cli 创建的项目,不支持使用 ES7 的 async 和 await 来简化 Promise API 的调用。需要手动开启此功能:

打开 src -> app.wpy,找到 constructor() 构造函数,在构造函数中代码的最后一行,添加 this.use(‘promisify’) 即可

constructor() {
  super()
  this.use('requestfix')
  this.use('promisify') // 添加此行代码,即可启用 async 和 await
}
使用 wepy.request 发起 Get 请求

WePY 框架对原生小程序做了封装,之前通过 wx 调用的 API,都可以直接使用 wepy 进行调用,例如:wx.request() 是原生小程序的数据请求 API,现在可以直接通过 wepy.request() 发起网络数据请求
利用 Promise 的.then 方式来获取数据

<template>
    <view>
        <button type="primary" @tap.stop="requestHandler">请求</button>
    </view>
</template>
<script>
import wepy from 'wepy'
import homeWxs from '../wxs/home.wxs'
export default class Home extends wepy.page{
     ...
     methods={
        requestHandler:function(){
            wepy.request({ 
                url:'https://www.liulongbin.top:8082/api/get?id=1&username=itheima',
                method: 'GET'
            }).then(res=>{
                //成功后调用
                console.log(res);
                //弹出土司,提示请求成功
                wepy.showToast({
                    title:res.data.message,
                    icon:'none',
                    duration:1000
                });
            }).catch(error =>{
                 wepy.showToast({
                    title:'请求失败',
                    icon:'none',
                    duration:1000
                });
            })
        }
     }
}
</script>

利用 async await 来实现

<template>
    <view>
        <button type="primary" @tap.stop="requestHandlerAsync">async请求</button>
    </view>
</template>
<script>
import wepy from 'wepy'
import homeWxs from '../wxs/home.wxs'
export default class Home extends wepy.page{
     ...
     methods={
        async requestHandlerAsync(){
            let res = await wepy.request({
                url: 'https://www.liulongbin.top:8082/api/get?id=1&username=itheima',
                method: 'get'
            });
            wepy.showToast({
                title: res.data.message,
                icon: 'none',
                duration: 1000
            })
        }
     }
}
</script>
使用 wepy.request 发起 Post 请求

通过 wepy.request() 方法发起 Post 请求,与get不同的点在于,post请求的参数需要设置进去,不能跟在请求路径后面
利用 Promise 的.then 方式来获取数据

<template>
    <view>
        <button type="primary" @tap.stop="requestHandler">请求</button>
    </view>
</template>
<script>
import wepy from 'wepy'
import homeWxs from '../wxs/home.wxs'
export default class Home extends wepy.page{
     ...
     methods={
        requestHandler:function(){
            wepy.request({ 
                url:'https://www.liulongbin.top:8082/api/post',
                method: 'POST',
                data: {name:'itheima',age: 18}
            }).then(res=>{
                //成功后调用
                console.log(res);
                //弹出土司,提示请求成功
                wepy.showToast({
                    title:res.data.message,
                    icon:'none',
                    duration:1000
                });
            }).catch(error =>{
                 wepy.showToast({
                    title:'请求失败',
                    icon:'none',
                    duration:1000
                });
            })
        }
     }
}
</script>

利用 async await 来实现

<template>
    <view>
        <button type="primary" @tap.stop="requestHandlerAsync">async请求</button>
    </view>
</template>
<script>
import wepy from 'wepy'
import homeWxs from '../wxs/home.wxs'
export default class Home extends wepy.page{
     ...
     methods={
        async requestHandlerAsync(){
            let res = await wepy.request({
                url:'https://www.liulongbin.top:8082/api/post',
                method: 'POST',
                data: {name:'itheima',age: 18}
            });
            wepy.showToast({
                title: res.data.message,
                icon: 'none',
                duration: 1000
            })
        }
     }
}
</script>
异步更新数据

在异步函数中更新数据的时候,页面检测不到数据的变化,必须手动调用 this.$apply 方法。作用是强制页面重新渲染

<template>
    <view>
        <button type="primary" @tap.stop="requestHandlerAsync">async请求</button>
    </view>
    <view>
        {{msg}}
    </view>
</template>
<script>
import wepy from 'wepy'
import homeWxs from '../wxs/home.wxs'
export default class Home extends wepy.page{
    ...
    data={
        msg: ''
    }
    methods={
        async requestHandlerAsync(){
            let res = await wepy.request({
                url:'https://www.liulongbin.top:8082/api/post',
                method: 'POST',
                data: {name:'itheima',age: 18}
            });
            wepy.showToast({
                title: res.data.message,
                icon: 'none',
                duration: 1000
            })
            this.msg = res.data;
            this.$apply();//刷新页面
        }
     }
}
</script>
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值