微信小程序笔记
项目构成
- pages存放小程序的页面
- utils存放工具性质的模块
- app.js小程序项目的入口文件
- app.json小程序的项目的全局配置文件
- app.wxss全局样式文件
- project.config.json项目配置文件
- sitemap.json用来配置小程序及其页面是否允许被微信索引
微信推荐页面都放到pages中
json配置文件
project.config.json
记录对小程序开发工具所做的个性化配置
{ |
sitemap.json
支持小程序内的搜索、类似于PC网页的SEO
{ |
页面.json
页面样式配置全局样式
新建页面
{ |
将新建的页面放在第一位,就是当前编译器渲染的首页
WXML和HTML
WXSS和CSS
小程序.JS
app.js
// app.js |
什么是宿主环境
- 程序运行必须的依赖环境
- 脱离了宿主环境的软件没有任何意义
- 小程序的宿主环境是微信
微信宿主环境
- 通信模型
- 运行机制
- 组件
- API
通信的主体
- 渲染层和逻辑层
- WXML和WXSS工作在渲染层
- JS脚本工作在逻辑层
通信模型
- 渲染层和逻辑层之间的通信
- 逻辑层和第三方服务器之间的通信
- 均由微信客户端转发
运行机制
-
启动过程
- 下载小程序的代码包到本地
- 解析app.json全局配置文件
- 执行app.js小程序入口文件,调用App()创建小程序实例
- 渲染小程序的首页
- 启动完成
-
渲染过程
- 加载解析页面的.json配置文件
- 加载页面的.wxml模板和.wxss样式
- 执行页面的.js文件,调用Page()创建页面实例
- 页面渲染完成
组件
容器组件
名称 | 用途 |
---|---|
view | 普通视图区域、类似于HTML中的div,是块级元素,用来布局 |
scroll-view | 可滚动的视图区域、用来实现滚动列表的效果 |
swiper和swiper-item | 轮播图容器组件和轮播图item组件,item是内部的轮播小组件 |
view
<!--类似HTML的div--> |
/* pages/list/list.wxss */ |
scroll-view
<!--滚动窗口--> |
/* pages/list/list.wxss */ |
swiper
<!--轮播图--> |
/*轮播图样式*/ |
内容组件
text
只有text组件支持长按选中按钮
<view> |
rich-text
<rich-text nodes="<h1 style='color: red;'>标题</h1>"></rich-text> |
功能组件
button
- 默认按钮独占一行
<!--不同类型的按钮样式--> |
image
<image>同样占据一定空间</image> |
image { |
默认情况下,图片会被缩放或剪裁
API分类
协同工作和发布
发布上线,通过后台设置
数据绑定
基本原则,在data中定义数据,在wxml中使用数据
Mustache语法或者叫插值表达式Mustache应用场景
- 绑定内容
- 绑定属性
- 运算
动态绑定内容
// pages/list/list.js |
<view> {{info}}</view> |
动态绑定属性
// pages/list/list.js |
<image src="{{imgsrc}}" mode="widthFix"></image> |
三元运算
Page({ |
<view>{{randomNum >= 5 ? '数字大于或等于5':'数字小于5'}}</view> |
事件绑定
事件是渲染层到逻辑层的通讯方式,通过事件可以将用户在渲染层产生的行为,反馈到逻辑层进行业务的处理。
常见事件
当事件回调触发的时候,会收到一个事件对象event,他的详细属性如下表所示
target和currentTarget的区别
target是出发该事件的源头组件,而currentTarget则是当前事件所绑定的组件。点击内部的按钮时,点击事件以冒泡的方式向外扩散,也会出发外层的tap事件处理函数,此时,对于外层的view来说
e.target指向的是触发事件的源头组件,也就是view当中的button
e.currentTarget指向的是当前正在触发事件的那个组件,也就是当前的view组件
bindtap的语法格式
page({ |
<button type="primary" bindtap="btnTapHandler">按钮</button> |
数据赋值
page({ |
<button type="primary" bindtap="CountChange"> +1</button> |
事件传参
在小程序中不能在绑定时间的同时为事件处理函数传递参数
<button type="primary" bindtap="btnTapHandler(123)">事件传参</button> |
小程序会认为btnTapHandler(123)是名称
使用data-*自定义属性传参,*表示参数的名字,2这样传的是数字2,单纯写2是字符2
<button type="primary" bindtap="btnTapHandler" data-info="{{2}}">事件传参</button> |
page({ |
<button type="primary" bindtap="btnTap2" data-info="{{2}}">+2</button> |
bindinput的语法格式
通过input事件来响应文本框的输入事件
inputHandler(e){ |
<input bindinput="inputHandler"></input> |
数据同步(文本框和data)
-
定义数据
page({
/**
* 页面的初始数据
*/
data: {
Num:0
},
}) -
渲染结构
<input value="{{Num}}" bindinput="inputHandler"></input>
-
美化样式
input {
border: 1px solid #221133;
padding:5px;
margin: 5px;
border-radius: 3px;
} -
绑定input事件处理函数
page({
/**
* 页面的初始数据
*/
data: {
Num:0
},
inputHandler(e){
this.setData({
Num:e.detail.value
})
},
})
条件渲染
wx:if
<view wx:if="{{type == 1}}">男</view> |
data: { |
结合block使用wx:if
如果要一次性控制多个组件的展示或隐藏,可以使用block标签
<block wx:if="{{true}}"> |
hidden
控制组件的显示或隐藏,可以和wx:if有相同的效果但是原理不同
<view hidden="{{!flag}}">这是hidden控制的</view> |
data: { |
使用建议,当频繁切换的时候使用hidden
列表渲染
wx:for
data: { |
<view wx:for="{{arr1}}"> |
手动指定索引和当前项的变量名*
<view wx:for="{{arr1}}" wx:for-index="idx" wx:for-item="itemName"> |
wx:key
类似于Vue列表渲染中的:key,小程序也建议在列表渲染时为渲染出来的列表项指定唯一的key值,从而提高渲染效率,没有id可用index作为key值
data: { |
<view wx:for="{{arr2}}" wx:key="id"> |
WXSS
WXSS具有大部分CSS特性
rpx
根据不同的设备,将设备的屏幕宽度等分为750份
- 在较小的设备上1rpx代表的宽度较小
- 在较大的设备上1rpx代表的宽度较大
rpx与px的单位换算
样式导入
路径/common/common.wxss
.username { |
在index.wxcss中
@import "/common/common.wxss"; |
在index.wxml中
<view wx:for="{{arr2}}" wx:key="id" class="username"> |
全局样式
在app.wxss中配置全局的样式
局部样式
在页面文件中.wxss中配置页面局部样式
- 当局部样式和全局样式冲突时,根据就近原则,使用当前页面样式
- 当局部的样式权重大于等于全局样式的权重,局部的才会覆盖
全局配置
window
期中导航栏和背景区域可以通过window节点配置
{ |
tabBar
"tabBar": { |
在每个tab中可以包含如下的配置项
- 图片放到image文件夹中,从根目录加入路径
- 在全局app.json中添加代码
"tabBar": { |
页面配置
在页面的json文件中配置
"enablePullDownRefresh": true //下拉刷新不推荐在全局中使用 |
网路数据请求
get请求
调用wx.request()方法
<button bindtap="getInfo">发送请求</button> |
//发起get数据请求 |
url: ‘https://www.escook.cn/api/get’,必须先配置到小程序的后台
Post请求
同样调用wx.request()方法
<button bindtap="postInfo">发送get请求</button> |
//发起post数据请求 |
在页面刚加载时就请求数据
在页面刚刚加载的时候,自动请求一些初始化数据,希望进入首页就自动执行post和get请求,使用onload
/** |
跳过合法域名校验
跨域和Ajax
跨域问题只存在于基于浏览器的web开发中,由于小程序的宿主环境不是浏览器,而是微信客户端,所以小程序中不存在跨域的问题。
Ajax技术的和兴时依赖于浏览器中的XMLHttpRequest这个对象,由于小程序宿主环境是尾行客户端,所以小程序中不能叫做“发起Ajax请求”,而是叫做“发起网络数据请求”
案例-本地生活
链接:https://pan.baidu.com/s/1WJ_Bh6b8HBaF7tpCpg0APg?pwd=18if
提取码:18if
页面导航
导航到tabBar-声明式导航
<navigator url="/pages/index/index" open-type="switchTab">导航到消息页面</navigator> |
导航到tabBar页面-编程式导航
<button bindtap="gotoMessage">跳转到消息页面</button> |
//通过编程式导航跳转到消息页面 |
导航到非tabBar页面-编程式
<button bindtap="gotoRead">跳转到非tabBar页面</button> |
//通过编程式导航跳转到消息页面 |
后退导肮-编程式
<button bindtap="gotoRead">通过编程式导航后退</button> |
//通过编程式导航后退 |
导航传参-声明式
<navigator url="/pages/info/info?name=wx&age=20" open-type="navigate">跳转到info并传参</navigator> |
导航传参-编程式
<button bindtap="gotoInfo">跳转到info并传参</button> |
//通过编程式导航到info页面并传递参数 |
onLoad获取参数
/** |
其他页面可以获取到值
/** |
页面事件
下拉刷新
- 全局开启下拉刷新
- 局部开启下拉刷新
{ |
配置下拉刷新窗口颜色
{ |
监听下拉刷新窗口函数
/** |
下拉刷新关闭
/** |
上拉触底
- 上拉触底距离是可以自定义的,在页面或全局的json文件中,配置onReachBottomDistance来改变,默认50
/** |
案例-上拉触底
-
定义获取随机颜色的方法
/**
* 页面的初始数据
*/
data: {
colorList:[]
},
//得到随机颜色
getColors(){
wx.showLoading({title:'数据加载中...'})
wx.request({
url: 'https://www.escook.cn/api/color',
method:'GET',
success:({data:res}) =>{
this.setData({
colorList:[...this.data.colorList,...res.data]
})
}
})
}, -
页面加载时获取初始数据
/* *
*生命周期函数--监听页面加载
*/
onLoad(options) {
this.getColors()
},
-
渲染UI,美化页面效果
<view wx:for="{{colorList}}" wx:key="index" class="num-item" style="background-color: rgb({{item}}) ;">{{item}}</view>
.num-item{
border: 1rpx solid #efefef;
border-radius: 8rpx;
line-height: 200rpx;
margin: 15rpx;
text-align: center;
text-shadow: 0rpx 0rpx 5rpx #fff;
box-shadow: 1rpx 1rpx 6rpx #aaa;
} -
上拉触底获取颜色
/**
* 页面上拉触底事件的处理函数
*/
onReachBottom() {
this.getColors()
}, -
添加loading提示效果
//得到随机颜色
getColors(){
//查官方API文档
wx.showLoading({title:'数据加载中...'})
wx.request({
url: 'https://www.escook.cn/api/color',
method:'GET',
success:({data:res}) =>{
this.setData({
colorList:[...this.data.colorList,...res.data]
})
}
})
}, -
对上拉触底进行节流处理
/**
* 页面的初始数据
*/
data: {
colorList:[],
//节流值
isloading: false
},
//得到随机颜色
getColors(){
//节流操作
this.setData({
isloading:true
})
wx.showLoading({
title:'数据加载中...'
}),
wx.request({
url: 'https://www.escook.cn/api/color',
method:'GET',
success:({data:res}) =>{
this.setData({
colorList:[...this.data.colorList,...res.data]
})
},
complete:()=>{
wx.hideLoading()
this.setData({
isloading:false
})
}
})
},
/**
* 页面上拉触底事件的处理函数
*/
onReachBottom() {
if(this.data.isloading){
return
}
this.getColors()
},
生命周期
-
应用生命周期
-
页面生命周期
-
生命周期函数,自动按次序执行
- 页面生命周期函数
- 应用生命周期函数
应用生命周期函数
App({ |
页面生命周期函数
// pages/info/info.js |
WXS
在html中无法使用.js的函数,但是可以使用wxs,从而完成过滤器等的功能
-
数据类型
number、string、boolean、object、function、array、date、regexp
-
wxs不支持类似于ES6以上的语法
-
wxs遵循CommonJS
内嵌wxs脚本
<view>{{m1.toUpper(username)}}</view> |
外联wxs脚本
案例-本地生活
自定义组件
- 根目录下component文件夹,键入组件的名称之后回车
局部引用
- 放在页面的.json文件中
"usingComponents": { |
全局引用
- 放在全局app的.json文件中
组件和页面区别
- 组件.json的声明不同
- 组件的.js文件为Component()函数
- 组件的事件处理函数需要定义到methods节点中
组件样式隔离
组件中的样式不会影响外界页面,外界页面样式也不会影响组件
- app.wxss中的全局样式对组件无效
- 只有class选自其会有样式隔离效果,id选择器、属性选择器、标签选择器不受样式隔离的影响
- 在组件和引用组建的页面中建议使用class选择器,不使用id、属性、标签选择器
修改组件的样式隔离
stylelsolation可选值
data数据
// compoment/test1/test1.js |
methods方法
// compoment/test1/test1.js |
properties属性
/** |
data和properties的区别
-
data更倾向与存储组件的私有数据
-
properties更倾向于存储外界传递到组建的中的数据
-
本质上相同
数据监听器
- 作用类似于vue中的watch侦听器
- 可以在一个监听器中监听多个字段
Component({ |
<view style="text-align: center;">监听器的应用:{{num1}} + {{num2}} = {{sum}}</view> |
监听对象属性的变化
- 数据监听器支持监听对象中单个或多个属性的变化
Component({ |
案例-颜色变化块
<text style="text-align: center;">组件2:对象监听器的应用,改变颜色</text> |
data: { |
简化监听项
observers:{ |
纯数据字段
概念:指不用于界面渲染的data字段,既不会展示在界面上,也不会出纳递给其他组件,仅在组件内部使用
好处:提升页面更新的性能
// compoment/test1/test1.js |
组件的生命周期函数
生命周期函数 | 参数 | 描述说明 |
---|---|---|
created | 无 | 在组件实例刚刚被创建时执行 |
attached | 无 | 在组件实例静页面节点树时执行 |
ready | 无 | 在钻进在试图层布局完成后执行 |
moved | 无 | 在组件实例被移动到节点树另一个位置时执行 |
detached | 无 | 在组件实列 被从页面节点数移除时执行 |
error | Object Error | 每当组件方法抛出错误时执行 |
组件所在页面的生命周期
自定义的组件行为依赖于页面状态变化,此时就需要用到组件所在页面的生命周期
生命周期函数 | 参数 | 描述 |
---|---|---|
show | 无 | 组件所在页面被展示时执行 |
hide | 无 | 组件所在页面被隐藏时执行 |
resize | Object Size | 组件所在页面尺寸变化时执行 |
插槽
在组件中用于承载组件使用者提供的wxml结构,即替换为wxml标签
<!-- 组件封装者--> |
<!-- 组件使用者--> |
多个插槽的使用
//启用多个节点 |
<!-- 定义的时候用name指定名称--> |
父子组件之间的通信
-
属性绑定
- 用于父组件向子组件的指定属性设置数据
-
事件绑定
- 用于子组件向父组件传递数据,可以传递任意数据
-
获取组件实例
-
父组件还可以通过this.selectComponent()获取子组件实例对象
-
这样就可以直接访问子组件的任意数据和方法
-
属性绑定
<!-- 父组件 --> |
//父组件js |
<!-- 子组件 --> |
/** |
事件绑定
-
在父组件的js中,定义一个函数,这个函数即将通过自定义事件的形式,传递给子组件。
syncCount(e){
// console.log('syncCount')
this.setData({
count:e.detail.value
})
} -
在父组件的wxml,通过自定义事件的形式,将步骤1定义的函数引用,传递给子组件
<my-test4 count="{{count}}" bind:sync="syncCount"></my-test4>
-
在组件的js中,通过调用this.triggerEvent(‘自定义事件名称’,{/参数对象/}),将数据发送到父组件
addCount(){
this.setData({
count : this.properties.count + 1
}),
this.triggerEvent('sync',{value: this.properties.count})
} -
在父组件的js中,通过e.detail获取到子组件
获取组件实例
可在父组件里调用this.selectComponent(“id或class选择器”),获取子组件的实例对象,从而直接访问子组件的任意数据的方法。调用时需要传入一个选择器,例如this.selectComponent(".my-component")。
<!-- 为了获取子组件,需要给子组件配置class或者id(id是#ca) --> |
getChild(){ |
behaviors
类似与vue中的mixins
工作方式,每个beavior可以包含一组属性、数据、生命周期函数和方法。组件引用它时,它的属性、数据和方法会被合并到组件中。每个组件可以引用多个behavior,behavior也可以应用其它behavior。
//组件.js |
//behavior.js |
<view>在behavior中的用户名为:{{username}}</view> |
behavior的可用节点
behavior重名规则
- 同名数据字段重名规则
- 同名的属性或方法
- 同名的生命周期函数
npm包
- 不依赖于Node.js内置库的包
- 不支持依赖于浏览器内置对象的包
- 不支持依赖于C++的包
Vant Weapp
- 有赞前端团队开源
安装
- 环境node.js 安装教程https://cloud.tencent.com/developer/article/1572591
- 安装步骤 https://vant-ui.github.io/vant-weapp/#/quickstart
-
初始化包管理文件
npm init -y
-
安装npm包
npm i @vant/weapp@1.3.3 -S --production
-
构建npm包
微信开发者工具 --> 工具 --> 构建npm
本地设置,使用npm包,新版本不用勾选
-
删除style:“v2”
-
在页面或全局的json组件usingComponents中添加组件
"usingComponents": {
"van-button": "@vant/weapp/button/index"
} -
根据vant的文档来当作组件一样使用
定制全局主题样式
在app.wxss中,写入CSS变量,即对全局生效
page{ |
API Promise化
基于回调函数的异步API的缺点:在默认情况下,小程序官方提供的异步API都是基于回调函数实现的,容易造成回调地狱
API Promsie化通过额外的配置,将官方提供、基于回调函数的异步API,升级改在为基于Promise的异步API,从而提高代码的可对那个、维护性,避免回调地狱的问题。
实现API的Promise化,主要依赖于miniprogram-api-promise这个第三方包。
在当前项目文件夹终端中安装npm包,记得先要初始化 |
//在小程序的入口文件中(app.js),只需调用一次promisifyAll()方法 |
全局数据共享
状态管理,解决组件之间数据共享的问题,开发中常用的全局数据共享方案有:Vuex、Redux、MobX等。
在小程序中,可以使用mobx-miniprogram配合mobx-miniprogram-bindings实现全局数据共享。其中:
- mobx-miniprogram用来创建Store实例对象
- mobx-miniprogram-bindings用来把Store中的共享数据或方法,绑定到组件或页面中使用。