设置外观和代理
外观
代理
项目结构
主要目录
pages
:存放所有小程序的页面utils
:存放工具性质的模块(例如:格式化时间的自定义模块)app.js
:小程序项目的入口文件app.json
:小程序项目的全局配置文件app.wxss
:小程序项目的全局样式文件(在此文件内写入的样式会被全局生效)project.config.json
:项目配置文件sitemap.json
:配置小程序及其页面是否允许被微信索引pages目录
小程序官方建议将所有小程序的页面,都存放在pages目录中,以单独的文件夹存在
其中,每个页面由4个基本文件组成:.js
文件(页面的脚本文件,存放页面的数据、事件处理函数等).json
文件(当前页面的配置文件,配置窗口的外观、表现等).wxml
文件(页面的模板结构文件)-
JSON配置文件
通过不同的
.json
配置文件,可以对小程序项目进行不同级别的配置 根目录中的
app.json
配置文件- 根目录中的
project.config.json
配置文件 - 根目录中的
sitemap.json
配置文件 - 每个页面文件夹中的
.json
配置文件app.json
小程序的全局配置,包括小程序的所有页面路径、窗口外观、界面表现、底部tab等
"pages"
:小程序所有页面的路径"window"
:全局定义小程序所有页面的背景色、文字颜色等"tabBar"
:全局定义小程序底部的 tab 栏"style"
:全局定义小程序组件所使用的样式版本"sitemapLocation"
:用来指明 sitemap.json 的位置{
"pages":[
"pages/index/index",
"pages/logs/logs"
],
"window":{
"backgroundTextStyle":"light",
"navigationBarBackgroundColor": "#fff",
"navigationBarTitleText": "Weixin",
"navigationBarTextStyle":"black"
},
"tabBar": {
"list": [
{
"pagePath": "pages/index/index",
"text": "首页"
}
]
},
"style": "v2",
"sitemapLocation": "sitemap.json"
}
project.config.json
项目配置文件,用来记录我们对小程序开发工具所做的个性化配置
setting
:编译相关的配置projectname
:项目名称-
sitemap.json
配置小程序页面是否允许微信索引
page
:所有页面都能被索引action
:是否允许被索引(allow
为允许,disallow
为不允许)
注:sitemap
的索引提示是默认开启的,如需关闭sitemap
的索引提示,在小程序项目配置文件project.config.json
的setting
中配置字段checkSiteMap
为false
页面的.json配置文件
小程序中每个页面都可以使用`.json`文件来对本页面的窗口外观进行配置,页面中的配置项会覆盖`app.json`的`window`中相同的配置项<br />![image.png](https://cdn.nlark.com/yuque/0/2022/png/22832478/1652183462583-da886fdb-3eb6-4344-85ba-84ffa067b274.png#clientId=ud1b63a6a-c9a2-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=432&id=ud1184ccc&margin=%5Bobject%20Object%5D&name=image.png&originHeight=432&originWidth=789&originalType=binary&ratio=1&rotation=0&showTitle=false&size=35754&status=done&style=stroke&taskId=u2950efa8-8f21-4f0b-9f40-5ffdcf18fb1&title=&width=789)
新建小程序页面
只需在app.json
中的pages
节点中新增页面的存放路径,小程序开发者工具会帮我们自动创建对应的页面文件
WXML模板
什么是 WXML
WXML是小程序框架设计的一套标签语言,用来构建小程序页面的结构,作用类似于网页开发中的 HTML
WXML 和 HTML 的区别
- 标签名称不同
- HTML(div,span,img,a)
- WXML(view,text,image,navigator)
- 属性节点不同
<a href="#">超链接</a>
<navigator url="/pages/home/home">超链接</navigator>
提供了类似于 Vue 中的模板语法
新增了
rpx
尺寸单位- CSS 中需要手动进行像素单位换算,例如 rem
- WXSS 在底层支持新的尺寸单位
rpx
,在不同大小的屏幕上小程序会自动进行换算
- 提供了全局的样式和局部样式
- 项目根目录中的
app.wxss
会作用域所有小程序页面 - 局部页面的
.wxss
样式仅对当前页面生效
- 项目根目录中的
WXSS 仅支持部分 CSS 选择器
app.js
- 整个小程序项目的入口文件,通过调用
App()
函数来启动整个小程序
- 整个小程序项目的入口文件,通过调用
- 页面的 .js 文件
- 页面的入口文件,通过调用
Page()
函数来创建并运行页面
- 页面的入口文件,通过调用
普通的 .js 文件
主体:渲染层和逻辑层
- WXML 模板和 WXSS 样式工作在渲染层
- JS 脚本工作在逻辑层
- 通信
- 渲染层和逻辑层之间的通信
- 由微信客户端进行转发
- 逻辑层和第三方服务器之间的通信
- 由微信客户端进行转发
- 渲染层和逻辑层之间的通信
运行机制
- 启动过程
- 把小程序的代码包下载到本地
- 解析
app.json
全局配置文件 - 执行
app.js
小程序入口文件,调用App()
创建小程序实例 - 渲染小程序首页
- 小程序启动完成
渲染过程
view
- 普通视图区域
- 类似于 HTML 中的 div,是一个块级元素
scroll-view
- 可滚动的视图区域
- 常用来实现滚动列表效果
swiper
和swiper-item
text
:文本组件- 类似于 HTML 中的 span 标签,是个行内元素
rich-text
:富文本组件- 支持把 HTML 字符串渲染为 WXML 结构
button
:按钮组件- 功能比 HTML 中的 button 按钮丰富
- 通过
open-type
属性可以调用微信提供的各种功能(客服、转发、获取用户授权、获取用户信息等)
image
:图片组件
- 特点:以
on
开头,用来监听某些事件的触发 举例:
wx.onWindowResize(function callback)
监听窗口尺寸变化的事件同步 API
特点1:以
Sync
结尾的 API 都是同步 API- 特点2:同步 API 的执行结果,可以通过函数返回值直接获取,如果执行出错会抛出异常
举例:
wx.setStorageSync('key','value')
向本地存储中写入内容异步 API
特点:类似于 Jquery 中的
$.ajax(options)
函数,需要通过 success、fail、complete 接收调用的结果举例:
wx.request()
发起网络数据请求,通过 success 回调函数接收数据组件
view
view组件基本使用
实现 flex 横向布局效果:
- 更多属性请查阅相关文档:view文档链接
```html
// about.wxml
A B C
// about.wxss
- 效果图如下所示:
![image.png](https://cdn.nlark.com/yuque/0/2022/png/22832478/1652190974052-54ae671e-44bb-42b8-9d60-49fe2c213344.png#clientId=u632ea260-7ee1-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=184&id=u28e6bf39&margin=%5Bobject%20Object%5D&name=image.png&originHeight=184&originWidth=375&originalType=binary&ratio=1&rotation=0&showTitle=false&size=6047&status=done&style=stroke&taskId=ufee76354-3497-4f49-a9dd-aac8fdc1f65&title=&width=375)
<a name="b1MLd"></a>
## scroll-view
<a name="hO0nL"></a>
### scroll-view 组件基本使用
- 实现纵向滚动效果:
- 更多属性请查阅相关文档:[scroll-view文档链接](https://developers.weixin.qq.com/miniprogram/dev/component/scroll-view.html)
```html
// scroll.wxml
<scroll-view class="container1" scroll-y>
<view>A</view>
<view>B</view>
<view>C</view>
</scroll-view>
// scroll.wxss
<style> // 使用时要将 style 标签去掉
.container1 view {
width: 100px;
height: 100px;
text-align: center;
line-height: 100px;
}
.container1 view:nth-child(1) {
background-color: lightgreen;
}
.container1 view:nth-child(2) {
background-color: lightskyblue;
}
.container1 view:nth-child(3) {
background-color: lightcoral;
}
.container1 {
border: 1px solid #000;
height: 120px;
width: 100px;
}
</style>
- 效果图如下所示:
swiper 和 swiper-item
swiper 和 swiper-item 组件的基本使用
- 实现轮播图效果:
- 更多属性请查阅相关文档:swiper文档链接、swiper-item文档链接
```html
// swiper.wxml
A B C
// swiper.wxss
- 效果图如下所示:
![image.png](https://cdn.nlark.com/yuque/0/2022/png/22832478/1652192447047-a21e2a40-b59a-4ef8-9711-9ec59d6258ee.png#clientId=u632ea260-7ee1-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=247&id=u2eca5876&margin=%5Bobject%20Object%5D&name=image.png&originHeight=247&originWidth=375&originalType=binary&ratio=1&rotation=0&showTitle=false&size=6202&status=done&style=stroke&taskId=u1159fd36-c625-4e14-b802-2ec6c4a57ee&title=&width=375)
- `swiper`组件的常用属性
![image.png](https://cdn.nlark.com/yuque/0/2022/png/22832478/1652192952035-1d39da4b-7158-44f0-9cca-14268bb90fec.png#clientId=u632ea260-7ee1-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=382&id=u173e92bc&margin=%5Bobject%20Object%5D&name=image.png&originHeight=382&originWidth=990&originalType=binary&ratio=1&rotation=0&showTitle=false&size=128482&status=done&style=stroke&taskId=u228365f3-f6cd-4847-8ad6-f142e2d73c1&title=&width=990)
<a name="mOMJd"></a>
## text
<a name="AP6Tx"></a>
### text 组件基本使用
- `selectable`:实现长按文本选中文本内容的效果
- `user-select`:实现长按文本选中,该属性会将文本显示为`inline-block`效果
- 更多属性请查阅相关文档:[text文档链接](https://developers.weixin.qq.com/miniprogram/dev/component/text.html)
```html
<view>
手机号支持长按选中效果
<text selectable>18888888888</text>
<text user-select>我会在手机号后面显示</text>
</view>
rich-text
rich-text 组件基本使用
nodes
:将该属性节点内的内容渲染为 HTML 元素- 更多属性请查阅相关文档:rich-text文档链接
```html
// richText.wxml
// richText.wxss .aqua { color: aqua; }
- 最终效果如下所示:
![image.png](https://cdn.nlark.com/yuque/0/2022/png/22832478/1652237902136-58d51ba1-6c61-4ad7-a90d-361c0705c52a.png#clientId=u05a5e54a-a5d9-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=176&id=ua6aef54b&margin=%5Bobject%20Object%5D&name=image.png&originHeight=176&originWidth=373&originalType=binary&ratio=1&rotation=0&showTitle=false&size=9613&status=done&style=stroke&taskId=u3dd11d60-cd15-4c31-8048-e01807b3189&title=&width=373)
<a name="qkTMt"></a>
## button
- `type`:设置按钮类型样式
- `size`:设置按钮大小样式
- `plain`:设置按钮背景色是否透明(默认不透明)
- `disabled`:是否禁用按钮
- `loading`:是否在按钮名称前带上 loading 图标
- 更多属性请查阅相关文档:[button文档链接](https://developers.weixin.qq.com/miniprogram/dev/component/button.html)
```html
// button.wxml
<!-- type属性使用 -->
<button>默认按钮</button>
<button type="primary">绿色按钮</button>
<button type="default">白色按钮</button>
<button type="warn">红色按钮</button>
<!-- size属性使用 -->
<button type="primary" size="mini">绿色按钮</button>
<button type="default" size="mini">白色按钮</button>
<button type="warn" size="mini">红色按钮</button>
<!-- plain属性使用 -->
<button plain type="primary">绿色按钮</button>
<button plain type="default">白色按钮</button>
<button plain type="warn">红色按钮</button>
<!-- disabled属性使用 -->
<button type="primary" disabled>绿色按钮</button>
<!-- loading属性使用 -->
<button type="primary" loading></button>
image
注意:
image
元素默认宽高为width: 320px; height: 240px;
标签中即使没有src
路径或src
路径下没有内容,宽高依旧不改变
src
:图片路径,/
默认表示项目根目录mode
:指定图片的剪裁模式和缩放模式- 缩放模式:
scaleToFill(默认值)
:不保持纵横比缩放图片,使图片的宽高完全拉伸至填满 image 元素aspectFit
:保持纵横比缩放图片,完全展示图片的长边,会完整地将图片显示出来aspectFill
:保持纵横比缩放图片,完全展示图片的短边,会使图片有一定的裁剪widthFix
:宽度不变,高度自动变化,保持原图宽高比不变heightFix
:高度不变,宽度自动变化,保持原图宽高比不变
- 剪裁模式:不缩放图片
top
:只显示图片的顶部区域bottom
:只显示图片的底部区域center
:只显示图片的中间区域left
:只显示图片的左边区域right
:只显示图片的右边区域top left
:只显示图片的左上区域top right
:只显示图片的右上区域bottom left
:只显示图片的左下区域bottom right
:只显示图片的右下区域
- 缩放模式:
lazy-load
:图片懒加载,在即将进入一定范围(上下三屏)时才开始加载show-menu-by-longpress
:长按图片显示发送给朋友、收藏、保存图片、搜一搜、打开名片/前往群聊/打开小程序(若图片中包含对应二维码或小程序码)的菜单- 更多属性请查阅相关文档:image文档链接 ```html
效果如下图所示:<br />![image.png](https://cdn.nlark.com/yuque/0/2022/png/22832478/1652255399538-924e7385-3886-4248-a05d-db642d94dd8a.png#clientId=uc52462ba-3e6b-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=313&id=u814ebae6&margin=%5Bobject%20Object%5D&name=image.png&originHeight=625&originWidth=439&originalType=binary&ratio=1&rotation=0&showTitle=false&size=212770&status=done&style=stroke&taskId=ufcf4182b-e02a-4e9b-8532-e23c4406c65&title=&width=220)![image.png](https://cdn.nlark.com/yuque/0/2022/png/22832478/1652255454531-33094e92-c867-4367-8027-99c8f10ada0f.png#clientId=uc52462ba-3e6b-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=283&id=u184a1ae1&margin=%5Bobject%20Object%5D&name=image.png&originHeight=565&originWidth=423&originalType=binary&ratio=1&rotation=0&showTitle=false&size=205545&status=done&style=stroke&taskId=ue24d393f-1d47-4101-98c4-7ae84c5525e&title=&width=212)![image.png](https://cdn.nlark.com/yuque/0/2022/png/22832478/1652255507983-9b76dad5-970e-487f-864a-83292ccca155.png#clientId=uc52462ba-3e6b-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=348&id=u8a2e2396&margin=%5Bobject%20Object%5D&name=image.png&originHeight=694&originWidth=429&originalType=binary&ratio=1&rotation=0&showTitle=false&size=280496&status=done&style=stroke&taskId=u63bf9487-56df-406e-9f31-6430f630be2&title=&width=215)
html
效果如下图所示:<br />![image.png](https://cdn.nlark.com/yuque/0/2022/png/22832478/1652255802055-b8547918-4540-49cd-85be-047b18b1b115.png#clientId=uc52462ba-3e6b-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=376&id=ua9eb258e&margin=%5Bobject%20Object%5D&name=image.png&originHeight=691&originWidth=419&originalType=binary&ratio=1&rotation=0&showTitle=false&size=88786&status=done&style=stroke&taskId=u4db21cbb-7d97-4fff-92a3-e1aa086db5e&title=&width=228)![image.png](https://cdn.nlark.com/yuque/0/2022/png/22832478/1652255872754-13175715-6760-4e78-9b70-5d0b8093cdfd.png#clientId=uc52462ba-3e6b-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=374&id=u9cec270f&margin=%5Bobject%20Object%5D&name=image.png&originHeight=695&originWidth=424&originalType=binary&ratio=1&rotation=0&showTitle=false&size=211966&status=done&style=stroke&taskId=ude977d5c-e3df-4817-80e2-a64463b50a6&title=&width=228)![image.png](https://cdn.nlark.com/yuque/0/2022/png/22832478/1652255934170-3ee84102-a330-48b7-aecc-f675fc66a874.png#clientId=uc52462ba-3e6b-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=371&id=ube989ed6&margin=%5Bobject%20Object%5D&name=image.png&originHeight=693&originWidth=422&originalType=binary&ratio=1&rotation=0&showTitle=false&size=215528&status=done&style=stroke&taskId=u429ff4f3-f2dc-4012-ad8a-7c125df3ade&title=&width=226)![image.png](https://cdn.nlark.com/yuque/0/2022/png/22832478/1652255998119-c078de6c-065c-4b1a-9628-919a7462061b.png#clientId=uc52462ba-3e6b-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=550&id=u56319da9&margin=%5Bobject%20Object%5D&name=image.png&originHeight=692&originWidth=425&originalType=binary&ratio=1&rotation=0&showTitle=false&size=261884&status=done&style=stroke&taskId=u75950056-086f-4797-915b-018990b33c7&title=&width=338)![image.png](https://cdn.nlark.com/yuque/0/2022/png/22832478/1652256051513-cfab36fe-4661-4e9e-b277-48b2f8eea469.png#clientId=uc52462ba-3e6b-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=553&id=ue1c4eb87&margin=%5Bobject%20Object%5D&name=image.png&originHeight=692&originWidth=423&originalType=binary&ratio=1&rotation=0&showTitle=false&size=248555&status=done&style=stroke&taskId=uc7a9dbf5-4bfc-4d5f-922b-0614a25fd29&title=&width=338)
html
![image.png](https://cdn.nlark.com/yuque/0/2022/png/22832478/1652256281683-c14db025-6ff4-4f92-a315-ba14884bb8ec.png#clientId=uc52462ba-3e6b-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=557&id=u5125a32b&margin=%5Bobject%20Object%5D&name=image.png&originHeight=742&originWidth=420&originalType=binary&ratio=1&rotation=0&showTitle=false&size=101931&status=done&style=stroke&taskId=u0545740c-ee83-46e6-9d8e-f1255ee7651&title=&width=315)
<a name="WPvfq"></a>
# WXML模板
<a name="rgrIN"></a>
## 数据绑定
<a name="FRk2T"></a>
### 基本原则
1. 在 data 中定义数据
javascript
Page({
data: {
// 字符串类型
info: ‘init data’,
imgSrc: “https://s.cn.bing.net/th?id=OIP-C.nRlAFygdctTCHmIWN7GxRwHaEK&w=333&h=187&c=8&rs=1&qlt=90&o=6&pid=3.1&rm=2“,
randomNum1: Math.random() * 10,
randomNum2: Math.random().toFixed(2)
}
})
2. 在 WXML 中使用数据
html
最终效果如下所示:<br />![image.png](https://cdn.nlark.com/yuque/0/2022/png/22832478/1652274508094-a8cba32d-0d13-48df-8622-2c7a49ccbcd1.png#clientId=uc52462ba-3e6b-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=381&id=ud5f06901&margin=%5Bobject%20Object%5D&name=image.png&originHeight=381&originWidth=416&originalType=binary&ratio=1&rotation=0&showTitle=false&size=101639&status=done&style=none&taskId=u2d281747-3f5e-496d-91b8-d10fc4e44cc&title=&width=416)
<a name="i1Kkm"></a>
## 事件绑定
- 定义:在`.js`文件中的`Page()`函数中
- 绑定:在`element`中绑定事件
<a name="cjOBM"></a>
### 常用事件
| 类型 | 绑定方式 | 事件描述 |
| --- | --- | --- |
| `tap` | bindtap 或 bind:tap | 手指触摸后马上离开,类似于 HTML 的 click 事件 |
| `input` | bindinput 或 bind:input | 文本框的输入事件 |
| `change` | bindchange 或 bind:change | 状态改变时触发 |
<a name="dp80f"></a>
#### bindtap 语法格式
1. 通过`bindtap`可以为组件绑定`tap`触摸事件,语法如下:
html
2. 在页面的`.js`文件中定义对应的事件处理函数,事件参数通过形参`event(简写:e)`来接收:
javascript
btnTapHandler(e) { // 按钮的 tap 事件处理函数
console.log(e) // 事件参数对象 e
}
结果如下所示:<br />![image.png](https://cdn.nlark.com/yuque/0/2022/png/22832478/1652318677026-22266d5f-04cb-4935-b7a1-c41c09d03803.png#clientId=u0e7d81c7-fdd3-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=201&id=uf8fd4838&margin=%5Bobject%20Object%5D&name=image.png&originHeight=201&originWidth=735&originalType=binary&ratio=1&rotation=0&showTitle=false&size=22436&status=done&style=shadow&taskId=u625f6cc0-6516-4402-b496-06c5da1ea0c&title=&width=735)
<a name="nNj1z"></a>
#### bindinput 语法格式
1. 通过`bindinput`为文本框绑定**输入**事件:
html
2. 在页面的`.js`中定义事件处理函数:
javascript
inputHandler(e) {
console.log(e.detail.value)
},
> `e.detail.value`获取 input 框的最新值
结果如下所示:<br />![image.png](https://cdn.nlark.com/yuque/0/2022/png/22832478/1652318699240-357d9ac4-79e7-4521-ab62-18b20bb8a2c7.png#clientId=u0e7d81c7-fdd3-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=43&id=u5e343148&margin=%5Bobject%20Object%5D&name=image.png&originHeight=43&originWidth=415&originalType=binary&ratio=1&rotation=0&showTitle=false&size=901&status=done&style=shadow&taskId=uab4f807f-dd4a-4be9-a0c2-f518c31444d&title=&width=415)![image.png](https://cdn.nlark.com/yuque/0/2022/png/22832478/1652318706562-4f2e9367-8ef9-4126-8b97-80fa503de506.png#clientId=u0e7d81c7-fdd3-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=81&id=u675c2bd5&margin=%5Bobject%20Object%5D&name=image.png&originHeight=81&originWidth=398&originalType=binary&ratio=1&rotation=0&showTitle=false&size=1016&status=done&style=shadow&taskId=u129b8052-6af8-488e-a790-fc3a87823c7&title=&width=398)
<a name="TykVI"></a>
#### bindinput 实现 v-model 效果
html
```javascript
Page({
data: {
msg: 'Hello World!'
},
inputModel(e) {
this.setData({
msg: e.detail.value
})
},
})
### 事件对象属性
| 属性 | 类型 | 说明 |
| —- | —- | —- |
| type
| String | 事件类型 |
| timeStamp
| Integer | 页面打开到触发事件所经过的毫秒数 |
| target
| Object | 触发事件的组件的一些属性值集合 |
| currentTarget
| Object | 当前组件的一些属性值合集 |
| detail
| Object | 额外的信息 |
| touches
| Array | 触摸事件,当前停留在屏幕中的触摸点信息的数组 |
| changedTouches
| Array | 触摸事件,当前变化的触摸点信息的数组 |
#### target
和currentTarget
的区别
- e.target
指向的是触发事件的源头组件,因此,e.target
是内部的按钮组件
- e.currentTarget
指向的是当前正在触发事件的组件,因此,e.currentTarget
是当前源头组件最外部的组件
### 数据赋值 this.setData()
- 使用this.setData()
方法,给 Data 中的数据重新赋值
html
<view>count值:{{count}}</view>
<button type="primary" bindtap="changeCount">Count++</button>
javascript
changeCount() {
this.setData({
count: this.data.count + 1
})
}
> 用this.data
拿到 Page()
中的 data
对象
### 事件传参
- 传递参数:使用`data-=”{{value}}”给事件传参,
表示参数名,
value表示参数值
- **获取参数值**:使用
e.target.dataset,获取事件传递过来的参数值,一般来说是个对象,使用
e.target.dataset.info获取指定的参数值
```html
<button type="primary" bindtap="btnTapHandler1" data-info="{{3}}">事件传参</button>
```
```javascript
btnTapHandler1(e) {
// 获取的是参数对象
console.log(e.target.dataset);
// 获取的是具体的参数值,info 为传来的参数名
console.log(e.target.dataset.info);
},
```
<a name="t7eZO"></a>
## 条件渲染
<a name="t87fu"></a>
### wx:if、wx:elif、wx:else(属性)
```html
<view wx:if="{{num >= 95}}">学霸</view>
<view wx:elif="{{num >= 90}}">优等生</view>
<view wx:elif="{{num >= 60}}">普通生</view>
<view wx:else>学渣</view>
```
```javascript
data: {
num: 99
},
```
<a name="AOu3Z"></a>
### block 标签(组件)
- 作用:类似 Vue 中的
template标签,只用来包裹
```html
<block wx:if="{{true}}">
<view>为 true 显示我</view>
<view>为 true 显示我</view>
</block>
```
![image.png](https://cdn.nlark.com/yuque/0/2022/png/22832478/1652322275327-890f79e3-9ea1-4837-92a8-296cdd09db91.png#clientId=u0e7d81c7-fdd3-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=140&id=u28440f93&margin=%5Bobject%20Object%5D&name=image.png&originHeight=187&originWidth=420&originalType=binary&ratio=1&rotation=0&showTitle=false&size=12571&status=done&style=shadow&taskId=uc56bd316-5f62-406b-a534-073c1309ec6&title=&width=315)![image.png](https://cdn.nlark.com/yuque/0/2022/png/22832478/1652322246905-e21eaf9e-a18b-43fd-b280-491e8a23e323.png#clientId=u0e7d81c7-fdd3-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=138&id=u6f96d34d&margin=%5Bobject%20Object%5D&name=image.png&originHeight=155&originWidth=367&originalType=binary&ratio=1&rotation=0&showTitle=false&size=7294&status=done&style=shadow&taskId=ubcfdba12-49a0-47a6-b2d3-01697d546a0&title=&width=327)
> 真实渲染时,
block标签并不会渲染到页面中
<a name="wYnoo"></a>
### hidden(属性)
- 作用:使用
display: none;来控制元素的 **显示** 和 **隐藏**,
true为**显示**,
false`为*隐藏
html
<view hidden="{{ false }}">为 true 隐藏我,为 false 显示我</view>
## 列表渲染
### wx:for、wx:for-index、wx:for-item
- wx:for-index
:指定 index
索引的名字
- wx:for-item
:指定item
值的名字
```html
// cycle.js Page({ data: { arr: [‘iPhone’, ‘HUAWEI’, ‘vivo’] } })
![image.png](https://cdn.nlark.com/yuque/0/2022/png/22832478/1652323381802-1ef13aa2-046c-4962-90b7-c630598b62f2.png#clientId=u0e7d81c7-fdd3-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=148&id=u22f0090f&margin=%5Bobject%20Object%5D&name=image.png&originHeight=148&originWidth=422&originalType=binary&ratio=1&rotation=0&showTitle=false&size=9447&status=done&style=shadow&taskId=ueb36475b-2c23-4977-aac9-8978d869fea&title=&width=422)
<a name="ucub6"></a>
# WXSS
<a name="Um8lZ"></a>
## 特性:
1. `rpx`尺寸单位
1. `@import`样式导入
![image.png](https://cdn.nlark.com/yuque/0/2022/png/22832478/1652324109219-530ea845-6c3f-48fb-9572-18c59bf23a89.png#clientId=u02bd2a5a-3a4f-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=254&id=uccdb2c46&margin=%5Bobject%20Object%5D&name=image.png&originHeight=279&originWidth=422&originalType=binary&ratio=1&rotation=0&showTitle=false&size=57603&status=done&style=shadow&taskId=u5b3e80a5-c389-4b9b-a15d-2a041ff6d57&title=&width=383.63635532126955)
<a name="fn8YN"></a>
## rpx尺寸单位
<a name="GzG0C"></a>
### 了解
- `rpx`是小程序独有的,用来**解决屏幕适配的尺寸单位**
<a name="FGlMZ"></a>
### 实现原理
- 鉴于不同设备屏幕的大小不同,为了实现屏幕的自动适配,**rpx** 把所有设备的屏幕在宽度上**等分为 750 份**(即:当前屏幕的总宽度为 **750rpx**)
- 小设备上,1rpx 代表的宽度就小
- 大设备上,1rpx 代表的宽度就大
- 小程序在不同的设备中运行时,会自动将 rpx 单位换算为 px 单位进行渲染,从而实现屏幕适配
<a name="TTTdR"></a>
## @import (样式导入)
- `@import` 后跟需要导入的外联样式表的相对路径,用 `;` 表示语句结束
```html
// Pages/index/index.wxml
<view wx:for="{{userList}}" wx:key="id" class="username">
id:{{item.id}} --- value:{{item.name}}
</view>
// common/common.wxss
.username {
color: aqua;
}
// Pages/index.index.wxss
@import "../../common/common.wxss"
全局样式(app.wxss)
- 作用于所有页面
view {
padding: 10rpx;
margin: 10rpx;
background-color: #888;
}
当全局样式和局部样式冲突时,根据就近原则,局部样式会覆盖全局样式 当局部样式的权重大于或等于全局样式的权重时,才会覆盖全局的样式
全局配置
window
全局/页面常用配置项
属性名 | 类型 | 默认值 | 说明 |
---|---|---|---|
navigationBarTitleText | String | 字符串 | 导航栏标题文字内容 |
navigationBarBackgroundColor | HexColor | #000 | 导航栏背景颜色 |
navigationBarTextStyle | String | white | 导航栏标题颜色,black / white |
backgroundColor | HexColor | #fff | 窗口的背景色 |
backgroundTextStyle | String | light | 下拉 loading 的样式,drak / light |
enablePullDownRefresh | Boolean | false | 是否全局开启下拉刷新 |
onReachBottomDistance | Number | 50 | 页面上拉触底事件触发时距页面底部距离,单位为 px |
tabBar
- tabBar 中只能配置最少 2 个、最多 5 个 tab 页签
- 当渲染顶部 tabBar 时,不显示 icon,只显示文本
节点配置项
| 属性 | 类型 | 必填 | 默认值 | 描述 | | —- | —- | —- | —- | —- | | position | String | 否 | bottom | tabBar 的位置,bottom / top | | borderStyle | String | 否 | black | tabBar 上边框的颜色,black / white | | color | HexColor | 否 | | tab 上文字的默认(未选中)颜色 | | selectedColor | HexColor | 否 | | tab 上文字选中时的颜色 | | backgroundColor | HexColor | 否 | | tabBar 的背景色 | | list | Array | 是 | | tab 页签的列表,最少2个、最多5个 |
tab 项的配置项
属性 | 类型 | 必填 | 描述 |
---|---|---|---|
pagePath | String | 是 | 页面路径,页面必须在 pages 中预先定义 |
text | String | 是 | tab 上显示的文字 |
iconPath | String | 否 | 未选中时的图标路径; 当前 position 为 top 时,不显示 icon |
selectedIconPath | String | 否 | 选中时的图标路径; 当 position 为 top 时,不显示 icon |
网络数据请求
限制
- 只能请求 HTTPS 类型的接口
-
配置 request 合法域名
配置步骤
登录微信小程序管理后台
- 开发
- 开发设置
- 服务器域名
- 修改 request 合法域名
注意事项:
- 域名只支持 https 协议
- 域名不能使用 IP 地址或 localhost
- 域名必须经过 ICP 备案
- 服务器域名一个月内最多可申请 50 次修改
发起 GET 请求
<!-- index.wxml -->
<button type="primary" bindtap="getInfo">发起GET请求</button>
<!-- index.js -->
Page({
// 发起 GET 请求
getInfo() {
wx.request({
url: 'https://api.muxiaoguo.cn/api/tiangourj?api_key=c342043936758a92',
method: 'GET',
success: (res) => {
console.log(res);
}
})
}
})
发起 POST 请求
<!-- index.wxml -->
<button type="primary" bindtap="postInfo">发起POST请求</button>
<!-- index.js -->
Page({
// 发起 POST 请求
postInfo() {
wx.request({
url: 'https://api.muxiaoguo.cn/api/tianqi?api_key=29abdbf534ebdca5',
methosd: "POST",
data: {
type: 1,
city: "南昌"
},
success(res) {
console.log(res);
}
})
}
})
页面刚加载时请求数据
Page({
onLoad(options) {
// 调用 get 请求事件
this.getInfo()
}
})
跳过 request 合法域名校验
- 开启后可暂时跳过 https 校验域名,请求 http 接口
跳过 request 合法域名校验的选项,仅在开发和调试阶段使用
页面导航
声明式导航(属性实现跳转)
概述
- 在页面上声明一个
<navigator>
导航组件 -
导航 tabBar 页面
使用
<navigator>
组件跳转到指定的 tabBar 页面时,需要指定 url 属性和 open-type 属性,其中:使用
<navigator>
组件跳转到指定的非 tabBar 页面时,需要指定 url 属性和 open-type 属性,其中:- url 表示要跳转的页面地址,必须以 / 开头
- open-type 表示跳转的方式,必须为 navigate
在跳转的页面非 tabBar 页面时,可以省略
open-type="navigate"
属性不写
<!-- 导航跳转至分类页 -->
<navigator url="/pages/contents/contents" open-type="navigate">导航至contents页</navigator>
后退导航
- 后退上一页面或多级页面,需要指定 delta 属性和 open-type 属性,其中:
- open-type 的值必须是 navigateBack,表示要进行后退导航
- delta 的值必须是数字,表示要后退的层级(默认值为 1)
如果只是后退至上一页面,delta 属性则可以省略不写,因为默认值就为 1 在 tabBar 页面中使用不会生效,只能在非 tabBar 页面使用法
<!-- 后退导航 -->
<navigator open-type="navigateBack" delta="1">返回上一页</navigator>
导航传参
- 参数和路径之间使用
?
分隔 - 参数键和参数值用
=
连接 不同参数用
&
分隔<navigator url="/pages/contents/contents?name=smallfish&age=18">跳转 contents 页</navigator>
编程式导航(js实现跳转)
概述
-
导航 tabBar 页面
调用 wx.switchTab(Object Object) 方法,跳转至 tabBar 页面;其中 Object 的参数对象的属性列表如下: | 属性 | 类型 | 是否必选 | 说明 | | —- | —- | —- | —- | | url | string | 是 | 需要跳转的 tabBar 页面路径,路径后不能带参数 | | success | function | 否 | 接口调用成功的回调函数 | | fail | function | 否 | 接口调用失败的回调函数 | | complete | function | 否 | 接口调用结束的回调(调用成功、失败都会执行) |
<!-- 导航到 users 页 -->
<button type="primary" bindtap="gotoUsers">跳转至users页</button>
// 导航到 users 页
gotoUsers() {
wx.switchTab({
url: '/pages/users/users',
})
},
导航非 tabBar 页面
- 调用 wx.navigateTo(Object Object) 方法,可以跳转至非 tabBar 页面;其中 Object 参数对象的属性列表如下: | 属性 | 类型 | 是否必选 | 说明 | | —- | —- | —- | —- | | url | string | 是 | 跳转至非 tabBar 页面的路径,路径后可带参数 | | success | function | 否 | 接口调用成功的回调 | | fail | function | 否 | 接口调用失败的回调 | | complete | function | 否 | 接口调用结束的回调(调用成功、失败都会执行) |
<!-- 导航至 contents 页 -->
<button type="primary" bindtap="gotoContents">跳转 contents 页</button>
// 导航至非 tabBar 页
gotoContents() {
wx.navigateTo({
url: '/pages/contents/contents',
})
},
后退导航
- 调用 wx.navigateBack(Object Object) 方法,可以返回上一页或多页;其中 Object 参数对象的属性列表如下: | 属性 | 类型 | 默认值 | 是否必选 | 说明 | | —- | —- | —- | —- | —- | | delta | number | 1 | 否 | 返回的页面数,delta 大于现有页面数,则返回首页 | | success | function | | 否 | 接口调用成功的回调 | | fail | function | | 否 | 接口调用失败的回调 | | complete | function | | 否 | 接口调用结束的回调(调用成功、失败都会执行) |
如果只是后退至上一页面,delta 属性则可以省略不写,因为默认值就为 1 在 tabBar 页面中使用不会生效,只能在非 tabBar 页面使用
<!-- 返回上一页 -->
<button type="primary" bindtap="gotoBack">返回上一页</button>
// 返回上一页
gotoBack() {
wx.navigateBack()
},
导航传参
- 调用 wx.navigateTo(Object Object) 方法,可携带参数,示例如下: ```html
// 导航至非 tabBar 页 gotoContents() { wx.navigateTo({ url: ‘/pages/contents/contents?name=smallfish&age=18’, }) },
<a name="qMUyB"></a>
## onLoad 接收导航参数
```javascript
onLoad(options) {
// options 就是导航传递的参数对象
console.log(options)
}
页面事件
实现下拉刷新
<view>下拉刷新效果</view>
<view>count:{{ count }}</view>
<button bindtap="addCount">count++</button>
Page({
data: {
count: 0
},
onPullDownRefresh() {
this.setData({
count: 0
})
// 关闭下拉刷新效果
wx.stopPullDownRefresh()
}
})
实现上拉触底
配置上拉触底距离
- 小程序启动,生命周期开始
- 小程序关闭,生命周期结束
- 中间小程序运行的过程,就是小程序的生命周期
自动按次序执行
应用生命周期
- 小程序:启动 -> 运行 -> 销毁
在
app.js
中进行声明,代码如下:App({
// 小程序初始化完成时,执行此函数,全局只触发一次,做初始化工作
onLaunch(options) {},
// 小程序启动,或从后台进入前台显示时触发
onShow(options) {},
// 小程序从前台进入后台时触发
onHide() {}
})
页面生命周期
小程序:页面加载 -> 渲染 -> 销毁
在页面对应的
.js
中进行声明:代码如下:Page({
onLoad(options) {}, // 监听加载,一个页面只调用一次
onShow() {}, // 监听页面显示
onReady() {}, // 监听页面初次渲染完成,一个页面只调用一次
onHide() {}, // 监听页面隐藏
onUnload() {} // 监听页面卸载,一个页面只调用一次
})
WXS脚本
WXS 是小程序独有的一套脚本语言,结合 WXML,可以构建出页面的结构
- wxs 不支持:let 、const 、解构赋值、展开运算符、箭头函数、对象属性简写等
module
:模块的名称- src:模块的路径(相对路径)
- wxs 中定义的函数不能作为组件的事件回调函数
- wxs 不能调用 js 文件中定义的函数
- wxs 不能调用小程序提供的 API
- 在 ios 设备上,wxs 比 js 快 2~20倍
- 在 Android 设备上,二者的运行效率无差异
内联WXS脚本
<!-- m1 wxs模块 -->
<view class="title">m1 模块</view>
<view>{{ m1.toUpper(name) }}</view>
<!-- m1 wxs模块 -->
<wxs module="m1">
module.exports.toUpper = function(str) {
return str.toUpperCase()
}
</wxs>
外链WXS脚本
// xxx.wxml
<!-- m2 wxs模块 -->
<view class="title">m2 模块</view>
<view>{{ m2.toLower(country) }}</view>
<!-- m2 wxs模块 -->
<wxs src="../../utils/tools.wxs" module="m2"></wxs>
// utils/tools.wxs
function toLower(str) {
return str.toLowerCase()
}
module.exports = {
toLower: toLower
}
自定义组件
组件创建
- 在项目根目录中,创建
components
文件夹 - 在新建的
components
文件夹中新建你想要的组件文件夹 - 鼠标右键,点击组件文件夹,点击“新建Component”
- 输入组件名称后回车,会生成组件对应的 4 个文件,分别是
.js
、.json
、.wxml
、.wxss
为了保证目录结构清晰,把不同组件存放到单独的目录中
组件引用
局部引用
- 在页面的
.json
配置文件中引用组件,示例如下:// 页面的 .json 文件中,引入组件
```json
{
"usingComponents": {
"test1": "/components/test1/test1"
}
}
// 在页面的 .wxml 文件中,使用组件
<test1></test1>
<a name="xKQUO"></a>
### 全局引用
- 在项目根目录下的`app.json`文件中,和`window`节点平级,新增`usingComponents`节点,示例如下:
```markdown
// 在 app.json 文件中,引入组件
```json
{
"usingComponents": {
"test1": "/components/test1/test1"
}
}
// xxx.wxml 文件中,使用组件
<test1></test1>
<a name="ruUP9"></a>
## 全局和局部的区别
- 组件的`.json`需要声明“component”: true 属性
- 组件的`.js`调用的是 Component() 函数
- 组件的事件处理函数需要定义到 methods 节点中
<a name="etHcG"></a>
## 样式隔离:stylelsolation
:::danger
注意点:
1. app.wxss 中的全局样式对组件无效
1. 只有 class 选择器有样式隔离效果,id、属性、标签选择器不受样式隔离的影响
1. 在组件和引用组件的页面中建议使用 class 选择器,不要使用 id、属性、标签选择器
:::
- 防止组件内外样式互相干扰;有时,希望外界可以控制组件内部样式
```javascript
// 方法 1
Component({
options: {
styleIsolation: 'isolated'
}
})
// 方法 2
{
"styleIsolation": "isolated"
}
可选值 | 默认值 | 描述 |
---|---|---|
isolated | 是 | 启用样式隔离,在自定义组件内外,使用class 指定的样式将不会互相影响 |
apply-shared | 否 | 页面 WXSS 样式将影响自定义组件,但自定义组件 WXSS 中的样式不会影响页面 |
shared | 否 | 页面 WXSS 样式将影响自定义组件,自定义组件 WXSS 样式也会影响页面和其他设置了 apply-shared 或 shared 的自定义组件 |
事件处理函数和自定义方法:methods
<view>count值是:{{ count }}</view>
<button type="primary" bindtap="addCount">count++</button>
Component({
data: {
count: 0
},
methods: {
addCount() { // 事件处理函数
this.setData({
count: this.data.count + 1
})
this._showCount()
},
_showCount() { // 自定义方法,以 _ 开头
wx.showToast({ // 弹窗方法
title: 'count值为:' + this.data.count,
icon: 'none'
})
}
}
properties 和 data
- 类似于 Vue 中的 props
- 用于接收外界传递到组件中的数据
- properties 中的数据是可读写的
- properties 和 data 指向的是同一个对象
- data:存储组件私有数据
- properties:存储外界传递到组件中的数据
<test max="15"><test1>
Component({
properties: {
max: Number, // 简单定义类型
max: { // 复杂定义类型
type: Number,
value: 10 // 默认值
}
},
})
数据监听器:observers
<view>{{n1}} + {{n2}} = {{sum}}</view>
<button bindtap="addN1">n1 + 1</button>
<button bindtap="addN2">n2 + 1</button>
Component({
data: {
n1: 0,
n2: 0,
sum: 0
},
methods: {
addN1() {
this.setData({
n1: this.data.n1 + 1
})
},
addN2() {
this.setData({
n2: this.data.n2 + 1
})
},
},
observers: {
'n1, n2': function(n1, n2) {
this.setData({
sum: n1 + n2
})
}
}
})
:::danger
observers中,如果键为对象,需要监听对象中的所有属性,可以使用
obj.**
方法即可 :::纯数据字段
概念:不用于界面渲染的 data 字段
好处:有助于提升页面更新的性能
Component({
options: {
pureDataPattern: /^_/
},
data: {
a: 0,
_b: 10
}
})
组件的生命周期函数
Component({
lifetimes: {
created() {}, // 组件实例刚被创建时执行
attached() {}, // 组件实例进入页面节点树时执行
ready() {}, // 组件再视图层布局完成后执行
moved() {}, // 组件实例被移动到节点树的另一个位置时执行
detached() {}, // 组件实例被页面节点树移除时执行
error(Object Error) {} // 组件方法抛出错误时执行
}
})
:::danger
created 执行时并不能使用 this.setData
attached 执行时可以使用 this.setData :::
组件所在页面的生命周期函数
Component({
pageLifetimes: {
show() {}, // 组件所在页面被展示时执行
hide() {}, // 组件所在页面被隐藏时执行
resize(size) {} // 组件所在页面尺寸变化时执行
}
})
插槽
<view>
<view>这是slots组件内部</view>
<slot></slot>
</view>
<slots>
<view>这是要插入到slots组件中的内容</view>
</slots>
使用多个插槽
Component({
options: {
multipleSlots: true // 在组件定义时的选项中启用了多 slot 支持
}
})
父子组件通信
属性绑定
父组件向子组件的指定属性设置数据,仅能设置JSON兼容的数据 ```html // pages/home/home.wxml
父组件中,count值为:{{ count }} —————————————
// components/attr/attr.wxml
```javascript
// pages/home/home.js
Page({
data: {
count: 0
},
addCount() {
this.setData({
count: this.data.count + 1
})
}
})
// components/attr/attr.js
Component({
properties: {
count: Number
}
})
事件绑定
- 子组件向父组件传递数据,可传递任何数据
在父组件的
js
中,定义一个函数,这个函数将通过自定义事件的形式,传递给子组件Page({
data: {
count: 0
},
syncCount(e) {
console.log(e.detail.value);
}
})
在父组件的
wxml
中,通过自定义事件的形式,将步骤 1 中定义的函数引用,传递给子组件<emit count="{{count}}" bind:sync="syncCount"></emit>
在子组件的
js
中,通过调用this.triggerEvent('自定义事件名称', {/*参数对象*/})
,将数据发送到父组件<view>子组件的count值为:{{count}}</view>
<button type="primary" bindtap="addCount">count+1</button>
Component({
properties: {
count: Number
},
methods: {
addCount() {
this.setData({
count: this.properties.count + 1
})
this.triggerEvent('sync', {value: this.properties.count})
}
}
})
在父组件的
js
中,通过e.detail
获取到子组件传递过来的数据Page({
syncCount(e) {
this.setData({
count: e.detail.value
})
},
})
获取组件实例
- 父组件可通过 this.selectComponent(只能传class或id选择器) 获取子组件实例对象
这样可以直接访问子组件的任意数据和方法
<view>父组件的count值为:{{count}}</view>
<view>----------------------------</view>
<get-instance-obj bind:sync="syncCount" count="{{count}}" class="customA" id="cA"></get-instance-obj>
<button bindtap="getChild">获取子组件实例对象</button>
Page({
data: {
count: 0
},
syncCount(e) {
this.setData({
count: e.detail.value
})
},
getChild() {
const child = this.selectComponent('.customA')
child.addCount()
},
})
<view>子组件的count值为:{{count}}</view>
<button bindtap="addCount">count++</button>
Component({
properties: {
count: Number
},
methods: {
addCount() {
this.setData({
count: this.properties.count + 1
})
this.triggerEvent('sync', {value: this.properties.count})
}
}
})
behaviors
在项目根目录下创建 behaviors 目录,并创建自己想要的 js 文件
- 在 js 文件中定义数据、属性、方法、生命周期等节点
- 在组件中使用 require 导入,在与 data 节点平级,创建 behaviors 节点,为一个数组,数组中的元素便是引入的变量名
module.exports = Behavior({
behaviors: [], // 用来保存引入的其他 behaviors
properties: { // 同组件属性
myBehaviorProperty: {
type: String
}
},
data: { // 同组件数据
myBehaviorData: {}
},
attached: function(){}, // 生命周期函数
methods: { // 同自定义组件的方法
myBehaviorMethod: function(){}
}
})
var myBehavior = require('my-behavior')
Component({
behaviors: [myBehavior] // 使用
})
使用npm包
- 通过 miniprogram-api-promise 第三方包,实现 API Promise 化:
```javascript import { promisifyAll } from ‘miniprogram-api-promise’npm install --save miniprogram-api-promise@1.0.4
const wxp = wx.p = {} promisifyAll(wx, wxp)
- 通过额外的配置,将官方提供的、基于回调函数的异步 API,升级改造为基于 Promise 的异步 API,从而提高代码的可读性、维护性、避免回调地狱的问题
- 调用 Promise 化之后的异步 API
```html
<van-button type="danger" bindtap="getInfo">vant按钮</van-button>
<script>
async getInfo() {
const { data: res } = await wx.p.request({
method: 'GET',
url: 'https://www.escook.cn/api/get',
data: {
name: 'zs',
age: 18
}
})
console.log(res)
}
</script>
安装使用 Vant Weapp
npm i @vant/weapp -S --production
npm i @vant/weapp@1.3.3 -S --production
在项目根目录下右键打开 cmd 命令行窗口,运行如下命令:
# 创建一个 package.json 配置文件
npm init -y
# 在 app.json 中删除 style 节点
{
...
"setting": {
...
"packNpmManually": true,
"packNpmRelationList": [
{
"packageJsonPath": "./package.json",
"miniprogramNpmDistDir": "./miniprogram/"
}
]
}
}
// 注册使用 vant 组件
"usingComponents": {
"van-button": "@vant/weapp/button/index"
}
在开发者工具左上角的 工具 选项中,选择 构建 npm,打开右上角 详情,打开 本地设置,勾选 使用 npm 模块
自定义全局主题(app.wxss)
更多主题样式,请参考:主题配置文件
page{
--button-danger-background-color: #c00000;
--button-danger-border-color: #D60000;
}
:::danger 以上变量皆是 Vant 组件库已经定义好的,作用域组件的样式 :::
全局数据共享 Mobx
- mobx-miniprogram:创建 Store 实例对象
- mobx-miniprogram-bindings:把 Store 中的共享数据或方法,绑定到组件或页面中使用
安装
npm install --save mobx-miniprogram@4.13.2 mobx-miniprogram-bindings@1.2.1
创建 Store 实例
```javascript // store/store.js
import { action, observable } from ‘mobx-miniprogram’
export const store = observable({ // 数据字段 numA: 1, numB: 2, // 计算属性 get sum() { return this.numA + this.numB }, // action 方法,用来修改 store 中的数据 updateNum1: action(function (step) { this.numA += step }), updateNum2: action(function (step) { this.numB += step }) })
<a name="uHOPl"></a>
## 绑定实例到页面
```html
// 页面的 .wxml 文件
<view>{{numA}} + {{numB}} = {{sum}}</view>
<van-button type="primary" bindtap="btnHandler1" data-step="{{1}}">numA + 1</van-button>
<van-button type="danger" bindtap="btnHandler1" data-step="{{-1}}">numA + 1</van-button>
// 页面的 .js 文件
<script>
import { createStoreBindings } from 'mobx-miniprogram-bindings'
import { store } from '../../store/store'
Page({
btnHandler1(e) {
this.updateNum1(e.target.dataset.step)
},
onLoad() {
this.storeBindings = createStoreBindings(this, {
store, // 数据源
fields: ['numA', 'numB', 'sum'], // 数据字段
actions: ['updateNum1'] // 方法
})
},
onUnload() {
this.storeBindings.destroyStoreBindings()
}
})
</script>
绑定到组件
// numbers.wxml 组件
<view>{{numA}} + {{numB}} = {{sum}}</view>
<van-button type="primary" bindtap="btnHandler2" data-step="{{1}}">numB + 1</van-button>
<van-button type="danger" bindtap="btnHandler2" data-step="{{-1}}">numB + 1</van-button>
// numbers.js 组件
<script>
import { storeBindingsBehavior } from 'mobx-miniprogram-bindings'
import { store } from '../../store/store'
Component({
behaviors: [storeBindingsBehavior],
storeBindings: {
store,
fields: {
numA: 'numA',
numB: 'numB',
sum: 'sum'
},
actions: {
updateNum2: 'updateNum2'
}
},
methods: {
btnHandler2(e) {
this.updateNum2(e.target.dataset.step)
</script>
分包
概念:
把一个完整的小程序项目,按照需求划分为不同的子包,在构建时打包成不同的分包,用户在使用时按需进行加载
好处:
- 主包:包含 启动页面 或 tabBar 页面,以及所有分包都需要用到的公共资源
- 分包:只包含当前分包有关的页面和私有资源
加载规则
- 小程序启动时,默认会下载主包并启动主包内页面
- tabBar 页面需要放到主包中
当用户进入分包内某个页面时,客户端会把对应分包下载下来,下载完成后在进行展示
主包无法引用独立分包内的私有资源
- 独立分包之间,不能相互引用私有资源
- 独立分包和普通分包之间,不能相互引用私有资源
- 独立分包中不能引用主包内的公共资源
:::
分包预下载
- 进入小程序的某个页面时,由框架自动预下载可能需要的分包,从而提升进入后续分包页面时的启动速度
{
"preloadRule": { // 分包预下载的规则
"pages/classify/classify": { // 触发分包预下载的页面路径
// 指定的网络模式下进行预下载
// 默认值为:wifi
// all 为不限网络
"network": "all",
// 进入页面后,预下载哪些分包
// 可通过 root 或 name 指定预下载的分包
"packages": ["pkgA"]
}
},
}