赞
踩
微信小程序是运行在微信APP内部的子程序,它使用前端技术进行开发,但是又不同于手机APP中的内嵌网页webView。
APP内嵌页面的本质还是一个网页,在APP内部启动了一个简单的浏览器(webView)去打开并显示这个网页。而微信小程序是使用前端技术写成的程序代码,微信在启动小程序时,使用的是原生手机API去渲染小程序。所以小程序相比内嵌页面能够使用更多的手机API(功能)。例如蓝牙功能、地图功能、通讯录等。
网页开发者在开发网页的时候,只需要使用到浏览器,并且搭配上一些辅助工具或者编辑器即可。小程序的开发则有所不同,需要经过申请小程序帐号、安装小程序开发者工具、配置项目等等过程方可完成
开发指南:https://developers.weixin.qq.com/miniprogram/dev/framework/
一个小程序主体部分由三个文件组成,必须放在项目的根目录,如下:
文件 | 必需 | 作用 |
---|---|---|
app.js | 是 | 小程序逻辑 |
app.json | 是 | 小程序公共配置 |
app.wxss | 否 | 小程序公共样式表 |
一个小程序页面由四个文件组成,分别是:
文件类型 | 必需 | 作用 |
---|---|---|
js | 是 | 页面逻辑 |
wxml | 是 | 页面结构 |
json | 否 | 页面配置 |
wxss | 否 | 页面样式表 |
注意:为了方便开发者减少配置项,描述页面的四个文件必须具有相同的路径与文件名。
project.config.json
开发工具的配置文件。
sitemap.json
文件用来配置小程序及其页面是否允许被微信索引。
app.js
应用程序入口文件,在这个文件中注册小程序实例对象(app)。
app.wxss
全局样式文件,定义的样式为全局样式,对所有页面都生效的样式文件。
app.json
是当前小程序的全局配置文件,包括了小程序的所有页面路径、界面表现、网络超时时间、底部 tab 等。例如在这个文件中设置页面背景色为红色,那么项目中所有的页面背景色都是红色。
pages
是页面目录,其中存放项目的所有页面。每个页面是一个文件夹。文件夹中包含4个文件,分别是
xxx.wxml
WeiXin Markup Language 微信标记语言。它和html类似,都用于编写页面内容,但是不能使用DOM标签,只能使用微信组件或自定义组件。
xxx.wxss
WeiXin Style Sheets 微信样式表,和css类似,它兼容大部分css3中的样式,并且增加了一些额外功能。作用域当前页面的样式文件。定义的样式为局部样式,只作用在对应的页面,并会覆盖 app.wxss 中相同的选择器。
xxx.js
页面逻辑文件,在这个js文件中,编写本页面的逻辑和数据。
xxx.json
本页面的配置文件,页面中配置项会覆盖 app.json 的 window 中相同的配置项,在这个配置文件中,可以设置本页面的导航条,主体颜色,导入自定义组件等。
JSON的值只能是以下几种数据格式,其他任何格式都会触发报错,例如 JavaScript 中的 undefined。
WXML
和 HTML
非常相似,WXML
由标签、属性等等构成。但是也有很多不一样的地方:
HTML
的的标签是 div
, p
, span
WXML
用的标签是 view
, button
, text
等等,这些标签就是小程序给开发者包装好的基本能力,我们还提供了地图、视频、音频等等组件能力。wx:if
这样的属性以及 {{ }} 这样的表达式WXSS
具有 CSS
大部分的特性,小程序在 WXSS
也做了一些扩充和修改。
rpx
;app.wxss
作为全局样式,会作用于当前小程序的所有页面,局部页面样式 page.wxss
仅对当前页面生效。WXSS
仅支持部分 CSS
选择器和用户做交互:响应用户的点击、获取用户的位置等等。
<button bindtap="tapClick">点击改变message</button>
Page({
data: {
message: 'Hello World',
},
tapClick(){
this.setData({
message:'小程序',
});
}
})
微信客户端在打开小程序之前,会把整个小程序的代码包下载到本地。
(开发小程序过程中启动小程序)紧接着通过 app.json
的 pages
字段就可以知道你当前小程序的所有页面路径:
{
"pages":[
"pages/index/index",
"pages/user/user"
]
}
写在 pages
字段的第一个页面就是这个小程序的首页(打开小程序看到的第一个页面)。
小程序根目录下的 app.json
文件用来对微信小程序进行全局配置,决定页面文件的路径、窗口表现、设置网络超时时间、设置多 tab 等。
全局配置:https://developers.weixin.qq.com/miniprogram/dev/reference/configuration/app.html
指定小程序的默认启动路径(首页),常见情景是从微信聊天列表页下拉启动、小程序列表启动等。如果不填,将默认为 pages
列表的第一项。不支持带页面路径参数。
用于指定小程序由哪些页面组成,每一项都对应一个页面的 路径(含文件名) 信息。文件名不需要写文件后缀,框架会自动去寻找对应位置的 .json
, .js
, .wxml
, .wxss
四个文件进行处理。
未指定 entryPagePath
时,数组的第一项代表小程序的初始页面(首页)。
创建新的页面,会自动在pages字段中添加页面的路径。
"pages": [
"pages/index/index",
"pages/user/user"
],
用于设置小程序的状态栏、导航条、标题、窗口背景色。
属性 | 类型 | 默认值 | 描述 |
---|---|---|---|
navigationBarBackgroundColor | HexColor | #000000 | 导航栏背景颜色,如 #000000 |
navigationBarTextStyle | string | white | 导航栏标题颜色,仅支持 black / white |
navigationBarTitleText | string | 导航栏标题文字内容 | |
navigationStyle | string | default | 导航栏样式,仅支持以下值: default 默认样式 custom 自定义导航栏,只保留右上角胶囊按钮。参见注 2。 |
backgroundColor | HexColor | #ffffff | 窗口的背景色 |
backgroundTextStyle | string | dark | 下拉 loading 的样式,仅支持 dark / light |
backgroundColorTop | string | #ffffff | 顶部窗口的背景色,仅 iOS 支持 |
backgroundColorBottom | string | #ffffff | 底部窗口的背景色,仅 iOS 支持 |
enablePullDownRefresh | boolean | false | 是否开启全局的下拉刷新。 详见 Page.onPullDownRefresh |
onReachBottomDistance | number | 50 | 页面上拉触底事件触发时距页面底部距离,单位为 px。 详见 Page.onReachBottom |
pageOrientation | string | portrait | 屏幕旋转设置,支持 auto / portrait / landscape 详见 响应显示区域变化 |
restartStrategy | string | homePage | 重新启动策略配置 |
initialRenderingCache | string | 页面初始渲染缓存配置,支持 static / dynamic | |
visualEffectInBackground | string | none | 切入系统后台时,隐藏页面内容,保护用户隐私。支持 hidden / none |
handleWebviewPreload | string | static | 控制预加载下个页面的时机。支持 static / manual / auto |
如果小程序是一个多 tab 应用(客户端窗口的底部或顶部有 tab 栏可以切换页面),可以通过 tabBar 配置项指定 tab 栏的表现,以及 tab 切换时显示的对应页面。
属性 | 类型 | 必填 | 默认值 | 描述 |
---|---|---|---|---|
color | HexColor | 是 | tab 上的文字默认颜色,仅支持十六进制颜色 | |
selectedColor | HexColor | 是 | tab 上的文字选中时的颜色,仅支持十六进制颜色 | |
backgroundColor | HexColor | 是 | tab 的背景色,仅支持十六进制颜色 | |
borderStyle | string | 否 | black | tabbar 上边框的颜色, 仅支持 black / white |
list | Array | 是 | tab 的列表,详见 list 属性说明,最少 2 个、最多 5 个 tab | |
position | string | 否 | bottom | tabBar 的位置,仅支持 bottom / top |
custom | boolean | 否 | false | 自定义 tabBar,见详情 |
其中 list 接受一个数组,只能配置最少 2 个、最多 5 个 tab。tab 按数组的顺序排序,每个项都是一个对象,其属性值如下:
属性 | 类型 | 必填 | 说明 |
---|---|---|---|
pagePath | string | 是 | 页面路径,必须在 pages 中先定义 |
text | string | 是 | tab 上按钮文字 |
iconPath | string | 否 | 图片路径,icon 大小限制为 40kb,建议尺寸为 81px * 81px,不支持网络图片。 当 position 为 top 时,不显示 icon。 |
selectedIconPath | string | 否 | 选中时的图片路径,icon 大小限制为 40kb,建议尺寸为 81px * 81px,不支持网络图片。 当 position 为 top 时,不显示 icon。 |
微信客户端 7.0 开始,UI 界面进行了大改版。小程序也进行了基础组件的样式升级。app.json 中配置 "style": "v2"
可表明启用新版的组件样式。
本次改动涉及的组件有 button icon radio checkbox switch slider
。可前往小程序示例进行体验
每一个小程序页面也可以使用同名 .json
文件(比如:index页面下的 index.json)来对本页面的窗口表现进行配置,页面中配置项会覆盖 app.json
的 window
中相同的配置项。
app.json 中的部分配置,也支持对单个页面进行配置,可以在页面对应的 .json
文件来对本页面的表现进行配置。
页面中配置项在当前页面会覆盖 app.json
中相同的配置项(样式相关的配置项属于 app.json
中的 window
属性,但这里不需要额外指定 window
字段。
页面配置:https://developers.weixin.qq.com/miniprogram/dev/reference/configuration/page.html
属性 | 类型 | 默认值 | 描述 |
---|---|---|---|
navigationBarBackgroundColor | HexColor | #000000 | 导航栏背景颜色,如 #000000 |
navigationBarTextStyle | string | white | 导航栏标题颜色,仅支持 black / white |
navigationBarTitleText | string | 导航栏标题文字内容 | |
navigationStyle | string | default | 导航栏样式,仅支持以下值: default 默认样式 custom 自定义导航栏,只保留右上角胶囊按钮。 |
backgroundColor | HexColor | #ffffff | 窗口的背景色 |
backgroundTextStyle | string | dark | 下拉 loading 的样式,仅支持 dark / light |
backgroundColorTop | string | #ffffff | 顶部窗口的背景色,仅 iOS 支持 |
backgroundColorBottom | string | #ffffff | 底部窗口的背景色,仅 iOS 支持 |
enablePullDownRefresh | boolean | false | 是否开启当前页面下拉刷新。 详见 Page.onPullDownRefresh |
onReachBottomDistance | number | 50 | 页面上拉触底事件触发时距页面底部距离,单位为px。 详见 Page.onReachBottom |
pageOrientation | string | portrait | 屏幕旋转设置,支持 auto / portrait / landscape 详见 响应显示区域变化 |
disableScroll | boolean | false | 设置为 true 则页面整体不能上下滚动。 只在页面配置中有效,无法在 app.json 中设置 |
usingComponents | Object | 否 | 页面自定义组件配置 |
initialRenderingCache | string | 页面初始渲染缓存配置,支持 static / dynamic | |
style | string | default | 启用新版的组件样式 |
singlePage | Object | 否 | 单页模式相关配置 |
restartStrategy | string | homePage | 重新启动策略配置 |
handleWebviewPreload | string | static | 控制预加载下个页面的时机。支持 static / manual / auto |
app.json
中的配置都可以在页面覆盖或单独指定,仅限于本文档包含的选项。navigationStyle
只在 app.json
中生效。整个小程序框架系统分为两部分:逻辑层(App Service)和 视图层(View)。小程序提供了自己的视图层描述语言 WXML
和 WXSS
,以及基于 JavaScript
的逻辑层框架,并在视图层与逻辑层间提供了数据传输和事件系统,让开发者能够专注于数据与逻辑。
场景值列表:https://developers.weixin.qq.com/miniprogram/dev/reference/scene-list.html
小程序开发框架的逻辑层使用 JavaScript
引擎为小程序提供开发者 JavaScript
代码的运行环境以及微信小程序的特有功能。
逻辑层将数据进行处理后发送给视图层,同时接受视图层的事件反馈。
开发者写的所有代码最终将会打包成一份 JavaScript
文件,并在小程序启动的时候运行,直到小程序销毁。这一行为类似 ServiceWorker,所以逻辑层也称之为 App Service。
在 JavaScript
的基础上,我们增加了一些功能,以方便小程序的开发:
App
和 Page
方法,进行程序注册和页面注册。getApp
和 getCurrentPages
方法,分别用来获取 App
实例和当前页面栈。注意:小程序框架的逻辑层并非运行在浏览器中,因此 JavaScript
在 web 中一些能力都无法使用,如 window
,document
等。
每个小程序都需要在 app.js
中调用 App
方法注册小程序实例,绑定生命周期回调函数、错误监听和页面不存在监听函数等。
文档:https://developers.weixin.qq.com/miniprogram/dev/reference/api/App.html
用法:App(Object object)
:注册小程序。接受一个 Object
参数,其指定小程序的生命周期回调等。
App() 必须在 app.js
中调用,必须调用且只能调用一次。不然会出现无法预期的后果
onLaunch(Object object):小程序初始化完成时触发,全局只触发一次。
onShow(Object object):小程序启动,或从后台进入前台显示时触发。
onHide():小程序从前台进入后台时触发。
小程序的生命周期函数在一个小程序中只存在app.js中。
整个小程序只有一个 App 实例,是全部页面共享的。开发者可以通过 getApp
方法获取到全局唯一的 App 实例,获取App上的数据或调用开发者注册在 App
上的函数。
用法:getApp()
获取到小程序全局唯一的 App
实例。
注意事项
App()
内的函数中,或调用 App
前调用 getApp()
,使用 this
就可以拿到 app 实例。getApp()
获取实例之后,不要私自调用生命周期函数。App({
onShow(options){
// 指向app实例:小程序全局唯一的 App 实例。
console.log(this);
},
// 添加全局共享的数据,是用户自定义的,名字可以是globalData,也可以是其他名字
// 多个页面共享的数据,通过getApp()获取app实例,通过app实例获取 globalData
globalData: {
rootCount: 16,
}
})
// index.js
const app = getApp();
console.log(app.globalData.rootCount);
// find.js
const app = getApp();
console.log(app.globalData.rootCount);
对于小程序中的每个页面,都需要在页面对应的 js
文件中进行注册,指定页面的初始数据、生命周期回调、事件处理函数等。
简单的页面可以使用 Page()
进行构造。
用法:Page(Object object):注册小程序中的一个页面。接受一个 Object
类型参数,其指定页面的初始数据、生命周期回调、事件处理函数等。
说明:
Page 中还可以定义组件事件处理函数。在渲染层的组件中加入事件绑定,当事件被触发时,就会执行 Page 中定义的事件处理函数。
<button bindtap="tapClick">点击改变message</button>
Page({ data: { message: 'Hello World', }, // tabClick是自定义的函数 tapClick(){ this.setData({ message:'小程序', }); this.add();// 调用自定义的函数 }, add(){ console.log('add 函数'); }, })
在小程序中改变data中的数据,需要使用 setData函数,不能直接改变。
setData
函数用于将数据从逻辑层发送到视图层(异步),同时改变对应的 this.data
的值(同步)。
用法:setData(Object data, Function callback)
参数说明
字段 | 类型 | 必填 | 描述 |
---|---|---|---|
data | Object | 是 | 这次要改变的数据 |
callback | Function | 否 | setData引起的界面更新渲染完毕后的回调函数 |
Object
以 key: value
的形式表示,将 this.data
中的 key
对应的值改变成 value
。
其中 key
可以以数据路径的形式给出,支持改变数组中的某一项或对象的某个属性,如 array[2].message
,a.b.c.d
,
key 并且不需要在 this.data 中预先定义,也可以在this.data中预先定义。
注意:
undefined
,否则这一项将不被设置并可能遗留一些潜在问题。Page({ data: { message: 'Hello World', num:1, arr:[1,2,3], obj:{ name:'张三', age: 18, } }, tapClick(){ // 在小程序中改变data中的数据,需要使用 setData函数,不能直接改变this.data this.setData({ message:'小程序', // num: 100, num: this.data.num + 100, // arr:[3,4,5,6],// 改变整个数组 'arr[1]': 66,// 支持路径的写法 // obj:{name:'李四', age: 20},// 改变整个对象 'obj.age': 22,// 支持路径的写法 }); })
Page
构造器适用于简单的页面。但对于复杂的页面, Page
构造器可能并不好用。
此时,可以使用 Component
构造器来构造页面。 Component
构造器的主要区别是:方法需要放在 methods: { }
里面。
一般的页面通常使用Page注册,一般页面功能复杂的时候,也可以使用Component注册
自定义组件需要使用Component注册
Page和Component注册的页面都可以引用 behaviors 。 behaviors 可以用来让多个页面有相同的数据字段和方法。
behaviors
是用于组件间代码共享的特性,类似于Vue中的 “mixins”。
每个 behavior
可以包含一组属性、数据、生命周期函数和方法。组件引用它时,它的属性、数据和方法会被合并到组件中,生命周期函数也会在对应时机被调用。 每个组件可以引用多个 behavior
,behavior
也可以引用其它 behavior
。
获取当前页面栈。数组中第一个元素为首页,最后一个元素为当前页面。
注意事项
App.onLaunch
的时候调用 getCurrentPages()
,此时 page
还没有生成。可以将一些公共的代码抽离成为一个单独的 js 文件,作为一个模块。模块只有通过 module.exports
才能对外暴露接口。
module.exports = {}
const xxx = require('');
在 JavaScript 文件中声明的变量和函数只在该文件中有效;不同的文件中可以声明相同名字的变量和函数,不会互相影响。
通过全局函数 getApp
可以获取全局的应用实例,如果需要全局的数据可以在 App()
中设置。
框架的视图层由 WXML 与 WXSS 编写,由组件来进行展示。
将逻辑层的数据反映成视图,同时将视图层的事件发送给逻辑层。
WXML(WeiXin Markup language) 用于描述页面的结构。
WXS(WeiXin Script) 是小程序的一套脚本语言,结合 WXML
,可以构建出页面的结构。
WXSS(WeiXin Style Sheet) 用于描述页面的样式。
组件(Component)是视图的基本组成单元。
WXML(WeiXin Markup Language)是框架设计的一套标签语言,结合基础组件、事件系统,可以构建出页面的结构。
WXML和html类似,都用于编写页面内容,但是不能使用DOM标签,只能使用微信组件或自定义组件。
WXML 中的动态数据均来自对应 Page 的 data。
简单绑定:数据绑定使用 Mustache 语法(双大括号)将变量包起来。
<view>message = {{message}}</view>
文档:https://developers.weixin.qq.com/miniprogram/dev/reference/wxml/data.html
在组件上使用 wx:for
控制属性绑定一个数组,即可使用数组中各项的数据重复渲染该组件。
默认数组的当前项的下标变量名默认为 index
,数组当前项的变量名默认为 item
文档:https://developers.weixin.qq.com/miniprogram/dev/reference/wxml/list.html
在框架中,使用 wx:if=""
来判断是否需要渲染该代码块。
文档:https://developers.weixin.qq.com/miniprogram/dev/reference/wxml/conditional.html
WXML提供模板(template),可以在模板中定义代码片段,然后在不同的地方调用。
定义模板有两种方式:
方式一:直接在index.wxml中定义,并在index.wxml中使用,这种方式只能在当前页面中使用
<template/>
内定义代码片段<!-- 定义模板 -->
<template name="myTem">
{{name}}-{{age}}
</template>
<!-- 使用模板 -->
<template is="myTem" data="{{name:'张三',age: 12}}"></template>
方式二:使用外部.wxml文件模板
使用import导入模板,可以传递数据
引用模板使用import
使用独立的模板文件,可以在多个页面中使用import导入,复用模板,并且还可以给模板传递数据
<!-- header.wxml -->
<template name="header">
<view class="header">
{{title}}
</view>
</template>
<!-- index.wxml -->
<import src="../../template/header.wxml"></import>
<template is="header" data="{{title:'首页'}}"></template>
<template/> <wxs/>
<!-- footer.wxml -->
<view class="footer">底部</view>
<!-- index.wxml -->
<include src="../../template/footer.wxml"></include>
模板拥有自己的作用域,只能使用 data 传入的数据以及模板定义文件中定义的 <wxs />
模块。
WXSS (WeiXin Style Sheets)是一套样式语言,用于描述 WXML 的组件样式。
WXSS 用来决定 WXML 的组件应该怎么显示。
为了适应广大的前端开发者,WXSS 具有 CSS 大部分特性。同时为了更适合开发微信小程序,WXSS 对 CSS 进行了扩充以及修改。
与 CSS 相比,WXSS 扩展的特性有:
设备 | rpx换算px (屏幕宽度/750) | px换算rpx (750/屏幕宽度) |
---|---|---|
iPhone5 | 1rpx = 0.42px | 1px = 2.34rpx |
iPhone6 | 1rpx = 0.5px | 1px = 2rpx |
iPhone6 Plus | 1rpx = 0.552px | 1px = 1.81rpx |
建议: 开发微信小程序时设计师可以用 iPhone6 作为视觉稿的标准。
注意: 在较小的屏幕上不可避免的会有一些毛刺,请在开发时尽量避免这种情况
写项目以iPhone6为参考,尺寸:1px = 2rpx,换算尺寸比较简单。
使用@import
语句可以导入外联样式表,@import
后跟需要导入的外联样式表的相对路径,用;
表示语句结束。
/** common.wxss **/
.small-p {
padding:5px;
}
/** app.wxss **/
@import "common.wxss";
.middle-p {
padding:15px;
}
框架组件上支持使用 style、class 属性来控制组件的样式。
<view style="color:{{color}};" />
.
,样式类名之间用空格分隔。<view class="normal_view box" />
<view class="box {{className}}">属性绑定,动态类名</view>
<view
bindtap="itemClick"
data-index="{{index}}"
class="{{selectedIndex==index ? 'active' : ''}}"
wx:for="{{arr}}"
wx:key="index"
>属性绑定,动态类名 {{index}}</view>
目前支持的选择器有:
选择器 | 样例 | 样例描述 |
---|---|---|
.class | .intro | 选择所有拥有 class=“intro” 的组件 |
#id | #firstname | 选择拥有 id=“firstname” 的组件 |
element | view | 选择所有 view 组件 |
element, element | view, checkbox | 选择所有文档的 view 组件和所有的 checkbox 组件 |
::after | view::after | 在 view 组件后边插入内容 |
::before | view::before | 在 view 组件前边插入内容 |
定义在 app.wxss 中的样式为全局样式,作用于每一个页面。在 page 的 wxss 文件中定义的样式为局部样式,只作用在对应的页面,并会覆盖 app.wxss 中相同的选择器。
WXS(WeiXin Script)是小程序的一套脚本语言,结合 WXML
,可以构建出页面的结构。
WXS 与 JavaScript 是不同的语言,有自己的语法,并不和 JavaScript 一致。
WXS 代码可以编写在 wxml 文件中的 <wxs>
标签内,或以 .wxs
为后缀名的文件内。
.wxs
文件是一个单独的模块。<wxs>
标签也是一个单独的模块。模块作用域:
每个wxs模块都有自己独立的作用域。在一个模块里面定义的变量与函数,默认为私有的,对其他模块不可见。
wxs模块导出数据:
一个模块要想对外暴露其内部的私有变量与函数,只能通过 module.exports
实现。
<wxs>
标签属性名 | 类型 | 默认值 | 说明 |
---|---|---|---|
module | String | 当前 <wxs> 标签的模块名。必填字段。 | |
src | String | 引用 .wxs 文件的相对路径。仅当本标签为单闭合标签或标签的内容为空时有效。 |
<wxs>
标签的 module 属性是当前 <wxs>
标签的模块名。在单个 wxml 文件内,建议其值唯一。有重复模块名则按照先后顺序覆盖(后者覆盖前者)。不同文件之间的 wxs 模块名不会相互覆盖。
module 属性值的命名必须符合下面两个规则:
<wxs>
标签的 src 属性可以用来引用其他的 wxs
文件模块。引用的时候,要注意如下几点:
.wxs
文件模块,且必须使用相对路径。wxs
模块均为单例,wxs
模块在第一次被引用时,会自动初始化为单例对象。多个页面,多个地方,多次引用,使用的都是同一个 wxs
模块对象。wxs
模块在定义之后,一直没有被引用,则该模块不会被解析与运行。<wxs module="tool">
var count = 1;
var add = function(a, b){
return a + b;
}
module.exports = {
count: count,
add: add,
}
</wxs>
<view>
{{tool.count}} -- {{tool.add(100, 200)}}
</view>
在一个.wxs文件可以定义一些功能代码,比如:保留两位小数等,在每一个页面中导入wxs文件,可以重复使用。
// utils/format.wxs
// wxs 模块
var numFormat = function(vlaue){
return Number(vlaue).toFixed(2);
}
module.exports = {
numFormat:numFormat,
}
<!-- index.wxml -->
<wxs src="../../utils/format.wxs" module="format"></wxs>
<view>{{format.numFormat(num)}}</view>
在.wxs
模块中引用其他 wxs
文件模块,可以使用 require
函数。引用的时候,要注意如下几点:
.wxs
文件模块,且必须使用相对路径。wxs
模块均为单例,wxs
模块在第一次被引用时,会自动初始化为单例对象。多个页面,多个地方,多次引用,使用的都是同一个 wxs
模块对象。wxs
模块在定义之后,一直没有被引用,则该模块不会被解析与运行。// utils/a.wxs
var count = 1;
var add = function(a, b){
return a + b;
}
module.exports = {
count: count,
add: add,
}
// utils/format.wxs // 在一个wxs模块中引入其他的wxs模块 var a = require('./a.wxs'); console.log(a.count); console.log(a.add(200,300)) // wxs 模块 var numFormat = function(vlaue){ return Number(vlaue).toFixed(2); } module.exports = { numFormat:numFormat, }
<wxs>
模块只能在定义模块的 WXML 文件中被访问到。使用 <include>
或 <import>
时,<wxs>
模块不会被引入到对应的 WXML 文件中。<template>
标签中,只能使用定义该 <template>
的 WXML 文件中定义的 <wxs>
模块。在小程序中使用.js文件创建模块
可以使用ES6模块化
commonJS模块化
不管是使用ES6模块化,还是使用commonJS模块化,都可以在模块中使用ES6的语法
JS模块是在js文件中导入使用
在小程序中使用wxs模块
<wxs>
配合src和module属性使用wxs模块在wxml文件中使用,可以实现在wxml 文件中调方法,进行数据处理。
除了WXS模块和JS模块不一样,在WXS模块中使用变量、注释、运算符、语句、数据类型、基础类库与ES5基本保持一致。
如bindtap
,当用户点击该组件的时候会在该页面对应的Page中找到相应的事件处理函数。
<view id="tapTest" data-hi="Weixin" bindtap="tapName"> Click me! </view>
Page({
tapName(event) {
console.log(event)
}
})
事件分类:事件分为冒泡事件和非冒泡事件:
WXML的冒泡事件列表:
类型 | 触发条件 |
---|---|
touchstart | 手指触摸动作开始 |
touchmove | 手指触摸后移动 |
touchcancel | 手指触摸动作被打断,如来电提醒,弹窗 |
touchend | 手指触摸动作结束 |
tap | 手指触摸后马上离开 |
longpress | 手指触摸后,超过350ms再离开,如果指定了事件回调函数并触发了这个事件,tap事件将不被触发 |
longtap | 手指触摸后,超过350ms再离开(推荐使用longpress事件代替) |
transitionend | 会在 WXSS transition 或 wx.createAnimation 动画结束后触发 |
animationstart | 会在一个 WXSS animation 动画开始时触发 |
animationiteration | 会在一个 WXSS animation 一次迭代结束时触发 |
animationend | 会在一个 WXSS animation 动画完成时触发 |
touchforcechange | 在支持 3D Touch 的 iPhone 设备,重按时会触发 |
注:除上表之外的其他组件自定义事件如无特殊声明都是非冒泡事件,如 form 的submit
事件,input 的input
事件,scroll-view 的scroll
事件,(详见各个组件)
普通事件使用 bind绑定,事件会向上冒泡
<view bindtap="handleTap">Click here!</view>
自基础库版本 1.5.0 起,在大多数组件和自定义组件中, bind
后可以紧跟一个冒号,其含义不变,如 bind:tap
。基础库版本 2.8.1 起,在所有组件中开始提供这个支持。
<view bind:tap="handleTap">Click here!</view>
用 catch
来绑定事件。与 bind
不同, catch
会阻止事件向上冒泡。
在小程序中没有ev.stopPropagation();方法,想要阻止事件冒泡,使用catch绑定事件。
例如在下边这个例子中,点击 inner view 会先后调用handleTap3
和handleTap2
(因为tap事件会冒泡到 middle view,而 middle view 阻止了 tap 事件冒泡,不再向父节点传递),点击 middle view 会触发handleTap2
,点击 outer view 会触发handleTap1
。
<view id="outer" bindtap="handleTap1">
outer view
<view id="middle" catchtap="handleTap2">
middle view
<view id="inner" bindtap="handleTap3">
inner view
</view>
</view>
</view>
用 mut-bind
来绑定事件。一个 mut-bind
触发后,如果事件冒泡到其他节点上,其他节点上的 mut-bind
绑定函数不会被触发,但 bind
绑定函数和 catch
绑定函数依旧会被触发。
换而言之,所有 mut-bind
是“互斥”的,只会有其中一个绑定函数被触发。同时,它完全不影响 bind
和 catch
的绑定效果。
例如在下边这个例子中,点击 inner view 会先后调用 handleTap3
和 handleTap2
,点击 middle view 会调用 handleTap2
和 handleTap1
。
<view id="outer" mut-bind:tap="handleTap1">
outer view
<view id="middle" bindtap="handleTap2">
middle view
<view id="inner" mut-bind:tap="handleTap3">
inner view
</view>
</view>
</view>
触摸类事件支持捕获阶段。捕获阶段位于冒泡阶段之前,且在捕获阶段中,事件到达节点的顺序与冒泡阶段恰好相反。需要在捕获阶段监听事件时,可以采用capture-bind
、capture-catch
关键字,后者将中断捕获阶段和取消冒泡阶段。
在下面的代码中,点击 inner view 会先后调用handleTap2
、handleTap4
、handleTap3
、handleTap1
。
<view id="outer" bind:touchstart="handleTap1" capture-bind:touchstart="handleTap2">
outer view
<view id="inner" bind:touchstart="handleTap3" capture-bind:touchstart="handleTap4">
inner view
</view>
</view>
如果将上面代码中的第一个capture-bind
改为capture-catch
,将只触发handleTap2
。
<view id="outer" bind:touchstart="handleTap1" capture-catch:touchstart="handleTap2">
outer view
<view id="inner" bind:touchstart="handleTap3" capture-bind:touchstart="handleTap4">
inner view
</view>
</view>
文档:https://developers.weixin.qq.com/miniprogram/dev/framework/view/wxml/event.html#%E4%BA%8B%E4%BB%B6%E5%AF%B9%E8%B1%A1
把数据从渲染层传递到逻辑层
在组件节点中可以附加一些自定义数据。这样,在事件中可以获取这些自定义的节点数据,用于事件的逻辑处理。
在 WXML 中,这些自定义数据以 data-
开头,多个单词由连字符 -
连接。这种写法中,连字符写法会转换成驼峰写法,而大写字符会自动转成小写字符。如:
data-element-type
,最终会呈现为 event.currentTarget.dataset.elementType
;data-elementType
,最终会呈现为 event.currentTarget.dataset.elementtype
。示例:
<view data-index="66" data-alpha-beta="1" data-alphaBeta="2" bindtap="bindViewTap"> DataSet Test </view>
Page({
bindViewTap:function(event){
event.currentTarget.dataset.alphaBeta === 1 // - 会转为驼峰写法
event.currentTarget.dataset.alphabeta === 2 // 大写会转为小写
event.currentTarget.dataset.index === 66
}
})
在基础库版本 2.7.1 以上,可以使用 mark
来识别具体触发事件的 target 节点。此外, mark
还可以用于承载一些自定义数据(类似于 dataset
)。
当事件触发时,事件冒泡路径上所有的 mark
会被合并,并返回给事件回调函数。(即使事件不是冒泡事件,也会 mark
。)
<view mark:myMark="last" bindtap="bindViewTap">
<button mark:anotherMark="leaf" bindtap="bindButtonTap">按钮</button>
</view>
Page({
bindViewTap: function(e) {
e.mark.myMark === "last" // true
e.mark.anotherMark === "leaf" // true
}
})
mark
和 dataset
很相似,主要区别在于: mark
会包含从触发事件的节点到根节点上所有的 mark:
属性值;而 dataset
仅包含一个节点的 data-
属性值。
细节注意事项:
mark
,父节点的 mark
会被子节点覆盖。mark
不包含自定义组件外的节点的 mark
。dataset
,节点的 mark
不会做连字符和大小写转换。其他内容见文档:https://developers.weixin.qq.com/miniprogram/dev/framework/view/wxml/event.html
1、DOM中:<div onclick="fn()"></div >
2、Vue中:<div @click="fn()"></div >
3、小程序中:<view bindtap="boxTap"></view>
在小程序中所有页面的路由全部由框架进行管理。
框架以栈的形式维护了当前的所有页面。 当发生路由切换的时候,页面栈的表现如下:
getCurrentPages()
函数获取当前页面栈。open-type | 路由方式 | 页面栈表现 |
---|---|---|
小程序打开的第一个页面 | 初始化 | 新页面入栈 |
navigate | 打开新页面 | 新页面入栈 |
redirect | 页面重定向 | 当前页面出栈,新页面入栈 |
navigateBack | 页面返回 | 页面不断出栈,直到目标返回页 |
switchTab | Tab 切换 | 页面全部出栈,只留下新的 Tab 页面 |
reLaunch | 重加载 | 页面全部出栈,只留下新的页面 |
路由方式有两种:
方式一:使用 navigator 组件
方式二:使用路由的API,比如 wx.navigateTo
对于路由的触发方式:
路由方式 | 触发时机 |
---|---|
初始化 | 小程序打开的第一个页面 |
打开新页面 | 调用 API wx.navigateTo 使用组件 <navigator open-type="navigateTo"/> |
页面重定向 | 调用 API wx.redirectTo 使用组件 <navigator open-type="redirectTo"/> |
页面返回 | 调用 API wx.navigateBack 使用组件 <navigator open-type="navigateBack"> 用户按左上角返回按钮 |
Tab 切换 | 调用 API wx.switchTab 使用组件 <navigator open-type="switchTab"/> 用户切换 Tab |
重启动 | 调用 API wx.reLaunch 使用组件 <navigator open-type="reLaunch"/> |
navigateTo
, redirectTo
只能打开非 tabBar 页面。switchTab
只能打开 tabBar 页面。reLaunch
可以打开任意页面。onLoad
中获取。路由传参使用 ?和& 在路页面路径后添加参数,类似GET请求传参。
调用页面路由带的参数可以在目标页面的onLoad
中获取。
<!--index.wxml-->
<navigator url="/pages/second/second?username=张三&age=12" open-type="navigate">
<button>去第二页面</button>
</navigator>
// pages/second/second.js
Page({
// 获取路由传递的参数
onLoad(options){
console.log('options=',options); // options= {username: "张三", age: "12"}
},
});
类似于页面,一个自定义组件由 json
wxml
wxss
js
4个文件组成。要编写一个自定义组件,首先需要在自定义组建的 json
文件中进行自定义组件声明(将 component
字段设为 true
可将这一组文件设为自定义组件):
{
"component": true
}
同时,还要在 wxml
文件中编写组件模板,在 wxss
文件中加入组件样式,它们的写法与页面的写法类似。
注意:在组件wxss中不应使用ID选择器、属性选择器和标签名选择器。
在自定义组件的 js
文件中,需要使用 Component()
来注册组件,并提供组件的属性定义、内部数据和自定义方法。
组件的属性值和内部数据将被用于组件 wxml
的渲染,其中,属性值是可由组件外部传入的。
使用已注册的自定义组件前,首先要在页面(使用自定义组件的页面)的 json
文件中进行引用声明。此时需要提供每个自定义组件的标签名和对应的自定义组件文件路径:
{
"usingComponents": {
"m-c":"../../components/m-c/m-c"
}
}
这样,在页面的 wxml
中就可以像使用基础组件一样使用自定义组件。节点名即自定义组件的标签名,节点属性即传递给组件的属性值。
<!--index.wxml-->
<m-c></m-c>
一些需要注意的细节:
<m-c></m-c>
usingComponents
字段)。注意,是否在页面文件中使用 usingComponents
会使得页面的 this
对象的原型稍有差异,包括:
usingComponents
页面的原型与不使用时不一致,即 Object.getPrototypeOf(this)
结果不同。usingComponents
时会多一些方法,如 selectComponent
。usingComponents
时, setData
内容不会被直接深复制,即 this.setData({ field: obj })
后 this.data.field === obj
。(深复制会在这个值被组件间传递时发生。)如果页面比较复杂,新增或删除 usingComponents
定义段时建议重新测试一下。
在组件模板中可以提供一个 <slot>
节点,用于承载组件引用时提供的子节点。
使用单个不带name属性的<slot>
,是匿名插槽
<view class="m-c">
<slot></slot>
</view>
默认情况下,一个组件的 wxml 中只能有一个 slot 。需要使用多 slot 时,可以在组件 js 中声明启用。
Component({
options: {
multipleSlots: true // 在组件定义时的选项中启用多slot支持
},
properties: { /* ... */ },
methods: { /* ... */ }
})
此时,可以在这个组件的 wxml 中使用多个 slot ,以不同的 name
来区分。
<!-- 组件模板 components/m-c/m-c.wxml-->
<view class="m-c">
<view class="header">
<slot name="header"></slot>
</view>
<view class="main">
<slot></slot>
</view>
<view class="footer">
<slot name="footer"></slot>
</view>
</view>
<m-c>
<view slot="header">页面头部</view>
<view >这里是插入到组件slot中的内容</view>
<view slot="footer">页面底部</view>
</m-c>
组件对应 wxss
文件的样式,只对组件wxml内的节点生效。编写组件样式时,需要注意以下几点:
#a
)、属性选择器([a]
)和标签名选择器,请改用class选择器。.a .b
)在一些极端情况下会有非预期的表现,如遇,请避免使用。.a>.b
)只能用于 view
组件与其子节点之间,用于其他组件可能导致非预期的情况。font
、 color
,会从组件外继承到组件内。app.wxss
中的样式、组件所在页面的的样式对自定义组件无效(除非更改组件样式隔离选项)。#a { } /* 在组件中不能使用 */
[a] { } /* 在组件中不能使用 */
button { } /* 在组件中不能使用 */
.a > .b { } /* 除非 .a 是 view 组件节点,否则不一定会生效 */
除此以外,组件可以指定它所在节点的默认样式,使用 :host
选择器。
默认情况下,自定义组件的样式只受到自定义组件 wxss 的影响。除非以下两种情况:
app.wxss
或页面的 wxss
中使用了标签名选择器(或一些其他特殊选择器)来直接指定样式,这些选择器会影响到页面和全部组件。通常情况下这是不推荐的做法。styleIsolation
。Component({
options: {
styleIsolation: 'isolated'
}
})
styleIsolation
选项支持以下取值:
isolated
表示启用样式隔离,在自定义组件内外,使用 class 指定的样式将不会相互影响(一般情况下的默认值);apply-shared
表示页面 wxss 样式将影响到自定义组件,但自定义组件 wxss 中指定的样式不会影响页面;shared
表示页面 wxss 样式将影响到自定义组件,自定义组件 wxss 中指定的样式也会影响页面和其他设置了 apply-shared
或 shared
的自定义组件。https://developers.weixin.qq.com/miniprogram/dev/framework/custom-component/wxml-wxss.html#%E7%BB%84%E4%BB%B6%E6%A0%B7%E5%BC%8F
https://developers.weixin.qq.com/miniprogram/dev/framework/custom-component/wxml-wxss.html#%E5%BC%95%E7%94%A8%E9%A1%B5%E9%9D%A2%E6%88%96%E7%88%B6%E7%BB%84%E4%BB%B6%E7%9A%84%E6%A0%B7%E5%BC%8F
组件间的基本通信方式有以下几种。
this.selectComponent
方法获取子组件实例对象,这样就可以直接访问组件的任意数据和方法。父组件(页面)向子组件传递数据,传递数字、字符串、布尔、数组、对象类型的数据。
<m-c count="{{num}}"></m-c>
Component({
// 组件的属性列表,类似vue的props,接收页面向组件的传值(父组件向子组件传值)
// properties中定义的属性会自动成为data的属性
properties: {
// count: Number,// 指定count的类型
count:{
// type: Number,// type指定为数字类型,type和vue的type不同,这里不仅仅是类型验证,为了规定接收的数据类型,不管传递的是什么类型的数据,最终都会转化为数字类型
optionalTypes:[Number, String, Boolean],// 指定多个类型
value: 6,// 默认值
}
},
})
子组件使用 triggerEvent
发射自定义事件,指定事件名、detail对象和事件选项:
// components/m-c/m-c.js
Component({
data: {
m: 12,
},
methods: {
btnClick: function(){
// 发射自定义事件,事件名为 sendM
this.triggerEvent('sendM', {
m:this.data.m
});
}
}
})
<!--index.wxml-->
<!-- 当自定义组件触发(发射)“sendM”事件时,调用“receiveM”方法 -->
<!-- 监听send有两种写法 -->
<m-c bindsendM="receiveM" />
<!-- 或者可以写成 -->
<m-c bind:sendM="receiveM" />
// index.js
Page({
data: {
num: 1,
},
receiveM(ev){
console.log('监听到sendM事件', ev.detail);
this.setData({
num: ev.detail.m
});
}
})
可在父组件里调用 this.selectComponent
,获取子组件的实例对象。
调用时需要传入一个匹配选择器 selector
,如:this.selectComponent(".my-component")
。
获取子组件实例分两种情况:
情况一:在自定义组件中不使用内置的 behavior:
wx://component-export
// index.js
// mc 是子组件实例
const mc = this.selectComponent('.m-c');
console.log(mc.data);
情况一:在自定义组件中使用内置的 behavior:
wx://component-export
// // components/m-c/m-c.js
Component({
behaviors: ['wx://component-export'],
// 导出组件的数据
export() {
return {
mx: this.data.m,
value: '导出的数据'
}
}
})
// index.js
// mc 不是子组件实例,是导出的对象 { mx: 12,value: '导出的数据'}
const mc = this.selectComponent('.m-c');
console.log(mc);
多个页面共享的数据,可以存放在app.js的globalData属性中,在页面或者组件中使用 const app = getApp()
获取。
组件的生命周期,指的是组件自身的一些函数,这些函数在特殊的时间点或遇到一些特殊的框架事件时被自动触发。
其中,最重要的生命周期是 created
attached
detached
,包含一个组件实例生命流程的最主要时间点。
created
生命周期被触发。此时,组件数据 this.data
就是在 Component
构造器中定义的数据 data
。 此时还不能调用 setData
。 通常情况下,这个生命周期只应该用于给组件 this
添加一些自定义属性字段。attached
生命周期被触发。此时, this.data
已被初始化为组件的当前值。这个生命周期很有用,绝大多数初始化工作可以在这个时机进行。detached
生命周期被触发。退出一个页面时,如果组件还在页面节点树中,则 detached
会被触发。定义生命周期方法:
生命周期方法可以直接定义在 Component
构造器的第一级参数中。
组件的的生命周期也可以在 lifetimes
字段内进行声明(这是推荐的方式,其优先级最高)。
组件的生命周期如下表所示。
生命周期 | 参数 | 描述 |
---|---|---|
created | 无 | 在组件实例刚刚被创建时执行 |
attached | 无 | 在组件实例进入页面节点树时执行 |
ready | 无 | 在组件在视图层布局完成后执行 |
moved | 无 | 在组件实例被移动到节点树另一个位置时执行 |
detached | 无 | 在组件实例被从页面节点树移除时执行 |
还有一些特殊的生命周期,它们并非与组件有很强的关联,但有时组件需要获知,以便组件内部处理。这样的生命周期称为“组件所在页面的生命周期”,在 pageLifetimes
定义段中定义。其中可用的生命周期包括:
生命周期 | 参数 | 描述 |
---|---|---|
show | 无 | 组件所在的页面被展示时执行 |
hide | 无 | 组件所在的页面被隐藏时执行 |
resize | Object Size | 组件所在的页面尺寸变化时执行 |
behaviors
是用于组件间代码共享的特性,类似于一些编程语言中的 “mixins” 或 “traits”。
每个 behavior
可以包含一组属性、数据、生命周期函数和方法。组件引用它时,它的属性、数据和方法会被合并到组件中,生命周期函数也会在对应时机被调用。 每个组件可以引用多个 behavior
,behavior
也可以引用其它 behavior
。
同名字段的覆盖和组合规则:
组件和它引用的 behavior
中可以包含同名的字段,对这些字段的处理方法如下:
behavior
中的同名属性或方法;behaviors
字段中定义靠后的 behavior
的属性或方法会覆盖靠前的同名属性或方法;behavior
的情况,则规则为:引用者 behavior
覆盖 被引用的 behavior
中的同名属性或方法。引用者 behavior
> 被引用的 behavior
、 靠后的 behavior
> 靠前的 behavior
。(优先级高的覆盖优先级低的,最大的为优先级最高)behavior
优先于组件执行;被引用的 behavior
优先于 引用者 behavior
执行;靠前的 behavior
优先于 靠后的 behavior
执行;behavior
被一个组件多次引用,它定义的生命周期函数只会被执行一次https://developers.weixin.qq.com/miniprogram/dev/framework/custom-component/relations.html
数据监听器可以用于监听和响应任何属性和数据字段的变化。
Component({ properties: { count: Number,// 指定count的类型 }, data: { message:'自定义组件mc', m: 12, arr:[1,2,3], obj:{name:'张三', age:12, weight: 100}, }, observers: { // 监听单个属性 count(newVal){}, // 监听多个属性 'count, m'(newVal){}, // 改变arr 或者 arr[1] 都会触发 'arr[1]'(){}, // 改变 obj 或者 obj.name 都会触发 'obj.name'(){}, // 监听所有子数据字段的变化,可以使用通配符 ** 'obj.**'(){}, // 仅使用通配符 ** 可以监听全部属性 '**'(){} } })
https://github.com/wechat-miniprogram/computed
https://github.com/wechat-miniprogram/mobx-miniprogram-bindings
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。