1.准备工作
1.1.注册小程序账号
百度微信公众平台官网:mp.weixin.qq.com,选择小程序注册即可,个人小程序注册比较快,企业级的小程序需要审核一段时间。
1.2.获取APPID
注册成功以后登陆进去,点击开发设置,复制并保存APPID,如图所示:
1.3.开发工具
下载并安装微信开发者工具,下载地址:developers.weixin.qq.com/miniprogram…
如图所示:
1.4.新建小程序项目
安装好以后打开微信开发者工具,微信扫码登录,左侧菜单选择“小程序”,右侧tab选择“新建项目”,输入“项目名称”,选择项目存放“目录”,输入已经注册好的小程序的“APPID”,如果没有可以使用“测试号”,“开发模式”选择小程序,“后端服务”勾选“不使用云服务”,“语言”选择“JavaScript”,点击“新建”即可开始小程序开发,如图所示:
2.小程序结构目录介绍
小程序框架提供了自己的视图层描述语言WXML(相当于传统web的HTML)和WXSS(相当于传统web的css)以及JavaScript,并在视图层与逻辑层之间提供了数据传输和事件系统,让开发者能够专注于数据与逻辑。
小程序官方文档地址:developers.weixin.qq.com/miniprogram…
小程序文件结构与传统web的对比:
基本项目目录介绍,如图所示:
3.配置介绍
小程序的配置包括全局配置app.json和某个页面自己的配置page.json,并且配置文件不能注释,否则报错。
3.1.全局配置app.json
当前小程序的全局配置,包括当前小程序的所有页面路径、界面表现、网络超时时间、底部tab等,普通基本项目的app.json配置如图所示:
pages:用于描述当前小程序所有页面的路径,最前面的页面可以直接在微信开发者工具的“模拟器”中直接展示,如图所示:
window:用于全局设置小程序的窗口表现,包括导航栏标题内容、导航栏标题颜色、导航栏背景颜色、下拉loading样式等,如图所示:
tabbar:如果小程序是一个多 tab 应用(客户端窗口的底部或顶部有 tab 栏可以切换页面),可以通过 tabBar 配置项指定 tab 栏的表现,以及 tab 切换时显示的对应页面,具体配置及效果如图所示:
3.2.页面配置page.json
这里的page.json用来表示某个页面目录下的page.json,其配置只与当前页面相关。
开发者可以根据需要单独定义当前页面的一些属性,如顶部的颜色、标题、标题颜色、是否允许下拉刷新等。
页面的配置只能设置app.json中部分window配置项的内容,并且页面中配置项会覆盖app.json中window中相同的配置项。
更多配置可以参考微信小程序开放文档:developers.weixin.qq.com/miniprogram…
4.视图层
WXML(WeiXin Markup Language)是框架设计的一套标签语言,结合基础组件、事件系统,可以构建出页面的结构。
4.1.数据绑定
4.1.1.普通写法
<!--wxml-->
<view> {{message}} </view>
// page.js
Page({
data: {
message: 'Hello MINA!'
}
})
4.1.2.组件属性
<!--wxml-->
<view id="{{message}}"></view>
// page.js
Page({
data: {
message: 'first'
}
})
4.1.3.布尔类型
不要直接写checked="false",其计算结果是一个字符串
<!--wxml-->
<checkbox checked="{{false}}"></checkbox>
4.2.运算
4.2.1.三元运算
<!--wxml-->
<view hidden="{{flag? true : false}}"> hidden </view>
4.2.2.算数运算
<!--wxml-->
<view> {{a + b}} + {{c}} + d </view>
// page.js
Page({
data: {
a: 1,
b: 2,
c: 3
}
})
4.2.3.逻辑判断
<!--wxml-->
<view wx:if="{{length > 5}}"> </view>
4.2.4.字符串运算
<!--wxml-->
<view> {{"hello" + name}} </view>
// page.js
Page({
data: {
name: 'world'
}
})
4.2.5.注意
花括号和引号之间如果有空格,将最终被解析成字符串
4.3.列表渲染
4.3.1.wx:for
项的变量名默认为 item,wx:for-item 可以指定数组当前元素的变量名
下标变量名默认为 index,wx:for-index 可以指定数组当前下标的变量名
<!--wxml-->
<view wx:for="{{array}}"> {{index}}:{{item.message}} </view>
// page.js
Page({
data: {
array: [{
message: 'first',
},{
message: 'second',
}]
}
})
4.3.2.wx:for
渲染一个包含多节点的结构块block最终不会变成真正的dom元素
<!--wxml-->
<block wx:for="{{[1, 2, 3]}}">
<view >{{index}}:</view>
<view>{{item}}</view>
</block>
4.3.3.wx:key
在使用"wx:for"的时候应该使用"wx:key"属性,这样可以提升效率。
**官方解释:**当数据改变触发渲染层重新渲染的时候,会校正带有 key 的组件,框架会确保他们被重新排序,而不是重新创建,以确保使组件保持自身的状态,并且提高列表渲染时的效率。
个人理解: 不使用 wx:key时, 如果 array 内的数据发生改变,会重新创建每个Item对象然后渲染列表,比较费时费力;使用 wx:key时,如果array中的数据发生改变,只是将对应的对象重新排序,未发生变化的对象,不会重新创建。
<!--wxml-->
<block>
<switch wx:for="{{objectArray}}" wx:key="id" style="display : block;">
{{item.id}}
</switch>
<button bindtap="randomSort">随机交换数据</button>
</block>
// page.js
Page({
data: {
objectArray: [{
id: 2,
name: "Kangkang"
}, {
id: 1,
name: "Meria"
}, {
id: 0,
name: "Luna"
}]
},
randomSort: function(e) {
const length = this.data.objectArray.length
for (let i = 0; i < length; i++) {
const x = Math.floor(Math.random() * length)
const y = Math.floor(Math.random() * length)
const tmp = this.data.objectArray[x]
this.data.objectArray[x] = this.data.objectArray[y]
this.data.objectArray[y] = tmp
}
this.setData({
objectArray : this.data.objectArray
})
}
})
更多视图层相关内容参考微信小程序开放文档:
developers.weixin.qq.com/miniprogram…
5.样式WXSS
5.1.尺寸单位
传统web的尺寸单位是px,且无自适应,WXSS的尺寸单位是rpx,自适应
换算公式:1px = 2rpx
推荐使用iphone6做调试
5.2.样式导入
使用@import语句可以导入外联样式表,@import后要跟需要导入的外联样式表的相对路径,用;表示语句结束。
/** common.wxss **/
.small-p{
padding: 5px;
}
/** app.wxss **/
@import "common.wxss";
.middle-p{
padding: 15px;
}
5.3.内联样式
框架组件上支持使用style、class属性来控制组件的样式。
style:静态的样式统一写到class中。style接收动态的样式,在运行时会进行解析,请尽量避免将静态样式写进style中,以免影响渲染速度。
<!-- wxml -->
<view style="color:{{color}};"></view>
// page.js
Page({
data: {
color: '#000000'
}
})
class:用于指定样式规则,其属性值是样式规则中类选择器名(样式类名)的集合,样式类名不需要带上.,样式类名之间用空格分隔。
<!-- wxml -->
<view class="part1"></view>
5.4.选择器
目前支持的选择器有:
5.5.全局样式与局部样式
定义在app.wxss中的样式为全局样式,作用于每一个页面。在page的wxss文件中定义的样式为局部样式,只作用于对应的页面,并且会覆盖app.wxss中相同的选择器。
具体有关WXSS的内容请查看微信小程序开放文档:
developers.weixin.qq.com/miniprogram…
6.基本组件
6.1.view
类似传统web中的div
<!-- wxml -->
<view hover-class="h-class">
点我试试
</view>
/** wxss **/
.h-class{
background-color: red;
}
6.2.text
类似传统web中的span,显示普通的文本text只能嵌套text
<!-- wxml -->
<text selectable="{{false}}" decode="{{false}}">
测 试
</text>
如果decode为true, 将被解码成空格,反之输出字符串
6.3.image
图片标签,默认宽度320px、默认高度240px
注意:该标签其实是传统web中图片标签和背景图片的结合,且不支持传统web中背景图片的写法!mode的合法值:
6.4.swiper
swiper(默认宽度100%、默认高度150px)滑块视图容器,跟swiper-item(默认宽度和高度都是100%)一起使用可以做轮播图。
6.5.navigator
导航组件,页面链接,类似于传统web的a标签。
open-type的合法值:
6.6.video
视频组件
更多组件及详细信息参考官方文档:
developers.weixin.qq.com/miniprogram…
7.自定义组件
类似于页面,一个自定义组件由json、wxml、wxss、js4个文件组成。
7.1.声明组件
要编写一个自定义组件,首先需要在 json文件中进行自定义组件声明(将 component 字段设为 true 可将这一组文件设为自定义组件):
{
"component": true
}
7.2.编辑组件
同时,还要在 wxml 文件中编写组件模板,在 wxss 文件中加入组件样式,它们的写法与页面的写法类似。具体细节和注意事项参见 组件模板和样式 。
注意:在组件wxss中不应该使用ID选择器、属性选择器和标签选择器
<view class="inner">
{{innerText}}
</view>
<slot></slot>
.inner{
color: red;
}
7.3.注册组件
在自定义组件的 js 文件中,需要使用 Component() 来注册组件,并提供组件的属性定义、内部数据和自定义方法。
组件的属性值和内部数据将被用于组件 wxml 的渲染,其中,属性值是可由组件外部传入的。更多细节参见 Component构造器 。
Component({
properties: {
// 这里定义了innerText属性,属性值可以在组件使用时指定
innerText: {
type: String,
value: 'default value',
}
},
data: {
// 这里是一些组件内部数据
someData: {}
},
methods: {
// 这里是一个自定义方法
customMethod: function(){}
}
})
7.4.使用自定义组件
使用已注册的自定义组件前,首先要在页面的 json 文件中进行引用声明。此时需要提供每个自定义组件的标签名和对应的自定义组件文件路径:
{
"usingComponents": {
"component-tag-name": "path/to/the/custom/component"
}
}
这样,在页面的 wxml 中就可以像使用基础组件一样使用自定义组件。节点名即自定义组件的标签名,节点属性即传递给组件的属性值。
<view>
<!-- 以下是对一个自定义组件的引用 -->
<component-tag-name inner-text="Some text"></component-tag-name>
</view>
自定义组件的 wxml 节点结构在与数据结合之后,将被插入到引用位置内。
一些需要注意的细节:
- 因为 WXML 节点标签名只能是小写字母、中划线和下划线的组合,所以自定义组件的标签名也只能包含这些字符。
- 自定义组件也是可以引用自定义组件的,引用方法类似于页面引用自定义组件的方式(使用
usingComponents字段)。 - 自定义组件和页面所在项目根目录名不能以“wx-”为前缀,否则会报错。
注意,是否在页面文件中使用 usingComponents 会使得页面的 this 对象的原型稍有差异,包括:
- 使用
usingComponents页面的原型与不使用时不一致,即Object.getPrototypeOf(this)结果不同。 - 使用
usingComponents时会多一些方法,如selectComponent。 - 出于性能考虑,使用
usingComponents时,setData内容不会被直接深复制,即this.setData({ field: obj })后this.data.field === obj。(深复制会在这个值被组件间传递时发生。)
如果页面比较复杂,新增或删除 usingComponents 定义段时建议重新测试一下。
具体请查看微信小程序开放文档: