百度百科:
微信小程序,简称小程序,英文名Mini Program,是一种不需要下载安装即可使用的应用,它实现了应用“触手可及”的梦想,用户扫一扫或搜一下即可打开应用。
全面开放申请后,主体类型为企业、政府、媒体、其他组织或个人的开发者,均可申请注册小程序。小程序、订阅号、服务号、企业号是并行的体系。
2017年1月9日,张小龙在2017微信公开课Pro上发布的小程序正式上线。
2018年2月,微信官方发布公告称:已对涉及假货高仿、色情低俗和违规“现金贷”等超过2000个小程序,进行永久封禁处理。
小程序是一种不用下载就能使用的应用,也是一项门槛非常高的创新,经过将近两年的发展,已经构造了新的小程序开发环境和开发者生态。
小程序也是这么多年来中国IT行业里一个真正能够影响到普通程序员的创新成果,现在已经有超过150万的开发者加入到了小程序的开发,与我们一起共同发力推动小程序的发展,小程序应用数量超过了一百万,覆盖200多个细分的行业,日活用户达到两个亿,小程序还在许多城市实现了支持地铁、公交服务。小程序发展带来更多的就业机会,2017年小程序带动就业104万人,社会效应不断提升。
小程序的特点:
小程序是一种不需要下载安装即可使⽤的应⽤,它实现了应⽤ “触⼿可及” 的梦想。
⽤户扫⼀扫或者搜⼀下即可打开应⽤,也体现了 “⽤完即⾛” 的理念。
用户不用关心是否安装太多应用的问题。应用将无处不在,随时可用,但又 无需安装卸载 。
目前微信小程序已经非常的成熟,依托于微信平台,我们常用的一些应用也都有了小程序。
注册地址:https://mp.weixin.qq.com/wxopen/waregister?action=step1&token=&lang=zh_CN,如图所示:
注册信息提交后,需要通过邮箱激活,并且需要填写开发者信息(选择个人),才可以登录。
注册成功后,需要进行一些设置,如设置项目名称、logo以及获取appid等。如图所示:
微信小程序为小程序开发工程师提供了开发者工具,该工具下载地址:
https://developers.weixin.qq.com/miniprogram/dev/devtools/download.html,如图所示:
说明:在课程资料中提供了win64位的安装包,其余的自行下载。
下载后,一路下一步安装即可。
1.启动开发者工具后,需要进行微信扫码登录。如图所示:
2.选择小程序项目。如图所示:
3.创建项目,如图所示:
4.点击“确定”按钮,尽快进入工具,并且项目已经创建成功。如图所示:
在小程序中,对于html、js、css均做了扩展与限制,并且对其文件后缀有了新的定义。
主体文件,由三个文件组成,必须放在项目的根目录,如下:
页面由四个文件组成,分别是:
app.json 文件用来对微信小程序进行全局配置,决定页面文件的路径、窗口表现、设置网络超时时间、设置多 tab 等。
演示的代码如下:
{
"pages": [
"pages/index/index",
"pages/logs/logs"
],
"window": {
"backgroundTextStyle": "light",
"navigationBarBackgroundColor": "#fff",
"navigationBarTitleText": "Weixin",
"navigationBarTextStyle": "black"
},
"style": "v2",
"sitemapLocation": "sitemap.json"
}
用于设置小程序的状态栏、导航条、标题、窗口背景色。
注:HexColor(十六进制颜色值),如"#ff00ff"
注:navigationStyle 只在 app.json 中生效。开启 custom 后,低版本客户端需要做好兼容。开发者工具基础库版本切到 1.7.0(不代表最低版本,只供调试用)可方便切到旧视觉
注:客户端 6.7.2 版本开始,navigationStyle: custom 对 组件无效。
演示的代码如下:
{
"pages": [
"pages/index/index",
"pages/logs/logs"
],
"window": {
"backgroundTextStyle": "light",
"navigationBarBackgroundColor": "#33FF00",
"navigationBarTitleText": "我的微信小程序",
"navigationBarTextStyle": "black"
},
"style": "v2",
"sitemapLocation": "sitemap.json"
}
如果小程序是一个多 tab 应用(客户端窗口的底部或顶部有 tab 栏可以切换页面),可以通过 tabBar 配置项指定tab栏的表现,以及 tab 切换时显示的对应页面。
其中 list 接受一个数组,只能配置最少2个、最多5个 tab。tab 按数组的顺序排序,每个项都是一个对象,其属性值如下:
演示的代码如下:
{
"pages": [
"pages/index/index",
"pages/logs/logs"
],
"window": {
"backgroundTextStyle": "light",
"navigationBarBackgroundColor": "#33FF00",
"navigationBarTitleText": "我的微信小程序",
"navigationBarTextStyle": "black"
},
"tabBar": {
"list": [
{
"pagePath": "pages/index/index",
"text": "首页"
},
{
"pagePath": "pages/logs/logs",
"text": "日志"
}
]
},
"style": "v2",
"sitemapLocation": "sitemap.json"
}
如图所示:
会发现,下面的tabBar文字不居中,实际上这是编辑器的问题,在真机上测试是正常的。
问题来了,如何在真机上测试呢?如图所示:
用手机微信扫码该二维码即可进行真机调试,非常的方便。如图所示:
视图容器,相当于html中的div。如图所示:
演示的代码如下:
<view class="section">
<view class="section__title">flex-direction: row</view>
<view class="flex-wrp" style="flex-direction:row;">
<view class="flex-item bc_green">1</view>
<view class="flex-item bc_red">2</view>
<view class="flex-item bc_blue">3</view>
</view>
</view>
<view class="section">
<view class="section__title">flex-direction: column</view>
<view class="flex-wrp" style="height: 300px;flex-direction:column;">
<view class="flex-item bc_green">1</view>
<view class="flex-item bc_red">2</view>
<view class="flex-item bc_blue">3</view>
</view>
</view>
.page-section{
margin-bottom: 20rpx;
}
.flex-wrp {
display: flex;
}
.bc_green {
background: green;
width:100px;
height: 100px;
}
.bc_red {
background: red;
width:100px;
height: 100px;
}
.bc_blue {background: blue;
width:100px;
height: 100px;
}
<swiper indicator-dots="true" autoplay="true" interval="3000" duration="500">
<swiper-item>
<image src="http://txwyomall.oss-cn-chengdu.aliyuncs.com/images/2022-05-13/16524061273808992.jpg" width="375" height="150"/>
</swiper-item>
<swiper-item>
<image src="http://txwyomall.oss-cn-chengdu.aliyuncs.com/images/2022-05-13/16524061273808992.jpg" width="375" height="150"/>
</swiper-item>
</swiper>
<view class="group">
<icon type="success" size="20" />
<icon type="success_no_circle" size="30" />
<icon type="waiting" size="40" />
<icon type="search" size="50" />
</view>
文本。
space 有效值:
说明:
decode可以解析的有 < > & '
各个操作系统的空格标准并不一致。
text组件内只支持text嵌套。
除了文本节点以外的其他节点都无法长按选中。
演示的代码如下:
<view class="container">
<text>这是一段文本</text>
</view>
<view>
<progress percent="20" show-info />
<progress percent="40" stroke-width="12" />
<progress percent="60" color="pink" />
<progress percent="80" active />
</view>
progress{
margin: 10px
}
<view>
<button size='default'>默认尺寸按钮</button>
<button size='mini'>mini按钮</button>
<button size='mini' type="primary">绿色mini按钮</button>
<button size='mini' type="warn">红色mini按钮</button>
</view>
表单,将组件内的用户输入的内容提交。
当点击表单中 form-type 为 submit 的按钮组件时,会将表单组件中的 value 值进行提交,需要在表单组件中加上
name 来作为 key。
演示的代码如下:
<form bindsubmit="formSubmit" bindreset="formReset">
<view class="section section_gap">
<view class="section__title">switch</view>
<switch name="switch" />
</view>
<view class="section section_gap">
<view class="section__title">slider</view>
<slider name="slider" show-value></slider>
</view>
<view class="section">
<view class="section__title">input</view>
<input name="input" placeholder="please input here" />
</view>
<view class="section section_gap">
<view class="section__title">radio</view>
<radio-group name="radio-group">
<label>
<radio value="radio1" /> radio1
</label>
<label>
<radio value="radio2" /> radio2
</label>
</radio-group>
</view>
<view class="section section_gap">
<view class="section__title">checkbox</view>
<checkbox-group name="checkbox">
<label>
<checkbox value="checkbox1" /> checkbox1
</label>
<label>
<checkbox value="checkbox2" /> checkbox2
</label>
</checkbox-group>
</view>
<view class="btn-area">
<button form-type="submit">Submit</button>
<button form-type="reset">Reset</button>
</view>
</form>
Page({
formSubmit: function(e) {
console.log('form发生了submit事件,携带数据为:', e.detail.value)
},
formReset: function() {
console.log('form发生了reset事件')
}
})
注1:image组件默认宽度300px、高度225px
注2:image组件中二维码/小程序码图片不支持长按识别。仅在wx.previewImage中支持长按识别。
mode 有 13 种模式,其中 4 种是缩放模式,9 种是裁剪模式。
演示的代码如下:
<image src="http://txwyomall.oss-cn-chengdu.aliyuncs.com/images/2022-05-13/16524061273808992.jpg"></image>
<image src="http://txwyomall.oss-cn-chengdu.aliyuncs.com/images/2022-05-13/16524061273808992.jpg" mode="top"></image>
App() 函数用来注册一个小程序。接受一个 Object 参数,其指定小程序的生命周期回调等。
App() 必须在 app.js 中调用,必须调用且只能调用一次。不然会出现无法预期的后果。
Object 参数说明:
前台、后台定义: 当用户点击左上角关闭,或者按了设备 Home 键离开微信,小程序并没有直接销毁,而是进入了后台;当再次进入微信或再次打开小程序,又会从后台进入前台。需要注意的是:只有当小程序进入后台一定时间,或者系统资源占用过高,才会被真正的销毁。
演示的代码如下:
App({
onLaunch(options) {
// Do something initial when launch.
},
onShow(options) {
// Do something when show.
},
onHide() {
// Do something when hide.
},
onError(msg) {
console.log(msg)
},
globalData: 'I am global data'
})
App({
onLaunch(options) {
// Do something initial when launch.
},
onShow(options) {
// Do something when show.
},
onHide() {
// Do something when hide.
},
onError(msg) {
console.log(msg)
},
globalData: 'I am global data'
})
Page(Object) 函数用来注册一个页面。接受一个 Object 类型参数,其指定页面的初始数据、生命周期回调、
事件处理函数等。
Object 参数说明:
data 是页面第一次渲染使用的初始数据。
页面加载时, data 将会以 JSON 字符串的形式由逻辑层传至渲染层,因此 data 中的数据必须是可以转成 JSON
的类型:字符串,数字,布尔值,对象,数组。
渲染层可以通过 WXML 对数据进行绑定。
演示的代码如下:
<view>{{text}}</view>
<view>{{array[0].msg}}</view>
Page({
data: {
text: 'init data',
array: [{msg: '1'}, {msg: '2'}]
}
})
演示的代码如下:
Page({
data: {
text: 'init data',
array: [{
msg: '1'
},
{
msg: '2'
}]
},
onLoad(options) {
console.log("页面加载完成", options);
},
onReady() {
console.log("页面初次渲染完成");
},
onShow() {
console.log("页面显示");
},
onHide() {
console.log("页面隐藏");
},
onUnload() {
console.log("页面卸载");
}
})
Page 中还可以定义组件事件处理函数。在渲染层的组件中加入事件绑定,当事件被触发时,就会执行Page中定义的事件处理函数。
演示的代码如下:
<!--绑定点击事件-->
<view bindtap="viewTap">click me</view>
viewTap() {
console.log('view tap')
},
Page.prototype.setData(Object data, Function callback)
setData 函数用于将数据从逻辑层发送到视图层(异步),同时改变对应的 this.data 的值(同步)。
参数说明:
注意:
1. 直接修改 this.data 而不调用 this.setData 是无法改变页面的状态的,还会造成数据不一致。
2. 仅支持设置可 JSON 化的数据。
3. 单次设置的数据不能超过1024kB,请尽量避免一次设置过多的数据。
4. 请不要把 data 中任何一项的 value 设为 undefined ,否则这一项将不被设置并可能遗留一些潜在问题。
演示的代码如下:
<view>{{text}}</view>
<button bindtap="changeText">Change normal data</button>
<view>{{num}}</view>
<button bindtap="changeNum">Change normal num</button>
<view>{{array[0].text}}</view>
<button bindtap="changeItemInArray">Change Array data</button>
<view>{{object.text}}</view>
<button bindtap="changeItemInObject">Change Object data</button>
<view>{{newField.text}}</view>
<button bindtap="addNewField">Add new data</button>
Page({
data: {
text: 'init data',
num: 0,
array: [{ text: 'init data' }],
object: {
text: 'init data'
}
},
changeText() {
// this.data.text = 'changed data'
// 不要直接修改 this.data
// 应该使用 setData
this.setData({
text: 'changed data'
})
},
changeNum() {
// 或者,可以修改 this.data 之后马上用 setData 设置一下修改了的字段
this.data.num = 1
this.setData({ num: this.data.num })
},
changeItemInArray() {
// 对于对象或数组字段,可以直接修改一个其下的子字段,这样做通常比修改整个对象或数组更好
this.setData({
'array[0].text': 'changed data'
})
},
changeItemInObject() {
this.setData({
'object.text': 'changed data'
})
},
addNewField() {
this.setData({
'newField.text': 'new data'
})
}
})
可以将一些公共的代码抽离成为一个单独的 js 文件,作为一个模块。模块只有通过 module.exports 或者exports 才能对外暴露接口。
需要注意的是:
exports 是 module.exports 的一个引用,因此在模块里边随意更改 exports 的指向会造成未知的错误。所以更推荐开发者采用 module.exports 来暴露模块接口,除非你已经清晰知道这两者的关系。
小程序目前不支持直接引入 node_modules , 开发者需要使用到 node_modules 时候建议拷贝出相关的代码到小程序的目录中或者使用小程序支持的 npm 功能。
演示的代码如下:
function sayHello(name) {
console.log(`Hello ${name} !`)
}
function sayGoodbye(name) {
console.log(`Goodbye ${name} !`)
}
module.exports.sayHello = sayHello
exports.sayGoodbye = sayGoodbye
如图所示:
在需要使用这些模块的文件中,使用 require(path) 将公共代码引入。
演示的代码如下:
const common = require('common.js')
Page({
helloMINA() {
common.sayHello('MINA')
},
goodbyeMINA() {
common.sayGoodbye('MINA')
}
})
WXML(WeiXin Markup Language)是框架设计的一套标签语言,结合基础组件、事件系统,可以构建出页面的结构。
演示的代码如下:
<!--wxml-->
<view>{{message}}</view>
message: 'Hello MINA!',
演示的代码如下:
<!--wxml-->
<view wx:for="{{array}}">{{item}}</view>
array: [1, 2, 3, 4, 5],
演示的代码如下:
<!--wxml-->
<view wx:if="{{view == 'WEBVIEW'}}">WEBVIEW</view>
<view wx:elif="{{view == 'APP'}}">APP</view>
<view wx:else="{{view == 'MINA'}}">MINA</view>
view: 'MINA',
演示的代码如下:
<!--wxml-->
<template name="staffName">
<view>FirstName: {{firstName}}, LastName: {{lastName}}</view>
</template>
<template is="staffName" data="{{...staffA}}"></template>
<template is="staffName" data="{{...staffB}}"></template>
<template is="staffName" data="{{...staffC}}"></template>
staffA: {firstName: 'Hulk', lastName: 'Hu'},
staffB: {firstName: 'Shang', lastName: 'You'},
staffC: {firstName: 'Gideon', lastName: 'Lin'}
WXML 提供两种文件引用方式 import 和 include 。
import 可以在该文件中使用目标文件定义的 template ,如:在 item.wxml 中定义了一个叫 item 的 template :
演示的代码如下:
<!-- item.wxml -->
<template name="item">
<text>{{text}}</text>
</template>
如图所示:
在 index.wxml 中引用了 item.wxml,就可以使用 item 模板的代码如下:
<import src="item.wxml" />
<template is="item" data="{{text: 'forbar'}}" />
import 有作用域的概念,即只会 import 目标文件中定义的 template,而不会 import 目标文件 import 的
template。
如:C import B,B import A,在C中可以使用B定义的template,在B中可以使用A定义的template,但是C不
能使用A定义的template。
演示的代码如下:
<!-- A.wxml -->
<template name="A">
<text>A template</text>
</template>
<!-- B.wxml -->
<import src="a.wxml" />
<template name="B">
<text>B template</text>
</template> <!-- C.wxml -->
<import src="b.wxml" />
<template is="A" />
<!-- Error! Can not use tempalte when not import A. -->
<template is="B" />
include 可以将目标文件除了 外的整个代码引入,相当于是拷贝到 include 位置。
演示的代码如下:
<!-- index.wxml -->
<include src="header.wxml" />
<view>body</view>
<include src="footer.wxml" />
<!-- header.wxml -->
<view>header</view>
<!-- footer.wxml -->
<view>footer</view>
WXSS(WeiXin Style Sheets)是一套样式语言,用于描述 WXML 的组件样式。
WXSS 用来决定 WXML 的组件应该怎么显示。
为了适应广大的前端开发者,WXSS 具有 CSS 大部分特性。同时为了更适合开发微信小程序,WXSS 对 CSS 进行了扩充以及修改。
与 CSS 相比,WXSS 扩展的特性有:
尺寸单位
样式导入
rpx(responsive pixel): 可以根据屏幕宽度进行自适应。规定屏幕宽为750rpx。如在 iPhone6 上,屏幕宽度为375px,共有750个物理像素,则750rpx = 375px = 750物理像素,1rpx = 0.5px = 1物理像素。
建议: 开发微信小程序时设计师可以用 iPhone6 作为视觉稿的标准。
注意: 在较小的屏幕上不可避免的会有一些毛刺,请在开发时尽量避免这种情况。
使用 @import 语句可以导入外联样式表, @import 后跟需要导入的外联样式表的相对路径,用 ; 表示语句结束。
演示的代码如下:
.small-p {
padding:5px;
}
@import "common.wxss";
.middle-p {
padding:15px;
}
框架组件上支持使用 style、class 属性来控制组件的样式。
style:静态的样式统一写到 class 中。style 接收动态的样式,在运行时会进行解析,请尽量避免将静态的样式写进 style 中,以免影响渲染速度。
演示的代码如下:
<view style="color:{{color}};" />
如图所示:
class:用于指定样式规则,其属性值是样式规则中类选择器名(样式类名)的集合,样式类名不需要带上,样式类名之间用空格分隔。
演示的代码如下:
<view class="normal_view" />
定义在 app.wxss 中的样式为全局样式,作用于每一个页面。在 page 的 wxss 文件中定义的样式为局部样式,只作用在对应的页面,并会覆盖 app.wxss 中相同的选择器。
WXS(WeiXin Script)是小程序的一套脚本语言,结合 WXML ,可以构建出页面的结构。
注意:
<!--wxml-->
<wxs module="m1">
var msg = "hello world"; module.exports.message = msg;
</wxs>
<view>{{m1.message}}</view>
<!--wxml-->
<!-- 下面的 getMax 函数,接受一个数组,且返回数组中最大的元素的值 -->
<wxs module="m1">
var getMax = function (array) { var max = undefined; for (var i = 0; i < array.length; ++i) { max = max === undefined ? array[i] : (max >= array[i] ? max : array[i]); } return max; } module.exports.getMax = getMax;
</wxs>
<!-- 调用 wxs 里面的 getMax 函数,参数为 page.js 里面的 array -->
<view>{{m1.getMax(array)}}</view>
array: [1, 2, 3, 4, 5, 1, 2, 3, 4]