小程序
- 注册账号
https://mp.weixin.qq.com/
- 下载微信开发者工具
https://developers.weixin.qq.com/miniprogram/dev/devtools/stable.html
项目结构
pages 用来存放所有小程序的页面
utils 用来存放工具性质的模块
app.js 小程序项目的入口文件
app.json 小程序项目的全局配置文件
app.wxss 小程序项目的全局样式文件
project.config.json 项目配置文件
sitemap.json 用来配置小程序及其页面是否允许被微信索引
配置
https://developers.weixin.qq.com/miniprogram/dev/reference/
pages里页面的文件
.js 文件(页面的脚本文件,存放页面数据,事件处理函数等)
.json 文件(当前页面的配置文件,配置窗口的外观等)
.wxml 文件(页面模板结构文件)
.wxss 文件(当前页面样式文件)
app.json 配置文件
是当前小程序的全局配置,包含了所有页面路径、窗口外观、界面表现、底部tab等 。
配置内容如下
pages 用来记录当前小程序所有页面的路径,新增路径会自动创建页面
window 全局定义小程序背景色、文字颜色等
style 全局定义小程序组件所使用的样式版本
sitemapLocation 用来指明 sitemap.json 的位置
pages里新增路径会自动创建页面
pages第一个路径会自动做为首页
project.config.json 配置文件
项目配置文件,用来记录我们对小程序开发工具所做的个性化配置
setting 是保存了编译相关的配置
projectname 是保存的项目名称
appid 是小程序账号ID
setting:{
"checkSiteMap":false // 隐藏输出框里的警告
}
sitemap.json 配置文件
微信现已开放小程序内搜索,效果类似于PC网页的SEO。
此文件用来配置小程序页面是否允许被微信搜索
全局配置
app.json > window节点内的配置
"window":{
// 下拉loading的样式,仅支持dark/light
"backgroundTextStyle":"light",
// 配置导航栏背景色,仅支持16进制的颜色
"navigationBarBackgroundColor": "#fff",
// 导航栏标题文本
"navigationBarTitleText": "微信读书",
// 导航栏标题颜色,仅支持 black/white
"navigationBarTextStyle":"black",
// 开启下拉刷新
"enablePullDownRefresh": true,
// 下拉窗口的背景色
"backgroundColor": "#efefef",
// 上拉触底的距离:默认50像素,单位省去,我们会在触发了上拉触底事件时获取下一页的数据
"onReachBottomDistance": 50
}
app.json > tabBar 节点内的配置
最少2个最多5个 分为顶部和底部
"tabBar": {
// 按钮项数组 最少2个最多5个
"list": [{
// 对应的页面
"pagePath": "pages/home/home",
// 按钮名
"text": "首页",
// 按钮图标 未选中时的
"iconPath": "/images/tabs/home.png",
// 按钮图标 选中时的
"selectedIconPath": "/images/tabs/active.png"
}],
"backgroundColor":'#ffffff', // tabBar背景颜色
"selectedColor":"" // 选中项的文本颜色
},
局部配置
当前页面文件的.json文件 和全局配置一样
{
// 当前页面导航栏背景颜色
"navigationBarBackgroundColor": "#f00",
// 当前页面的标题
"navigationBarTitleText": "主页",
// 当前页面开启下拉刷新
"enablePullDownRefresh": true,
"usingComponents": {}
}
尺寸
rpx
在不同大小的屏幕上小程序会自动进行换算,相当于rem
标签
view
等于 div 标签
text
等于 span 标签
selectable 属性 可实现长按选中
<text selectable>13000000000</text>
image
等于 img 标签
navigator
等于 a 标签
<navigator url="/pages/home/home"> </navigator>
组件
具体可看文档,以下只介绍常用的
https://developers.weixin.qq.com/miniprogram/dev/component/
rich-text - 富文本组件
nodes 属性 将字符串渲染成标签
具体看官网 https://developers.weixin.qq.com/miniprogram/dev/component/rich-text.html
<rich-text nodes="<h1>标题</h1>"> </rich-text>
scroll-view - 滑动组件
手指按住滑动
用scroll-view标签包裹给这个标签设高度或宽度 当里面的盒子超过这个标签的宽度或高度就会自动隐藏超出部分
scroll-y 允许竖向滚动
scroll-x 允许横向滚动
scroll-top 滚动条距离顶部的距离 :scroll-top=‘0’具体看官网 https://developers.weixin.qq.com/miniprogram/dev/component/scroll-view.html
<scroll-view scroll-y>
<view>1</view>
<view>2</view>
<view>3</view>
</scroll-view>
swiper - 轮播图组件
swiper代表大盒子 swiper-item 代表子项
以下为常用属性
indicator-dots:true 显示小圆点
indicator-color: ‘’ 小圆点颜色
indicator-active-color:“” 圆点选中时的颜色
autoplay:true 是否自动切换
interval:5000 自动切换时长
circular:true 是否采用衔接滑动 就是滑到最后一张后下一次就回到第一张具体看官网 https://developers.weixin.qq.com/miniprogram/dev/component/swiper.html
<swiper indicator-dots>
<swiper-item>
<view>1</view>
</swiper-item>
<swiper-item>
<view>2</view>
</swiper-item>
<swiper-item>
<view>3</view>
</swiper-item>
</swiper>
button - 按钮组件
type 属性指定按钮颜色类型
size 属性指定按钮尺寸
plain 属性显示按钮边框,按钮颜色透明
disabled 禁用
open-type 属性可以调用微信提供的各种功能(客服、转发、获取授权、获取信息等)
具体看官网 https://developers.weixin.qq.com/miniprogram/dev/component/button.html
<button type='primary' size="mini" plain>按钮</button>
<button type='warn' size="mini" plain>按钮</button>
image - 图片组件
mode 属性功能 指定图片的裁剪和缩放模式
image 标签有个默认宽高
mode='scaleToFill'
// 默认的 图片宽高完全填充 相当于w h100%
mode='aspectFit'
// 图片等比例缩放 长边完全显示出来 会造成短边有空隙不充满
mode='aspectFill'
// 图片等比例缩放 短边完全显示 长边会显示不全
mode='widthFix'
// 图片宽度不变 高度自适应
mode='heightFix'
// 图片高度不变 宽度自适应
API 操作
具体看官网 https://developers.weixin.qq.com/miniprogram/dev/api/
以下只举例
事件监听api
以on开头 用来监听某些事件的触发
举例
wx.onWindowResize(function callback) // 监听窗口尺寸变化
同步api
以Sync结尾的api都是同步的,可通过函数返回值直接获取
举例
wx.setStorageSync('key','value') // 向本地存储写入内容
异步api
发起请求 通过success回调函数接收数据
举例
wx.request() // 发起网络请求
数据请求
只能请求 https 类型的接口
配置合法域名之后才可以请求这个域名下的接口
如果后端仅提供了http的,可以在微信开发者工具右上角详情》本地设置》勾选不检验合法域名
登录微信小程序管理后台 -> 开发 -> 开发设置 -> 服务器域名 -> 修改 request 合法域名
原版发起请求
小程序的异步API都是基于回调函数,容易造成回调地狱
getInfo(){
wx:request({
url:'',
method:'GET',// 或 POST
data:{
// 要发送的数据
},
success:(res)=>{
log(res)
}
})
}
使用以下方法
API Promise化
小程序的异步API都是基于回调函数,容易造成回调地狱
通过额外的配置,将异步API改造为基于 Promise的异步API
下包
npm i --save miniprogram-api-promise@1.0.4
微信开发工具 > 工具 > 构建npm
app.js 中
// 按需导入
import {promisifyAll} from 'miniprogram-api-promise'
const wxp = wx.p = {}
promisifyAll(wx,wxp)
App({})
发起请求
async getInfo(){
const res = await wx.p.request({
method:'GET',
url:'',
data:{}
})
}
// 这样就会返回一个promise对象
发布上线
小程序的发布上线一般要经过 上传代码 》提交审核 》发布 这三个步骤
上传发布
- 点击开发者工具顶部工具栏中的 上传 按钮
- 填写版本号以及项目备注
- 登录小程序管理后台 > 管理 > 版本管理 > 开发版本,查看刚才提交的版本
- 点击开发版本提交审核
- 审核通过后,管理员微信会收到通知,此时审核版本的列表中,点击发布按钮,即可把审核通过的版本发布为线上版本,供用户访问和使用
推广
基于小程序码进行推广
登录小程序管理后台 》设置 》基本设置 》基本信息 》小程序码及线下物料下载
运营数据
查看小程序运营数据 * 两种方式
- 在 小程序管理后台 查看
登录小程序管理后台 》点击侧边栏的统计 》点击相应的tab可以看到相关的数据
- 使用 小程序数据助手 查看
打开微信 》搜索小程序数据助手 》查看已发布的小程序相关的数据
数据绑定
在data中定义页面数据,在页面中使用数据
小程序使用数据都需要 {{ }}包裹
// 页面.js文件中
Page({
data:{
msg:'哈哈哈',
img:'http/........'
}
})
// 使用
<view> {{ msg }} </view>
<image src="{{ img }}"/>
事件绑定 - bind
bind:事件名 或 bind事件名
以下常用的
tap - 点击事件
click事件 - bindtap
catchtap 也是点击事件,并且可阻止事件冒泡
<view bindtap="handleTap"></view>
<view catchtap="handleTap"></view>
input
文本框输入事件 - bindinput
e.detail.value 可以拿到input框里的值
<view bindinput="handleTap"></view>
change
状态改变事件 - bindchange
事件的回调函数接收一个 e 参数
<view bindchange="handleTap"></view>
event 事件对象所包含的属性
e.type // 事件类型
e.timeStamp // 页面打开到触发事件所经过的毫秒数
e.target // 是触发该事件的源头标签
e.currentTarget // 则是当前事件所绑定的标签
e.detail // 额外的信息
e.touches // 当前屏幕上所有触摸手指的信息
e.changedTouches // 触摸手指发生变化的信息
事件传参/改值
拿data中的变量需使用 this.data.变量
this.setData({ }) - 更改变量值
更改data中变量的值
this.setData({
变量名:新值
})
data-* 事件传参
标签上的点击事件的传参方式,*代表参数名
无法使用 函数名(参数) 的方法传参
<view bindtap="handleTap" data-info="{{ 数字参数 }}"></view>
<view bindtap="handleTap" data-info="字符串参数"></view>
// info就是传过去的参数名
接收参数
handleTap(event) {
// dataset是一个对象,包含所有通过 data-* 传过来的参数项
log(event.target.dataset.info)
}
条件渲染 显示/隐藏
标签条件渲染
wx:if - wx:elif - wx:else
<view wx:if="{{ }}"></view>
<view wx:elif="{{ }}"></view>
<view wx:else></view>
hidden=‘{{ }}’
<view hidden="{{ }}"></view>
循环
wx:for=‘{{ }}’
<view wx:for='{{ arr }}' wx:key='id或index'>
索引:{{index}} 当前项:{{item}}
</view>
wxss样式
rpx 尺寸单位
解决屏幕适配的尺寸单位 把所有屏幕宽度分为750rpx
@import 样式导入
@import ".../commit.wxss"
生命周期
应用生命周期
需要在app.js 中声明
App({
onLaunch:function(options){
// 小程序初始化完成执行全局值触发一次 可以读取本地存储的值
},
onShow:function(options){
// 每次小程序打开后会执行从桌面返回也可以 就是从后台到前台
},
onHide:function(options){
// 小程序从打开状态切到桌面会触发 就是从前台到后台
}
})
页面生命周期
页面的js文件中
Page({
onLoad:function(){
// 页面加载 相当于 created() 一个页面只调用一次
},
onShow:function(){
// 页面展示会触发
},
onReady:function(){
// 页面渲染完成会触发 可以在这里重新设置标题 一个页面只调用一次
},
onHide:function(){
// 页面被隐藏会触发
},
onUnload:function(){
// 页面卸载会触发 一个页面只调用一次
}
})
页面跳转
open-type 代表跳转的方式
声明式导航
awitchTab
跳转到导航栏中的页面
必须指定 open-type 属性 值为 awitchTab
<navigator url='/index' open-type='awitchTab'>首页</navigator>
navigate
跳转到非导航栏中的页面
open-type 属性 值为 navigate (可不写)
<navigator url='/index' open-type='navigate'>跳转到非导航栏页面</navigator>
navigateBack
后退到上一页面
navigateBack 代表后退 delta=’ ’ 代表后退几个页面
<navigstor open-type='navigateBack' delta='1'>后退一个页面</navigstor>
编程式导航
wx:switchTab({ })
跳转到导航栏中的页面
<button bindtap='goTo'>点击跳转</button>
goTo(){
wx:switchTab({
url:''
})
}
wx:navigateTo({ })
跳转到非导航栏中的页面
<button bindtap='goTo'>点击跳转</button>
goTo(){
wx:navigateTo({
url:''
})
}
wx:navigateBack( )
后退到上一页面
<button bindtap='goTo'>点击跳转</button>
goTo(){
wx:navigateBack()
}
// 后退多层
goTo(){
wx:navigateBack({
delta:5
})
}
导航传参
地址后面 ?拼接参数 例: ?name=zs&age=20
options - 接收参数
通过 onLoad生命周期函数 拿到参数
onLoad:function(options){
log(options) // 可以拿到参数
}
下拉刷新 / 上拉触底
下拉刷新的开启
全局:在app.json的window中,“enablePullDownRefresh”: true
局部:页面的.json中,“enablePullDownRefresh”: true
下拉刷新的配置
在全局或者页面的.json中 通过 backgroundColor 和 backgroundTextStyle 来配置下拉样式
“backgroundColor”: “#ffffff” 仅支持16进制的颜色值
“backgroundTextStyle”: “dark” 配置下拉loading样式,仅支持 dark 和 light
下拉刷新的触发函数
onPullDownRefresh( )
下拉会触发这个函数
下拉刷新的停止函数
wx.stopPullDownRefresh()
事件处理完在函数里调用停止刷新
onPullDownRefresh() {
console.log(2);
wx.stopPullDownRefresh()
}
上拉触底的配置
配置上拉触底的触发距离,默认50px
app.json的window中 或 页面的.json文件中 “onReachBottomDistance”: 50
上拉触底的触发函数
onReachBottom( )
上拉触底后会触发这个函数
全局方法 .wxs
utils > tools.wxs
function 方法名(value) {
// 执行函数
return 将值返回出去
}
// 将方法导出
module.exports={
方法名:方法名
}
使用
// 在要用的wxml页面
<view> {{ tools.方法名(实参) }} </view>
// 引入wxs文件 并给起个名字
<wxs src='../../utils/tools.wxs' module='tools'></wxs>
自定义组件
创建组件
创建components > 右键创建组件文件夹 > 右键创建component > 输入组件名自动生成4个文件
局部引用组件
// 页面的.json文件中
{
"usingComponents": {
"组件名":'/components/组件文件夹名/组件wxml名'
}
}
全局引用组件
// app.json文件中
{
"usingComponents": {
"组件名":'/components/组件文件夹名/组件wxml名'
}
}
使用组件
// 使用组件
<组件名></组件名>
组件内的样式
组件内的样式只作用当前组件 外界无法修改如果要在外界修改组件内的样式,需要在组件的.json文件中添加以下属性
{
"styleIsolation":''
// isolated 启动样式隔离 默认的
// apply-shared 全局wxss样式将影响自定义组件
// shared 代表双向的影响
}
observers - 监听器
可以监听单个也可以监听多个属性的变化
// 组件内的js代码都是写在Components里
Components({
// 监听 可以监听多个属性
observers: {
'属性A, 属性B': function(A的新值, B的新值) {
}
})
监听对象的属性 .key
Components({
// 监听 可以监听多个属性
observers: {
'对象.属性A,对象.属性B': function(A的新值, B的新值) {
}
})
监听整个对象 .**
Components({
// 监听 可以监听多个属性
observers: {
'对象.**': function(obj) {
}
})
纯数据字段
概念:纯数据字段指的是那些不用于界面渲染的data字段
好处:有助于提升页面更新的性能
// 定义纯数据字段
Component({
// options配置对象中
options: {
// 指定所有_开头的数据字段为 纯数据字段
pureDataPattern: /^_/ // 这是个正则表达式
},
data: {
a: true, // 普通数据字段
_b: true // 纯数据字段
}
})
组件的生命周期
created 组件实例刚刚被创建时执行
attached 组件实例进入页面时执行
ready 组件在视图层布局完成后执行
moved 组件实例在移动到另一个位置时执行
detached 组件被移除时执行
error 每当组件方法抛出错误时执行
attached 生命周期里发起请求
组件的生命周期函数定义在 lifetimes 节点里
Component({
// 推荐用法
lifetimes: {
attached() {}, // 在组件实例进入页面节点树时执行
detached() {}, // 在组建实例被从页面节点树移除时执行
}
})
组件中使用所在页面的生命周期函数
Component({
// 用法
pageLifetimes: {
show: function(){}, // 页面被展示触发
hide: function(){}, // 页面被隐藏触发
resize: function(size){} // 页面尺寸变化触发
}
})
插槽
如果有一个组件里想使用多个插槽就需要在配置项里启用
Component({
// 配置项 启用多个插槽
options: {
multipleSolts: true // 启用多 slot支持
}
})
使用
// 子组件里slot插槽占位
<slot name='slot1'></slot>
// 父组件中 相当于具名插槽 只不过不能用#
<view slot='slot1'></view>
父子组件通信
父向子通信
<子组件 属性名='{{ 传值 }}'></子组件>
子组件 properties 接收
在小程序里 properties里的值也是可以修改的 同data里的值修改方式一样 但是并不会同步修改父组件里的那个值
properties: {
属性名:{
type: 数据类型
value: 默认值
}
// 简写方法
属性名:数据类型
}
子向父通信
父组件自定义事件 bind:事件名 或 bind事件名 = ‘事件执行函数’
<子组件 bind事件名='事件执行函数'></子组件>
子组件触发父组件的自定义事件
// 此处的事件名不要带 bind
this.triggerEvent('事件名',传参)
父组件接收参数 在事件执行函数里 e.detail
事件执行函数(e){
log(e.detail)
}
获取子组件实例对象
this.selectComponent(‘类名或id’)
// 父页面
<子组件 id='' class=''></子组件>
<button bindTap='fn'></button>
fn(){
// 拿到子组件实例对象
const child = this.selectComponent('.类名 或 #id')
// 更改子组件里的属性 或 使用子组件里的方法 child.
child.setData({
子组件内的属性:新值
})
// 调用子组件内定义的方法 add是子组件里的方法名
child.add()
}
代码共享 behavior
behaviors 是小程序中,用于实现组件间代码共享的特性
behaviors > behavior.js
每个 behavior 可以包含一组属性、数据、生命周期函数、方法。
组件引用他时,他的属性、数据、方法会被合并到组件中
// 调用 Behavior()方法, 创建实例对象
// 并使用 module.exports 将 behavior 实例对象共享出去
module.exports = Behavior({
// 属性节点
properties: {},
// 私有数据节点
data: {
username: 'zs'
},
// 事件处理函数和自定义方法节点
methods: {},
// 引入其他behaviors
behaviors:{}
})
要使用的页面 .js中
// 1.使用 required() 导入自定义的 behavior 模块
const Behavior =required("../../behaviors/behavior")
// 2.将导入的behavior 实例对象, 挂载在 behaviors 数组节点中, 即可生效
Component({
// 在组件内部 与data节点平级的位置定义该属性,挂载behavior模块
behaviors: [Behavior]
})
// 3.在组件中可以直接使用behavior中的属性
<view> {{username}} </view>
npm包
不支持依赖于 Node.js 内置库的包
不支持依赖于浏览器内置对象的包
不支持依赖于 C++ 插件的包
Vant weapp组件库
创建 package.json 文件
npm init -y
根据官网完成后续操作
https://vant-contrib.gitee.io/vant-weapp/#/quickstart
wxss变量
// app.wxss 中
// 定义节点
page {
// 定义变量
--color: #ccc;
}
.box {
// 使用变量
background-color: var(--color)
}
MobX - 状态管理工具
相当于 vuex
下包
npm install --save mobx-miniprogram@4.13.2
npm install --save mobx-miniprogram-bindings@1.2.1
微信开发工具 > 工具 > 构建npm
创建store 实例对象
在项目根目录下新建store文件夹,并且新建 store.js 文件
// 按需导入第三方包的方法observable, action
import { observable, action } from 'mobx-miniprogram'
// 导出 这里面的属性是共享的
export const store = observable({
// 定义数据
属性1: value,
// action函数 专门用来修改这里面属性的值 value形参
方法名: action(function(value){
this.属性名 = value
})
})
在页面中使用
导航栏中的那几个页面
要用的页面的.js文件中
// 1.首先 导入第三方包,将数据绑定到页面
import { createStoreBindings } from 'mobx-miniprogram-bindings'
// 2.其次 在页面的js文件的头部区域导入容器的数据
import { store } from '../../store/store'
// 3. 绑定操作:将仓库的东西绑定到当前的页面中,在页面的js文件的Page方法中
Page({
// 生命周期函数 页面加载触发
onLoad:function(){
// 调用createStoreBindings方法
// 参数1: 绑定给谁:当前页面this
// 参数2: 对象{ store(容器), fields(数据), actions(修改方法)
this.storeBindings = createStoreBindings(this, {
// 映射容器的实例
store,
// 映射容器里的数据 可以在页面直接使用
fields: ['属性1', '属性2'],
// 映射容器修改的方法 this.方法名() 就可以调用
actions: ['方法名']
})
},
// 页面卸载的生命周期
onUnload: function () {
// 进行销毁
this.storeBindings.destroyStoreBindings()
}
})
在组件中使用
在组件的 .js中
// 1. 按需导入容器成员
import { storeBindingsBehavior } from 'mobx-miniprogram-bindings'
import { store } from '../../store/store'
Component({
// 2. 在组件的behaviors节点 实现自动绑定
behaviors: [storeBindingsBehavior],
// 3. 在storeBindings节点绑定store和数据以及方法
storeBindings: {
store,
fields: { 属性1:'属性1'}, // 可以在页面直接使用
actions:{方法名:'方法名'} // this.方法名()就可调用
}
})
注意: fields中前面是在组件中的名称,可自定义,后面是容器中的名称,必须和仓库一致
分包
是指把一个完整的小程序项目,按照要求划分为不同的子包,在构建时打包成不同的分包,用户在使用时按需加载
所有分包不能超过16M (分包加主包)
单个分包不能大于2M
配置方法
app.json 内
"pages": [ // 主包的所有页面
"pages/index/index"
],
"subPackages": [ // 通过这个节点,声明分包的结构
// 要分几个包就写几个对象
{
"root": "pkgA", // 第一个分包的根目录
"name": "", // 分包的别名
"pages": [ // 当前分包下的页面的路径
"pages/testA/testA",
"pages/testB/testB"
],
"independent": true // 声明当前分包为独立分包,不依赖主包也可以运行
}
]
分包预下载
指的是在进入某个页面是自动下载哪个分包
app.json 内
"preloadRule": { // 分包预下载规则
"pages/index/index" :{ // 触发分包预下载的页面
"network": "all", // 表示指定网络进行预下载 all(所有网络) 和 wifi(wifi网络下进行预下载)
"packages": ['pkgA'] // 表示预下载哪些分包,可通过root指定的名和name别名
}
},