S12-01 小程序-基础
[TOC]
入门
概念
1、什么是小程序
小程序(Mini Program)是一种不需要下载安装即可使用的应用,它实现了“触手可及”的梦想,使用起来方便快捷,用完 即走。
小程序的定位:介于 原生 App 和手机 H5 页面之间的产品
小程序都是由我们前端来开发,因为小程序使用的技术是WXML
、WXSS
、JavaScript
,更接近于我们前端的开发技术栈
2、各平台小程序时间线
- 2017 年 1 月 微信小程序上线,依附于微信 App
- 2018 年 7 月 百度小程序上线,依附于百度 App
- 2018 年 9 月 支付宝程序上线,依附于支付宝 App
- 2018 年 10 月 抖音小程序上线,依附于抖音 App
- 2018 年 11 月 头条小程序上线,依附于头条 App
- 2019 年 5 月 QQ 小程序上线,依附于 QQApp
- 2019 年 10 月 美团小程序上线,依附于美团 App
3、为什么各个平台都支持小程序
- 第一:你有,我也要有
- 第二:小程序作为介于 H5 页面和 App 之间的一项技术,它有自身很大的优势:
- 体验比传统 H5 页面要好很多
- 相当于传统的 App,使用起来更加方便,不需要在应用商店中下载安装,甚至注册登录等麻烦的操作;
- 第三:小程序可以间接的动态为 App 添加新功能
- 传统的 App 更新需要先打包,上架到应用商店之后需要通过审核(App Store)
- 小程序可以在 App 不更新的情况下,动态为自己的应用添加新的功能需求
4、目前使用最广泛的小程序平台
微信小程序最多,支付宝、抖音小程序也或多或少有人在使用
目前公司开发小程序主要开发的还是微信小程序
5、技术选型
A、原生小程序开发:
微信小程序:WXML、WXSS、JavaScript
微信开发文档:https://developers.weixin.qq.com/miniprogram/dev/framework/
支付宝小程序:AXML、ACSS、JavaScript
B、框架开发
- mpvue : 是一个使用 Vue 开发小程序的前端框架,支持微信小程序、百度智能小程序,头条小程序和支付宝小程序 目前已经被放弃
- wepy : 由腾讯开源,让小程序支持组件化开发的框架,目前维护也很少
- uni-app : 由 DCloud 团队开发维护,跨平台,是一个使用 Vue 开发所有前端应用的框架,目前是很多公司的技术选型
- taro : 由京东团队开发维护,跨平台,是一个开放式跨端、跨框架解决方案,支持
React
/Vue
/Nerv
等框架。在 Taro3.x 之后,支持 Vue3、React Hook 写法 - uni-app 和 taro 开发原生 App
7、小程序的核心技术
- 页面布局:WXML,类似 HTML
- 页面样式:WXSS,几乎就是 CSS(某些不支持,某些进行了增强,但是基本是一致的)
- 页面脚本:JavaScript+WXS(WeixinScript)
8、小程序的核心思想
核心思想和 Vue 、React 一致:
- 组件化开发
- 数据响应式
- mustache 语法
- 事件绑定
- ...
环境搭建
1、注册账号-申请 AppID
注册 / 登录地址:https://mp.weixin.qq.com/cgi-bin/wx
注册过程(略)
2、下载小程序开发工具
地址:https://developers.weixin.qq.com/miniprogram/dev/devtools/download.html
注意: 要下载 稳定版 Stable Build
3、使用 VSCode 开发
插件:
WXML - Language Service
: 微信小程序 .wxml 文件代码高亮,标签、属性的智能补全(同时支持原生小程序、mpvue 和 wepy 框架,并提供 code snippets)小程序开发助手
: 代码提示 + 语法高亮,支持 js,json,wxml 文件的代码提示,支持 wxml 文件语法高亮wechat-snippet
: 由微信官方文档照搬下来的代码片段
4、创建小程序项目
5、项目目录结构
基本入门
1、新建页面的方式
示例:基本用法
<!-- 显示普通文本 -->
<text class="text">基础语法</text>
示例:数据绑定 (mustache 语法)
<!-- base.wxml -->
<view class="line message">{{ message }}</view>
// base.js
Page({
data: {
message: '你好,微信~'
}
})
示例:列表渲染
<!-- 列表渲染 ( wx:for, wx:key ) -->
<view class="line movies">
+ <view wx:for="{{ movies }}" wx:key="*this">
+ {{ index }}: {{ item }}
+ </view>
</view>
<!-- 3、列表渲染 (wx:for在block元素上使用) -->
<view class="line moives">
+ <block wx:for="{{ movies }}" wx:key="*this">
<view> {{ item }} </view>
+ </block>
</view>
// base.js
Page({
data: {
movies: ['大话西游', '英雄', '长津湖', '我和我的祖国']
}
})
注意:
<block>
相当于 vue 中的<template>
*this
: 表示item
示例:计数器
<view class="line counter">
<view>
<text>当前计数:</text>
{{ counter }}
</view>
<view class="opr">
+ <button size="mini" type="primary" bind:tap="increment">+</button>
+ <button size="mini" type="warn" bind:tap="decrement">-</button>
</view>
</view>
Page({
data: {
counter: 0
},
increment() {
+ this.setData({
+ counter: this.data.counter + 1
+ })
},
decrement() {
this.setData({
counter: this.data.counter - 1
})
}
})
注意:
bind: tap="increment"
: 绑定事件,也可以写成:bindtap="increment"
this.setData({counter})
: 响应式修改 data 中的数据,并被重新渲染到页面中,如果通过this.data.counter
只能修改 data 中的数据,但是不会被重新渲染到页面中
MVVM 架构
Vue 和小程序的 MVVM 架构对比:
MVVM 架构的好处:
DOM Listeners
: ViewModel 层可以将 DOM 的监听绑定到 Model 层Data Bindings
: ViewModel 层可以将数据的变量, 响应式的反应到 View 层- MVVM 架构让我们从
命令式编程
转到了声明式编程
架构和配置
双线程模型
1、小程序宿主环境
宿主环境:微信客户端给小程序所提供的环境为宿主环境
2、双线程模型
小程序基于 WebView 环境下时,WebView 的 JS 逻辑、DOM 树创建、CSS 解析、样式计算、Layout、Paint (Composite) 都发生 在同一线程,在 WebView 上执行过多的 JS 逻辑可能阻塞渲染,导致界面卡顿
小程序同时考虑了性能与安全,采用了目前称为「双线程模型」的架构。
双线程模型:
WXML
模块和WXSS样式
运行于 渲染层,渲染层使用WebView
线程渲染(一个程序有多个页面,会使用多个 WebView 的线程)。JS脚本
(app.js/home.js 等)运行于 逻辑层,逻辑层使 用JsCore
运行 JS 脚本- 这两个线程都会经由微信客户端(Native)进行中转交互
skyline(最新的渲染器):用来取代 WebView,直接渲染到底层 GPU
配置文件
小程序的很多开发需求被规定在了配置文件中,这样可以更有利于我们提升开发效率;保证开发出来的小程序的风格比较一致
project.config.json
: 项目配置文件, 比如项目名称、appid 等 链接:项目配置文件project.private.config.json
:sitemap.json
: 小程序搜索相关。链接:小程序搜索app.json
: 全局配置<page>.json
: 页面配置
项目配置
- 可以在
project.config.json
文件中配置公共的配置,在project.private.config.json
配置个人的配置,可以将project.private.config.json
写到.gitignore
避免版本管理的冲突。 - 开发者工具内的设置修改会优先覆盖
project.private.config.json
的内容 project.private.config.json
中的相同设置优先级高于project.config.json
全局配置
小程序根目录下的 app.json
文件用来对微信小程序进行全局配置。文件内容为一个 JSON 对象,有以下属性
常用配置
属性 | 类型 | 必填 | 描述 | 最低版本 |
---|---|---|---|---|
pages | string[] | 是 | 页面路径列表 | |
window | Object | 否 | 全局的默认窗口表现 | |
tabBar | Object | 否 | 底部 tab 栏的表现 | |
sitemapLocation | string | 是 | 指明 sitemap.json 的位置 | |
style | string | 否 | 指定使用升级后的 weui 样式,如'v2' | 2.8.0 |
其他配置
entryPagePath 、networkTimeout、debug、functionalPages、subpackages、workers、requiredBackgroundModes、requiredPrivateInfos、plugins、preloadRule、resizable、usingComponents、permission、useExtendedLib、entranceDeclare、darkmode、themeLocation、lazyCodeLoading、singlePage、supportedMaterials、serviceProviderTicket、embeddedAppIdList、halfPage、debugOptions、enablePassiveEvent、resolveAlias、renderer、
页面配置
常用配置
属性 | 类型 | 默认值 | 描述 | 最低版本 |
---|---|---|---|---|
navigationBarBackgroundColor | HexColor | #000000 | 导航栏背景颜色,如 #000000 | |
navigationBarTextStyle | string | white | 导航栏标题颜色,仅支持 black / white | |
navigationBarTitleText | string | 导航栏标题文字内容 | ||
navigationStyle | string | default | 导航栏样式,仅支持以下值: default 默认样式 custom 自定义导航栏,只保留右上角胶囊按钮。 | iOS/Android 微信客户端 7.0.0,Windows 微信客户端不支持 |
backgroundColor | HexColor | #ffffff | 窗口的背景色 | |
backgroundTextStyle | string | dark | 下拉 loading 的样式,仅支持 dark / light | |
backgroundColorTop | string | #ffffff | 顶部窗口的背景色,仅 iOS 支持 | 微信客户端 6.5.16 |
backgroundColorBottom | string | #ffffff | 底部窗口的背景色,仅 iOS 支持 | 微信客户端 6.5.16 |
enablePullDownRefresh | boolean | false | 是否开启当前页面下拉刷新。 详见 Page.onPullDownRefresh | |
onReachBottomDistance | number | 50 | 页面上拉触底事件触发时距页面底部距离,单位为 px。 详见 Page.onReachBottom | |
usingComponents | Object | 否 | 页面自定义组件配置 | 1.6.3 |
其他配置
homeButton、pageOrientation、disableScroll、initialRenderingCache、style、singlePage、restartStrategy、handleWebviewPreload、visualEffectInBackground、enablePassiveEvent、renderer
注:并不是所有
app.json
中的配置都可以在页面覆盖或单独指定,仅限于本文档包含的选项。注:iOS/Android 客户端 7.0.0 以下版本,
navigationStyle
只在app.json
中生效。
示例:tabbar 导航栏
// app.json
"tabBar": {
"selectedColor": "#ff8198",
"list": [
{
"pagePath": "pages/index/index",
"iconPath": "assets/tabbar/home.png",
"selectedIconPath": "assets/tabbar/home_active.png",
"text": "首页"
},
{
"pagePath": "pages/category/category",
"iconPath": "assets/tabbar/category.png",
"selectedIconPath": "assets/tabbar/category_active.png",
"text": "分类"
},
{
"pagePath": "pages/cart/cart",
"iconPath": "assets/tabbar/cart.png",
"selectedIconPath": "assets/tabbar/cart_active.png",
"text": "购物车"
},
{
"pagePath": "pages/profile/profile",
"iconPath": "assets/tabbar/profile.png",
"selectedIconPath": "assets/tabbar/profile_active.png",
"text": "我的"
}
]
},
示例:下拉刷新缩短等待时间
// category.json
{
+ "enablePullDownRefresh": true,
"backgroundTextStyle": "dark"
}
// category.js
Page({
+ onPullDownRefresh() {
console.log('下拉刷新 - 开始');
setTimeout(function() {
+ wx.stopPullDownRefresh({
+ success: (res) => { console.log('停止刷新 - 成功'); },
+ fail: (err) => { console.log('停止刷新 - 失败'); }
+ })
},500)
}
})
示例:上拉加载更多数据
<!-- category.wxml -->
<view class="load-more">
<block wx:for="{{ dataList }}" wx:key="*this">
<view> 数据列表:{{ item }} </view>
</block>
</view>
// category.js
Page({
data: {
+ dataList: 30
},
onPullDownRefresh() {
console.log('下拉刷新 - 开始');
+ // 重置dataList
+ this.setData({
+ dataList: 30
+ })
},
+ onReachBottom() {
+ console.log('已经触底');
+ this.setData({
+ dataList: this.data.dataList + 30
+ })
}
})
注册小程序
App()
注册小程序。接受一个 Object
参数,其指定小程序的生命周期回调等。
*注意:*App() 必须在 app.js 中调用,必须调用且只能调用一次。不然会出现无法预期的后果。
- App():
(options)
,注册小程序。接受一个Object
参数,其指定小程序的生命周期回调等。参数:options:
{ onLaunch, onShow, onHide, onError, onPageNotFound, onUnhandledRejection, onThemeChange }
onLaunch:
(options) => void
,生命周期回调——监听小程序初始化。- options
- scene:
number
,启动小程序的场景值
onShow:
(options) => void
,生命周期回调——监听小程序启动或切前台。- options
- scene:
number
,启动小程序的场景值
onHide:
() => void
,生命周期回调——监听小程序切后台。onError:
function
,错误监听函数。onPageNotFound:
function
,页面不存在监听函数。onUnhandledRejection:
function
,未处理的 Promise 拒绝事件监听函数。onThemeChange:
function
,监听系统主题变化其他:
any
,开发者可以添加任意的函数或数据变量到Object
参数中,用this
可以访问
4、注册 App 时,内部做了什么
- 判断小程序的进入场景
- 监听生命周期函数,在生命周期中执行对应的业务逻辑
- 定义全局 App 的数据,因为 App()实例只有一个,并是全局共享的单例对象,所以可以保存共享数据
作用一:判断打开场景
1、常见打开场景:
- 1008: 群聊会话中打开
- 小程序列表中打开
- 1011: 微信扫一扫打开
- 1037: 另一个小程序打开
2、场景值列表:https://developers.weixin.qq.com/miniprogram/dev/reference/scene-list.html
3、在 onLaunch 和 onShow 生命周期回调函数中,会有 options 参数,其中有 scene 值
作用二:定义全局 App 的数据
1、在app.js
中定义
2、在page.js
中访问
作用三:生命周期函数
用户登录
Page()
注册小程序中的一个页面。接受一个 Object
类型参数,其指定页面的初始数据、生命周期回调、事件处理函数等。
Page():
(options)
,注册小程序中的一个页面。接受一个Object
类型参数,其指定页面的初始数据、生命周期回调、事件处理函数等。参数:options
data:
object
,页面的初始数据options:
object
,页面的组件选项,同 Component 构造器 中的 options ,需要基础库版本 2.10.1behaviors:
string | array
,类似于 mixins 和 traits 的组件间代码复用机制,参见 behaviors,需要基础库版本 2.9.2生命周期回调函数
onLoad:
function(query)
,生命周期回调—监听页面加载- 参数:
query
- 参数:
onShow:
function()
,生命周期回调—监听页面显示onReady:
function()
,生命周期回调—监听页面初次渲染完成onHide:
function()
,生命周期回调—监听页面隐藏onUnload:
function()
,生命周期回调—监听页面卸载事件处理函数
onPullDownRefresh():
function
,监听用户下拉动作onReachBottom():
function
,页面上拉触底事件的处理函数onShareAppMessage():
function
,用户点击右上角转发。- 参数:
{from, target, webViewUrl}
。 - 返回值:
{title, path, imageUrl, promise}
- 参数:
onShareTimeline():
function
,用户点击右上角转发到朋友圈onAddToFavorites():
function
,用户点击右上角收藏。- 参数:
{webViewUrl, title, imageUrl, query}
- 参数:
onPageScroll():
function
,页面滚动触发事件的处理函数。- 参数:
{scrollTop}
- 参数:
onResize():
function
,页面尺寸改变时触发,详见 响应显示区域变化- 参数:
res
- 参数:
onTabItemTap():
function
,当前是 tab 页时,点击 tab 时触发- 参数:
{index, pagePath, text}
- 参数:
onSaveExitState():
function
,页面销毁前保留状态回调其他:
any
,开发者可以添加任意的函数或数据到 Object 参数中,在页面的函数中用 this 可以访问。这部分属性会在页面实例创建时进行一次深拷贝。组件事件处理函数
Page.route:
string
,到当前页面的路径Page.prototype.setData():
function
,将数据从逻辑层发送到视图层(异步),同时改变对应的this.data
的值(同步)- 参数:
{data, callback}
- 参数:
业务 1:发送网络请求,获取服务器数据
业务 2:初始化本地数据
业务 3:监听 WXML 点击,绑定事件函数
示例: 点击不同按钮,打印对应的内容
1、定义按钮内容
2、遍历渲染按钮,并设置不同的颜色
3、监听按钮点击事件,并通过data-xxx
携带参数
4、定义事件函数,并通过event.target.dataset.xxx
获取参数值
业务 4:监听其他事件:页面滚动,上拉加载,下拉刷新
1、开启下拉刷新功能
2、定义下拉刷新,上拉加载,页面滚动事件函数
页面滚动时可以通过event.scrollTop
获取滚动的距离
Page 页的生命周期
onshow(options) 判断进入场景
常见内置组件
text
基本使用
<text>Hello World</text>
<text>{{ message }}</text>
属性-常用
user-select:
boolean
,文本是否可选,该属性会使文本节点显示为 inline-blockspace:
string
,显示连续空格- ensp:中文字符空格一半大小
- emsp:中文字符空格大小
- nbsp:根据字体设置的空格大小
decode:
boolean
,是否解码
user-select
<text user-select>{{ message }}</text>
<text user-select="{{ true }}">{{ message }}</text>
decode
<text decode>></text>
注意:
- decode 可以解析的有
<
>
&
'
 
 
- text 组件内只支持 text 嵌套
- 除了文本节点以外的其他节点都无法长按选中
button
基本使用
<!-- 块级元素 -->
<button>按钮</button>
属性-常用
- size:
default | mini
,按钮的大小 - type:
primary | default | warn
,按钮的样式类型 - plain:
boolean
,按钮是否镂空,背景色透明 - disabled:
boolean
,是否禁用 - loading:
boolean
,名称前是否带 loading 图标 - form-type:
submit | reset
,用于 form 组件,点击分别会触发 form 组件的 submit/reset 事件 - hover-class:
string
,指定按钮按下去的样式类。当hover-class="none"
时,没有点击态效果 - open-type:
string
,微信开放能力- contact:
,打开客服会话,如果用户在会话中点击消息卡片后返回小程序,可以从 bindcontact 回调中获得具体信息,具体说明 (小程序插件中不能使用)
- share:
,触发用户转发,使用前建议先阅读使用指引
- getPhoneNumber:
,获取用户手机号,可以从 bindgetphonenumber 回调中获取到用户信息,具体说明 (小程序插件中不能使用)
- getUserInfo:
,获取用户信息,可以从 bindgetuserinfo 回调中获取到用户信息 (小程序插件中不能使用)
- launchApp:
,打开 APP,可以通过 app-parameter 属性设定向 APP 传的参数具体说明
- openSetting:
,打开授权设置页
- feedback:
,打开“意见反馈”页面,用户可提交反馈内容并上传日志,开发者可以登录小程序管理后台后进入左侧菜单“客服反馈”页面获取到反馈内容
- chooseAvatar:
,获取用户头像,可以从 bindchooseavatar 回调中获取到头像信息
- contact:
size: default | mini
<button size="mini">按钮size属性</button>
type: primary | warn | default
<button type="primary">按钮type属性</button>
<button type="warn">按钮type属性</button>
plain
<button plain>按钮plain属性</button>
disabled
<button disabled>按钮disabled属性</button>
loading
<button loading>按钮loading属性</button>
hover-class
<button hover-class="active">按钮hover-class属性</button>
open-type
open-type="contact"
打开客服会话,如果用户在会话中点击消息卡片后返回小程序,可以从 bindcontact 回调中获得具体信息
open-type="getUserInfo"
获取用户信息,可以从wx.getUserProfile()
回调中获取到用户信息
1、绑定事件(注意:不用绑定open-type="getUserInfo"
)
2、事件回调
open-type="getPhoneNumber"
获取用户手机号,可以从 bindgetphonenumber 回调中获取到用户信息
注意:
- 个人开发者没有获取手机号的权限
- 企业开发者有获取手机号的权限,会获取到一个 code,然后根据该 code 去服务器请求真实的手机号。收费:0.03 元/次
1、绑定事件
2、事件回调
3、个人开发者没有获取手机号的权限
view
视图容器
基本使用
<view>我是view组件</view>
属性-常用
- hover-class:
string
,指定按下去的样式类。当hover-class="none"
时,没有点击态效果 - hover-stop-propagation:
boolean
,默认:false
,指定是否阻止本节点的祖先节点出现点击态 - hover-start-time:
number
,默认:50
,按住后多久出现点击态,单位毫秒 - hover-stay-time:
number
,默认:400
,手指松开后点击态保留时间,单位毫秒
注意: 如果需要使用滚动视图,请使用 <scroll-view>
示例
<view bindtap="onViewClick" hover-class="active">我是view组件</view>
onViewClick() {
console.log('onViewClick')
}
image
基本使用
图片
注意:
- image 元素默认宽高:320x240
<image src="/assets/zznh.png" />
<image
src="https://www.gannett-cdn.com/-mm-/8d3b98b3882527c4b1777d0b11b082fdfebfb6d9/c=0-0-3400-1918/local/-/media/Salisbury/2014/08/09/bobcatt.jpg"
/>
属性-常用
src:
string
,图片资源地址mode:
string
,图片裁剪、缩放的模式- widthFix:``,(推荐),缩放模式,宽度不变,高度自动变化,保持原图宽高比不变
- heightFix:``,缩放模式,高度不变,宽度自动变化,保持原图宽高比不变
- aspectFit:``,缩放模式,保持纵横比缩放图片,使图片的长边能完全显示出来。也就是说,可以完整地将图片显示出来
webp:
boolean
,默认不解析 webP 格式,只支持网络资源lazy-load:
boolean
,图片懒加载,在即将进入一定范围(上下三屏)时才开始加载show-menu-by-longpress:
boolean
,长按图片显示发送给朋友、收藏、保存图片、搜一搜、打开名片/前往群聊/打开小程序(若图片中包含对应二维码或小程序码)的菜单。binderror:
eventhandle
,当错误发生时触发,event.detail = {errMsg}
bindload:
eventhandle
,当图片载入完毕时触发,event.detail = {height, width}
mode
选择本地图片并展示
1、绑定事件,选择图片
2、事件函数
3、res 返回值
4、保存图片地址
5、展示图片
scroll-view
常用属性
属性 | 类型 | 默认值 | 必填 | 说明 | 最低版本 | |
---|---|---|---|---|---|---|
scroll-x | boolean | false | 否 | 允许横向滚动 | 1.0.0 | |
scroll-y | boolean | false | 否 | 允许纵向滚动 | 1.0.0 | |
enable-flex | boolean | false | 否 | 启用 flexbox 布局。开启后,当前节点声明了 display: flex 就会成为 flex container,并作用于其孩子节点。 | 2.7.3 | |
bindscrolltoupper | eventhandle | 否 | 滚动到顶部/左边时触发 | 1.0.0 | ||
bindscrolltolower | eventhandle | 否 | 滚动到底部/右边时触发 | 1.0.0 | ||
bindscroll | eventhandle | 否 | 滚动时触发,event.detail = {scrollLeft, scrollTop, scrollHeight, scrollWidth, deltaX, deltaY} | 1.0.0 |
注意: 滚动的前提:
- 固定的宽度或高度
- 内容需要超出宽度或高度
- 设置 scroll-x 或 scroll-y
上下滚动
1、遍历生成多个 view,撑起 scroll-view
2、设置 scroll-view 固定的高度
3、开启上下滚动
左右滚动
1、设置 scroll-view 固定的宽度(默认占据整行)
2、水平布局 view 元素
- 开启 scroll-view 的 enable-flex 属性
- 使用 wxss 水平布局
3、开启左右滚动
监听 scroll-view 滚动
1、监听事件
2、事件函数
3、event 参数
4、deltaX 表示当前是想左还是向右滚动
- deltaX > 0:向右滚动
- deltaX < 0:向左滚动
input
新增 input 支持双向绑定
组件共同属性
属性名 | 类型 | 描述 | 注解 |
---|---|---|---|
id | String | 组件的唯一标示 | 保持整个页面唯一 |
class | String | 组件的样式类 | 在对应的 WXSS 中定义的样式类 |
style | String | 组件的内联样式 | 可以动态设置的内联样式 |
hidden | Boolean | 组件是否显示 | 所有组件默认显示 |
data-* | Any | 自定义属性 | 组件上触发的事件时,会发送给事件处理函数 |
bind * / catch* | EventHandler | 组件的事件 | 详见事件 |
WXSS 语法
基本语法
全局样式、页面样式、行内样式
wxss 支持的选择器:
选择器 | 样例 | 样例描述 |
---|---|---|
.class | .intro | 选择所有拥有 class="intro" 的组件 |
#id | #firstname | 选择拥有 id="firstname" 的组件 |
element | view | 选择所有 view 组件 |
element, element | view, checkbox | 选择所有文档的 view 组件和所有的 checkbox 组件 |
::after | view::after | 在 view 组件后边插入内容 |
::before | view::before | 在 view 组件前边插入内容 |
权重
WXSS 的权重和 CSS 类似:
尺寸单位 rpx
rpx(responsive pixel): 可以根据屏幕宽度进行自适应。规定屏幕宽为 750rpx。
如在 iPhone6 上,屏幕宽度为 375px,共有 750 个物理像素,则 750rpx = 375px = 750 物理像素,1rpx = 0.5px = 1 物理像素。
设备 | rpx 换算 px (屏幕宽度/750) | px 换算 rpx (750/屏幕宽度) |
---|---|---|
iPhone5 | 1rpx = 0.42px | 1px = 2.34rpx |
iPhone6 | 1rpx = 0.5px | 1px = 2rpx |
iPhone6 Plus | 1rpx = 0.552px | 1px = 1.81rpx |
建议: 开发微信小程序时设计师可以用 iPhone6 作为视觉稿的标准。
注意: 在较小的屏幕上不可避免的会有一些毛刺,请在 2 开发时尽量避免这种情况
以 375px 宽度屏幕的 iPhone6 为标准,如下设置
导入样式
使用@import
语句可以导入外联样式表,@import
后跟需要导入的外联样式表的相对路径。
/** app.wxss **/
+ @import "common.wxss";
.middle-p {
padding:15px;
}
WXML 语法
基本规则
- 类似于 HTML 代码,可以写成单标签,也可以写成双标签
- 必须有严格的闭合,否则会导致编译错误
- 大小写敏感
数据绑定 Mustache
<!-- 1. Munstache语法 -->
<view>{{ message }}</view>
<view>{{ firstname + ' ' + lastname }}</view>
注意: 不允许在 中调用方法
<!-- 错误的写法:不允许调用方法 -->
<view>{{ testDemo() }}</view>
条件渲染 wx:if
和 Vue 的区别:
- v-if === wx:if
- v-else-if === wx:elif
hidden 属性
列表渲染 wx:for
基本使用
遍历数组
遍历数字
遍历字符串
block 组件
item、index 重命名
wx:key 的作用
WXS 语法
介绍
注意: wxs 中不支持 ES6+语法
基本入门
1、添加价格符号
wxs 写法一:标签<wxs>
wxs 写法二:独立的.wxs 文件,通过 src 引入
2、计算总价格
3、格式化数字单位
4、格式化时间
补零函数
事件处理
事件监听
什么时候会产生事件
- 小程序需要经常和用户进行某种交互,比如点击界面上的某个按钮或者区域,比如滑动了某个区域;
- 事件是视图层到逻辑层的通讯方式;
- 事件可以将用户的行为反馈到逻辑层进行处理;
- 事件可以绑定在组件上,当触发事件时,就会执行逻辑层中对应的事件处理函数;
- 事件对象可以携带额外信息,如 id, dataset, touches;
事件如何处理
- 事件是通过 bind/catch 这个属性绑定在组件上的(和普通的属性写法很相似, 以
key="value"
形式); - key 以 bind 或 catch 开头, 从 1.5.0 版本开始, 可以在 bind 和 catch 后加上一个冒号;
- 同时在当前页面的 Page 构造器中定义对应的事件处理函数, 如果没有对应的函数, 触发事件时会报错;
- 比如当用户点击该 button 区域时,达到触发条件生成事件 tap,该事件处理函数会被执行,同时还会收到一个事件对象 event。
事件的基本使用
常见事件
公共事件
- touchstart:``,手指触摸动作开始
- touchmove:``,手指触摸后移动
- touchcancel:``,手指触摸动作被打断,如来电提醒,弹窗
- touchend:``,手指触摸动作结束
- tap:``,手指触摸后马上离开
- longpress:``,手指触摸后,超过 350ms 再离开,如果指定了事件回调函数并触发了这个事件,tap 事件将不被触发
- longtap:``,手指触摸后,超过 350ms 再离开(推荐使用 longpress 事件代替)
input 常见特有事件
- bindinput:
eventhandle
,键盘输入时或内容改变时触发。event.detail = { value: string, cursor?: number, keyCode?: number }
,cursor 为光标位置,keyCode 为键值。2.1.0 起支持,处理函数可以直接 return 一个字符串,将替换输入框的内容。 - bindfocus:
eventhandle
,输入框聚焦时触发,event.detail = { value, height }
,height 为键盘高度,在基础库 1.9.90 起支持 - bindblur:
eventhandle
,输入框失去焦点时触发,event.detail = { value, encryptedValue, encryptError }
scroll-view 常见特有事件
- bindscrolltoupper:
eventhandle
,滚动到顶部/左边时触发 - bindscrolltolower:
eventhandle
,滚动到底部/右边时触发
事件对象 event
当某个事件触发时, 会产生一个事件对象, 并且这个对象被传入到回调函数中, 事件对象有哪些常见的属性呢?
BaseEvent 基础事件对象属性列表:
- type:
string
,事件类型 - timeStamp:
integer
,事件生成时的时间戳 - target:
{ id, dataset... }
,当前触发事件的组件的一些属性值集合 - currentTarget:
{ id, dataset... }
,当前处理事件的组件的一些属性值集合 - mark:
object
,事件标记数据
区分 currentTarget、target
说明: 事件绑定在 outer 元素上,点击的是 inner 元素
建议使用event.currentTarget
接收参数
区分 touches、changedTouches
事件参数传递
data-*
使用 data-*
来传递参数
建议使用event.currentTarget
接收参数
案例:切换标签
mark
注意:
- 在 2.7.1 版本后支持该属性
- mark 会将元素及其子元素上所有用
mark:*
传递的参数统一放入event.mark
中
接收参数
结果
冒泡和捕获的区别
1、捕获阶段
2、冒泡阶段
3、catch
和 bind 的区别:catch 捕获到事件后,会阻止事件再继续传递
组件化开发
Component()
创建自定义组件,接受一个 Object
类型的参数。
1、语法
Component(Object: options)
2、参数
- properties:
object | map
,组件的对外属性,是属性名到属性设置的映射表- type:``,属性的类型
- value:``,属性的初始值
- observer:
function
,属性值变化时的回调函数
- data:
object
,组件的内部数据,和properties
一同用于组件的模板渲染 - observers:
object
,组件数据字段监听器,用于监听 properties 和 data 的变化,参见 数据监听器 - methods:
object
,组件的方法,包括事件响应函数和任意的自定义方法,关于事件响应函数的使用,参见 组件间通信与事件 - behaviors:
string | array
,类似于 mixins 和 traits 的组件间代码复用机制,参见 behaviors - 组件生命周期函数
- created:
function
,组件生命周期函数 - 在组件实例刚刚被创建时执行,注意此时不能调用 setData - attached:
function
,组件生命周期函数 - 在组件实例进入页面节点树时执行 - ready:
function
,组件生命周期函数 - 在组件布局完成后执行 - moved:
function
,组件生命周期函数 - 在组件实例被移动到节点树另一个位置时执行 - detached:
function
,组件生命周期函数 - 在组件实例被从页面节点树移除时执行 - relations:
object
,组件间关系定义,参见 组件间关系 - externalClasses:
string | array
,组件接受的外部样式类,参见 外部样式类 - options:
object | map
,一些选项(文档中介绍相关特性时会涉及具体的选项设置,这里暂不列举)- styleIsolation:
string
,样式隔离- isolated:启用样式隔离,在自定义组件内外,使用 class 指定的样式将不会相互影响(默认)
- apply-shared:页面 wxss 样式将影响到自定义组件,但自定义组件 wxss 中的样式不会影响页面
- shared:页面 wxss 样式将影响到自定义组件,自定义组件 wxss 中的样式也会影响页面和其他设置
- multipleSlots:
boolean
,是否启用多插槽
- styleIsolation:
- lifetimes:
object
,组件生命周期声明对象,参见 组件生命周期 - pageLifetimes:
object
,组件所在页面的生命周期声明对象,参见 组件生命周期
3、组件实例方法(常用)
使用示例:this.setData({ name: '张飞' })
- setData:
function({})
,设置 data 并执行视图层渲染 - triggerEvent:
function({name, detail, options})
,触发事件 - selectComponent:
function(selector)
,使用选择器选择组件实例节点,返回匹配到的第一个组件实例对象 - selectAllComponents:
function(selector)
,使用选择器选择组件实例节点,返回匹配到的全部组件实例对象组成的数组 - getTabBar:``,返回当前页面的 custom-tab-bar 的组件实例
- getPageId:``,返回页面标识符(一个字符串),可以用来判断几个自定义组件实例是不是在同一个页面内
- animate:
function(selector, keyframes, duration, callback)
,执行关键帧动画 - clearAnimation:
function(selector, options, callback)
,清除关键帧动画
组件化思想
小程序在刚刚推出时是不支持组件化的, 也是为人诟病的一个点。从 v1.6.3 开始, 小程序开始支持自定义组件开发
组件化思想的应用
可以将页面内的功能模块抽象成自定义组件,以便在不同的页面中重复使用;
也可以将复杂的页面拆分成多个低耦合的模块,有助于代码维护
尽可能的将页面拆分成一个个小的、可复用的组件,这样让我们的代码更加方便组织和管理,并且扩展性也更强
自定义组件
1、内置组件
<!-- 内置组件 -->
<text>内置组件 text</text>
2、创建组件
1、创建组件文件夹,创建一个自定义组件
2、在 json 文件中设置:
{ "component": true }
3、在 wxml 中编写组件模板
4、在 wxss 中编写组件样式
5、在 js 中定义数据和组件内部的逻辑
3、使用组件
全局使用组件:
在
app.json
中设置 usingComponentsjson{ "usingComponents": { "section-info": "/components/section-info/section-info" } }
局部使用组件:
在
pages/D03-component/D03-component.json
中设置 usingComponentsjson{ "usingComponents": { "section-info": "/components/section-info/section-info" } }
4、注意事项
- 自定义组件也可以引用自定义组件,引用方法类似于页面引用自定义组件的方式(使用 usingComponents 字段)
- 自定义组件和页面所在项目根目录名 不能以“wx-”为前缀,否则会报错。
- 如果在app.json的usingComponents声明某个组件,那么所有页面和组件可以直接使用该组件
组件样式-实现细节
1、组件内的样式 对 外部样式 的影响
- 结论一:组件内的 class 样式,只对组件 wxml 内的节点生效, 对引用组件的 Page 页面不生效。
- 结论二:组件内不能使用 id 选择器、属性选择器、标签选择器
<!-- 组件内部 -->
<view class="title">我是组件内部的样式</view>
<!-- 组件外部 -->
<test-style></test-style>
<view class="title">我是组件外部的样式</view>
2、外部样式 对 组件内样式 的影响
- 结论一:外部使用class的样式,只对外部 wxml 的 class 生效,不会影响组件内部样式
- 结论二:外部使用了id 选择器、属性选择器,不会影响组件内部样式
- 结论三:外部使用了标签选择器,会影响组件内部
3、如何让 class 可以相互影响
- 在 Component 对象中,可以传入一个 options 属性,其中 options 属性中有一个 styleIsolation(隔离)属性。
- styleIsolation 有三个取值:
- isolated: (默认),表示启用样式隔离,在自定义组件内外,使用 class 指定的样式将不会相互影响;
- apply-shared: 表示页面 wxss 样式将影响到自定义组件,但自定义组件 wxss 中指定的样式不会影响页面;
- shared: 表示页面 wxss 样式将影响到自定义组件,自定义组件 wxss 中指定的样式也会影响页面和其他设置
<!-- 组件内部 -->
<view class="title">我是组件内部的样式</view>
<script>
+ Component({
+ options: {
+ styleIsolation: 'shared'
}
})
</script>
<style>
.title {
+ color: red
}
</style>
<!-- 组件外部 -->
<test-style></test-style>
<view class="title">我是页面的样式</view>
<style>
.title {
+ background-color: orange;
}
</style>
组件通信
很多情况下,组件内展示的内容(数据、样式、标签),并不是在组件内写死的,而且可以由使用者来决定
1、向组件传递数据 - properties
给组件传递数据:
- 大部分情况下,组件只负责布局和样式,内容是由使用组件的对象决定的;
- 所以,我们经常需要从外部传递数据给我们的组件,让我们的组件来进行展示;
如何传递呢?
- 使用
properties
属性;
支持的类型:
- String、Number、Boolean
- Object、Array、null(不限制类型)
默认值:
- 可以通过 value 设置默认值;
示例:
<!-- 组件外部 -->
<test-style title="鹅鹅鹅" content="鹅,鹅,鹅,曲项向天歌。白毛浮绿水,红掌拨清波。"></test-style>
<test-style title="静夜思" content="床前明月光,疑是地上霜。举头望明月,低头思故乡。"></test-style>
<!-- 组件内部 -->
+ <view class="title">{{ title }}</view> + <view>{{ content }}</view>
<script>
Component({
+ properties: {
+ title: {
+ type: String,
+ value: '组件标题' // Vue中使用的是default
},
+ content: {
+ type: String,
+ value: '组件内容,展示'
}
}
})
</script>
2、向组件传递样式 - externalClasses
给组件传递样式:
- 有时候,我们不希望将样式在组件内固定不变,而是外部可以决定样式。
这个时候,我们可以使用 externalClasses 属性:
- 1、在 Component 对象中,定义 externalClasses 属性
- 2、在组件内的 wxml 中使用 externalClasses 属性中的 class
- 3、在页面中传入对应的 class,并且给这个 class 设置样式
示例:
<!-- 组件外部 -->
+ <test-external-classess info="info"></test-external-classess>
<style>
+ .info {
color: blue;
}
</style>
<!-- 组件内部 -->
+ <view class="info">组件:externalClasses</view>
<script>
Component({
+ externalClasses: ['info']
})
</script>
3、组件向外传递事件 – 自定义事件
有时候是自定义组件内部发生了事件,需要告知使用者,这个时候可以使用自定义事件
注意:
- 自定义组件中的处理函数需要写在
methods
中,而 Page 页面中的处理函数,是直接写在Page
中的 - 组件内部传递的参数,在组件外部需要通过
event.detail
来获取
<!-- 组件内部 -->
<!-- 1、组件内部发生了点击事件onCpnClick -->
<view bind:tap="onCpnClick">组件:标题</view>
<script>
Component({
methods: {
// 2、实现点击事件
onCpnClick() {
console.log('组件title点击!') +
// 3、向组件外部发送cpnClick事件,并传递参数
this.triggerEvent('cpnClick', 'message')
}
}
})
</script>
<!-- 组件外部 -->
<!-- 4、组件外部通过bind:cpnClick获取内部发送过来的事件cpnCLick,并绑定到处理函数onOuterClick上 -->
+ <test-trigger-event bind:cpnClick="onOuterClick"></test-trigger-event>
<script>
Page({
// 5、实现处理函数onOuterClick
+ onOuterClick(e) {
console.log('Outer点击', e.detail, e)
}
})
</script>
4、自定义组件练习
<!-- 组件内部 -->
<view class="tab-control">
<block wx:for="{{ tabs }}" wx:key="*this">
<view class="item {{ currIndex === index ? 'active' : '' }}" + data-index="{{ index }}" bind:tap="onTabClick">
{{ item }}
</view>
</block>
</view>
<script>
Component({
properties: {
tabs: {
type: Array,
value: []
}
},
data: {
currIndex: 0
},
methods: {
// 点击item,处理函数
onTabClick(e) {
+ const index = e.currentTarget.dataset.index // 获取data-index中的index
+ this.setData({ // 设置data中的属性
currIndex: index
})
// 向外发送currIndex
+ this.triggerEvent('emitCurrIndex', this.data.currIndex) // 访问data中的属性currIndex
}
}
})
</script>
<!-- 组件外部 -->
+ <case-tab-control tabs="{{ tabs }}" bind:emitCurrIndex="getCurrIndex"></case-tab-control>
<script>
Page({
data: {
tabs: ['手机','电脑','硬盘','鼠标']
},
// 实现处理函数getCurrIndex
getCurrIndex(e) {
+ const index = e.detail // 获取组件内传递的参数
console.log('点击了:', this.data.tabs[index]);
}
})
</script>
5、页面直接调用组件中的方法
可在父组件里调用 this.selectComponent(selector)
,获取子组件的实例对象。
调用时需要传入一个匹配选择器 selector,如:this.selectComponent(".my-component")。
<!-- 组件外部 -->
<button bind:tap="onChangeIndex">修改index</button>
+ <case-tab-control class="tab-control" tabs="{{ tabs }}" bind:emitCurrIndex="getCurrIndex"></case-tab-control>
<script>
Page({
// 在页面中调用组件中的方法,修改组件中的index
onChangeIndex(e) {
+ const tabControlInstance = this.selectComponent('.tab-control') // 获取组件实例
+ tabControlInstance.innerTest(2) // 调用组件实例中的方法
}
})
</script>
<!-- 组件内部 -->
<script>
Component({
data: {
currIndex: 0
},
methods: {
// 内部被调用的方法
+ innerTest(index) {
console.log('组件内部被调用的方法:innerTest');
+ this.setData({
+ currIndex: index
})
}
}
})
</script>
组件插槽
1、什么是插槽
slot 翻译为插槽:
- 在生活中很多地方都有插槽,电脑的 USB 插槽,插板当中的电源插槽。
- 插槽的目的是让我们原来的设备具备更多的扩展性。
- 比如电脑的 USB 我们可以插入 U 盘、硬盘、手机、音响、键盘、鼠标等等。
组件的插槽:
- 组件的插槽也是为了让我们封装的组件更加具有扩展性。
- 让使用者可以决定组件内部的一些内容到底展示什么。
栗子:移动网站中的导航栏。
- 移动开发中,几乎每个页面都有导航栏。
- 导航栏我们必然会封装成一个插件,比如 nav-bar 组件。
- 一旦有了这个组件,我们就可以在多个页面中复用了。
2、单个插槽的使用
除了内容和样式可能由外界决定之外,也可能外界想决定显示的方式
比如我们有一个组件定义了头部和尾部,但是中间的内容可能是一段文字,也可能是一张图片,或者是一个进度条。
在不确定外界想插入什么其他组件的前提下,我们可以在组件内预留插槽:
基本使用
<!-- 组件内部 -->
<view class="slot-single">
<view class="header">Header</view>
<view class="content">
+ <slot></slot>
</view>
<view class="footer">Footer</view>
</view>
<!-- 组件外部 -->
<slot-single> + <button>我是按钮</button> </slot-single>
<slot-single> + <text>我是文字</text> </slot-single>
解决小程序不支持插槽默认值
说明:和 Vue 不同,小程序中插槽不支持默认值
<!-- 组件内部 -->
<view class="slot-single">
<view class="header">Header</view>
+ <view class="content"> + <slot></slot> </view> + <view class="default">我是插槽默认值</view>
<view class="footer">Footer</view>
</view>
<style>
.default {
display: none;
}
+ /* 当content中为空时,其兄弟元素default显示 */
+ .content:empty + .default {
display: block;
}
</style>
<!-- 组件外部 -->
<slot-single> + <button>我是按钮</button> </slot-single>
<slot-single> + <text>我是文字</text> </slot-single>
3、多个插槽的使用
有时候为了让组件更加灵活, 我们需要定义多个插槽
说明:
- 组件内部:
- slot 的
name
属性,定义了插槽的名称 options.multipleSlots: true
:启用多插槽模式
- slot 的
- 组价外部:
slot
属性,表示使用的是哪个插槽(此为 Vue 早起语法)
<!-- 组件内部 -->
<view class="slot-multi">
<view class="left"> + <slot name="left"></slot> </view>
<view class="center"> + <slot name="center"></slot> </view>
<view class="right"> + <slot name="right"></slot> </view>
</view>
<script>
Component({
+ options: {
+ multipleSlots: true
}
})
</script>
<!-- 组件外部 -->
<slot-multi>
+ <view slot="left">左侧</view> + <view slot="center">内容</view> + <view slot="right">右侧</view>
</slot-multi>
Behavior()
behaviors 是用于组件间代码共享的特性,类似于一些编程语言中的 “mixins”。
每个 behavior 可以包含一组属性、数据、生命周期函数和方法;
组件引用它时,它的属性、数据和方法会被合并到组件中,生命周期函数也会在对应时机被调用;
每个组件可以引用多个 behavior ,behavior 也可以引用其它 behavior ;
语法
Behavior(Object: object)
参数
- properties:
object | map
,组件的对外属性,是属性名到属性设置的映射表 - data:
object
,组件的内部数据,和properties
一同用于组件的模板渲染 - observers:
object
,组件数据字段监听器,用于监听 properties 和 data 的变化 - methods:
object
,组件的方法,包括事件响应函数和任意的自定义方法,关于事件响应函数的使用 - behaviors:
string | array
,类似于 mixins 和 traits 的组件间代码复用机制 - 生命周期函数
- created:
function
,组件生命周期函数 - 在组件实例刚刚被创建时执行,注意此时不能调用 setData - attached:
function
,组件生命周期函数 - 在组件实例进入页面节点树时执行 - ready:
function
,组件生命周期函数 - 在组件布局完成后执行 - moved:
function
,组件生命周期函数 - 在组件实例被移动到节点树另一个位置时执行 - detached:
function
,组件生命周期函数 - 在组件实例被从页面节点树移除时执行 - relations:
object
,组件间关系定义 - lifetimes:
object
,组件生命周期声明对象 - pageLifetimes:
object
,组件所在页面的生命周期声明对象 - definitionFilter:
function
,定义段过滤器,用于自定义组件扩展
返回值
示例
<!-- 组件内部 -->
<!-- 组件的混入-定义一个计数器 -->
<view>当前计数:{{ counter }}</view>
<button bind:tap="increment">+1</button>
<button bind:tap="decrement">-1</button>
<script>
+ import counterBehavior from '../../../../behaviors/counter.js'
Component({
+ behaviors: [counterBehavior]
})
</script>
// behaviors/counter.js 页面
+ export default Behavior({
data: {
counter: 100
},
methods: {
increment() {
this.setData({ counter: this.data.counter + 1 })
},
decrement() {
this.setData({ counter: this.data.counter - 1 })
}
}
})
组件的生命周期
组件的生命周期,指的是组件自身的一些函数,这些函数在特殊的时间点或遇到一些特殊的框架事件时被自动触发。
- 其中,最重要的生命周期是 created attached detached ,包含一个组件实例生命流程的最主要时间点。
自小程序基础库版本 2.2.3 起,组件的的生命周期也可以在 lifetimes
字段内进行声明(这是推荐的方式,其优先级最高)
还有一些特殊的生命周期,它们并非与组件有很强的关联,但有时组件需要获知,以便组件内部处理。样的生命周期称为“组件所在页面的生命周期”,在 pageLifetimes 定义段中定义。
参数
- 组件的生命周期(lifetimes)
- lifetimes:
object
,组件生命周期声明对象,参见 组件生命周期- created:
function
,组件生命周期函数 - 在组件实例刚刚被创建时执行,注意此时不能调用 setData - attached:
function
,组件生命周期函数 - 在组件实例进入页面节点树时执行 - ready:
function
,组件生命周期函数 - 在组件布局完成后执行 - moved:
function
,组件生命周期函数 - 在组件实例被移动到节点树另一个位置时执行 - detached:
function
,组件生命周期函数 - 在组件实例被从页面节点树移除时执行
- created:
- 组件所在页面的生命周期
- pageLifetimes:
object
,组件所在页面的生命周期声明对象,参见 组件生命周期- show:
function
,组件所在的页面被展示时执行 - hide:
function
,组件所在的页面被隐藏时执行 - resize:
function(size)
,组件所在的页面尺寸变化时执行
- show:
示例
Component({
lifetimes: {
created() {
console.log('生命周期: created')
},
attached() {
console.log('生命周期: attached')
},
detached() {
console.log('生命周期: detached')
}
},
pageLifetimes: {
show() {
console.log('页面生命周期: show')
},
hide() {
console.log('页面生命周期: hide')
},
resize(size) {
console.log('页面生命周期: resize', size)
}
}
})
Component 构造器
API
网络请求
wx.request()
wx.request():
(options)
,发起 HTTPS 网络请求参数: options
url:
string
,(必填),开发者服务器接口地址data:
string | object | arrayBuffer
,请求的参数header:
object
,设置请求的 header,header 中不能设置 Referer。content-type
默认为application/json
timeout:
number
,超时时间,单位为毫秒。默认值为 60_000method:
OPTIONS | GET | HEAD | POST | PUT | DELETE | TRACE | CONNECT
,(默认 GET),HTTP 请求方法dataType:
json | 其他
,(默认 json),返回的数据格式responseType:
text | arraybuffer
,(默认 text),响应的数据类型enableHttp2:
boolean
,开启 http2enableQuic:
boolean
,开启 quicenableCache:
boolean
,开启 cacheenableHttpDNS:
boolean
,是否开启 HttpDNS 服务。如开启,需要同时填入 httpDNSServiceIdhttpDNSServiceld:
string
,HttpDNS 服务商 IdenableChunked:
boolean
,开启 transfer-encoding chunkedforceCellularNetwork:
boolean
,wifi 下使用移动网络发送请求success:
function(res)
,接口调用成功的回调函数- 参数:
res: {data, statusCode, header, cookies, errMsg}
- 参数:
fail:
function(err)
,接口调用失败的回调函数- 参数:
err: {errMsg, errno}
- 参数:
complete:
function
,接口调用结束的回调函数(调用成功、失败都会执行)
基本使用
<!-- page页面 -->
+ <learn-request houselist="{{ houselist }}"></learn-request>
<script>
Page({
data: {
allCities: {},
houselist: []
},
+ onLoad() {
+ /* 网络请求的基本使用 */
+ wx.request({
url: 'http://123.207.32.32:1888/api/city/all',
method: 'get',
success: (res) => {
this.setData({ allCities: res.data.data })
},
fail: (err) => {
console.log(err)
}
})
+ /* 网络请求的基本使用-携带参数 */
+ wx.request({
url: 'http://123.207.32.32:1888/api/home/houselist',
data: {
page: 1
},
success: (res) => {
this.setData({ houselist: res.data.data })
}
})
}
})
</script>
<!-- 组件内部 -->
<view class="houselist">
+
<!-- 注意:此处wx:key=""中不能写成 "{{item.data.houseId}}" 或 "data.houseId" 或 "houseId",会报错 -->
+
<block wx:for="{{houselist}}" wx:key="index">
<view class="item">
<view class="item-inner">
+ <image class="album" src="{{item.data.image.url}}" alt="" mode="widthFix" />
<view>{{item.data.houseName}}</view>
</view>
</view>
</block>
</view>
<script>
Component({
+ properties: {
+ houselist: {
type: Array,
value: []
}
}
})
</script>
API 封装
1、封装成函数
function mrRequest(options) {
return new Promise((resolve, reject) => {
wx.request({
...options,
success(res) {
resolve(res.data)
},
fail: reject
})
})
}
export default mrRequest
使用 mrRequest-then 方法
/* 2、网络请求-封装函数 */
mrRequest({
url: 'http://123.207.32.32:1888/api/city/all'
}).then((res) => {
this.setData({ allCities: res.data })
})
mrRequest({
url: 'http://123.207.32.32:1888/api/home/houselist',
data: { page: this.data.nextPage }
}).then((res) => {
const totalHouselist = [...this.data.houselist, ...res.data]
this.setData({ houselist: totalHouselist })
this.data.nextPage++
})
使用 mrRequest-async/await 方法(推荐)
onLoad() {
/* 3、使用 async/await方式 */
this.getAllCities()
this.getHouselist()
},
onReachBottom() {
this.getHouselist()
},
/* 发送请求,获取allCities */
async getAllCities() {
const res = await mrRequestFn({
url: 'http://123.207.32.32:1888/api/city/all'
})
this.setData({ allCities: res.data })
},
/* 发送请求,获取houselist */
async getHouselist() {
const res = await mrRequestFn({
url: 'http://123.207.32.32:1888/api/home/houselist',
data: { page: this.data.nextPage }
})
const totalHouselist = [...this.data.houselist, ...res.data]
this.setData({ houselist: totalHouselist })
this.data.nextPage ++
}
2、封装成类
/* 封装成类 */
class MrRequest {
+ constructor(baseUrl) {
+ this.baseUrl = baseUrl
}
request(options) {
return new Promise((resolve, reject) => {
wx.request({
...options,
+ url: this.baseUrl + options.url,
success: res => {
resolve(res.data)
},
fail: reject
})
})
}
get(options) {
+ return this.request({...options, method: 'GET'})
}
post(options) {
return this.request({ ...options, method: 'POST' })
}
put(options) {
return this.request({ ...options, method: 'PUT' })
}
delete(options) {
return this.request({ ...options, method: 'DELETE' })
}
patch(options) {
return this.request({ ...options, method: 'PATCH' })
}
}
export const mrRequest = new MrRequest('http://123.207.32.32:1888/api')
使用 mrRequest
/* 4、使用类封装的mrRequest发送请求 */
+ mrRequest.get({
+ url: '/city/all'
+ }).then(res => {
console.log(res);
})
网络请求域名配置
每个微信小程序需要事先设置通讯域名,小程序只可以跟指定的域名进行网络通信。
- 小程序登录后台 – 开发管理 – 开发设置 – 服务器域名;
服务器域名请在 「小程序后台 - 开发 - 开发设置 - 服务器域名」 中进行配置,配置时需要注意:
- 域名只支持 https (wx.request、wx.uploadFile、wx.downloadFile) 和 wss (wx.connectSocket) 协议;
- 域名不能使用 IP 地址(小程序的局域网 IP 除外)或 localhost;
- 可以配置端口,如 https://myserver.com:8080,但是配置后只能向 https://myserver.com:8080 发起请求。如果向 https://myserver.com、https://myserver.com:9091 等 URL 请求则会失败。
- 如果不配置端口。如 https://myserver.com,那么请求的 URL 中也不能包含端口,甚至是默认的 443 端口也不可以。如果向 https://myserver.com:443 请求则会失败。
- 域名必须经过 ICP 备案;
- 出于安全考虑,api.weixin.qq.com 不能被配置为服务器域名,相关 API 也不能在小程序内调用。 开发者应将 AppSecret 保存到后台服务器中,通过服务器使用 getAccessToken 接口获取 access_token,并调用相关 API;
- 不支持配置父域名,使用子域名。
展示弹窗
小程序中展示弹窗有四种方式:
wx.showToast():
options
,显示消息提示框- 参数:options
- title:
string
,(必填),提示的内容 - mask:
boolean
,(默认:false),是否显示透明蒙层,防止触摸穿透 - icon:
success | error | loading | none
,图标 - image:
string
,自定义图标的本地路径,image 的优先级高于 icon - duration:
number
,(默认:1500),提示的延迟时间 - success:
function(res)
,接口调用成功的回调函数 - fail:
function(err)
,接口调用失败的回调函数 - complete:
function(res)
,接口调用结束的回调函数(调用成功、失败都会执行)
wx.showModal():
options
,显示模态对话框参数:options
title:
string
,提示的标题content:
string
,提示的内容showCancel:
boolean
,(默认:true),是否显示取消按钮cancelText:
string
,(默认:取消),取消按钮的文字,最多 4 个字符cancelColor:
string
,(默认:#000000),取消按钮的文字颜色,必须是 16 进制格式的颜色字符串confirmText:
string
,(默认:确定),确认按钮的文字,最多 4 个字符confirmColor:
string
,(默认:#576B95),确认按钮的文字颜色,必须是 16 进制格式的颜色字符串editable:
boolean
,(默认:false),是否显示输入框placeholderText:
string
,显示输入框时的提示文本success:
function(res)
,接口调用成功的回调函数- 参数:res
- content:
string
,editable 为 true 时,用户输入的文本 - confirm:
boolean
,为 true 时,表示用户点击了确定按钮 - cancel:
boolean
,为 true 时,表示用户点击了取消(用于 Android 系统区分点击蒙层关闭还是点击取消按钮关闭)
fail:
function(err)
,接口调用失败的回调函数complete:
function(res)
,接口调用结束的回调函数(调用成功、失败都会执行)
wx.showLoading():
options
,显示 loading 提示框。需主动调用 wx.hideLoading 才能关闭提示框- 参数:opitons
- title:
string
,提示的内容 - mask:
boolean
,(默认:false),是否显示透明蒙层,防止触摸穿透 - success:
function(res)
,接口调用成功的回调函数 - fail:
function(err)
,接口调用失败的回调函数 - complete:
function(res)
,接口调用结束的回调函数(调用成功、失败都会执行)
wx.showActionSheet():
options
,显示操作菜单参数:opitons
alertText:
string
,警示文案itemList:
string[]
,按钮的文字数组,数组长度最大为 6itemColor:
string
,(默认:#000000),按钮的文字颜色success:
function(res)
,接口调用成功的回调函数- 参数 res
- tapIndex:
number
,用户点击的按钮序号,从上到下的顺序,从 0 开始
fail:
function(err)
,接口调用失败的回调函数complete:
function(res)
,接口调用结束的回调函数(调用成功、失败都会执行)
/* 展示消息提示框 */
methods: {
onToast() {
wx.showToast({
title: 'showToast',
icon: 'loading',
image: '/assets/tabbar/home_active.png',
duration: 1500,
mask: true,
success:res => {
console.log('success' + res);
},
fail: err => {
console.log('fail' + err);
}
})
},
onLoading() {
wx.showLoading({
title: '加载中...',
mask: true,
success: res => {
console.log('成功:' + res);
wx.hideLoading()
}
})
},
onModal() {
wx.showModal({
title: '删除文件',
content: '确定删除文件?',
editable: true,
cancelText: '我再想想',
confirmText: '决定了',
complete: (res) => {
if (res.cancel) {
console.log('取消删除文件~', res.content);
}
if (res.confirm) {
console.log('确定删除文件~', res.content);
}
}
})
},
onActionSheet() {
wx.showActionSheet({
alertText: '选一个吧~',
itemList: ['苹果','梨子','香蕉','荔枝','火龙果'],
success: res => {
console.log(res, res.tapIndex);
}
})
}
}
分享功能
分享是小程序扩散的一种重要方式,小程序中有两种分享方式:
- 方式一:点击右上角的菜单按钮,之后点击转发
- 方式二:点击某一个按钮,直接转发
当我们转发给好友一个小程序时,通常小程序中会显示一些信息:
- 如何决定这些信息的展示呢?通过 onShareAppMessage
- 监听用户点击页面内转发按钮(button 组件 open-type="share")或右上角菜单“转发”按钮的行为,并自定义转发内容。
- 此事件处理函数需要 return 一个 Object,用于自定义转发内容;
语法
- onShareAppMessage:
function(object)
,监听用户点击页面内转发按钮(button 组件 open-type="share")或右上角菜单“转发”按钮的行为,并自定义转发内容- 参数:object
- from:
button | menu
,转发事件来源。 - target:
object
,如果 from 值是 button,则 target 是触发这次转发事件的 button,否则为 undefined webViewUrl:
string
,页面中包含 web-view 组件时,返回当前 web-view 的 url - 返回值:object
- title:
string
,转发标题(默认:当前小程序名称) - path:
string
,转发路径,(默认:当前页面 path ,必须是以 / 开头的完整路径) - imageUrl:
string
,自定义图片路径,可以是本地文件路径、代码包文件路径或者网络图片路径。支持 PNG 及 JPG。显示图片长宽比是 5:4。 - promise:``,如果该参数存在,则以 resolve 结果为准,如果三秒内不 resolve,分享会使用上面传入的默认参数
Page({
onShareAppMessage() {
return {
title: '我的小程序',
path: '/pages/D05-api/D05-api',
imageUrl: '/assets/tabbar/cart.png'
}
}
})
获取设备信息
在开发中,我们需要经常获取当前设备的信息,用于手机信息或者进行一些适配工作
小程序提供了相关个 API:wx.getSystemInfo(Object object)
语法
- wx.getSystemInfo():
object
,获取系统信息。由于历史原因,wx.getSystemInfo 是异步的调用格式,但是是同步返回,需要异步获取系统信息请使用 wx.getSystemInfoAsync- 参数:object
- success:
function(res)
,接口调用成功的回调函数参数 res(部分常用):
{screenWidth, screenHeight, windowWidth, windowHeight}
- fail:
function(err)
,接口调用失败的回调函数 - complete:
function(res)
,接口调用结束的回调函数(调用成功、失败都会执行)
/* 2、获取设备信息 */
onGetSystemInfo() {
wx.getSystemInfo({
success: function(res) {
console.log(res);
}
})
}
获取位置信息
开发中我们需要经常获取用户的位置信息,以方便给用户提供相关的服务
我们可以通过 API 获取:wx.getLocation(Object object)
语法
- wx.getLocation():
object
,获取当前的地理位置、速度- 参数;object
- type:
wgs84 | gcj02
,(默认:wgs84),wgs84 返回 gps 坐标,gcj02 返回可用于 wx.openLocation 的坐标 - altitude:
boolean
,(默认:false),传入 true 会返回高度信息,由于获取高度需要较高精确度,会减慢接口返回速度 - isHighAccuracy:
boolean
,(默认:false),开启高精度定位 - highAccuracyExpireTime:
number
,高精度定位超时时间(ms),指定时间内返回最高精度,该值 3000ms 以上高精度定位才有效果 - success:
function(res)
,接口调用成功的回调函数- 参数 res
- latitude:
number
,纬度,范围为 -90~90,负数表示南纬 - longitude:
number
,经度,范围为 -180~180,负数表示西经 - speed:
number
,速度,单位 m/s - accuracy:
number
,位置的精确度,反应与真实位置之间的接近程度,可以理解成 10 即与真实位置相差 10m,越小越精确 - altitude:
number
,高度,单位 m - verticalAccuracy:
number
,垂直精度,单位 m(Android 无法获取,返回 0) - horizontalAccuracy:
number
,水平精度,单位 m
- fail:
function(err)
,接口调用失败的回调函数 - complete:
function(res)
,接口调用结束的回调函数(调用成功、失败都会执行)
示例
/* 获取位置信息 */
onGetLocation() {
wx.getLocation({
success(res) {
console.log(res);
}
})
}
*注意:*对于用户的关键信息,需要获取用户的授权后才能获得
在 app.json
中设置如下:
"permission" {
"scope.userLocation": {
"desc": "获取您的位置信息"
}
}
Storage 存储
在开发中,某些常见我们需要将一部分数据存储在本地:比如 token、用户信息等。
- 小程序提供了专门的 Storage 用于进行本地存储。
同步存取数据的方法:
wx.setStorageSync(key, data):``,将数据存储在本地缓存中指定的 key 中。会覆盖掉原来该 key 对应的内容
- 参数:key, data
- key:
string
,本地缓存中指定的 key - data:
any
,需要存储的内容。只支持原生类型、Date、及能够通过JSON.stringify
序列化的对象
wx.getStorageSync(key):``,从本地缓存中同步获取指定 key 的内容
- 参数:key
- key:
string
,本地缓存中指定的 key - 返回值:any
- any:
any
,key 对应的内容
wx.removeStorageSync(key):``,从本地缓存中移除指定 key。
- 参数:key
- key:
string
,本地缓存中指定的 key
wx.clearStorageSync():``,清理本地数据缓存。
异步存储数据的方法:
语法
wx.setStorage(object):``,将数据存储在本地缓存中指定的 key 中。会覆盖掉原来该 key 对应的内容
- 参数:object
- key:
string
,本地缓存中指定的 key - data:
any
,需要存储的内容。只支持原生类型、Date、及能够通过JSON.stringify
序列化的对象 - encrypt:
boolean
,(默认:false),是否开启加密存储。只有异步的 setStorage 接口支持开启加密存储。最低版本 2.21.3 - success:
function(res)
,接口调用成功的回调函数 - fail:
function(err)
,接口调用失败的回调函数 - complete:
function(res)
,接口调用结束的回调函数(调用成功、失败都会执行)
wx.getStorage(object):``,从本地缓存中异步获取指定 key 的内容
- 参数:object
- key:
string
,本地缓存中指定的 key - encrypt:
boolean
,(默认:false),是否开启加密存储。只有异步的 setStorage 接口支持开启加密存储。最低版本 2.21.3 - success:
function(res)
,接口调用成功的回调函数 - fail:
function(err)
,接口调用失败的回调函数 - complete:
function(res)
,接口调用结束的回调函数(调用成功、失败都会执行)
wx.removeStorage(object):``,从本地缓存中移除指定 key。
- 参数:object
- key:
string
,本地缓存中指定的 key - success:
function(res)
,接口调用成功的回调函数 - fail:
function(err)
,接口调用失败的回调函数 - complete:
function(res)
,接口调用结束的回调函数(调用成功、失败都会执行)
wx.clearStorage(object):``,清理本地数据缓存。
- 参数:object
- success:
function(res)
,接口调用成功的回调函数 - fail:
function(err)
,接口调用失败的回调函数 - complete:
function(res)
,接口调用结束的回调函数(调用成功、失败都会执行)
:``,
示例
同步存储
onSetStorage() {
+ wx.setStorageSync('name', '张飞')
wx.setStorageSync('age', 38)
wx.setStorageSync('friends', ['刘备', '关羽'])
},
onGetStorage() {
+ const name = wx.getStorageSync('name')
const age = wx.getStorageSync('age')
const friends = wx.getStorageSync('friends')
console.log(name, age, friends);
},
onRemoveStorage() {
+ wx.removeStorageSync('name')
},
onClearStorage() {
+ wx.clearStorageSync()
}
异步存储
onSetStorage() {
+ wx.setStorage({
key: 'name',
data: '张飞',
encrypt: true,
success(res) { console.log(res); }
})
wx.setStorage({
key: 'age',
data: 21,
encrypt: true,
success(res) { console.log(res); }
})
},
onGetStorage() {
+ wx.getStorage({
key: 'name',
encrypt: true,
success: res => {
console.log(res);
}
})
},
onRemoveStorage() {
+ wx.removeStorage({
key: 'name',
success: res => {
console.log(res);
}
})
},
onClearStorage() {
+ wx.clearStorage({
success: res => {
console.log(res);
}
})
}
界面跳转
界面的跳转有两种方式:
- 通过
navigator
组件 - 通过
wx的API
跳转
这里我们先以 wx 的 API 作为讲解
API
- wx.navigateTo(object):``,保留当前页面,跳转到应用内的某个页面。但是不能跳到 tabbar 页面。使用 wx.navigateBack 可以返回到原页面。小程序中页面栈最多十层。
- 参数:object
- url:
string
,(必填),需要跳转的应用内非 tabBar 的页面的路径 (代码包路径), 路径后可以带参数。参数与路径之间使用?
分隔,参数键与参数值用=
相连,不同参数用&
分隔;如'path?key=value&key2=value2'
- events:
object: {callbackFn,...}
,页面间通信接口,用于监听被打开页面发送到当前页面的数据。基础库 2.7.3 开始支持。 - success:
function(res)
,接口调用成功的回调函数 - fail:
function(err)
,接口调用失败的回调函数 - complete:
function(res)
,接口调用结束的回调函数(调用成功、失败都会执行)
- wx.navigateBack(object):``,关闭当前页面,返回上一页面或多级页面。可通过 getCurrentPages 获取当前的页面栈,决定需要返回几层。
- 参数:object
- delta:
number
,(默认:1),返回的页面数,如果 delta 大于现有页面数,则返回到首页 - success:
function(res)
,接口调用成功的回调函数 - fail:
function(err)
,接口调用失败的回调函数 - complete:
function(res)
,接口调用结束的回调函数(调用成功、失败都会执行)
- wx.redirectTo(object):``,关闭当前页面,跳转到应用内的某个页面。但是不允许跳转到 tabbar 页面
- 参数:object
- url:
string
,(必填),需要跳转的应用内非 tabBar 的页面的路径 (代码包路径), 路径后可以带参数。参数与路径之间使用?
分隔,参数键与参数值用=
相连,不同参数用&
分隔;如'path?key=value&key2=value2'
- success:
function(res)
,接口调用成功的回调函数 - fail:
function(err)
,接口调用失败的回调函数 - complete:
function(res)
,接口调用结束的回调函数(调用成功、失败都会执行)
- wx.switchTab(object):``,跳转到 tabBar 页面,并关闭其他所有非 tabBar 页面
- 参数:object
- url:
string
,(必填),需要跳转的 tabBar 页面的路径 (代码包路径)(需在 app.json 的 tabBar 字段定义的页面),路径后不能带参数。 - success:
function(res)
,接口调用成功的回调函数 - fail:
function(err)
,接口调用失败的回调函数 - complete:
function(res)
,接口调用结束的回调函数(调用成功、失败都会执行)
- wx.reLaunch(object):``,关闭所有页面,打开到应用内的某个页面
- 参数:object
- url:
,(必填),需要跳转的应用内页面路径 (代码包路径),路径后可以带参数。参数与路径之间使用?分隔,参数键与参数值用=相连,不同参数用&分隔;如
'path?key=value&key2=value2'
- success:
function(res)
,接口调用成功的回调函数 - fail:
function(err)
,接口调用失败的回调函数 - complete:
function(res)
,接口调用结束的回调函数(调用成功、失败都会执行)
- :``,
navigateTo
wx.navigateTo(Object object):保留当前页面,跳转到应用内的某个页面,但是不能跳到 tabbar 页面
// 起始页
/* 点击跳转 */
onJump() {
const name = this.data.name
const age = this.data.age
+ wx.navigateTo({
+ url: `/pages/detail/detail?name=${name}&age=${age}`,
})
}
// 跳转到的页面
+ onLoad(query) {
+ const { name, age } = query
+ this.setData({
name,
age
})
}
navigateBack
wx.navigateBack(Object object):关闭当前页面,返回上一页面或多级页面
onJumpBack() {
+ wx.navigateBack({
+ delta: 2 // 跳转2层
})
}
数据传回
如何在界面跳转过程中我们需要相互传递一些数据,应该如何完成呢?
1、数据传递-早期的方法
- 首页 -> 详情页:使用 URL 中的 query 字段
- 详情页 -> 首页:在详情页内部拿到首页的页面对象,直接修改数据
// 跳转到的页面
onJumpBack() {
wx.navigateBack()
// 返回的时候,传递数据回去
+ const pages = getCurrentPages()
+ const prevPage = pages[pages.length - 2]
+ prevPage.setData({ message: {title: 'Hello', content: '返回的内容~'} })
}
<!-- 原来的页面 -->
<!-- 注意:在微信中不能在差值语句{{}}中直接写js文件中的函数调用,只能用在wxs中定义的函数 -->
+ <view>{{format.objToStr(message)}}</view>
+
<wxs module="format">
+ function objToStr(obj) { + return JSON.stringify(obj) } + module.exports = { + objToStr: objToStr }
</wxs>
注意: 如果想让不同方式在返回上一页时,都可以传回参数的话,可以在onUnload
生命周期函数中传递参数
2、数据传递-events 参数对象
events:object: {callbackFn,...}
,页面间通信接口,用于监听被打开页面发送到当前页面的数据。基础库 2.7.3 开始支持。
如果一个页面由另一个页面通过 wx.navigateTo
打开,这两个页面间将建立一条数据通道:
- 被打开的页面可以通过
this.getOpenerEventChannel()
方法来获得一个EventChannel
对象; wx.navigateTo
的success
回调中也包含一个EventChannel
对象。
这两个 EventChannel
对象间可以使用 emit
和 on
方法相互发送、监听事件。
// 原来的页面
/* 点击跳转 */
onJump() {
const name = this.data.name
const age = this.data.age
wx.navigateTo({
url: `/pages/detail/detail?name=${name}&age=${age}`,
+ events: {
+ backData: data => {
+ this.setData({ message: data })
}
}
})
}
// 跳转到的页面
// 2、方法二:使用events,传递数据回去
+ const ec = this.getOpenerEventChannel()
+ ec.emit('backData', { title: 'events', content: '通过events返回的数据~' })
界面跳转的方式
<navigator>
组件主要就是用于界面的跳转的,也可以跳转到其他小程序中:
API
- <navigator>:
组件
,页面链接- 属性(部分):
- target:
self | miniProgram
,在哪个目标上发生跳转,默认当前小程序 - url:
string
,当前小程序内的跳转链接,可以携带 query 格式参数 - open-type:
navigate | navigateBack | redirect | switchTab | reLaunch | exit
,跳转方式 - delta:
number
,(默认:1),当 open-type 为 'navigateBack' 时有效,表示回退的层数 - app-id:
string
,要打开的小程序 appId,当target="miniProgram"
且open-type="navigate"
时有效 - path:
string
,打开的页面路径,如果为空则打开首页,当target="miniProgram"
且open-type="navigate"
时有效
示例
// 原来的页面
<!-- 方式二:navigator组件 -->
<navigator url="/pages/detail/detail?name=ZhangSan&age=15" open-type="navigate">navigator跳转</navigator>
// 跳转到的页面 <navigator open-type="navigateBack">navigate返回</navigator>
音频
InnerAudioContext
InnerAudioContext 实例,可通过 wx.createInnerAudioContext
接口获取实例。
语法
wx.createInnerAudioContext()
API
- 属性
- src:``,音频资源的地址,用于直接播放
- startTime:``,开始播放的位置(单位:s),默认为 0
- autoplay:``,是否自动开始播放,默认为 false
- loop:``,是否循环播放,默认为 false
- obeyMuteSwitch:``,是否遵循系统静音开关,默认为 true。从 2.3.0 版本开始此参数不生效
- volume:``,音量。范围 0~1。默认为 1
- playbackRate:``,播放速度。范围 0.5-2.0,默认为 1
- duration:``,当前音频的长度(单位 s)。只有在当前有合法的 src 时返回(只读)
- currentTime:``,当前音频的播放位置(单位 s)。只有在当前有合法的 src 时返回,时间保留小数点后 6 位(currentTime 属性在基础库 2.26.2 之前只读,基础库 2.26.2 开始可读可写,改变 currentTime 值等同于调用 seek)
- paused:``,当前是是否暂停或停止状态(只读)
- buffered:``,音频缓冲的时间点,仅保证当前播放时间点到此时间点内容已缓冲(只读)
referrerPolicy:
origin | no-referrer
,origin: 发送完整的 referrer ; no-referrer: 不发送。 - 方法
- InnerAudioContext.play():``,播放
- InnerAudioContext.pause():``,暂停。暂停后的音频再播放会从暂停处开始播放
- InnerAudioContext.stop():``,停止。停止后的音频再播放会从头开始播放。
- InnerAudioContext.seek(positionNum):``,跳转到指定位置,单位 s
InnerAudioContext.destroy():``,销毁当前实例
- 事件监听
- InnerAudioContext.onCanplay(listenerFn):``,监听音频进入可以播放状态的事件。但不保证后面可以流畅播放
- InnerAudioContext.offCanplay(listenerFn):``,移除音频进入可以播放状态的事件的监听函数
- InnerAudioContext.onPlay(listenerFn):``,监听音频播放事件
- InnerAudioContext.offPlay(listenerFn):``,移除音频播放事件的监听函数
- InnerAudioContext.onPause(listenerFn):``,监听音频暂停事件
- InnerAudioContext.offPause(listenerFn):``,移除音频暂停事件的监听函数
- InnerAudioContext.onStop(listenerFn):``,监听音频停止事件
- InnerAudioContext.offStop(listenerFn):``,移除音频停止事件的监听函数
- InnerAudioContext.onEnded(listenerFn):``,监听音频自然播放至结束的事件
- InnerAudioContext.offEnded(listenerFn):``,移除音频自然播放至结束的事件的监听函数
- InnerAudioContext.onTimeUpdate(listenerFn):``,监听音频播放进度更新事件
- InnerAudioContext.offTimeUpdate(listenerFn):``,移除音频播放进度更新事件的监听函数
- InnerAudioContext.onError(listenerFn):``,监听音频播放错误事件
- InnerAudioContext.offError(listenerFn):``,移除音频播放错误事件的监听函数
- InnerAudioContext.onWaiting(listenerFn):``,监听音频加载中事件。当音频因为数据不足,需要停下来加载时会触发
- InnerAudioContext.offWaiting(listenerFn):``,移除音频加载中事件的监听函数
- InnerAudioContext.onSeeking(listenerFn):``,监听音频进行跳转操作的事件
- InnerAudioContext.offSeeking(listenerFn):``,移除音频进行跳转操作的事件的监听函数
- InnerAudioContext.onSeeked(listenerFn):``,监听音频完成跳转操作的事件
- InnerAudioContext.offSeeked(listenerFn):``,移除音频完成跳转操作的事件的监听函数
小程序登录
小程序登录解析
为什么需要用户登录?
- 增加用户的粘性和产品的停留时间;
如何识别同一个小程序用户身份?
- 认识小程序登录流程
- openid 和 unionid
- 获取 code
- 换取 authToken
用户身份多平台共享
- 账号绑定
- 手机号绑定
小程序用户登录的流程
对比 WXML、HTML
WXML | HTML | 相同 | 不同 |
---|---|---|---|
view | div | ||
cover-view | |||
grid-view | |||
list-view | |||
movable-view | |||
scroll-view | |||
swiper | |||
swiper-item | |||
page-container | |||
text | span | ||
button | button | ||
block | template | ||
错误日志
1、从任务栏固定图标启动微信开发者工具会导致调试器显示空白
解决: 从其他地方(桌面、开始)启动编辑器