简介
介绍
小程序是一种全新的连接用户与服务的方式,它可以在微信内被便捷地获取和传播,同时具有出色的使用体验
小程序与普通网页开发的区别
小程序的主要开发语言是 JavaScript ,小程序的开发同普通的网页开发相比有很大的相似性。同时二者在各方面也有很大的区别
- 运行环境的不同
网页运行在浏览器环境之中
小程序运行在微信环境
- API不同
因为运行环境的不同,所以在小程序中是无法调用浏览器暴露出的BOM和DOM中的API的,但是小程序自身可以调用微信环境提供的各种API,例如:地理定位,扫码,支付等等
- 开发模式不同
网页的开发模式是浏览器加上代码编辑器就可以了
小程序开发之前需要走一套自己的流程
- 申请小程序开发者账号
- 安装开发小程序的微信开发者工具
- 创建和配置小程序项目
小程序项目的基本组成结构
pages 用来存放所有小程序的页面
utils 用来存放工具性质的模块(例如:wxs脚本的自定义模块函数)
app.js 小程序项目的入口文件
app.json 小程序项目的全局配置文件
app.wxss 小程序项目的全局样式文件
project.config.json 项目的配置文件
sitemap.json 用来配置小程序及其页面是否允许被微信索引
pages文件夹中的文件作用参考上
小程序宿主环境
微信客户端给小程序所提供的环境为宿主环境
小程序的运行环境
小程序的运行环境分成渲染层和逻辑层
小程序的渲染层和逻辑层分别由两个线程运行管理,所以不会出现js脚本运行事件过长而导致界面无法响应的问题
WXML 模板和 WXSS 样式工作在渲染层,JS 脚本工作在逻辑层。
渲染层的界面使用了WebView进行渲染,因为小程序有很多个页面,所以渲染层是存在多个线程,多个页面之间的交互由宿主环境作为中转
逻辑层在JsCore线程中运行JS脚本,渲染层和逻辑层之间的交互也由宿主环境(微信客户端)来进行转发
官方文档解释图
小程序启动的过程:
1.先将小程序的代码包下载到本地
2.解析app.json全局配置文件
3.执行app.js小程序入口文件,调用App()函数创建小程序实例
4.渲染小程序首页
5.小程序启动完成
页面渲染的过程
1.解析页面的.json全局配置文件
2.加载页面的.wxml模板和.wxss样式
3.执行页面的.js小程序入口文件,调用Pag()函数创建页面实例 4页面渲染完成
核心思想
小程序框架的核心是一个响应的数据绑定系统,可以让数据与视图非常简单地保持同步。当做数据修改的时候,只需要在逻辑层修改数据,视图层就会做相应的更新。
这点类似于vue的MVVM模型的开发思想,当代码量多时,可以大大提高开发效率
组件
小程序中的组件也是由宿主环境提供的,一共由九大类别
-
视图容器
①view:可以理解为html中的div块级元素,用来实现页面的布局效果
②scroll-view:可滚动的视图区域,常用来实现滚动列表效果,可以规定横向纵向滚动,需规定固定宽高度
③swiper,swiper-item:轮播图容器组件和轮播图item组件 -
基础内容
①text:文本组件,类似于html中的span标签,是一个行内元素
②rich-text:富文本组件,支持把html字符串渲染为wxml结构 -
表单组件
①button
②image:默认宽300px,高度240px,mode属性可用来指定图片的裁剪和缩放模式
③navigator
-
导航组件
-
媒体组件
-
map地图组件
-
canvas画布组件
-
开放能力
-
无障碍访问
小程序的宿主环境 - API
概述
小程序中的API是由宿主环境提供的,通过这些丰富的小程序API,开发者可以方便的调用微信提供的能力,例如:获取用户信息,本地存储,支付功能等
分类
- 事件监听API
特点:以on开头,用来监听某些事件的触发
例如:wx.onWindowResize((result) => {})监听窗口尺寸的变化事件
- 同步API
特点1:以Sync结尾的API都是同步API
特点2:同步API的执行结果,可以通过函数返回值直接获取,如果执行出错会抛出异常
举例:wx.setStorageSync(‘key’, data)向本地存储中写入内容
- 异步API
特点:类似与jquery中的$.ajax(options)函数,通过success,fail,complete接收调用的结果
举例:wx.request({ url: ‘url’, })发起网络数据请求,通过success回调函数接收数据
数据绑定
类似vue的插值语法
小程序中叫做Mustache语法
作用
- 绑定内容
//js
Page({
/**
* 页面的初始数据
*/
data: {
count:1,
}
})
xml
<view>count的值为{{count}}</view>
- 动态绑定属性
可通过双大括号给组件绑定动态属性值,与vue类似但区别是不需要在属性名前使用v-bind修饰
//js
Page({
/**
* 页面的初始数据
*/
data: {
imageUrl:图片地址,
}
})
xml
<image src="{{imageUrl}}" mode=""/>
- 三元表达式运算
可以在双大括号内进行三元表达式运算,根据值的内容渲染对应的结果
- 算数运算
事件绑定
概述
事件是渲染层到逻辑层之间的通讯方式,通过事件可以将用户在渲染层所产生的行为,反馈到逻辑层进行业务的处理
常用事件
tap事件:bindtap或bind:tap;手指触摸后马上离开,类似html中的click事件
input事件:bindinput或bind:input;文本框的输入事件
change事件:bindchange或bind:change;状态改变时触发
事件对象的属性列表
当事件回调触发的时候,会收到一个事件对象event,具有如下属性
获取文本框输入后的新值:e.detail.value
获取事件传参值:e.target.dataset.属性名
事件传参
使用组件提供的data-参数名,自定义属性传参
data-属性名= {{属性值}}
可在事件对象中通过e.target.dataset.参数名获取到具体的参数值
举例
绑定事件并获得事件对象event
<button bind:tap="change">按钮</button>
change(e){
console.log(e) 事件参数对象event
}
在事件处理函数中为data中的数据赋值,使用this.setData({
变量名:新值
})
<button bind:tap="changeCount">增加</button>
changeCount(){
this.setData({
count:this.data.count+1
})
},
事件传参
<button bind:tap="changeCount" data-number="{{2}}">增加</button>
changeCount(e){
console.log(e.target.dataset.number) //2
},
条件渲染
使用wx:if = "{{条件}}"来判断是否需要渲染
可配合 wx:elif 或者wx:else进行判断
列表渲染
通过wx:for = "{{array}}"动态渲染数据,wx:key添加主键
默认情况下,循环项的索引用index表示,当前循坏项用item表示
WXSS-rpx
rpx是微信小程序独有的,用来解决屏适配的尺寸单位
因为不同屏幕的大小不同,为了实现屏幕的自动适配,rpx把所有的设备屏幕在宽度上等分为750份
小程序在不同设备上运行的时候,会自动把rpx的样式单位换算成对应的像素单位来渲染,从而实现屏幕的适配
开发中通常使用iphone6作为视觉标准
WXSS-@import样式表导入
语法:@import ”外联样式表相对路径“;
全局配置
app.json为小程序的全局配置文件,有以下常用配置项
(页面配置项也可参考)
- pages
记录当前小程序所有页面的存放路径 - window
全局设置小程序窗口的外观 - tabBar
设置小程序底部的tabBar效果 - style
是否启用新版的组件样式
window配置项
tabBar
tabBar是移动端应用常见的页面效果,用于实现多页面的快速切换,分为顶部tabBar和底部tabBar
backgroundColor:tabBar的背景颜色
selectediconPath:选中时的图片路径
borderStyle:tabBar上边框的颜色
iconPath:未选中时图片的路径
selectedColor:tab上的文字选中时的颜色color:tab上文字未选中时的颜色
list数组是必填项,表示当前tab页签的列表(2-5)
tabBar中list属性:
pagePath,页面路径,必须在 pages 中先定义 text tab 上按钮文字
iconPath,图片路径, 当 position 为top 时,不显示 icon。
selectedIconPath 选中时的图片路径, 当 position 为 top 时,不显示 icon
示例
"tabBar": {
"list": [{
"pagePath": "pages/localLife/localLife",
"text": "首页",
"iconPath": "/images/底部栏-主页.png",
"selectedIconPath": "/images/底部栏-active.png"
},
{
"pagePath": "pages/list/list",
"text": "我的",
"iconPath": "/images/我的.png",
"selectedIconPath": "/images/我的-active.png"
}]
},
网络数据请求
小程序网络数据请求限制
小程序出于安全性考虑,对数据 接口的请求做出了如下两个限制:
- 只能请求https类型的接口
- 必须将接口的域名添加到信任列表中
发起数据请求:wx.request
wx.request({
url: '接口地址',
method:'GET', //请求方式,post
success:()=>{
}, //成功回调
fail:()=>{
}, //失败回调
complete:()=>{
} //请求完成
})
},
页面导航
页面导航就是页面之间的跳转,在小程序中页面跳转有两种方式:声明式导航和编程式导航
声明式导航
使用导航组件,通过点击实现页面跳转
导航到tabBar页面
tabBar页面是指被配置为tabBar的页面
条件:需要指定两个必须的属性
- url:代表要跳转的页面地址,绝对路径
- open-type:表示跳转的方式,必须为switchTab
语法:
<navigator url="绝对路径" open-type="switchTab"></navigator>
导航到非tabBar页面
- url:代表要跳转的页面地址,绝对路径
- open-type:表示跳转的方式,必须为navigate,也可省略
语法:
<navigator url="绝对路径" open-type="navigate">文案</navigator>
后退导航
若要后退到上一页面或多级页面,则需要指定open-type属性和delta属性
- open-type:必须为navigateBack,表示要进行后退导航
- delta:值必须为数字,表示要后退的层级
语法格式:
<navigator open-type="navigateBack" delta="后退层级">文案</navigator>
编程式导航
通过调用微信导航API来实现页面的跳转
导航到tabBar页面
调用wx.switchTab({})方法跳转到tabBar页面,方法中对象包裹的属性为
- url:跳转的tabBar页面路径,必选,路径后不能带参数
- success:接口调用成功的回调函数
- fail:接口调用失败的回调函数
- complete:接口调用结束的回调函数
导航到非tabBar页面
调用wx.navigateTo({})方法跳转到tabBar页面,方法中对象包裹的属性为
- url:跳转的tabBar页面路径,必选,路径后可以带参数
- success:接口调用成功的回调函数
- fail:接口调用失败的回调函数
- complete:接口调用结束的回调函数
传参:直接在url后加上参数使用?分隔参数和路径
后退导航
调用wx.navigateBack({})方法,可以返回上一页面或多级页面,方法中对象的属性如下:
- delta:表示后退的层级,若delta大于现有页面数,则返回到首页,默认值为1
- success:接口调用成功的回调函数
- fail:接口调用失败的回调函数
- complete:接口调用结束的回调函数
导航传参
直接在路径的后面加上需要传递的参数
参数与路径之间使用?进行分隔
多个参数用&分隔
参数与值间用=相连
注意:只使用于非tabBar页面
导航传递的参数可以在onLoad函数中获取
下拉刷新
下拉刷新是移动端的专有名词,指的是通过手指在屏幕上的下拉滑动操作,从而重新加载页面数据的行为
开启下拉刷新: “enablePullDownRefresh”:true
监听页面下拉刷新的行为
通过onPullDownRefresh(){}函数可以监听用户下拉动作,从而进行某些操作(例如请求新数据)
onPullDownRefresh() {
console.log('下拉刷新')
},
上拉触底
上拉触底是移动端的专有名词,通过手指在屏幕上的上拉滑动操作,从而加载 更多数据的行为
应用场景:下拉请求加载下一页的分页数据,但要进行节流处理
/**
* 页面上拉触底事件的处理函数
*/
onReachBottom() {
console.log('上拉触底')
},
生命周期
生命周期是指从一个对象从创建到运行至小销毁的整个阶段,强调时间段
- 应用生命周期
特指小程序从启动到运行到销毁的整个过程 - 页面声明周期
特指小程序中每个页面的加载到渲染到销毁的过程
生命周期函数
生命周期函数:是由小程序框架提供的内置函数,会伴随生命周期自动按序执行,强调时间点
作用:允许程序员在特定的时间点,执行某些特定的操作
- 应用的生命周期函数
特指小程序从启动到运行到销毁期间一次调用的那些函数
App({
/**
* 当小程序初始化完成时,会触发 onLaunch(全局只触发一次)
*/
onLaunch: function () {
},
/**
* 当小程序启动,或从后台进入前台显示,会触发 onShow
*/
onShow: function (options) {
},
/**
* 当小程序从前台进入后台,会触发 onHide
*/
onHide: function () {
},
/**
* 当小程序发生脚本错误,或者 api 调用失败时,会触发 onError 并带上错误信息
*/
onError: function (msg) {
}
})
- 页面的生命周期函数
特指小程序中每个页面从加载到渲染到销毁期间一次调用的那些函数
Page({
/**
* 生命周期函数--监听页面加载,一个页面只调用一次
* 场景:获取打开当前页面路径中的参数,初始化数据
*/
onLoad(options) {
},
/**
* 生命周期函数--监听页面显示
*/
onShow() {
},
/**
* 生命周期函数--监听页面初次渲染完成
* 场景:对界面内容进行修改,修改导航栏标题
*/
onReady() {
},
/**
* 生命周期函数--监听页面隐藏
*/
onHide() {
},
/**
* 生命周期函数--监听页面卸载,一个页面只调用一次
*/
onUnload() {
},
})
wxs
wxs是小程序独有的一套脚本语言,结合wxml可以构建出页面的结构
wxml中无法调用在页面.js中定义的函数
但是在wxml中可以调用在wxs中定义的函数
应用场景类似于vue中的过滤器
注意:不支持es6以上的语法形式
内嵌wxs脚本
语法:
举例:
<view>name的值为:{{m1.toUpper(name)}}</view>
<wxs module="m1">
module.exports.toUpper = function(str){
return str.toUpperCase()
}
</wxs>
定义外联的wxs脚本
写在以.wxs为后缀名的文件内
<view>name的值为:{{m2.toLower(country)}}</view>
<wxs src="相对路径" module="m2">
</wxs>
// 定义外联wx脚本
function toLower(str){
return str.toLowerCase()
}
module.exports = {
toLower:toLower
}
自定义组件
组件的创建
- 创建components-test文件夹
- 在test文件夹下新建自己的组件
- 直接输入组件名称之后回车,会自动生成组件所对应的四个文件,.js,.json,.wxml,.wxss
注意:为了使代码结构更加清晰,最好不同组件放在不同的components文件夹下
组件的引用
- 局部引用组件
在某一页面的json配置文件中配置,只能在某一页面上使用
`
{
“usingComponents”: {
”自定义组件名“ :’组件存放路径‘
}
}
使用:在wxml中以自定义组件名标签的形式使用
2.全局引用组件
与局部引入组件类似,不同的是要在app.json中配置
参考如上,可在所有页面上使用
组件和页面的区别
表面来看,组件和页面都是由.js,.json,.wxml和wxss这四个文件组成的,但是组件和页面的.js和.json文件有明显的不同
- 组件的.json文件中需要声明 “component”: true属性
- 组件的.js文件中调用的是Component()函数
- 组件的事件处理函数需要定义到methods节点中
组件样式隔离
默认情况下,自定义组件的样式只对当前组件生效,不会影响到组件之外的UI结构
- 全局样式对于组件来说不生效
- 除于class类名选择器会有样式隔离效果,id属性,标签选择器不会受样式隔离的影响
- 建议在组件和引用组件的页面中建议使用class选择器
修改组件的样式隔离选项
默认情况下,自定义组件的样式隔离特性能够防止组件内外样式互相干扰的问题,但是有时候我们又想去控制和修改组件内部的样式,这时候就可以通过stylelsolation修改组件的样式隔离选项
stylelsolation属性值
- isolated启用组件样式隔离,组件和页面互不影响
- apply-shared表示页面的样式可以影响组件,但组件的样式不能影响页面
- shared表示可以进行组件和页面的双向样式影响
1.在组件的js文件中增加配置项
options:{ styleIsolation:'isolated' }
2.在组件的json文件中增加配置项
"styleIsolation": "isolated"
组件的properties属性
在小程序组件中,properties是组件的对外属性,用来接收外界传递到组件中的数据(类似vue中props)
properties: { max:Number },
//简化方式
properties: { max:{ type:Number, value:10 } },
//可指定默认值
data和properties的区别
在小程序的组件中,properties属性和data数据的用法相同,他们都是可读可写的,但是data更倾向于存储组件的私有数据,properties更倾向于存储外界传递到组件中的数据
在程序运行的时候,将data和properties数据都存在了同一个对象中,所以this.data和this.properties的输出结果是完全相同的
properties的数据也可展示到页面上,也可使用事件函数进行修改
数据监听器
observers:{
'字段A,字段B':function(字段A新值,字段B新值){
操作
}
}
组件的生命周期函数
- created 在组件实例刚刚被创建时执行
此时还不能调用setData
通常在这个声明周期函数中,只应该用于给组件的this添加一些自定义的属性字段
- attached 在组件实例进入页面节点树时执行
此时,this.data已被初始化完毕
绝大多数初始化的工作可以在这个时机执行(发请求获取初始数据)
- ready 在组件在视图层布局完成后执行
- moved 在组件实例被移动到节点树另一个位置时执行
- detached 在组件实例被从页面节点树移除时执行(销毁)
推出一个页面的时候就会触发页面内每个自定义组件的移除生命周期函数
此时适合做一些清理性质的工作
- error 每当组件方法抛出错误时执行
推荐在lifetimes节点内定义生命周期函数
lifetimes:{
created(){},
attached(){}
},
组件所在页面的生命周期
pageLifetimes节点
组件所在页面的生命周期函数,需要定义在pageLifetimes节点中
pageLifetimes:{
show(){},//页面被展示
hide(){},//页面被隐藏
resize(size){}//页面尺寸变化
}
插槽
单个插槽
在小程序中,默认每个自定义组件只允许使用一个进行占位,这种个数上的限制叫做单个插槽
自定义组件例如名字叫做 test2
<view>这是组件的内部结构</view> <slot></slot> //利用插槽占位 </view> ```
页面
`<test2></test2> //使用自定义组件
<my-test2>
<view>内容<view>
</my-test2>` //填充自定义组件中slot插槽的内容
多个插槽
小程序中默认是不支持多个插槽的,需要在js中配置以下代码
options:{
options:true //启用多个插槽
},
在自定义组件中定义多个插槽,分别取不同的name,用来区分不同的插槽
自定义组件例如名字叫做 test2
<view>这是组件的内部结构</view> <slot name="one"></slot> //利用插槽占位 </view> ```
页面
`<test2></test2> //使用自定义组件
<my-test2>
<view slot = "one">内容1<view>
</my-test2>` //填充自定义组件中slot插槽的内容
父子组件之间的通信
- 属性绑定
用于父组件向子组件的指定属性设置数据,仅能设置JSON兼容的数据
- 事件绑定
用于子组件向父组件传递数据,可以传递任意数据
在父组件使用子组件时通过自定义事件的形式给子组件绑定事件
<子组件名 bind:传递给子组件的事件名 = “父组件定义的事件名”></子组件名>
- 获取组件实例
父组件还可以通过this.selectComponent(“id或class选择器”)获取子组件实例对象
这样可以直接访问子组件的任意数据和方法
自定义组件-behaviors
behaviors是小程序中,用于实现组件间代码共享的特性,类似vue中mixins
每个behavior可以包含一组属性,数据,生命周期函数和方法,组件引用它时,它的属性,数据,方法会被合并到组件中
每个组件可以引用多个behavior,当然behavior间也可以进行相互引用
使用
module.exports = Behavior({
data:{}, //私有数据节点
properties:{}, //属性节点
methods:{} //事件处理函数和自定义方法节点
})
导入
在组件中,使用require()方法导入需要的behavior,挂载后即可访问behavior中的数据和方法
const behavior = require('../../behavior/behavior')
Component({
behaviors:[behavior],
})
使用
直接在组件中使用behavior中的数据,属性和方法