(syntax)微信小程序
2022-09-01 00:00:00

微信小程序

开发文档:微信开放文档

Github

教程

视频

项目

入门

小程序基础

微信⼩程序,简称⼩程序,英⽂名 Mini Program ,是⼀种不需要下载安装即可使⽤的应⽤,⽤⼾扫⼀扫或搜⼀下即可打开应⽤

协同工作和发布

  • 权限管理 : 员工的权限边界划分
  • 项目成员的组织结构 项目管理者(管理员) ==> 产品组(提需求) 设计组(出设计方案) 开发组(代码开发) 测试组(项目测试)
  • 小程序开发流程 提出需求(产品组) => 设计(设计组) => 开发(开发组) => 体验(产品组和设计组) => 测试(测试组) => 发布(管理者)
  • 成员管理的两个方面 小程序成员管理体现在管理员对小程序项目成员(运营者 开发者 数据分析者)以及体验成员的管理
  • 不同项目成员的权限: 运营者 开发者(开发权限、体验者权限、登录(登录小程序管理后台)、开发设置(设置小程序服务器域名、消息推送以及扫描链接二维码打开小程序)、腾讯云管理(云开发设置)) 数据分析者

软件开发过程中的不同版本

  • 开发版本 、体验测试、发布正式版(修复BUG)

小程序版本

  • 开发版本 、体验版本、审核中的版本、线上版本

发布和上线

  • 上传代码 -> 提交审核 -> 发布(上传按钮 版本号 项目备注) 在小程序管理后台:查看上传之后的版本 管理 版本管理 => 提交审核 => 发布

小程序码 vs 普通二维码

  • 小程序管理后台 获取小程序码

运营数据

  • 小程序后台
  • 小程序数据助手(微信小程序)

宿主环境 指的是程序运行所必须的依赖环境(Android iOS)

  • 微信是微信小程序的宿主环境 小程序宿主环境包含的内容

    • 通信模型(模式) 通信的主体

      • 渲染层(WXML模板 WXSS样式) 逻辑层 (JS脚本) < = > Native (微信客户端) < = > 第三方客户端
      • 小程序的通信模型分为两部分
        • 渲染层和逻辑层的通信 微信客户端转发
        • 逻辑层和第三方服务器之间的通信 微信客户端转发
    • 运行机制

      • 小程序启动过程
        • 代码包下载到本地 => 解析app.json全局配置文件 => app.js小程序入口文件(调用App()创建小程序实例)=> 渲染首页 => 小程序启动完成
      • 页面渲染过程
        • 加载解析页面.json文件 => 加载页面的.wxml模板和.wxss样式 => 执行页面的.js文件,调用Page()创建实例 => 页面渲染完成

⼩程序框架的⽬标是通过尽可能简单、⾼效的⽅式让开发者可以在微信中开发具有原⽣ APP 体验的服务。⼩程序框架提供了⾃⼰的视图层描述语⾔ wxml 和 wxss,以及 javascript,并在视图层与逻辑层间提供了数据传输和事件系统,让开发者能够专注于数据与逻辑。

安装环境部署

  • AppID:后期调⽤微信⼩程序的接⼝等功能,需要索取开发者的⼩程序中AppID ,所以在注册成功后,可登录,然后获取APPID。
  • 注册账号 ==> 获取APPID ==> 开发工具

小程序结构目录

小程序文件结构和传统web对比

结构传统web微信小程序
结构HTMLWX ML
样式CSSWX SS
逻辑JavaScriptJavaScript
配置JSON
  • 传统web 是三层结构。⽽微信⼩程序 是四层结构,多了⼀层 配置.json

目录结构

  • pages 页面 utils app.js 入口文件 app.json 全局配置文件 app.wxss全局样式 .cofig.json 项目配置文件 sitemap.son sitemap.json // 微信索引配置文件 配置小程序及其页面是否允许被微信索引
  • page/index js(脚本文件)/json(页面的配置文件)/wxml(页面的模本结构文件)/wxss(页面的样式表文件)
  • json 配置文件 4种 app.json project.config.json sitemap.json 每个页面文件夹的json配置文件

基本配置目录

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// 页面文件夹
pages/
--index/ // 首页
----index.js
----index.json
----index.wxml
----index.wxss
--logs
----logs.js
----logs.json
----logs.wxml
----logs.wxss
utils
----util.js // 工具性质模块
app.js // 项目的全局 入口文件
app.json // 全局配置文件
app.wxss // 全局样式文件
project.config.json // 项目的配置文件如 appid
sitemap.json // 微信索引配置文件 配置小程序及其页面是否允许被微信索引

配置文件

  • 两种配置文件,一种是全局的app.json和页面⾃⼰的page.json
  • json文件中不能有注释

全局配置文件 app.json

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
//app.json  全局的配置文件 
{
"pages":[ // ⽤于描述当前⼩程序所有⻚⾯路径,这是为了让微信客⼾端知道当前你的⼩程序⻚⾯定义在哪个⽬录。 小程序所有页面的路径(页面路径)
"pages/index/index", // 页面index
"pages/logs/logs"
],
"window":{ // 定义⼩程序所有⻚⾯的顶部背景颜⾊,⽂字颜⾊定义等。 全局定义小程序所有页面的背景色、文字颜色等(窗口外观 界面表现 底部tab)
// backgroundTextStyle navigationBar backgroundColor/ TitleText /TextStyle
"backgroundTextStyle":"light",
"naviagtionBarBackgroundColor":"#fff",
"navigationBarTitleText": "WeChat",
"navigationBarTextStyle":"black"
}
"style":"v2", // 全局定义小程序组件使用的样式版本
"sitemapLocation":"sitemap.json" // 指明sitemap.json文件的位置
}

页面配置文件 page.json:

其实用来表示页面目录下的page.json这类和⼩程序⻚⾯相关的配置。开发者可以独⽴定义每个⻚⾯的⼀些属性,如顶部颜⾊、是否允许下拉刷新等等。

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

  • 页面 .json 配置文件

  • project.config.json 项目配置文件 小程序开发工具个性化配置

1
2
3
4
setting   编译相关设置
projectname 项目名称
appid 小程序的账号ID
// checkSiteMap false 关闭 sitemap.json 提示
1
2
3
4
5
sitemap.json 配置小程序是否允许微信索引 小程序内搜索 PC网页的SEO
rules[
action:"allow", // disallow
"page":"*"
]
属性类型默认值描述
navigationBarBackgroundColorHexColor#000000导航栏背景颜色
navigationBarTextStyleStringwhite导航栏标题颜⾊,仅⽀持 black/white
navigationBarTitleTextString导航栏标题文字内容
backgroundTextStyleHexColor#fffff窗口背景色
enablePullDownRefreshBooleanfalse是否全局开启下拉刷新。详⻅ Page.onPullDownRefresh
onReachBottomDistanceNumber50⻚⾯上拉触底事件触发时距⻚⾯底部距离,单位为px。 详⻅Page.onReachBottom
disableScrollBooleanfalse设置为 true则⻚⾯整体不能上下滚动;只在⻚⾯配置中有
效,⽆法在 app。json中设置该项

sitemap 配置

  • sitemap.json 文件用于配置小程序及其页面是否允许被微信索引

模板语法

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

数据绑定

  • 花括号和引号之间如果有空格,将最终被解析成为字符串
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<view>{{ message }}</view>
<view id="item-{{id}}"></view> // 组件属性
<view hidden="{{ flag ? true:false}} ">Show</view> // 三元运算符
<view> {{a + b}} + {{c}} + d </view> // 算数运算
<view wx:if="{{length > 5}}"> </view> // 逻辑判断
<view>{{"hello" + name}}</view> // 字符串运算

// 类似vue
Page({
data:{
message:'Hello Message',
id:1000,
name:'talk',
a:'100',
c:'1000'
}
})

全局配置 app.json

  • pages 页面存放路径
  • style
  • window 全局设置小程序窗口的外观
    • navigationBar 导航区域 TitleText TextStyle BackgroudColor
    • background 背景区域 Color(下来刷新时窗口的颜色) TextStyle(下拉刷新的loading样式 dark/light默认值 不能设置其他值)
    • enablePullDownRefresh=true 下拉刷新 每个小程序都会有
    • onReachBottomDistace=50 页面上拉触底事件触发时距页面底部的距离 单位50px默认 上拉触底是移动端的专有名词 通过手指在屏幕上的上拉滑动操作,从而加载更多数据的行为
  • tabBar 底部tabBar效果 移动端常见的页面效果 实现多页面的快速切换
    • 底部tabBar 顶部tabBar
    • 个数[2~5] 渲染顶部tabBar 不显示icon 显示文本
    • 节点配置选项 postion:bottom/top borderStyle color selectColor backgroundColor list
      • 每个tab选项的配置 list
        • pagePath text iconPath selectIconPath
    • tabBar的6个组成部分
      • backgroundColor tabBar 背景颜色
      • borderStyle tabBar上边框的颜色
      • iconPath 未选中时的图片路径 selectedIconPath 选中时的图片路径
      • color 颜色 selectedColor tab文字选中的颜色
1
2
3
4
5
6
7
8
9
10
11
"tabBar":{
"list":[
{
"pagePath":"pages/index/index",
"text":"首页",
"iconPath":"",
"selectedIconPath": "./assets/image/shouye-select.png",
},
{},
]
}
  • style 是否启用新版的组件样式 v2 新 v1 旧

页面配置 .json 配置文件 当前页面的窗口外观 页面效果进行配置

  • 冲突 页面配置覆盖全局配置
  • 页面配置中常用的配置项
    • navigationBar BackgroundColor/TextSytle(black/white)/TitleText/
    • background Color/TextStyle(dark/light)/ 下拉区域样式
    • enablePullDownRefresh=true/false 下拉刷新
    • onReachBottomDistance=100(50默认) 上拉触底

列表渲染

  • wx:for
    • wx:for-item 可以指定数组当前元素的变量名
    • wx:for-index 可以指定数组当前下标的变量名
  • wx:key
    • 提高数组渲染的性能
    • 绑定的值
      • string 类型,表示循环项中的唯一属性
      • 保留*this,它的意思是 item 本⾝ ,*this 代表的必须是 唯⼀的字符串和数组。
1
2
3
4
list:[{id:0,name:''},{id:1,name:''}]
wx:key="id"
list = [1,2,3,4,5,6]
wx:key="*this"
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// wx:for
<view wx:for="{{array}}" wx:key=“id”> // wx.key
{{index}}:{{item.message}}
</view>

Page({
data:{
array:[{
id:0,
message:'foo',
},{
id:1,
message:'bar'
}]
}
})

block

  • 渲染一个包含多节点的结构块block最终不会变成真正的dom元素
1
2
3
4
<block wx:for="{{[1,3,4,5]}}" wx:key="*this">
<view>{{index}}</view>
<view>{{item}}</view>
</block>

条件渲染

标签功能
wx:if条件渲染
hidden频繁切换
  • wx:if ="{{{condition}}}"
1
2
3
<view wx:if="{{false}}">1</view>
<view wx:elif="{{true}}">2</view>
<view wx:else>3</view>
  • hidden
1
<view hidden="{{condition}}">True</view>

事件绑定

  • 绑定事件通过bind关键字实现,bindtap、input、change
关键字作用
bindtap
bindinput绑定输入
bindchange绑定改变
1
2
3
4
5
6
7
8
9
<input bindinput="handleInput" />
// 绑定参数时不能带参数.不能带括号 以下为错误写法
<input bindinput="handleInput(100)" data-item="100"/>
Page({
handleInput:fucniton(e){
console.log(e.currentTarget.dataset)
console.log(e.detail.item)
}
})

样式WXSS

wxss 样式语言 类似css

  • 新增rpx尺寸单位 rpx 在不同大小的屏幕上程序会自动换算 rem css 手动换算
  • 提供全局的样式(app.wxss 使用小程序页面)和局部样式(.wxss 当前小程序页面)
  • 支持部分css选择器 # . element 并、后代 ::after ::before

js

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

WXSS扩展的特性有

  • 响应式长度单位 rpx
  • 样式导入

尺寸单位

尺寸单位功能
rpx自适应的屏幕宽度
px像素

rpx (responsive pixel) :可以根据屏幕宽度进行自适应。规定屏幕宽为750px。

在iphone6上、 750rpx = 375px = 750物理像素、1rpx = 0.5px = 1物理像素

设备rpx换算px(屏幕宽度/750)px换算rpx(750/屏幕宽度)
iphone51rpx = 0.42px1px = 2.34rpx
iphone61rpx = 0.5px1ps = 2rpx
iphone1rpx = 0.552px1px = 1.81rpx

确定设计稿宽度pageWitdth

  • 750px = pageWidth px, 因此 1 px = 750rpx / pageWith
  • 在less⽂件中,只要把设计稿中的 px => 750px/pageWidth rpx 即可。

样式导入

1
2
3
4
5
6
7
8
9
10
@import "common.wxss";
// 不⽀持通配符 * 因此以下代码⽆效
*{
margin:0;
padding:0;
box-sizing:border-box;
}
.box{

}

选择器

选择器样式样式
.class类选择器
#idid选择器
elementviewview 组件
element element
nth-child(n)选择某个索引的标签
::after后面插入
::before前面插入

⼩程序中使⽤less

  • 原生小程序 不支持less 其他基于⼩程序的框架⼤体都⽀持,如wepy 、mpvue、taro等。但是仅仅因为⼀个less功能,⽽去引⼊⼀个框架,肯定是不可取的。因此可以⽤以下⽅式来实现
    • 安装vscode 插件 easy less
1
2
3
4
// vscode 设置 
"less.compile":{
"outExt":".wxss"
}

wxss 模板样式

  • 样式语言 类似css

  • rpx 尺寸单位 微信小程序独有的单位 解决屏适配的尺寸单位 + @import 样式导入

    • rpx 不同设备屏幕的大小不一样 为了实现屏幕的自动适配 把所有设备的宽度等分为750份 (屏幕的总宽度为750rpx)相对不同屏幕的单位 等分单位
      • 小屏幕,1rpx代表的宽度较小 大屏幕 1rpx代表的宽度较大 (等比例缩小放大)
    • 小程序在不同设备运行是 会走动把rpx的样式单位换算成对应的像素单位来渲染
    • rpx vs px rpx => px 屏幕宽度/750=px px => rpx 750/屏幕宽度=rpx
      • iphone6 屏幕宽度 375px 物理像素点 750个 等分为 750rpx
        • 750rpx = 375px = 750 物理像素 1rpx=0.5px(屏幕宽度) = 1物理像素 1px = 2rpx 换算单位
  • @import "common.wxss" 样式导入

  • 全局样式 app.wxss 全局样式 、 页面.wxss 局部样式 当前页面

    • 局部样式覆盖全局样式 、局部样式权重大于或等于全局样式的权重时,才会覆盖全局样式

结构WXML

wxml 小程序 标签语言 构建小程序页面的结构 HTML

  • 标签名称不同 view text image navigator(a)
  • 属性节点不同 navigator url="/pages/home/home"
  • 类似Vue中的模板语法
    • 数据绑定
    • 列表绑定
    • 条件渲染
布局组件作用
view相当于div
scroll-view(scroll-x/y 纵向滚动 横向滚动 可滚动的视图区域 常用来实现滚动列表)
text文本标签、只能嵌套text
image图片标签
swiper内置轮播图组件swiper和swiper-item组成
navigator类似a链接
rich-text富文本标签 相 v-html
button按钮
icon图标
radio单选
checkbox多选
map地图组件
canvas画布组件
video

view

  • 基础内容
    • text(span) 文本组件 长按选中 view(不行)
      • selectable 长按选中
    • rich-text 富文本组件 html字符串渲染为wxml结构
1
<rich-text nodes="<h1 style='color:red'>标签</h1>"></rich-text>
  • 表单组件
    • button 按钮组件 open-type属性
      • type="primary/warn" size="mini" plain 镂空
  • 导航组件
    • navigator(a) 页面导航组件
  • 媒体组件
    • image(img) 图片组件 默认 300px 高 240px
    • video

类似div

1
<view hover-class="h-class">这是一段文本</view>

text

属性名类型默认值说明
selectableBooleanfalse文本是否可选
decodeBooleanfalse是否解码
  • 文本标签、只能嵌套text 、⻓按⽂字可以复制(只有该标签有这个功能)、可以对空格 回⻋ 进⾏编码
1
2
3
<text selectable="{{false}}" decode="{{false}}">
&nbsp;
</text>

image

  • 图片标签,image组件默认宽度320px,高度 240px
    • src="/image/" mode 指定裁剪和缩放模式
      • mode scaleToFill 默认值 aspectFit 使图片长边能显示 aspectFill使图片短边能显示 widthFix 宽度不变 高度自动变化 heightFix
属性名类型默认值
srcString图片资源地址
modeString‘scaleToFill‘图⽚裁剪、缩放的模式
lazy-loadBooleanfalse图片懒加载

mode 有效值

  • mode 有 13 种模式,其中 4 种是缩放模式,9 种是裁剪模式。
模式说明
缩放scaleToFill、aspectFit、aspectFill、widthFix不保持纵横⽐缩放图⽚,使图⽚的宽⾼完全拉伸⾄填满 image 元素、
保持纵横⽐缩放图⽚,使图⽚的⻓边能完全显⽰出来、
保持纵横⽐缩放图⽚,只保证图⽚的短边能完全显⽰出来、
宽度不变,⾼度⾃动变化,保持原图宽⾼⽐不变
裁剪top、bottom 、center、left、right、top left 、top right 、bottom left 、bottom right不缩放图⽚,只显⽰图⽚的顶部区域

swiper

属性名类型默认值说明
indicator-dotsBooleanfalse是否显示⾯板指⽰点
indicator-colorColorrgba()指⽰点颜⾊
indicator-active-colorColor#00000当前选中的指⽰点颜⾊
autoplayBooleanfalse是否自动切换
intervalNumber5000自动切换时间间隔
circularBooleanfalse是否循环轮播 是否采用衔接滑动
swiper
  • 滑块视图容器
swipter-item
  • 滑块
  • 默认宽度和⾼度都是100%
1
2
3
4
5
6
7
<view class="className" id="idName"> </view>
<scroll-view class="container" scroll-x> <view>A</view> </scroll-view
<swiper class="swiper-container" indicator-dots>
<swiper-item>
<view class="item"></view>
</swiper-item>
</swiper>
  • 导航组件,类似超链接a标签
属性名类型默认值说明
targetStringself在哪个目标上发生跳转,默认当前小程序,可选值self/miniProgram
urlString当前小程序内的跳转链接
open-typeStringnavigate跳转方式

open-type有效值

说明
navigate保留当前⻚⾯,跳转到应⽤内的某个⻚⾯,但是不能跳到 tabbar ⻚⾯
redirect关闭当前⻚⾯,跳转到应⽤内的某个⻚⾯,但是不允许跳转到 tabbar ⻚⾯。
switchTab跳转到 tabBar ⻚⾯,并关闭其他所有⾮ tabBar ⻚⾯
reLaunch关闭所有⻚⾯,打开到应⽤内的某个⻚⾯
navigateBack关闭当前⻚⾯,返回上⼀⻚⾯或多级⻚⾯。可通过 getCurrentPages() 获取当前的⻚⾯栈,决定需要返回⼏层
exit退出⼩程序,target= miniProgram 时⽣效

rich-text

  • 富文本标签

可以将字符串解析成对应标签,类似vue中的v-html功能

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<rich-text nodes="{{nodes}}" bindtap="tap"></rich-text>
<rich-text nodes="<img src="https://www.baidu.com/>" alt="" /></rich-text>
Page({
data:{
// nodes[{name:'',attrs:{},children:[{}] }]
nodes:[{
name:'div',
attrs:{
class:'div-class',
style:'line-height:60px;color:red'
},
children:[{
type:'text',
text:'Hello Message!!!'
}]
}]
},
tap(){
console.log('tap')
}
}}
  • node属性

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

属性说明类型必填备注
name标签名 name:’‘string支持部分受信任的HTML节点
attrs属性class:'' style:''object支持部分受信任的属性,遵循 Pascal 命名法
children子节点列表type textarray结构和 nodes ⼀致

文本节点:type=text

属性说明类型必填备注
text文本string支持entities
  • nodes 不推荐使⽤ String 类型,性能会有所下降。
  • rich-text 组件内屏蔽所有节点的事件。
  • attrs 属性不⽀持 id ,⽀持 class 。
  • name 属性⼤⼩写不敏感。
  • 如果使⽤了不受信任的 HTML 节点,该节点及其所有⼦节点将会被移除。
  • img 标签仅⽀持⽹络图⽚。

button

属性类型默认值必填说明
sizestringdefault(默认) 、mini(小)按钮的大小
typestringdefault(白色)、wam(红色)、primary(绿色)按钮的样式类型
plainbooleanfalse按钮是否镂空,背景⾊透明
disabledbooleanfalse是否禁用
loadingbooleanfalse名称前是否带loading图标
form-typestringsubmit(提交表单)、reset(重置表单)⽤于 组件,点击分别会触发 组件的
submit/reset 事件
open-typestring微信开发能力

open-type的合法值

  • open-type 的 contact 的实现流程
说明
contact打开客服会话,如果⽤⼾在会话中点击消息卡⽚后返回⼩程序,可以从
bindcontact 回调中获得具体信息,具体说明
share触发⽤⼾转发,使⽤前建议先阅读使⽤指引
getPhoneNumber获取⽤⼾⼿机号,可以从bindgetphonenumber回调中获取到⽤⼾信息,
具体说明
getUserInfo获取⽤⼾信息,可以从bindgetuserinfo回调中获取到⽤⼾信息
launchApp打开APP,可以通过app-parameter属性设定向APP传的参数具体说明
openSetting打开授权设置⻚
feedback打开“意⻅反馈”⻚⾯,⽤⼾可提交反馈内容并上传⽇志,开发者可以登
录⼩程序管理后台后进⼊左侧菜单“客服反馈”⻚⾯获取到反馈内容
1
<button type="default" size="{{defaultSize}}" loading="{{loading}}" plain="{plain}">按钮</button>

icon

  • 图标
属性类型默认值必填说明
typestringicon的类型,有效值:success, success_no_circle,
info, warn, waiting, cancel, download, search,
clear
sizenumberstring23icon的大小
colorstringicon的颜色,同css的color
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
<view class="group">
<block wx:for="{{iconSize}}">
<icon type="success" size="{{item}}"/>
</block>
</view>
<view class="group">
<block wx:for="{{iconType}}">
<icon type="{{item}}" size="40"/>
</block>
</view>
<view class="group">
<block wx:for="{{iconColor}}">
<icon type="success" size="40" color="{{item}}"/>
</block>
</view>
Page({
data: {
iconSize: [20, 30, 40, 50, 60, 70],
iconType: [
'success', 'success_no_circle', 'info', 'warn', 'waiting', 'cancel',
'download', 'search', 'clear'
],
iconColor: [
'red', 'orange', 'yellow', 'green', 'rgb(0,255,255)', 'blue', 'purple'
],
}
})

radio

单选按钮

  • radio-group
  • radio
1
2
3
4
<radio-group>
<radio>选中</radio>
<radio>没有选中</radio>
</radio-group>

checkbox

  • checkbox-group
  • checkbox

多选按钮

1
2
3
4
5
6
<checkbox-group>
<checkbox>1</checkbox>
<checkbox>2</checkbox>
<checkbox>3</checkbox>
<checkbox>4</checkbox>
</checkbox-group>

模板与配置

wxml 模板语法

  • 数据绑定 data定义数据 Page({ data:{ info:"messageInfo",arr:[{},{}] } }) wxml使用数据 双大括号 {{ info }} 插值表达式
    • 插值表达式:动态绑定内容 {{ info }} 动态绑定属性 <image src="{{imgSrc}}"> 运算(三元表达式、算术表达式){{ 100 + 200/ ? : }}

事件:事件时渲染层到逻辑层的通信方式 通过事件可以将用户在渲染层产生的行为,反馈到逻辑层进行业务的处理

  • 常用事件 tap(手指触摸马上离开click)/bindtap/bind:tap input/bindinput/bind:input change/bindchange/bind:change
    • bind*/bind:* 绑定方式
  • 事件对象的属性 type 事件类型 timeStamp 页面打开触发事件所经过的毫秒数 target 触发事件的组件的一些属性值集合 currenTarget 当前组件的属性值集合 detail 额外的信息 touches changedTouches
    • target vs currentTarget: target 触发该事件的源头组件 currentTarget 当前事件所绑定的组件(当前触发事件的组件)
  • wxml bingtap="bindTapHandler" 绑定tap触摸事件 js 形参 event (e) 接收 bindTapHandler(e){ }
  • 事件传参 不能一边绑定事件的同时为事件处理函数传递参数 data-* 自定义属性传参 *代表的是参数的名字 <button data-info="{{100}}"> info 参数名字 100 参数的值 获取事件参数 e.target.dataset.参数名
  • bindinput input事件响应文本框的输入事件 <input bindinput="inputHandler"></input> 获取input事件的值 e.detail.value
  • input和data数据同步 data:{ str:"Message" } this.setData({ str:e.detail.value })

data 数据重新赋值

  • this.setData(dataObject) 页面data中的数据重新赋值 changeCount(){ this.setData({ num: this.data.num + 100 }) }

w-if 条件渲染 vs hidden

  • wx:if="{{ condition }} / true or false" 判断是否渲染该代码块
  • wx:if={{ type = 1 }} wx:elif={{ type = 1 }} wx:else wx-if wx:elif wx-else
  • 结合<block>使用wx-if <block wx-if="{{ }}"> </block> 一次性控制多个组件的展示和隐藏 block 将多个组件包装起来 没有任何效果 并不是一个组件 包裹性质的容器 不会在页面中做任何渲染
  • hidden hidden="{{ condition }} // true or false" 控制元素的显示和隐藏
  • 区别 wx-if 动态创建和移除元素的方式 控制条件复杂 切换效率高 hidden 切换样式(display:none/block)频繁切换使用 渲染效率高

wx-for 列表渲染 可以根据指定的数组,循环渲染重复的组件结构

  • wx-for={{array}} {{index}} 索引 {{item}} 当前循环项 两个默认值
  • 手动指定索引和当前项的变量名 重命名索引和Item项 (不常用)
    • wx-for-index=“idx” 可以指定当前循环项的索引的变量名
    • wx-for-item=“itm” 可以指定当前项的变量名
  • wx:key wx:key="id"/"index" id是数组的一个键名 渲染出来的列表项指定唯一的key值 从而提高渲染效率 vue中 :key="id"

过滤器WXS

WXS(WeiXin Script) 过滤器使用 配合 Mustache 语法 {{ }} 使用

  • 是小程序独有的一套脚本语言 与WXML可以构建出页面的结构

  • WXML 无法调用页面js中的函数 WXML 可以调用WXS中定义的函数

  • 作用: WXS的使用场景:过滤器

  • WXS vs JS 完全不同的两种语言

    • WXS有自已的数据类型 number string boolean object function array date regexp
    • WXS不支持类似ES6及以上语法 不支持 let const 解构赋值 展开运算符 箭头函数 对象属性简写 支持 var function等
    • WXS遵循CommonJS规范 module requeire() module.exports对象
  • <wxs></wxs> 类似<script>标签 必须提供module属性 指定当前wxs的模块名称 方便在wxml中访问模块中的成员

  • 外联wxs脚本 .wxs后缀名的文件内 module 模块名称 src 相对路径

  • 隔离性 不能调用js函数和小程序的API

  • 性能好 IOS设备上 WXS比JS快 2~20倍 Android没有差异

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
// 内联<wxs>
<view>{{ m1.toUpper(username) }}</view>

<wxs module="m1"> // module.方法()
module.exports.toUpper = function(str){
return str.toUpperCase()
}
</wxs>

module.exports.splitPhone = function(str){
if(str.length !== 11) return str
var arr = str.split('')
arr.splice(3,0,'-')
arr.splice(8,0,'-')
return arr.join('')
}

// 外联wxs文件 tools.wxs
function toLower(str){
return str.toUpperCase()
}

module.exports = {
toLower: toLower
}

<view>{{ m2.toLower(username) }}</view>
<wxs module="m2" src="../../tool.wxs"></wxs>

API

  • 小程序API是宿主环境提供的 调用微信提供的能力 获取用户信息 本地存储 支付功能
  • 小程序的3大分类
    • 事件监听 API 以on开头,用来监听某些事件的触发
      • wx.onWindowResize(function callback) 监听窗户尺寸变化的事件
    • 同步 API 以Sync结尾的API 都是同步API 同步API的执行结果 可以通过函数返回值直接获取
      • wx.setStorageSync("key","vaklue") 向本地存储写入内容
    • 异步 API 类似jquery中国的$.ajax(option)函数 需要通过 success fail complete 接受调用
      • wx.require() 发起网络请求 success 回调函数接受数据

自定义组件

  • 小程序通过自定义组件的方式构建页面
1
2
3
4
5
6
Page({
"pages":[ // ⽤于描述当前⼩程序所有⻚⾯路径,这是为了让微信客⼾端知道当前你的⼩程序⻚⾯定义在哪个⽬录。
"pages/index/index", // 页面index
"pages/logs/logs"
]
})

创建自定义组件

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

声明组件 Component 4步曲

1
2
3
4
// newComponent.json 
{
"component":true
}
1
2
3
4
5
// newComponent.wxml 
<view class="inner">
{{innerText}}
<slot></slot>
</view>
1
2
3
4
5
6
// newComponent.wcss
// 不应该使用ID、属性、标签名选择器
.inner{
color:red;
font-size:16px;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// newComponent.js 注册组件
Component({
properties:{
// 这里定义了innerText属性,属性值可以在组件使用时指定
innerText:{
type:String,
value:'defalut value'
},
// 组件内部数据
data{
someData:{}
},
// 自定义方法
methods:{
customMethod:function(){}
}
}
})

页面引入自定义组件

  • 页面引入元素
1
2
3
4
5
6
// index.json
{
"usingComponents"{
"my-header":"/components/myHeader/myHeader"
}
}

页面中使用自定义组件

1
2
3
4
5
<view>
<my-header inner-text="Some text">
<view>用来替代slot的</view>
</my-header>
</view>

定义段与⽰例⽅法

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

组件间通信

  • 父传子
  • 子传父
  • 子传子

组件-⾃定义组件传参

  • 父组件 ==> 通过属性的方法 ==> 子组件 传递参数
  • 子组件==> 通过事件的方式 ==> 父组件 传递参数

父组件传递给子组件

  • 通过属性的方法
  • 父组件 中的 data 传递给 子组件
    • 父组件 tabItems="{{tabs}}" tabs 是data 中的数据
    • 子组件 tabItems 接收数据

子组件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
<view class="tabs">
<view class="tab_title">
<block wx:for="{{tabItems}}" wx:key="{{item}}">
<view bindtap="handleItemActive" data-index="{{index}}">{{item.name}}</view>
</block>
</view>
<view class="tab_content">
<slot></slot>
</view>
</view>

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

},
methods:{
handleItemActive(e){
this.triggerEvent('mytap','haha')
}
}
})

父组件

1
2
3
4
5
6
7
8
9
10
11
12
13
<tabs tabItem="{{tabs}}" bindmytap="onMytab">
内容
</tabs>

data:{
tabs:[
{ name:"体验问题" },
{name:"商品、商家投诉"}
],
onMyTab(e){
console.log(e.detail);
},
}
  • 标签名 是 中划线的⽅式
  • 属性的⽅式 也是要中划线的⽅式
  • 其他情况可以使⽤驼峰命名
    1. 组件的⽂件名如 myHeader.js的等
    2. 组件内的要接收的属性名 如 innerText

自定义小程序组件

  • components/test目录 test文件
  • 引用组件
    • 局部引用:组件只能在当前被引用的页面内使用 特定页面中用到
      • .json Page({ })“usingComponents:{ "my-test":"/componets/test/test" }”
      • <my-test></my-test>
    • 全局引用:组件可以在每个小程序页面中使用 多个页面中经常用到
      • app.json App({ })“usingComponents:{ "my-test":"/componets/test/test" }”
  • 组件 vs 页面
    • 组件 .json 需要声明“component”:true属性 .js文件调用 Component({})函数 组件的事件处理函数需要定义到methods节点中
      • data:{}\methods:{}
    • 页面 Page({})函数
  • 自定义组件样式
    • 组件之间的样式相互不会影响 防止外界的样式影响组件内部的样式 防止组件的样式被外界样式破坏
    • app.wxss的全局样式对组件的样式无效
    • 只有class选择器有样式隔离效果,id 属性 标签选择器不受样式隔离的影响(组件和引用组件的页面建议使用class,不要使用id\属性\标签)
    • 修改组件的样式隔离选项
      • 默认 自定义组件的样式隔离特性能够防止组件内外样式互相干扰的问题
      • 外界能够控制组件内部的样式 可以通过 styleIsolation 修改组件的样式隔离选项 可选值 isolated 样式隔离 apply-shared 页面样式影响自定义组件(组件不影响页面) shared (双向影响)
        • .js Component({ options:{ styleIsolation:"isolated" } })
        • .json “styleIsolation:"isolated"”
  • 自定义组件 数据(data:{}) 方法(method:{}) 属性(properties:{}) 数据监听器(observers:{}) .js
    • 数据 data:{} 组件模块渲染和私有数据 定义data节点 Component({ data:{ count:100 } })
      • 获取data this.data.xxx
      • 设置setData this.setData({ count:this.data.xxx })
    • 方法 methods:{} Component({ methods:{ addCount(){ } } })
      • 下划线开头_showCount(){} 自定义方法建议以_开头 addCount(){} 事件处理函数
    • 属性(页面传递参数到组件) properties:{} 组件的对外属性 用来接受外界传递到组件中的数据
      • <my-test max="100"></my-test> 传递参数 页面.wxml
      • Component({ properties:{ max:{ type:Number //属性值的数据类型 ,value:100 //默认值 } //完整定义属性的方式(有默认值) ,max:Number //简化定义属性(不需要默认值) } }) 接受参数 组件.js
        • 获取属性 this.properties.xxx
        • setData 修改 properties的值 this.setData({ count:this.data.xxx,max:this.properties.xxx })
    • 数据监听器(变化的值) observers:{ } 用于监听和响应任何属性和数据字段的变化,从而执行特定的操作 类似 watch 侦听器
      • 监听数据字段的变化 Component({ observers:{ "字段A,字段B":function(字段A的新值,字段B的新值){} } })
      • 监听对象属性的变化 数据监听器支持监听对象中的单个或多个属性的变化 observers:{ '对象.属性A,对象.属性B':function(属性A的新值,属性B的新值){} }
        • 触发监听器:属性A赋值 使用setData this.data.对象.属性A 属性B赋值 this.data.对象.属性B 直接为对象赋值 this.data.对象
        • this.setData({'rgb.a':this.data.rgb.r + 5 > 255 ? this.data.rgb.r + 5}) rgb.a 对象上的a值
        • 对象监听的属性太多 可以使用通配符 ** 来监听对象中所有属性的变化 "obj.**":function(obj){ obj.x obj.y obj.z }
    • 纯数据字段:那些不用于界面渲染的data字段(只在组件内使用) 提升页面更新的性能 页面中没有用到的都可以使用纯数据字段
      • 应用场景 data中的字段既不会展示在界面上 也不会传递给其他组件 只在组件内部使用 带有这种特性的data字段适合被设置为纯数据字段
      • 使用规则 Component({ options:{ pureDataPattern:/^_/ } }) 指定所有_开头的数据字段都是纯数据字段
    • data vs properties
      • 用法相同,都是可读可写
      • data 存储组件的私有数据
      • properties 存储外界存储到组件中的数据 外界传递的数据
    • 组件的生命周期 lifetimes:{ … }
      • created 创建 attached 进入页面节点树时执行 ready 视图层完成后执行 moved 被移动到节点树另一位置时执行 detached 从页面节点树移除是执行 error Object Error 组件方法抛出错误时执行
      • 主要生命周期
        • created 刚被创建好的时候 不能调用setData 只能给组件的this添加一些自定义的属性字段
        • attached 组件完全初始化完毕、进入页面节点树后 this.data 被初始化 绝大多数的attached 会在这个时机执行(例如发请求获取初始数据)
        • detahced 离开页面节点树后 生命周期函数会被触发
      • lifetimes节点
        • 小程序组件中,生命周期函数可以直接定义在Component构造器的第一级参数中,lifetimes字段进行声明
        • Component({ lifetimes:{ created(){},attached(){ } } })
          • 旧 不推荐使用 Component({ created(){}, }) 同时存在新覆盖旧的
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
data n1 n2 sum  rgb:{ r:0,g:0,b:0 }
observers:{
"n1,n2":function(new1,new2){ // 监听字段 新值 / 旧值
this.setData({ sum: new1+new2 })
},
"rgb.r,rgb.g,rgb.b":function(r,g,b){ // 监听字段 新值 / 旧值
this.setData({ color:`${r},${g},${b}` })
},
"rgb.**":function(obj){
this.setData({ color:`${obj.r},${obj.g},${obj.b}` })
}
}

Component({
options:{ pureDataPattern:/^_/ }
data:{
a:true, // 普通数据字段
_b:true, // 纯数据字段
_rgb:{
r: 0,
g: 0,
b: 0
}
}
})
  • 组件(Component)所在页面(Page)的生命周期 自定义组件的行为依赖于页面状态的变化 需要用到组件所在页面的生命周期 组件儿子监听页面爸爸的变化
    • 组件访问页面中生命周期(组件使用页面中的生命周期): 一个页面可以有多个组件 组件只是页面中的一部分
    • 3个组件所在页面的生命周期
      • show 组件所在页面被展示时执行
      • hide 隐藏
      • resize 尺寸变化
    • pageLifetimes 节点 组件所有页面的生命周期函数 需要定义在pageLifetimes节点中
      • Component({ pageLifetimes:{ show(){},hide(){},resize(){} } })
  • 插槽 在自定义组件的wxml结构中,可以提供一个<slot>节点(插槽) 用于承载组件使用者提供的wxml结构 实现不同页面共用一个组件 页面上不同的内容通过插槽动态渲染不同的
    • <slot></slot> 作为组件的封装者 在封装组件时 通过slot提供内容的 占位符
      • 具体渲染 <view></view> <text></text> 作为组件的 使用者渲染具体节点 在使用组件时 为<slot>占位符提供具体的内容节点
    • 单个插槽 默认每个自定义组件只允许使用一个<slot> 进行占位 单个插槽
    • 多个插槽 name/slot 使用多个<slot></slot> 在组件中.js启用 Component({ option:{ multipleSlots:true } }) 组件定义时的选项中启用多个slot支持 name 与 slot
      • 定义多个插槽 .wxml中使用多个<slot name="xxx">标签以 不同``name`区分不同插槽
      • 使用多个插槽 使用带有多个插槽的自定义组件 slot=“xxx” 来将节点插入到不同的<slot>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
Component({ options:{ multipleSlots:true }  })

组件文件
// 组件封装者 中使用<slot>
<view class="container">
<view>组件内部节点</view>
<slot></slot> // 不确定的内容 占位符 单个插槽
<slot name="before"></slot>
<slot name="after"></slot>
</view>

页面文件
// 组件使用者 使用
<component-tag-name> // component-tag-name 组件名字 usingComponents:{ "my-test":"/componets/test/test" } 注册组件
<view>插入到slot中的内容</view> // 发到slot上的内容
<view slot="before">TESTEETEE</view>
<view slot="after">TESTEETEE</view>
</component-tag-name>
  • 父子组件之前的通信(3种)
    • 属性绑定 properties:{} 父组件 => 子组件 指定属性设置数据 只能传递普通类型的数据 不能传递方法 仅能设置JSON兼容的数据
    • 事件绑定 子组件 => 父组件 可以传递任意类型数据
      • 父组件 父方法(e) e.detail.value bind:子方法=”父方法”
      • 子组件 this.triggerEvent
    • 获取子组件实例 子 => 父组件 父组件获取子组件实例
      • 父组件 this.selectComponent(// id或class选择器) 获取子组件实例对象 可以直接访问子组件的任意数据和方法 不能用标签选择器
    • 按钮 tap 事件的处理函数 传递参数 bindTap=“btnHandler” data-step=“1” btnHandler(e){ e.target.dataset.step } // step属性
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
// 属性绑定 父 子
// 父
data count:100
<my-test count="{{ count }}"></my-test>
// 子 properties节点 声明对应属性并应用
<view>{{ count }}</viewv>
properties:{
count:Number // 声明类型
}
// 事件绑定 子 父
// 父

父组件.js 父.js e.detail 获取子组件传递过来的数据
syncCount(e){
this.setData({
count:e.detail.value
})
}
父.wxml 自定义事件 bindSync/bind:sync
<my-test bind:sync="syncCount"></my-test> // bindSync bind:子=“父” // sync 子 syncCount 父


子组件.js this.triggerEvent("自定义事件名称",{ 参数对象 }) 将数据发送给对象
methods:{
add(){
this.triggerEvent("sync",{ value:1000 })
}
}

获取实例
// 父
<my-test class="child"></my-test>

getChild(){
const child = this.selectComponent(".child")
child.setData({ count: child.count + 1 })
child.data
}
  • 自定义组件中的behaviors 小程序中 用于实现组件代码间共享的特性 类型vue的 mixins 组件中公共的代码behavior
    • 每个behavior可以包含一组属性、数据、生命周期函数和方法。组件引用它时,它的属性、数据和方法会被合并到组件中
    • 每个组件中可以引用多个behavior,behavior也可以应用其他behavior
    • 创建behavior Behavior(Object object)方法创建一个 共享的behavior实例对象 供所有的组件使用
    • 导入并使用 require() 方法 导入需要的behavior 挂载后即可访问behavior中的数据和方法
    • 所有可用节点 properties data methods behaviors created attached ready moved detached
    • 同名字段的覆盖和组合规则 组件和它引用的behavior中可以包含同名的字段
      • 同名 data 、properties 、methods
1
2
3
4
5
6
7
8
9
10
11
12
13
14
/bbehavior/my-behavior.js
// 创建behavior
module.exports = Behavior({
properties:{}, //属性节点
data:{ usename:"zs" },
methods:{}
})

// 组件.js 导入使用
const myBahavior = require("../../behaviors/my-behavior")

Component({
behaviors:[myBehavior]
})

使用npm包

  • 不支持 node内置库包 浏览器内置对象包(jquery) C++插件包(加密的包)

生命周期

  • 生命周期 是指一个对象从创建->运行->销毁的整个阶段 ,强调的是一个时间段
    • 小程序的启动 生命周期的开始 小程序的关闭 生命周期的结束

生命周期(时间段)

-

生命周期函数(时间点)

  • 概念:由小程序框架提供的内置函数,会伴随生命周期,自动按次序执行
  • 作用:允许在特定的时间点,执行某些特定的操作

应用生命周期函数 App({ }) app.js ==Launch Show Hide==

  • onLaunch(){} 初始化完成 只初始化一次
  • onShow(option){ } 启动或从后台进入前台显示
  • onHide(){} 前台进入后台时

页面生命周期函数 Page({ }} page.js ==Load Show Ready Hide Unload==

  • onLoad(){ } 页面加载 一个页面只调用一次
  • onShow(){ } 显示
  • onReady(){ } 页面初次渲染完成 一个页面只调用一次
  • onHide(){ } 隐藏
  • onUnload(){ } 卸载 一个页面只调用一次

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

生命周期分类

  • 应用生命周期 小程序 启动 -> 运行(包含各个页面的生命周期) -> 销毁 的过程 范围大
  • 页面生命周期 页面 加载 -> 渲染 -> 销毁 的过程 范围小

应用生命周期 5个

5个应用生命周期:onLaunch(初始化)、onshow(启动或切前台)、onHide(切后台)、onError(错误监听)、onPageNotFound(不存在监听函数)

属性类型默认必填说明
onLaunchfunction监听⼩程序初始化
onShowfunction监听⼩程序启动或切前台
onHidefunction监听⼩程序切后台
onErrorfunction错误监听函数
onPageNotFoundfunction页面不存在监听函数
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// app.js 应用生命周期
App({
data:{},
onLaunch(){},
onShow(){},
onHide(){},
onError(){},
onPageNotFound(){}
})

App({
data:{}
onLaunch:funciton(){},
onShow:funciton(){},
onHide:funciton(){},
onError:funciton(){},
onPageNotFound:funciton(){}
})

页面生命周期 12个

12个页面生命周期:

  • data(初始化数据)、onLoad(页面加载)、onShow(页面显示)、onReady(初次渲染)、onHide(页面隐藏)、onUnload(页面卸载)
  • onPullDownRefresh(上拉动作)、onReachBottom(上拉触底事件)、onShareAppMessage(右上角转发)、onPageScroll(滚动触发事件的处理函数)、onResize(页面存储触发、响应显示区域变化)、onTabitemTap(tab页)

微信小程序-基础

属性类型说明
dataObject页面的初始数据
onLoadfunciton生命周期回调-监听页面加载
onShowfunction生命周期回调-监听页面显示
onReadyfunction生命周期回调-监听页面初次渲染完成
onHidefunction生命周期回调-监听页面隐藏
onUnloadfunction生命周期回调-监听页面卸载
onPullDownRefreshfunction监听用户上拉动作
onReachBottomfunction页面上拉触底事件的处理函数
onShareAppMessagefunction用户点击右上角转发
onPageScrollfunction页面滚动触发事件的处理函数
onResizefunction页面尺寸改变时触发,详见响应显示区域变化
onTabitemTapfunction当前是tab页,点击tab 时触发
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// app.js 页面生命周期
Page({
data:{},
onLoad:function(options){},
onReady:function(){},
onShow:funciton(){},
onHide:function(){},
onUnload:function(){},
onPullDownRefresh: function () {},
onReachBottom: function () {},
onShareAppMessage: function () {},
onPageScroll: function () {},
onResize: function () {},
onTabitemTap: function () {},
})

路由

视图与逻辑

  • 页面导航(跳转)指的是页面之间的相互跳转 浏览器实现页面跳转的方式:a location.href

    • 小程序中实现页面导航的两种方式

      • 声明式导航 wxml 在页面上声明<navigation> 导航组件 点击实现页面跳转
        • 导航到tabBar页面 <navigation url="/pages/message/message" open-type="switchTab">导航</navigator> url 页面地址 open-type 跳转方式 (switchTab/navigator(可以省略) )
        • 后退导航 <navigator open-type="navigatorBack" delta="1"></navigator> navigatorBack 后退导航 delta 数字 厚涂层级 上一个页面 delta 可以省略
      • 编程式导航 js 小程序的导航API
        • 导航到tabBar wx.switchTab(Object.object) Object参数对象 url success fail complete
          • goTo(){ wx.switchTab({ url:"/pages/message/message" }) }
        • 非tabBar页面 wx.navigatorTo(Object.object) Object url sucess fail complete
        • 后退导航 wx.navigatorBack(Object.object) Object data( number 默认1 回退页面数) sucess fail complete
          • wx.navigatorBack()
    • 导航传参

      • 声明式导航传参

        • <navigator url="/page/info/info?name=zs&age=20"> 跳转到页面 url路径后面可以携带参数 参数 路径 ?参数键 参数值 = 不同参数 &
      • 编程式导航传参wx.navigateTo(Object object) 方法跳转页面 可以携带参数

        • wx.navigateTo({ url:"/page/info/info?name=zs&age=20" })
      • onLoad事件中接收导航参数 onLoad option 导航的参数

        • onLoad:function(options){ console.log(options) }
    1
    2
    3
    4
    5
    6
    7
    data:{ query }
    onLoad:function(options){
    this.setData({
    query:options
    }}
    }
    this.setData({ }) this.data
  • 自定义编译模式

  • 启动页面 运行的页面 启动参数 传递到这个页面的参数 模式名称

网络请求

网络数据请求

  • 数据接口的请求
    • 只能请求HTTPS类型的接口 必须将接口的域名添加到信任列表中(详情 项目配置 request合法域名)
    • 配置request合法域名 微信小程序后台 修改request合法域名 只支持https协议 不支持ip地址或localhost 域名必须ICP备案 服务器域名一个月最多修改5次
  • 发起GET请求
    • wx.request({ }) 发起GET数据请求
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<button bingtap="getInfo">GET请求</button>

// onLoad() 事件 生命周期函数 监听页面加载
onLoad:function(options){
this.getInfo()
}

getInfo(){
wx.request({
url:"https://www.xxx.com/api/get", // https协议
method:"GET", // method:"POST"
data:{ name:"zs",age:19 },
success:(res) =>{ // 请求成功后的回调
console.log(res) // res.data
}
})
}
  • 发起POST请求

  • 页面刚加载时请求数据 自动请求一些初始化的数据 onLoad事件 调用获取数据的函数

  • 跳过request合法域名校验(开发 调试下使用) 本地设置 不校验…HTTPS证书

  • 跨域和AJAX 只存在基于浏览器的Web开发 小程序的宿主环境不是浏览器 而是微信客户端 小程序不存在跨域问题 小程序不能叫做发起AJAX请求,而是叫做发起网络数据请求

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
// 页面.js
data:{
swiperlist:[] //xxxlist:[]
}

onload(options){
this.getSwiperList()
}
// 数据格式 [{id name url},{},{}]
getSwiperList(){
wx.request({
url:'',
method:"GET",
success:(res) =>{
this.setData({
swiperlist:res.data // res.data {} {} {}
})
}
})
}

<view wx:for="{{ swiprlist }}" wx:key="id" >
<text>{{ item.name }}</text>
<image src="{{ item.url }}"></image>
</view>

小程序的API进行Promise化 依赖于miniprogram-api-promise 第三方包

  • 小程序官方异步API基于回调函数实现的 回调地狱 可读性 维护性差
  • API Promise 化 通过额外的配置,将官方提供的、基于回调函数的异步API 改造为基于Promise的异步函数 提高代码的可读性 维护性 避免回调地狱的问题
  • npm i -save miniprogram-api-promise 每次安装都要构建npm 删除mininprogram_npm 再构建
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
wx.request({
url:'',
method:'',
data:{},
success:()=>{},
fail:()=>{},
complete:()=>{}
})

// app.js
import { promisefyAll } from 'minprogram-api-promise'
const wxp = wx.p = {}
promisefyAll(wx,wxp)

async getInfo(){
const { data:res } = await wx.p.request({
method:'GET',
url:'',
data:{ name:zs,age:18 }
}),
console.log(res)
}

MobX

MobX实现全局数据共享 mobx-miniprogram mobx-miniprogram-bindings 实现全局数据共享

  • 全局数据共享(又称 状态管理 store) 是为了解决组件之间数据共享的问题
    • xxx:xxx
    • get xxx() 计算属性
    • 函数:action(function(step){ } action(){}
  • 开发常用的全局数据共享方案有:Vuex、Redux、MobX
  • mobx-miniprogram 创建Store实例对象
  • mobx-miniprogram-bindings 把Store中的共享数据或方法,绑定到组件或页面中使用
  • npm install -–save mobx-miniprogram mobx-miniprogram-bindings 安装后 重新构建npm
  • store 成员绑定到组件中
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
// 创建MobX 实例
/store/store.js 创建store实例对象 observable({ })
import { observable,action } from 'mobx-ac'

export const store = observable({
numA: 100,
numB: 200,
// 计算属性 get xxx(){}
get sum(){
return this.numA + this.numB
},
// action方法 修改store中的数据
updateNum1:action(function(step){
this.numA += step
}),
updateNum2:action(function(step){
this.numB += step
})
})

// store中的成员绑定到页面中 页面.js
import { createStoreBindings } from 'mobx-miniprogram-bindings'
import { store } from '../../store/store.js'

Page({
// this.storeBindings createStoreBindings({ })
onLoad(){
this.storeBindings = createStoreBindings(this,{ // this 实例
store, // 属性 方法
fields:["numA","numB","sum"], // 绑定到当前页面的字段
actions:["updateNum1","updateNum2"] // aciton方法
})
},
onUnload(){
this.storeBindings.destroyStoreBindings()
}
})

// 子组件修改stote
获取 {{ numA }}

// action
this.updateNum1(e.target.dataset.stop)

// store 绑定到组件
import { storeBindingsBehavior } from 'mobx-miniprogram-bindings'
import { store } from '../../store/store'

Component({
behaviors:[storeBindingsBehavior],
storeBindings:{
store, // 指定要绑定的store
fields:{ // 指定要绑定的字段数据
numA:() => store.numA,
numB:(store) => store.numB,
sum:"sum"
},
actions:{ // 绑定方法
updateNum1:"updateNum1"
}
}
})


// 使用
{{ numA }} {{ numB }} this.updateNum1() //方法

自定义tabBar

1
2
3
4
5
6
7
8
"tabBar":{
"custom":true,
"list":[] // 保存 兼容低版本
}

添加tabBar 代码文件

/根目录创建custom-tab-bar/index
  • wx-for 是在 子元素 生成重复内容的元素上 而不是父元素上的
1
2
3
4
5
6
7
8
9
10
11
12
13
14
json 
{
code:200 //状态码
data:[{},{},{}] 数据格式
}

data list:[ { name:"zs",age:20 },{ name:"ls",age:20 },{ name:"wz",age:30 } ]
list:[]

res.data (res是一个{}) json.data 是个一个对象

wx:for 遍历一个数组里面的对象
view wx:for="{{ list }}" wx:key="index"
{{ index }} {{ item.name }} item.age // item.name == list[x].name
  • var(—变量值,默认值)
1
info="{item.info ? item.info :''}"
  • 监听器 observers 监听一个值的改变 另一个值也改变
1
2
3
4
5
6
7
8
9
10
11
observers:{
"num":funciton(val){
this.setData({})
}
}

onchage(event){
wx.switchTab({
url:this.data.list[event.detail].pagePath
})
}

分包

分包

  • 分包指的是把 一个完整的小程序项目 按照需求划分为不同的子包 在构建时打包成不同的分包,用户在使用时按需进行加载

分包的好处

  • 优化小程序首次启动的下载时间 多团队共同开发时 可以更好的解耦协作

分包前项目的构成

  • 分包前 小程序所有的页面和资源都会被打包到一起 项目体积大 首次启动下载时间长

分包后项目构成

  • 分包后 1个主包 + 多个分包
    • 主包 一般包含项目的启动页面或TabBar页面 以及所有分包都需要用到的一些公共资源
    • 分包 只包含和当前分包有关的页面和私有资源
  • 分包的加载规则
    • 小程序启动时,默认会下载主包并启动主包内页面
      • tabBar 页面需要放到主包内
    • 当用户界面进入分包内某个页面时,客户端会把对应分包下载下来,下载完成后再进行展示
      • 非tabBar页面可以按照功能的不同,划分为不同的分包之后 进行按需下载

分包的体积限制

  • 分包(主包+分包)不能超过 16M
  • 单个分包、主包大小不能超过 2M

使用分包

  • 配置方法 app.json subpackages[{},{}] 节点中声明分包的结构

独立分包 independent:true

  • 本质上也是分包 只不过比较特殊 可以独立于主包和其他分包而单独运行
  • 应用场景 按需 具有一定功能独立性的页面配置到独立分包
    • 当小程序从普通的分包页面启动时 首先下载主包
    • 独立分包不依赖主包运行 可以提升分包页面的启动速度
  • 引用原则
    • 独立分包和普通分包之间 是相互隔绝的 不能相互引用彼此的资源
      • 其他分包(主包、普通分包、其他独立分包)都无法引用 独立分包的私有资源
      • 特别注意 独立分包 不能引用主包内的公共资源
  • 分包预下载 进入小程序的某个页面 框架自动预下载可能需要的分包 提升进入后续分包页面时的启动速度
  • 配置分包预下载 预下载分包的行为,会在进入指定的页面时触发 app.json中 使用 preloadRule:{}节点定义分包的预下载规则
  • 分包预下载限制
    • 同一分包中的页面 共同的预下载大小限额2M

独立分包 vs 普通分包

  • 主要区别 是否依赖于主包才能运行
  • 普通分包 必须依赖于主包才能运行
  • 独立分包可以在不下载主包的情况下 独立运行
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
分包目录
app.js
app.json
app.wxss
pages
--- index
--- logo
packageA
--pages
----cat
----dog
packageB
--pages
----apple
----banner

//app.json
App({
"pages":[ // 主包的所有页面
"pages/index",
"pages/logs"
],
// 添加配置项 编译 自动生成
"subpackages":[ // 通过 subpackages 节点 声明分包结构
{
"root":"packageA", // 第一个分包的根目录
"pages":[
"pages/cat/cat",
"pages/dog/cat"
]
},{
"root":"packageB", // 第二个分包的根目录
"name":"pack2", // 分包添加别名
"pages":[
"pages/apple/apple",
"pages/bannan/bannan"
],
"independent":true // 独立分包
}
],
"preloadRule":{ // 分包预下载规则
"pages/contact/contact":{ // 触发分包预下载的页面路径
"network":"all", // network 指定的网络模式下进行预下载 all 不限 wifi
"packages":["pagkageA"] // packages 表示进入页面 预下载分包 通过root或name指定预下载那些分包
},

"pages/log/log":{ // 触发分包预下载的页面路径
"network":"wifi", // network 指定的网络模式下进行预下载 all 不限 wifi
"packages":["pagkageB"] // packages 表示进入页面 预下载分包 通过root或name指定预下载那些分包
}
}
})

常见功能

下拉刷新

  • 下拉刷新 移动端专有名词 下拉滑动 重新加载页面数据的行为

    • 全局开启 app.json enablePullDownRefresh true
    • 局部开启(推荐) 页面.json enablePullDownRefresh true
      • backgroud/Color(16进制) TextStyle(dark/light)
    • Page() 内的 onPullDownRefresh(){ } 函数 监听当前页面的下拉刷新事件
    • 停止下拉刷新 处理完下拉刷新 loading 会一直显示 不会自动消失 手动隐藏 loading 效果 wx.stopPullDownRefresh() 停止当前页面的刷新效果
      • onPullDownRefresh(){ wx.stopPullDownRefresh() }
  • 上拉加载 上拉滑动 加载更多数据的行为

    • 监听页面上的上拉触底事件 页面.js onReachBottom() onReachBottom:function(){ }
      • 节流
    • 上拉触底距离 .json onReachBottomDistance=50(默认)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
<view wx:for="{{ colorList }}" wx:key="index" class="num-item" style="background-color: rgb({{ item }})">
{{ item }}
</view>
getColor(){
wx.request({
url: 'https://www.escook.cn/api/color',
method:'get',
success:( { data: res } ) =>{
// var [a,b] = [1,2] {}:{}
this.setData({
colorList: [...this.data.colorList, ...res.data] // 拼接数组 [...[1,2,3,4],...[23,4,5,5]]
//
})
console.log(res)
}
})
},
onLoad(){
this.getColor()
},

}
onReachBottom() {
this.getColor()
},


loading 提示框
wx.showLoading({ title:"数据加载中....." })

wx.request({
complete:()=>{
wx.hideLoading()
}
})
  • 提示框 wx.showLoading(Object object)/wx.hiddeLoading() object title
  • 上拉触底 节流操作
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// data 定义 isloading 节流阀
data:{
isloading: true // true 正在进行数据请求 false 没有任何数据请求
}

// getColors() 方法修改节流阀的值
getColors(){
wx.request({ // complete 回调函数中重置为false
complete:()=>{
wx.hideLoading()
this.setData({
isloading:false
})
}
})
}

// onReachBottom 判断节流阀的值,从而对数据进行节流操作
onReachBottom(){
if(isloading == true) return // 阻止请求
this.getColors() // false 发起请求
}
  • navigator 传递参数url和获取参数 onLoad(options){ options }
  • data中的this.setData({ }) 设置 this.data.xxx.xxx 获取
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// 传递参数 把json中的数据作为参数 传递给 下一个组件动态生成页面
<navigator url="/pages/shoplist/shoplist?id={{ item.id }}&title={{item.name}}" wx:for="{{ gridlist }}" wx:key="id" class="grid-item">
<image src="{{item.icon}}"></image>
<text>{{item.name}}</text>
</navigator>

data: {
query:{} // 参数
},
// this.setData({ }) this.data.xxx.xxx
onLoad(options) {
this.setData({
query:options
})
},
onReady() {
wx.setNavigationBarTitle({
title: this.data.query.title
})
},
  • wx.setNavigationBarTitle(Object object) onReady使用
  • 不同分页数据的获取
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
data: {
query: {},
showList: [], 所有数据
page: 1, 当前页
pageSize: 10, 页数
total: 0 总页数
},

getShowList(){
wx.request({
url:`https://www.escook.cn/categories/${this.data.query.id}/shops`,
method:"get",
data:{
_page: this.data.page,
_limit: this.data.pageSize
},
success:(res) =>{
this.setData({
showList: [...this.data.showList, ...res.data],
total: res.header["X-Total-Count"] - 0
})
}
})
}

onLoad(){
this.getShowList()
}
  • 数据渲染到页面
1
2
3
4
5
6
<view wx:for="{{ showList }}" wx:key="id">
<image src="{{ item.src }}"></image>
<text> {{ item.address }} <text>
<text> {{ item.name }} <text>
<text> {{ item.phone }} <text>
</view>
  • loading 效果
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
getShowList() {
wx.showLoad({
title:"数据加载中..."
}),
wx.request({
url: `https://www.escook.cn/categories/${this.data.query.id}/shops`,
method: "get",
data: {
_page: this.data.page,
_limit: this.data.pageSize
},
success: (res) => {
this.setData({
showList: [...this.data.showList, ...res.data],
total: res.header["X-Total-Count"] - 0
})
},
comlete: () => {
wx.hideLoading()
wx.stopPullDown
}
})
},
  • 下拉触底 页码加1
1
2
3
4
5
6
7
8
"onReachBottomDistance":200

onReachBottom() {
this.setData({
page: this.data.page + 1
})
this.getShowList()
},
  • 节流
    • data isloading 设置false
    • get数据方法 重置值 getShow (){} this.setData({isloading:true}) complete:()=>{ this.setData({isloading:false}) }
    • onLoad if(this.data.isloading) return
  • 判断下一页数就上限
    • 判断下一页有没有数据 page * pageSize >= total 页面值 * 每页显示多少条数据 >= 总数据条数
1
2
3
4
5
6
if (this.data.page * this.data.pageSize >= this.data.total) {
returnwx.showToast({
title:"数据加载完毕",
icon:"none"
})
}
  • 上拉重置
1
2
3
4
5
6
7
8
onPullDownRefresh() {
this.setData({
page: 1,
showList: [],
total:0
}),
this.getShowList()
},
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
{
"usingComponents": {},
"onReachBottomDistance": 200,
"enablePullDownRefresh": true,
"backgroundColor": "#efefef",
"backgroudnColor": "dark"
}

data: {
query: {},
showList: [],
page: 1,
pageSize: 10,
total: 0,
isloading: false
},

getShowList(cb) {
wx.showLoading({
title: "数据加载中..."
}),
this.setData({
isloading: true
}),
wx.request({
url: `https://www.escook.cn/categories/${this.data.query.id}/shops`,
method: "get",
data: {
_page: this.data.page,
_limit: this.data.pageSize
},
success: (res) => {
this.setData({
showList: [...this.data.showList, ...res.data],
total: res.header["X-Total-Count"] - 0
})
},
complete: () => {
wx.hideLoading()
this.setData({ isloading: false })
// wx.stopPullDownRefresh()
cb && cb() // cb
}
})
},
onLoad(options) {
this.setData({
query: options
})
this.getShowList()
},
onReady() {
wx.setNavigationBarTitle({
title: this.data.query.title,
})
},
onPullDownRefresh() {
this.setData({
page: 1,
showList: [],
total:0
}),
this.getShowList(()=>{
wx.stopPullDownRefresh()
})
},
onReachBottom() {
if (this.data.page * this.data.pageSize >= this.data.total) {
return wx.showToast({
title: "数据加载完毕",
icon:"none"
})
}
if (this.data.isloading) return
this.setData({
page: this.data.page + 1
})
this.getShowList()
}

框架

  • mpvue

  • taro

UI库

weui
iview
vant weapp
wux

vant-weapp(组件库) 介绍 - Vant Weapp

  • 安装npm(npm init npm init -y @vant/weapp -S –production) 构建npm(构建npm 使用npm模块) 修改app.json(style:v2删除)
  • 使用vant组件 app.json usingComponents节点中引入需要的组件
1
2
3
4
5
6
app.json
"usingComponents":{
"van-button": "@vant/weapp/button/index"
}

<van-button type="primary"></van-button>
1
2
3
4
5
6
7
8
9
10
:root{
--main-color:red; /// --main-bg-color:blue
}
color: var(--main-color); //

// page页面标签
// 重新覆盖官方的css样式
page{
--button-danger-background-color:#C00000; // 修改自定义样式
}

工具

postcss-px2units将 px 单位转换为 rpx 单位,或者其他单位的 PostCSS插件
gulp-upload-qcloud腾讯云 cos 静态资源上传 gulp 插件
qcloud-upload基于 nodejs 腾讯云上传插件
weapp-qrcodea微信小程序 中,快速生成二维码
  • app.js 入口文件 App()函数 启动整个小程序
  • 页面.js 页面入口文件 Page()函数 创建并运行页面
  • 普通.js 普通的功能模块 封装公共的函数或属性给页面使用 utils/utils.js module.exports = { name:name } / require

页面 vs 组件

  • 全局 App({ })
  • 页面 Pages Page({ })
  • 组件 Component 页面内导入 属性、数据、方法

App.json

  • pages:[]
  • tabBar:{ } postion:bottom/top 、borderStyle、color 、selectColor backgroundColor 、list
    • “list”:[ { pagePath text iconPath selectIconPath },{},{} ]
  • window
    • navigationBar(BackgroundColor,TextStyle,TitleText) 导航条
  • enablePullDownRefresh:false 下拉刷新
    • background(TextStyle(dark/light),Color) 下拉窗口样式
  • onReachBottomDistance=50 上拉触底

指令

  • wx:for={{ [{},{},{}] }} 遍历的是一个数组 + wx:key 提高数组渲染的性能

    • wx:for-item 数组元素 {{ item }} 当前循环项
    • wx:for-index 数组下标{{ index }}索引
    • 手动指定索引和当前项的变量名 重命名索引和Item项 (不常用)
      • wx-for-index=“idx” 可以指定当前循环项的索引的变量名
      • wx-for-item=“itm” 可以指定当前项的变量名
    • wx:key wx:key="id"/"index" id是数组的一个键名 渲染出来的列表项指定唯一的key值 从而提高渲染效率 vue中 :key="id"
  • wx:if wx:elif wx:else 条件渲染 vs hidden

    • hidden="{{ }}"
    • wx:if="{{ condition }} / true or false" 判断是否渲染该代码块
    • wx:if={{ type = 1 }} wx:elif={{ type = 1 }} wx:else wx-if wx:elif wx-else
    • 结合<block>使用wx-if <block wx-if="{{ }}"> </block> 一次性控制多个组件的展示和隐藏 block 将多个组件包装起来 没有任何效果 并不是一个组件 包裹性质的容器 不会在页面中做任何渲染
    • hidden hidden="{{ condition }} // true or false" 控制元素的显示和隐藏
    • 区别 wx-if 动态创建和移除元素的方式 控制条件复杂 切换效率高 hidden 切换样式(display:none/block)频繁切换使用 渲染效率高

事件绑定

  • bind*/bind:* bind(tap|input|change) or bind:(tap|input|change)
    • input事件的值 e.detail.value
  • 重点 事件传参数 事件不能直接传递参数
    • data-变量="{{ xxx }}"
    • handleInput:fucniton(e){ e.currentTarget.dataset.变量 }
  • target vs currentTarget: target 触发该事件的源头组件 currentTarget 当前事件所绑定的组件(当前触发事件的组件)

wxml 结构

数据绑定

  • data:{ info:"messaage" } {{ info }}
    • {{ 100 + 200/ ? : }} <image src="{{imgSrc}}">
  • this.setData({ num: this.data.num + 100 }) 页面data 重新赋值

组件

  • view
  • text 文本
  • rich-text 富文本组件 将字符串解析成对应标签,类似vue中的v-html功能 <rich-text nodes="<img src="https://www.baidu.com/>"
  • scrol-view scroll-x/y
  • input
  • button type="primary/warn" size="mini" plain 镂空 open-type属性 disabled loading form-type open-type
  • image 图片 src mode 指定裁剪和缩放模式 (scaleToFill、aspectFit、aspectFill、widthFix) lazy-load
  • icon 图标 type size color <icon type="success" size="40" color="{{item}}"/>
  • swiper swiper-item
    • indicator-dots、indicator-color、indicator-active-color
    • autoplay、interval、circular
  • navigator a 链接
    • url target 在哪个目标上发生跳转,默认当前小程序 open-type(跳转方式 navigate redirect switchTab reLaunch navigateBack)
  • radio radio-group radio 单选按钮
  • checkbox checkbox-group checkbox
  • map canvase
  • video

wxss 样式

  • rpx 响应式单位 自适应 iphone6 750rpx = 375px = 750物理像素、1rpx = 0.5px = 1物理像素 2rpx = 1px
  • 支持部分css选择器 # . element 并、后代 ::after ::before nth-child(n)
  • @import "common.wxss"

wxs 过滤器

  • <wxs></wxs> 类似<script>标签 必须提供module属性 指定当前wxs的模块名称 方便在wxml中访问模块中的成员
  • WXML 无法调用页面js中的函数 WXML 可以调用WXS中定义的函数
  • <wxs module="m1"> module.exports.xxx = function(str){} </wxs>
    • <view>{{ m1.xxx(str) }}</view>
  • <wxs module="m2" src="../../tool.wxs"></wxs>

API

  • 事件监听 API 以on开头,用来监听某些事件的触发
    • wx.onWindowResize(function callback) 监听窗户尺寸变化的事件
  • 同步 API 以Sync结尾的API 都是同步API 同步API的执行结果 可以通过函数返回值直接获取
    • wx.setStorageSync("key","vaklue") 向本地存储写入内容
  • 异步 API 类似jquery中国的$.ajax(option)函数 需要通过 success fail complete 接受调用
    • wx.require() 发起网络请求 success 回调函数接受数据

自定义组件

  • 声明组件
    • 新建组件 components/test目录 test文件
    • 全局/局部注册组件 “usingComponets:{ "my-header":"/components/myHeader/myHeader" }"
    • 定义组件 <view>Hello World</view> HelloWorld组件
    • 使用组件 <HelloWorld></HelloWorld>
  • 自定义组件
    • data:{} 数据
    • method:{} 方法
    • properties:{} 属性
    • observers:{} 数据监听器
    • 纯数据字段
  • 自定义组件样式
    • 组件样式互不影响、全局样式对组件无效、只有class选择器有影响推荐使用、id 属性 标签选择器不受样式隔离的影响
    • 修改组件的样式隔离
      • js Component({ options:{ styleIsolation:"isolated" } })
      • .json “styleIsolation:"isolated"”
  • 自定义组件中的behaviors

组件 vs 页面

  • 组件 .json 需要声明“component”:true属性 .js文件调用 Component({})函数 组件的事件处理函数需要定义到methods节点中
    • data:{}\methods:{}
  • 页面 Page({})函数

组件通信

  • 父传子
    • 属性方法 父组件是包含子组件的
  • 子传父
    • 事件绑定
    • 获取子组件实例

生命周期

  • 组价生命周期

    • 组件生命周期
    • 组件所在页面的生命周期
  • 应用生命周期函数 App({ }) app.js ==Launch Show Hide==

    • onLaunch(){} 初始化完成 只初始化一次
    • onShow(option){ } 启动或从后台进入前台显示
    • onHide(){} 前台进入后台时

    页面生命周期函数 Page({ }} page.js ==Load Show Ready Hide Unload==

    • onLoad(){ } 页面加载 一个页面只调用一次
    • onShow(){ } 显示
    • onReady(){ } 页面初次渲染完成 一个页面只调用一次
    • onHide(){ } 隐藏
    • onUnload(){ } 卸载 一个页面只调用一次

网络请求 (小程序不存在跨域)

  • wx.request({ })
    • getInfo: wx.request({ url,method,data:{},success:(res)=>{ } }) onLoad this.getInfo 发起GET数据请求
  • miniprogram-api-promise包
    • 官方异步API基于回调函数实现的 回调地狱 可读性 维护性差
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
// wx.request({ })
data:{
swiperList:[]
}

onLoad:function(option){
this.getInfo()
}

getInfo(){
wx.request({
url:"https://www.xxx.com/api/get", // https协议
method:"GET", // method:"POST"
data:{ name:"zs",age:19 },
success:(res) =>{ // 请求成功后的回调
console.log(res) // res.data
this.setData({
swiperlist:res.data // res.data {} {} {}
})
}
fail:()=>{},
complete:()=>{}
})
}

<view wx:for="{{ swiprlist }}" wx:key="id" >
<text>{{ item.name }}</text>
<image src="{{ item.url }}"></image>
</view>

// miniprogram-api-promise

微信小程序云开发

小程序云开发 tcb

云开发:云数据库、云函数、云存储(文件)、云调用

测试appid用不了

1
2
project.config.json
"cloudfunctionRoot": "cloudfunctions/", // cloudfunctions 名称

云数据库

  • 数据库增删改查

  • 数据库

    • 集合 添加记录
    • 权限设置
  • input e.detail.value

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
// 数据库初始化 app.json
onLaunch:function(){
wx.cloud.init({
env:"" // 云开发环境ID
})
}


addName(event){
name = event.detail.value
}

// clound.database() 数据库引入 conllection 手动新建collection
const DB = wx.cloud.database().conllection('list')

addData(){
// 数据库添加数据
DB.add({
data:{
name:"zs",
age:100
},
success(res){},
fail(error){}
})
}

getData(){
DB.get({
success(res){}
})
}
success(res){
that.setData({
arr:res.data
})
}


//删除 要id
DB.doc(id).remove({
success(res){},
fail(error){}
})

DB.doc(id).update({
data:{
age:age
}
})

云函数

  • 新建云函数 json package.js index.js
    • 创建云函数 上传并部署云函数
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
exports.main = async (event, context) => {
let a = event.a
let b = event.b
return a + b
}

Page({
getSum(){
wx.clound.callFunction({
name:"hello", // 云函数目录
data:{
a:100,
b:200
},
success(res){
console.log(res)
},
fail(res){
}
})
}
})

// openid 登陆 微信身份证号
wx.clound.callFunction({
name:'getopenid',
success(res){
res.result.openid
},fail(res){

}
})

使用云函数获取数据库的数据

  • 云函数获取数据库数据可以突破20条限制
  • 云函数不受数据库数据表的权限控制
  • 云函数可以实现的功能更多
1
2
3
4
5
6
7
8
9
10
11
12
13
14
// 数据库获取数据
wx.cloud.database().collection("users").get({
success(){

},
fail(res){

}
})

// 云函数获取数据 云函数中转 一个函数 每个目录一个函数
export.main = async (event,context) => {
return cloud.database().collection("users").get()
}

云存储

  • 文件上传
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
wx.cloud.uploadFile({
cloundPath:'' // 上传到云端的路径
filePaht:'', // 小程序临时文件路径
success: res => { res.fileID },
fail:console.error
})


wx.chooseMedia(Object object) 拍摄或从手机相册中选择图片或视频。


// 云存储 下载地址 或 FileID
<image src={{ imgsrc }}></image>
// 视频存储
<video src={{ vidsrc }} control></video>

data:{
imgsrc:''
}


getData(){
let that = this // 放大作用域 这个this指整个page({})
wx.chooseMedia({ //异步方法 用this 指代括号内的作用域
count: 9,
mediaType: ['image','video'],
sourceType: ['album', 'camera'],
maxDuration: 30,
camera: 'back',
success(res) {
//console.log(res.tempFiles.tempFilePath)
//console.log(res.tempFiles.size)
that.upload(res.tempFiles.tempFilePath[0])
}
})

//
upload(fileurl){
wx.cloud.uploadFile({
// 时间戳 new Date().getTime()
cloundPath: new Date().getTime + '.png' // 上传到云端的路 +'.png' // pdf.其他后缀
filePaht:'fileurl', // res.tempFilePath '' 小程序临时文件路径 // 其他文件 res.temFiles[0].path
success: res => {
this.setData({
imgUrl:res:fileID
})
}, // fileID 图片地址
fail:console.error
})
}

// 上传其他文件
wx.chooseMessageFile({
count: 10,
type: 'all', // all image
success (res) {
// tempFilePath可以作为 img 标签的 src 属性显示图片
const tempFilePaths = res.tempFiles
}
})

// 下载并打开excel
wx.cloud.downloadFile({
// 示例 url,并非真实存在
fileID: 'a7xzcb'
success: function (res) {
const filePath = res.tempFilePath
wx.openDocument({
filePath: filePath,
success: function (res) {
console.log('打开文档成功')
}
})
}
})

7-2 微信小程序哔哩哔哩

2022-09-01 00:00:00
下一页