前言
笔记大部分来自黑马程序员提供的ppt,部分来于自己总结
一、起步
简介
小程序与普通网页开发的区别
注册账号和微信开发者工具
注册
主体类型为个人
开发工具
https://developers.weixin.qq.com/miniprogram/dev/devtools/stable.html
微信开发者工具页面组成
小程序代码构成
项目结构
页面的组成部分
JSON配置文件
JSON配置文件的作用
JSON 是一种数据格式,在实际开发中,JSON 总是以配置文件的形式出现。小程序项目中也不例外:通过不同的 .json 配置文件,可以对小程序项目进行不同级别的配置。
小程序项目中有 4 种 json 配置文件,分别是:
- 项目根目录中的 app.json
- 配置文件项目根目录中的 project.config.json
- 配置文件项目根目录中的 sitemap.json
- 配置文件每个页面文件夹中的 .json 配置文件
app.json 文件
app.json 是当前小程序的全局配置,包括了小程序的所有页面路径、窗口外观、界面表现、底部 tab 等。Demo 项目里边的 app.json 配置内容如下:
project.config.json 文件
project.config.json 是项目配置文件,用来记录我们对小程序开发工具所做的个性化配置,例如:
- setting 中保存了编译相关的配置
- projectname 中保存的是项目名称
- appid 中保存的是小程序的账号 ID
sitemap.json 文件
微信现已开放小程序内搜索,效果类似于 PC 网页的 SEO。sitemap.json 文件用来配置小程序页面是否允许微信索引。
当开发者允许微信索引时,微信会通过爬虫的形式,为小程序的页面内容建立索引。当用户的搜索关键字和页面的索引匹配成功的时候,小程序的页面将可能展示在搜索结果中。
注意:sitemap 的索引提示是默认开启的,如需要关闭 sitemap 的索引提示,可在小程序项目配置文件 project.config.json 的 setting 中配置字段 checkSiteMap 为 false
页面的 .json 配置文件
小程序中的每一个页面,可以使用 .json 文件来对本页面的窗口外观进行配置,页面中的配置项会覆盖 app.json 的 window 中相同的配置项
新建小程序页面
只需要在 app.json -> pages 中新增页面的存放路径,小程序开发者工具即可帮我们自动创建对应的页面文件
修改项目首页
只需要调整 app.json -> pages 数组中页面路径的前后顺序,即可修改项目的首页。小程序会把排在第一位的页面,当作项目首页进行渲染
WXML模版
什么是 WXML?
WXML(WeiXin Markup Language)是小程序框架设计的一套标签语言,用来构建小程序页面的结构,其作用类似于网页开发中的 HTML。
WXML 和 HTML 的区别
WXSS样式
什么是 WXSS
类似于网页开发的CSS
区别
JS
没错,就是你想的JS(JavaScript)
分类
宿主环境
是什么?
小程序开发依赖的环境,那么微信就是小程序的宿主环境
小程序借助宿主环境提供的能力,可以完成许多普通网页无法完成的功能,例如:微信扫码、微信支付、微信登录、地理定位、etc…
通信模型
通信主体
通信模型
运行机制
小程序启动的过程
- 把小程序的代码包下载到本地
- 解析 app.json
- 全局配置文件执行 app.js
- 小程序入口文件,调用 App() 创建小程序实例
- 渲染小程序首页
- 小程序启动完成
页面渲染的过程
- 加载解析页面的 .json
- 配置文件加载页面的 .wxml 模板和 .wxss 样式
- 执行页面的 .js 文件,调用 Page() 创建页面实例
- 页面渲染完成
组件
小程序中组件的分类
小程序中的组件也是由宿主环境提供的,开发者可以基于组件快速搭建出漂亮的页面结构。官方把小程序的组件分为了 9 大类,分别是:
- 视图容器
- 基础内容
- 表单组件
- 导航组件
- 媒体组件map
- 地图组件canvas
- 画布组件
- 开放能力
- 无障碍访问
常用的视图容器类组件
view 组件的基本使用
scroll-view 组件的基本使用
swiper 和 swiper-item 组件的基本使用
swiper 组件的常用属性
常用的基础内容组件
通过 text 组件的 selectable 属性,实现长按选中文本内容的效果:
通过 rich-text 组件的 nodes 属性节点,把 HTML 字符串渲染为对应的 UI 结构:
其它常用组件
button 按钮的基本使用
image 组件的基本使用
image 组件的 mode 属性
API
小程序中的 API 是由宿主环境提供的,通过这些丰富的小程序 API,开发者可以方便的调用微信提供的能力,例如:获取用户信息、本地存储、支付功能等。
API 的 3 大分类
发布流程和小程序运营
上传代码 -> 提交审核 -> 发布
登录小程序管理后台 -> 管理 -> 版本管理 -> 开发版本,即可查看刚才提交上传的版本了:
审核
发布
查看小程序运营数据的两种方式
二、模版与配置
WXML模版语法
数据绑定
- 在 data 中定义数据
- 在 WXML 中使用数据
{{}}取出data定义的数据,和vue的用法一样
<!--pages/list/list.wxml-->
<!-- 1 字符串 -->
<view> {{msg}} </view>
<!-- 2 数字类型 -->
<view>{{num}}</view>
<!-- 3 bool类型 -->
<view> 是否是伪娘: {{isGirl}} </view>
<!-- 4 object类型 -->
<view>{{person.age}}</view>
<view>{{person.height}}</view>
<view>{{person.weight}}</view>
<view>{{person.name}}</view>
<!-- 5 在标签的属性中使用 -->
<view data-num="{{num}}"> 自定义属性</view>
<!--
6 使用bool类型充当属性 checked
1 字符串和 花括号之间一定不要存在空格 否则会导致识别失败
以下写法就是错误的示范
<checkbox checked=" {{isChecked}}"> </checkbox>
-->
<view>
<checkbox checked="{{isChecked}}"> </checkbox>
</view>
<!--
7 运算 => 表达式
1 可以在花括号中 加入 表达式 -- “语句”
2 表达式
指的是一些简单 运算 数字运算 字符串 拼接 逻辑运算。。
1 数字的加减。。
2 字符串拼接
3 三元表达式
3 语句
1 复杂的代码段
1 if else
2 switch
3 do while 。。。。
4 for 。。。
-->
<view>{{1+1}}</view>
<view>{{'1'+'1'}}</view>
<view>{{ 11%2===0 ? '偶数' : '奇数' }}</view>
<!--
8 列表循环
1 wx:for="{{数组或者对象}}" wx:for-item="循环项的名称" wx:for-index="循环项的索引"
2 wx:key="唯一的值" 用来提高列表渲染的性能
1 wx:key 绑定一个普通的字符串的时候 那么这个字符串名称 肯定是 循环数组 中的 对象的 唯一属性
2 wx:key ="*this" 就表示 你的数组 是一个普通的数组 *this 表示是 循环项
[1,2,3,44,5]
["1","222","adfdf"]
3 当出现 数组的嵌套循环的时候 尤其要注意 以下绑定的名称 不要重名
wx:for-item="item" wx:for-index="index"
4 默认情况下 我们 不写
wx:for-item="item" wx:for-index="index"
小程序也会把 循环项的名称 和 索引的名称 item 和 index
只有一层循环的话 (wx:for-item="item" wx:for-index="index") 可以省略
9 对象循环
1 wx:for="{{对象}}" wx:for-item="对象的值" wx:for-index="对象的属性"
2 循环对象的时候 最好把 item和index的名称都修改一下
wx:for-item="value" wx:for-index="key"
-->
<view>
<view>数组循环</view>
<view wx:for="{{list1}}" wx:for-item="item"
wx:for-index="id" wx:key="id">
索引:{{id}}--值:{{item.name}}
</view>
</view>
<view>
<view>对象循环</view>
<view wx:for="{{person}}" wx:for-item="value"
wx:for-index="aaa" wx:key="age">
属性:{{aaa}}--值:{{value}}
</view>
</view>
<!--
10 block
1 占位符的标签
2 写代码的时候 可以看到这标签存在
3 页面渲染 小程序会把它移除掉
-->
<view>
<block wx:for="{{list}}" wx:for-item="item"
wx:for-index="index" wx:key="id"
class="my_list">
索引:{{index}} -- 值:{{item.name}}
</block>
</view>
<!--
11 条件渲染
1 wx:if="{{true/false}}"
1 if , else , if else
wx:if
wx:elif
wx:else
2 hidden
1 在标签上直接加入属性 hidden
2 hidden="{{true}}"
3 什么场景下用哪个
1 当标签不是频繁的切换显示 优先使用 wx:if
直接把标签从 页面结构给移除掉
2 当标签频繁的切换显示的时候 优先使用 hidden
通过添加样式的方式来切换显示
hidden 属性 不要和 样式 display一起使用
-->
<view>
<view>条件渲染</view>
<view wx:if="{{true}}">显示</view>
<view wx:if="{{false}}">隐藏</view>
<view wx:if="{{flase}}">1</view>
<view wx:elif="{{flase}}">2 </view>
<view wx:else> 3 </view>
<view>---------------</view>
<view hidden>hidden1</view>
<view hidden="{{false}}" >hidden2</view>
<view>-----000-------</view>
<view wx:if="{{false}}">wx:if</view>
<view hidden style="display: flex;" >hidden</view>
</view>
<!--
1 长按文字复制 selectable
2 对文本内容 进行 解码
-->
<text selectable decode>
text 123 <
</text>
<image mode="bottom" lazy-load src="https://tva2.sinaimg.cn/large/007DFXDhgy1g51jlzfb4lj305k02s0sp.jpg" />
// pages/list/list.js
Page({
isChecked:true,
list1:[
{
id:0,
name1:"猪八戒"
},
{
id:1,
name:"天蓬元帅"
},
{
id:2,
name:"悟能"
}
],
/**
* 页面的初始数据
*/
data: {
msg: "hello mina",
num: 10000,
isGirl: false,
person: {
age: 74,
height: 145,
weight: 200,
name: "富婆"
}
},
})
事件绑定
**事件是渲染层到逻辑层的通讯方式。**通过事件可以将用户在渲染层产生的行为,反馈到逻辑层进行业务的处理。
小程序中常用的事件
事件对象的属性列表
target 是触发该事件的源头组件,而 currentTarget 则是当前事件所绑定的组件。
事件传参
条件、列表渲染
和vue一样的道理,不在展示,跟着做个项目救明白了
WXSS模版样式
样式导入
通过@import语法,导入别人写好的样式
全局样式和局部样式
定义在 app.wxss 中的样式为全局样式,作用于每一个页面。
在页面的 .wxss 文件中定义的样式为局部样式,只作用于当前页面。
当局部样式和全局样式冲突时,根据就近原则,局部样式会覆盖全局样式当局部样式的权重大于或等于全局样式的权重时,才会覆盖全局的样式
全局配置
全局配置文件及常用的配置项
window
小程序窗口的组成部分
window 节点常用的配置项
设置导航栏的标题
设置导航栏的背景色
设置导航栏的标题颜色
全局开启下拉刷新功能
设置下拉刷新时窗口的背景色
设置下拉刷新时 loading 的样式
设置上拉触底的距离
tabBar
tabBar 的 6 个组成部分
tabBar 节点的配置项
每个 tab 项的配置选项
页面配置
小程序中,每个页面都有自己的 .json 配置文件,用来对当前页面的窗口外观、页面效果等进行配置。
小程序中,app.json 中的 window 节点,可以全局配置小程序中每个页面的窗口表现。如果某些小程序页面想要拥有特殊的窗口表现,此时,“页面级别的 .json 配置文件”就可以实现这种需求。注意:当页面配置与全局配置冲突时,根据就近原则,最终的效果以页面配置为准。
常用的配置项
网络数据请求
小程序中网络数据请求的限制
配置 request 合法域名
案例
<!--pages/home/home.wxml-->
<text>pages/home/home.wxml</text>
<swiper indicator-dots circular>
<swiper-item wx:for="{{swiperList}}" wx:key="id" >
<image src="{{item.image}}"></image>
</swiper-item>
</swiper>
<!-- 九宫格 -->
<view class="grid-list">
<view class="grid-item" wx:for="{{gridList}}" wx:key="id">
<image src="{{item.icon}}"/>
<text>{{item.name}}</text>
</view>
</view>
<!-- 图片区域 -->
<view class="image-box">
<image src="/images/link-01.png" mode="widthFix"/>
<image src="/images/link-02.png" mode="widthFix"/>
</view>
// pages/home/home.js
Page({
/**
* 页面的初始数据
*/
data: {
swiperList: [],
gridList: []
},
/**
* 生命周期函数--监听页面加载
*/
onl oad(options) {
this.getSwiperList()
this.getGridList()
},
getSwiperList() {
wx.request({
url: 'https://applet-base-api-t.itheima.net/slides',
method: 'GET',
success: (res) => {
console.log(res)
this.setData({
swiperList: res.data
})
}
})
},
//获取九宫格数据
getGridList() {
wx.request({
url: 'https://applet-base-api-t.itheima.net/categories',
method: 'GET',
success: (res) => {
console.log(res)
this.setData({
gridList: res.data
})
}
})
},
/**
* 生命周期函数--监听页面初次渲染完成
*/
onReady() {
},
/**
* 生命周期函数--监听页面显示
*/
onShow() {
},
/**
* 生命周期函数--监听页面隐藏
*/
onHide() {
},
/**
* 生命周期函数--监听页面卸载
*/
onUnload() {
},
/**
* 页面相关事件处理函数--监听用户下拉动作
*/
onPullDownRefresh() {
},
/**
* 页面上拉触底事件的处理函数
*/
onReachBottom() {
},
/**
* 用户点击右上角分享
*/
onShareAppMessage() {
}
})
/* pages/home/home.wxss */
swiper {
height: 350rpx;
}
swiper image{
width: 100%;
height: 100%;
}
.grid-list{
display: flex;
flex-wrap: wrap;
border-left: 1rpx solid #efefef;
border-top: 1rpx solid #efefef;
}
.grid-item{
width: 33.33%;
height: 200rpx;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
border-right: 1rpx solid #efefef;
border-bottom: 1rpx solid #efefef;
box-sizing: border-box;
}
.grid-item image{
width: 60rpx;
height: 60rpx;
}
.grid-item text{
font-size: 24rpx;
margin-top: 10rpx;
}
.image-box{
display: flex;
padding: 50rpx 20rpx;
justify-content: space-around;
}
.image-box image{
/* display: flex; */
/* padding: 0rpx 10rpx; */
width: 45%;
}
三、视图与逻辑
页面导航
什么是页面导航
页面导航指的是页面之间的相互跳转。例如,浏览器中实现页面导航的方式有如下两种:
- 链接
- location.href
小程序中实现页面导航的两种方式
声明式导航
在页面上声明一个 导航组件
通过点击 组件实现页面跳转
编程式导航
调用小程序的导航 API,实现页面的跳转
声明式导航
编程式导航
导航传参
页面事件
下拉刷新事件
在页面的 .js 文件中,通过 onPullDownRefresh() 函数即可监听当前页面的下拉刷新事件。例如,在页面的 wxml 中有如下的 UI 结构,点击按钮可以让 count 值自增 +1:
上拉触底事件
什么是上拉触底
上拉触底是移动端的专有名词,通过手指在屏幕上的上拉滑动操作,从而加载更多数据的行为。
案例
<!--pages/cantact/cantact.wxml-->
<text>pages/cantact/cantact.wxml</text>
<view wx:for="{{colorList}}" wx:key="index" class="num-item" style="background-color: rgba({{item}});">{{item}}
</view>
/* pages/cantact/cantact.wxss */
.num-item {
border: 10rpx solid #efefef;
border-radius: 8rpx;
line-height: 200rpx;
margin: 350rpx;
text-align: center;
text-shadow: 0rpx 0rpx 5rpx #fff;
box-shadow: 1rpx 1rpx 6rpx #aaa;
}
// pages/cantact/cantact.js
Page({
/**
* 页面的初始数据
*/
data: {
colorList: [],
isloading: false
},
getColors() {
this.setData({
isloading:true
})
wx.request({
url: 'https://applet-base-api-t.itheima.net/api/color',
method: 'GET',
success: ({
data: res
}) => {
console.log(res.data)
this.setData({ //...的意思是对数据进行拼接,不是覆盖。第一个参数是旧数据,第二个参数是新数据
colorList: [...this.data.colorList, ...res.data]
})
},
complete:() => {
wx.hideLoading()
this.setData({
isloading:false
})
}
})
wx.showLoading({
title: '数据加载中',
})
},
/**
* 生命周期函数--监听页面加载
*/
onl oad(options) {
this.getColors()
},
/**
* 生命周期函数--监听页面初次渲染完成
*/
onReady() {
},
/**
* 生命周期函数--监听页面显示
*/
onShow() {
},
/**
* 生命周期函数--监听页面隐藏
*/
onHide() {
},
/**
* 生命周期函数--监听页面卸载
*/
onUnload() {
},
/**
* 页面相关事件处理函数--监听用户下拉动作
*/
onPullDownRefresh() {
},
/**
* 页面上拉触底事件的处理函数
*/
onReachBottom() {
console.log("触发了上拉触底事件")
if(this.data.isloading) return
this.getColors()
},
/**
* 用户点击右上角分享
*/
onShareAppMessage() {
}
})
生命周期
小程序的启动,表示生命周期的开始
小程序的关闭,表示生命周期的结束
WXS脚本
类似,html中<script>
标签
WXS(WeiXin Script)是小程序独有的一套脚本语言,结合 WXML,可以构建出页面的结构。
wxml 中无法调用在页面的 .js 中定义的函数,但是,wxml 中可以调用 wxs 中定义的函数。因此,小程序中 wxs 的典型应用场景就是“过滤器”。
wxs 和 JavaScript 的关系*
基础语法
WXS的特点
案例
比较简单,直接粘贴代码。
1、首先是把九宫格区域的单元格改成navigator
标签,让点击单元格能实现跳转功能
<!--pages/home/home.wxml-->
<!-- 轮播图区域 -->
<swiper indicator-dots circular>
<swiper-item wx:for="{{swiperList}}" wx:key="id">
<image src="{{item.image}}"></image>
</swiper-item>
</swiper>
<!-- 九宫格区域 -->
<view class="grid-list">
<navigator class="grid-item" wx:for="{{gridList}}" wx:key="id" url="/pages/shoplist/shoplist?id={{item.id}}&title={{item.name}}">
<image src="{{item.icon}}"></image>
<text>{{item.name}}</text>
</navigator>
</view>
<!-- 图片区域 -->
<view class="img-box">
<image src="/images/link-01.png" mode="widthFix"></image>
<image src="/images/link-02.png" mode="widthFix"></image>
</view>
2、编写跳转后的页面,每一个视图左边为图片,右边为介绍(通过WXSS来控制)。最后还通过WXS做过滤器对手机号进行分割,效果为分段显示
<!--pages/shoplist/shoplist.wxml-->
<view class="shop-item" wx:for="{{shopList}}" wx:key="id">
<view class="thumb">
<image src="{{item.images[0]}}"></image>
</view>
<view class="info">
<text class="shop-title">{{item.name}}</text>
<text>电话:{{tools.splitPhone(item.phone)}}</text>
<text>地址:{{item.address}}</text>
<text>营业时间:{{item.businessHours}}</text>
</view>
</view>
<wxs src="../../utils/tools.wxs" module="tools"></wxs>
3、样式调整
/* pages/shoplist/shoplist.wxss */
.shop-item {
display: flex;
padding: 15rpx;
border: 1rpx solid #efefef;
border-radius: 8rpx;
margin: 15rpx;
box-shadow: 1rpx 1rpx 15rpx #ddd;
}
.thumb image {
width: 250rpx;
height: 250rpx;
display: block;
margin-right: 15rpx;
}
.info {
display: flex;
flex-direction: column;
justify-content: space-around;
font-size: 24rpx;
}
.shop-title {
font-weight: bold;
}
// pages/shoplist/shoplist.js
Page({
/**
* 页面的初始数据
*/
data: {
query: {},
shopList: [],
page: 1,
pageSize: 10,
total: 0,
isloading: false
},
/**
* 生命周期函数--监听页面加载
*/
onl oad: function (options) {
this.setData({
query: options
})
this.getShopList()
},
// 以分页的形式获取商铺列表数据的方法
getShopList(cb) {
this.setData({
isloading: true
})
// 展示 loading 效果
wx.showLoading({
title: '数据加载中...'
})
wx.request({
url: `https://applet-base-api-t.itheima.net/categories/${this.data.query.id}/shops`,
method: 'GET',
data: {
_page: this.data.page,
_limit: this.data.pageSize
},
success: (res) => {
this.setData({
shopList: [...this.data.shopList, ...res.data],
total: res.header['X-Total-Count'] - 0
})
},
complete: () => {
// 隐藏 loading 效果
wx.hideLoading()
this.setData({ isloading: false })
// wx.stopPullDownRefresh()
cb && cb()
}
})
},
/**
* 生命周期函数--监听页面初次渲染完成
*/
onReady: function () {
wx.setNavigationBarTitle({
title: this.data.query.title
})
},
/**
* 生命周期函数--监听页面显示
*/
onShow: function () {
},
/**
* 生命周期函数--监听页面隐藏
*/
onHide: function () {
},
/**
* 生命周期函数--监听页面卸载
*/
onUnload: function () {
},
/**
* 页面相关事件处理函数--监听用户下拉动作
*/
onPullDownRefresh: function () {
// 需要重置关键的数据
this.setData({
page: 1,
shopList: [],
total: 0
})
// 重新发起数据请求
this.getShopList(() => {
wx.stopPullDownRefresh()
})
},
/**
* 页面上拉触底事件的处理函数
*/
onReachBottom: function () {
if (this.data.page * this.data.pageSize >= this.data.total) {
// 证明没有下一页的数据了
return wx.showToast({
title: '数据加载完毕!',
icon: 'none'
})
}
// 判断是否正在加载其他数据
if (this.data.isloading) return
// 页码值 +1
this.setData({
page: this.data.page + 1
})
// 获取下一页数据
this.getShopList()
},
/**
* 用户点击右上角分享
*/
onShareAppMessage: function () {
}
})
四、组件
自定义组件
创建与引用
创建
引用
组件的引用方式分为“局部引用”和“全局引用”,顾名思义:
- 局部引用:组件只能在当前被引用的页面内使用
- 全局引用:组件可以在每个小程序页面中使用
局部
全局
哪个更好?
根据组件的使用频率和范围,来选择合适的引用方式:
- 如果某组件在多个页面中经常被用到,建议进行“全局引用”
- 如果某组件只在特定的页面中被用到,建议进行“局部引用”
组件和页面的区别
从表面来看,组件和页面都是由 .js、.json、.wxml 和 .wxss 这四个文件组成的。但是,组件和页面的 .js 与 .json 文件有明显的不同:
- 组件的 .json 文件中需要声明 “component”: true 属性
- 组件的 .js 文件中调用的是 Component() 函数
- 组件的事件处理函数需要定义到 methods 节点中,而页面的处理函数是单独拎出来的在Page({})对象里
样式
组件样式隔离
如下:还是很好理解的
注意点
class选择器就是这样式的:
<h1 class = "c1"> html
.c1{} css
修改组件的样式隔离选项
styleIsolation 的可选值
可选值 | 默认值 | 描述 |
isolated | 是 | 表示启用样式隔离,在自定义组件内外,使用 class 指定的样式将不会相互影响 |
apply-shared | 否 | 表示页面 wxss 样式将影响到自定义组件,但自定义组件 wxss 中指定的样式不会影响页面 |
shared | 否 | 表示页面 wxss 样式将影响到自定义组件,自定义组件 wxss 中指定的样式也会影响页面和其他设置了 apply-shared 或 shared 的自定义组件 |
数据、方法和属性
data 和 properties 的区别
使用 setData 修改 properties 的值
数据监听器
是什么?
基本用法
1、ui代码
<!--components/test2/test2.wxml-->
<view>{{n1}} + {{n2}} = {{sum}}</view>
<button bindtap="addN1">n1+1</button>
<button bindtap="addN2">n2+1</button>
2、js代码
// components/test2/test2.js
Component({
/**
* 组件的属性列表
*/
properties: {
},
/**
* 组件的初始数据
*/
data: {
n1: 0,
n2: 0,
sum: 0
},
/**
* 组件的方法列表
*/
methods: {
addN1() {
this.setData({
n1: this.data.n1 + 1
})
},
addN2() {
this.setData({
n2: this.data.n2 + 1
})
}
},
//3、监听对象属性的变化
//数据监听器支持监听对象中单个或多个属性的变化
observers: {
'n1, n2': function (newN1, newN2) {
this.setData({
sum: newN1 + newN2
})
}
}
})
监听对象属性的变化示例语法:
Component({
observers:{
'对象.属性A,对象.属性B':function(形参A,形参B){
可以直接为属性赋值或者其他对象赋值
}
}
})
如果某个对象中需要被监听的属性太多,为了方便,可以使用通配符 ** 来监听对象中所有属性的变化
Component({
observers:{
'对象.**':function(形参A,形参B){
可以直接为属性赋值或者其他对象赋值
}
}
})
纯数据字段
1.是什么?
概念:纯数据字段指的是那些不用于界面渲染的 data 字段。
应用场景:例如有些情况下,某些 data 中的字段既不会展示在界面上,也不会传递给其他组件,仅仅在当前组件内部使用。带有这种特性的 data 字段适合被设置为纯数据字段。
好处:纯数据字段有助于提升页面更新的性能。
2.使用规则
在 Component 构造器的 options 节点中,指定 pureDataPattern 为一个正则表达式,字段名符合这个正则表达式的字段将成为纯数据字段
3.使用纯数据字段改造数据监听器案例
组件的生命周期
1.组件全部的生命周期函数
生命周期函数 | 参数 | 描述说明 |
created | 无 | 在组件实例刚刚被创建时执行 |
attached | 无 | 在组件实例进入页面节点树时执行 |
ready | 无 | 在组件在视图层布局完成后执行 |
moved | 无 | 在组件实例被移动到节点树另一个位置时执行 |
detached | 无 | 在组件实例被从页面节点树移除时执行 |
error | Object Error | 每当组件方法抛出错误时执行 |
- 组件主要的生命周期函数
在小程序组件中,最重要的生命周期函数有 3 个,分别是 created、attached、detached。它们各自的特点如下:
1.组件实例刚被创建好的时候,created 生命周期函数会被触发
- 此时还不能调用 setData
- 通常在这个生命周期函数中,只应该用于给组件的 this 添加一些自定义的属性字段
2.在组件完全初始化完毕、进入页面节点树后, attached 生命周期函数会被触发
- 此时, this.data 已被初始化完毕
- 这个生命周期很有用,绝大多数初始化的工作可以在这个时机进行(例如发请求获取初始数据)
3.在组件离开页面节点树后, detached 生命周期函数会被触发
- 退出一个页面时,会触发页面内每个自定义组件的 detached 生命周期函数
- 此时适合做一些清理性质的工作
- lifetimes 节点
组件所在页面的生命周期
1.是什么?
2.pageLifetimes 节点
- 生成随机的 RGB 颜色值
插槽
- 什么是插槽
- 单个插槽
- 启用多个插槽
- 定义多个插槽
- 使用多个插槽
示例:
1.定义模版
<view>
<slot name="before"></slot>
<view>这里是组件的内部结构</view>
<slot name="after"></slot>
</view>
2.注册组件
"usingComponents": {
"test4":"./components/test4/test4",
}
3.使用
<test4>
<van-button slot="before" type="primary" bindtap="getInfo">按钮</van-button>
<van-button slot="after" type="danger">按钮</van-button>
</test4>
效果如下:
父子组件之间的通信
1.父子组件之间通信的 3 种方式
- 属性绑定
- 事件绑定
- 获取组件实例
behaviors
- 什么是 behaviors
- behaviors 的工作方式
- 创建 behavior
- 导入并使用 behavior
- behavior 中所有可用的节点
可用的节点 | 类型 | 是否必填 | 描述 |
properties | Object Map | 否 | 同组件的属性 |
data | Object | 否 | 同组件的数据 |
methods | Object | 否 | 同自定义组件的方法 |
behaviors | String Array | 否 | 引入其它的 behavior |
created | Function | 否 | 生命周期函数 |
attached | Function | 否 | 生命周期函数 |
ready | Function | 否 | 生命周期函数 |
moved | Function | 否 | 生命周期函数 |
detached | Function | 否 | 生命周期函数 |
- 同名字段的覆盖和组合规则
组件和它引用的 behavior 中可以包含同名的字段,此时可以参考如下 3 种同名时的处理规则:
- 同名的数据字段 (data)
- 同名的属性 (properties) 或方法 (methods)
- 同名的生命周期函数
使用npm包
小程序对 npm 的支持与限制
Vant Weapp
Vant Weapp 是有赞前端团队开源的一套小程序 UI 组件库,助力开发者快速搭建小程序应用。它所使用的是 MIT 开源许可协议,对商业使用比较友好。
官方文档地址 https://youzan.github.io/vant-weapp
1.安装 Vant 组件库
在小程序项目中,安装 Vant 组件库主要分为如下 3 步:
- 通过 npm 安装(建议指定版本为@1.3.3)
- 构建 npm 包
- 修改 app.json
https://youzan.github.io/vant-weapp/#/quickstart#an-zhuang
2.使用 Vant 组件
3.定制全局主题样式
Vant Weapp 使用 CSS 变量来实现定制主题。 关于 CSS 变量的基本用法,请参考 MDN 文档:https://developer.mozilla.org/zh-CN/docs/Web/CSS/Using_CSS_custom_properties
4.定制全局主题样式
所有可用的颜色变量,请参考 Vant 官方提供的配置文件:https://github.com/youzan/vant-weapp/blob/dev/packages/common/style/var.less
API Promise化
1.基于回调函数的异步 API 的缺点
2.什么是 API Promise 化
API Promise化,指的是通过额外的配置,将官方提供的、基于回调函数的异步 API,升级改造为基于 Promise 的异步 API,从而提高代码的可读性、维护性,避免回调地狱的问题。
3.实现 API Promise 化
4.调用 Promise 化之后的异步 API
全局数据共享
1.什么是全局数据共享
2.小程序中的全局数据共享方案
MobX
1.安装 MobX 相关的包
2.创建 MobX 的 Store 实例
3.将 Store 中的成员绑定到页面中
4.在页面上使用 Store 中的成员
5.将 Store 中的成员绑定到组件中
6.在组件中使用 Store 中的成员
分包
基础概念
1.什么是分包
分包指的是把一个完整的小程序项目,按照需求划分为不同的子包,在构建时打包成不同的分包,用户在使用时按需进行加载。
2.分包的好处
对小程序进行分包的好处主要有以下两点:
- 可以优化小程序首次启动的下载时间
- 在多团队共同开发时可以更好的解耦协作
3.分包前项目的构成
4.分包后项目的构成
5.分包的加载规则
在小程序启动时,默认会下载主包并启动主包内页面
- tabBar 页面需要放到主包中
当用户进入分包内某个页面时,客户端会把对应分包下载下来,下载完成后再进行展示
- 非 tabBar 页面可以按照功能的不同,划分为不同的分包之后,进行按需下载
6.分包的体积限制
目前,小程序分包的大小有以下两个限制:整个小程序所有分包大小不超过 16M(主包 + 所有分包)单个分包/主包大小不能超过 2M
使用分包
1.配置方法
2.打包原则
- 小程序会按 subpackages 的配置进行分包,subpackages 之外的目录将被打包到主包中
- 主包也可以有自己的 pages(即最外层的 pages 字段)
- tabBar 页面必须在主包内
- 分包之间不能互相嵌套
3.引用原则
独立分包
1.什么是独立分包
2.独立分包和普通分包的区别
最主要的区别:是否依赖于主包才能运行
- 普通分包必须依赖于主包才能运行
- 独立分包可以在不下载主包的情况下,独立运行
3.独立分包的应用场景
开发者可以按需,将某些具有一定功能独立性的页面配置到独立分包中。原因如下:
- 当小程序从普通的分包页面启动时,需要首先下载主包
- 而独立分包不依赖主包即可运行,可以很大程度上提升分包页面的启动速度
注意:一个小程序中可以有多个独立分包。
4.独立分包的配置方法
5.引用原则
独立分包和普通分包以及主包之间,是相互隔绝的,不能相互引用彼此的资源!例如:
- 主包无法引用独立分包内的私有资源
- 独立分包之间,不能相互引用私有资源
- 独立分包和普通分包之间,不能相互引用私有资源
- 特别注意:独立分包中不能引用主包内的公共资源
分包预下载
1.什么是分包预下载
分包预下载指的是:在进入小程序的某个页面时,由框架自动预下载可能需要的分包,从而提升进入后续分包页面时的启动速度。
2.配置分包的预下载
预下载分包的行为,会在进入指定的页面时触发。在 app.json 中,使用 preloadRule 节点定义分包的预下载规则,示例代码如下:
3.分包预下载的限制