******************逻辑层******************
1:app.json文件用来对微信小程序进行全局配置,决定页面文件的路径、窗口表现、设置网络超时时间、设置多 tab 等,大致配置如下图所示:
效果图如下
2:每一个小程序页面也可以使用.json文件来对本页面的窗口表现进行配置。 页面的配置比app.json全局配置简单得多,只是设置 app.json 中的 window 配置项的内容,页面中配置项会覆盖 app.json 的 window 中相同的配置项。页面的.json只能设置 window 相关的配置项,以决定本页面的窗口表现,所以无需写 window 这个键。大致配置如下图所示:
效果图如下所示:
3:App() 函数用来注册一个小程序。接受一个 object 参数,其指定小程序的生命周期函数等。大致函数如下图所示:
测试结果如下所示:
注意:
1:可以在其它.js文件(非app.js文件)中通过getApp()可以用来获取到小程序实例;
2:App() 必须在 app.js 中注册,且不能注册多个;
3:不要在定义于 App() 内的函数中调用 getApp() ,使用 this 就可以拿到 app 实例;
4:不要在 onLaunch 的时候调用 getCurrentPages(),此时 page 还没有生成;
5:通过 getApp() 获取实例之后,不要私自调用生命周期函数;
测试如下:
运行之后截图为
4:Page() 函数用来注册一个页面。接受一个 object 参数,其指定页面的初始数据、生命周期函数、事件处理函数等。
日志输入如下所示:
另外page中的data 将会以 JSON 的形式由逻辑层传至渲染层,所以其数据必须是可以转成 JSON 的格式:字符串,数字,布尔值,对象,数组。
另外page中的route字段可以获取到当前页面的路径,测试如下:
另外page中的setData函数用于将数据从逻辑层发送到视图层(异步),同时改变对应的 this.data 的值(同步)。具体说明如下所示:
注意:
1:直接修改 this.data 而不调用 this.setData 是无法改变页面的状态的,还会造成数据不一致。
2:仅支持设置可 JSON 化的数据。
3:单次设置的数据不能超过1024kB,请尽量避免一次设置过多的数据。
4:请不要把 data 中任何一项的 value 设为 undefined ,否则这一项将不被设置并可能遗留一些潜在问题。
测试如下:
小心得:只要是在生命周期中的数据(不论是app()还是page()),定义数据都是用:并且不用关键字来修饰,因为app()以及page()中的object参数中的数据必须是json格式才行,所以不论是数据还是函数还是函数的参数都是用:来赋值的,另外在自己定义的js文件中调用wx自带的api时,其方法的参数也是以json格式来书写的,但是如果在生命周期以外的数据定义及函数中的数据定义是要用=并且需要const或者是var来修饰。
5:路由
5.1:getCurrentPages() 函数用于获取当前页面栈的实例,以数组形式按栈的顺序给出,第一个元素为首页,最后一个元素为当前页面。测试如下:
5.2:路由方式
注意:
1:navigateTo, redirectTo 只能打开非 tabBar 页面。
2:switchTab 只能打开 tabBar 页面。
3:reLaunch 可以打开任意页面。
4:页面底部的 tabBar 由页面决定,即只要是定义为 tabBar 的页面,底部都有 tabBar。
5:调用页面路由带的参数可以在目标页面的onLoad中获取。
6:模块化
6.1:文件作用域
在 JavaScript 文件中声明的变量和函数只在该文件中有效;不同的文件中可以声明相同名字的变量和函数,不会互相影响。通过全局函数 getApp()可以获取全局的应用实例,如果需要全局的数据可以在 App()中设置。
6.2:模块化
可以将一些公共的代码抽离成为一个单独的 js 文件,作为一个模块。模块只有通过 module.exports 或者 exports 才能对外暴露接口。
需要注意的是:
exports 是 module.exports 的一个引用,因此在模块里边随意更改 exports 的指向会造成未知的错误。所以更推荐开发者采用 module.exports 来暴露模块接口,除非你已经清晰知道这两者的关系。
小程序目前不支持直接引入 node_modules , 开发者需要使用到 node_modules 时候建议拷贝出相关的代码到小程序的目录中。
在需要使用这些模块的文件中,使用 require(path) 将公共代码引入。
测试截图如下:
******************视图层******************
1:数据绑定(WXML 中的动态数据均来自对应 Page 的 data)
1.1:简单绑定(使用双大括号{{}}将变量包起来),
可以作用于内容,eg:
{{ message }}
可以作用于组件属性(需要在双引号之内),eg:
可以作用于控制属性(需要在双引号之内),eg:
可以作用于关键字(需要在双引号之内),eg:
//特别注意:不要直接写 checked="false",不然上面的checkbox的状态还是选中状态,因为其计算结果是一个字符串,转成 boolean 类型后代表真值。
1.2:运算,可以在 {{}} 内进行简单的运算,支持的有如下几种方式:
三元运算,eg:
Hidden
算数运算,eg:
{{a + b}} + {{c}} + d
逻辑判断,eg:
字符串运算,eg:
{{"hello" + name}}
数据路径运算,eg:
{{object.key}} {{array[0]}}
Page({
data: {
object: {
key: 'Hello '
},
array: ['MINA']
}
})
1.3:组合,也可以在{{}}内直接进行组合,构成新的数组或者对象
数组,eg:
{{item}}
Page({
data: {
zero: 0
}
})
最终组合成数组[0, 1, 2, 3, 4]
注意:花括号和引号之间如果有空格,将最终被解析成为字符串,eg:
{{item}}
等同于
{{item}}
测试截图如下
2:列表渲染
2.1:wx:for(在组件上使用 wx:for 控制属性绑定一个数组,即可使用数组中各项的数据重复渲染该组件。默认数组的当前项的下标变量名默认为 index,数组当前项的变量名默认为 item),测试如下图:
使用 wx:for-item 可以指定数组当前元素的变量名,使用 wx:for-index 可以指定数组当前下标的变量名,当出现循环嵌套时就可以指定变量名达到区分的目的,测试如下:
2.2:block wx:for(类似 block wx:if,也可以将 wx:for 用在 标签上,以渲染一个包含多节点的结构块),测试如下:
2.3:wx:key(如果列表中项目的位置会动态改变或者有新的项目添加到列表中,并且希望列表中的项目保持自己的特征和状态(如 中的输入内容, 的选中状态),需要使用 wx:key 来指定列表中项目的唯一的标识符)
wx:key 的值以两种形式提供:
1:字符串,代表在 for 循环的 array 中 item 的某个 property,该 property 的值需要是列表中唯一的字符串或数字,且不能动态改变。
2:保留关键字 *this 代表在 for 循环中的 item 本身,这种表示需要 item 本身是一个唯一的字符串或者数字。
当数据改变触发渲染层重新渲染的时候,会校正带有 key 的组件,框架会确保他们被重新排序,而不是重新创建,以确保使组件保持自身的状态,并且提高列表渲染时的效率。
如不提供 wx:key,会报一个 warning, 如果明确知道该列表是静态,或者不必关注其顺序,可以选择忽略。测试如下:
注意:
当 wx:for 的值为字符串时,会将字符串解析成字符串数组
{{item}}
等同于
{{item}}
3:条件渲染
3.1:wx:if(使用 wx:if="{{condition}}" 来判断是否需要渲染该代码块,也可以用 wx:elif 和 wx:else 来添加一个 else 块),测试如下:
3.2:block wx:if(因为 wx:if 是一个控制属性,需要将它添加到一个标签上。如果要一次性判断多个组件标签,可以使用一个 标签将多个组件包装起来,并在上边使用 wx:if 控制属性),测试如下:
注意: 并不是一个组件,它仅仅是一个包装元素,不会在页面中做任何渲染,只接受控制属性
3.3:wx:if vs hidden
因为 wx:if 之中的模板也可能包含数据绑定,所以当 wx:if 的条件值切换时,框架有一个局部渲染的过程,因为它会确保条件块在切换时销毁或重新渲染。同时 wx:if 也是惰性的,如果在初始渲染条件为 false,框架什么也不做,在条件第一次变成真的时候才开始局部渲染。相比之下,hidden 就简单的多,组件始终会被渲染,只是简单的控制显示与隐藏。
一般来说,wx:if 有更高的切换消耗而 hidden 有更高的初始渲染消耗。因此,如果需要频繁切换的情景下,用 hidden 更好,如果在运行时条件不大可能改变则 wx:if 较好。hidden的用法如下:
4:模板(WXML提供模板(template),可以在模板中定义代码片段,然后在不同的地方调用)
4.1:定义模板(使用 name 属性,作为模板的名字。然后在内定义代码片段),测试如下:
4.2:使用模板(使用import先导入模板文件,然后使用 is 属性声明需要的使用的模板,最后将模板所需要的 data 传入,另外is 属性可以使用{{}}语法,来动态决定具体需要渲染哪个模板)
最后效果为:
5:事件(事件是视图层到逻辑层的通讯方式)
5.1:事件分类
事件分为冒泡事件和非冒泡事件:
冒泡事件:当一个组件上的事件被触发后,该事件会向父节点传递。
非冒泡事件:当一个组件上的事件被触发后,该事件不会向父节点传递。
注:除上表之外的其他组件自定义事件如无特殊声明都是非冒泡事件,如
的submit事件,的input事件,5.2:事件绑定和冒泡
事件绑定的写法同组件的属性,以 key、value 的形式。
key 以bind
或catch
开头,然后跟上事件的类型,如bindtap
,catchtouchstart
。自基础库版本1.5.0起,bind
和catch
后可以紧跟一个冒号,其含义不变,如bind:tap
、、catch:touchstart
。
value 是一个字符串,需要在对应的 Page 中定义同名的函数。不然当触发事件的时候会报错。
bind
事件绑定不会阻止冒泡事件向上冒泡,catch
事件绑定可以阻止冒泡事件向上冒泡。
如在下边这个例子中,点击 inner view 会先后调用handleTap3和handleTap2(因为tap事件会冒泡到 middle view,而 middle view 阻止了 tap 事件冒泡,不再向父节点传递),点击 middle view 会触发handleTap2,点击 outer view 会触发handleTap1。
outer view
middle view
inner view
5.3:事件对象(如无特殊说明,当组件触发事件时,逻辑层绑定该事件的处理函数会收到一个事件对象),测试如下:
另外,还有个dataset属性(在组件中可以定义数据,这些数据将会通过事件传递给 SERVICE。 书写方式: 以data-开头,多个单词由连字符-链接,不能有大写(大写会自动转成小写)如data-element-type,最终在 event.currentTarget.dataset 中会将连字符转成驼峰elementType),测试如下:
6:引用(WXML 提供两种文件引用方式import和include)
6.1:import(import可以在该文件中使用目标文件定义的template),测试如下:
6.2:import 的作用域(只会 import 目标文件中定义的 template,而不会 import 目标文件 import 的 template)
6.3:include(include 可以将目标文件除了 外的整个代码引入,相当于是拷贝到 include 位置),测试如下:
7:WXS 模块(每一个 .wxs 文件和 标签都是一个单独的模块。每个模块都有自己独立的作用域。即在一个模块里面定义的变量与函数,默认为私有的,对其他模块不可见。一个模块要想对外暴露其内部的私有变量与函数,只能通过 module.exports 实现)
7.1:.wxs 文件(在微信开发者工具里面,右键可以直接创建 .wxs 文件,在其中直接编写 WXS 脚本),测试如下:
注意:
wxs文件中写的公共代码是用在.wxml文件中的,它通过标签来导入,而.js文件中写的公共代码是用在其他.js文件中的,它通过require来导入。二者相同的地方就是都需要通过module.exports来将私有的数据变成公共的。另外template是用来存放公共的视图的。另外wxs文件可以通过require函数来导入其他wxs文件。
8:变量(WXS 中的变量均为值的引用;没有声明的变量直接赋值使用,会被定义为全局变量;如果只声明变量而不赋值,则默认值为 undefined;var表现与javascript一致,会有变量提升。),示例如下:
var foo = 1;
var bar = "hello world";
var i; // i === undefined
//上面代码,分别声明了 foo、 bar、 i 三个变量。然后,foo 赋值为数值 1 ,bar 赋值为字符串 "hello world"。
注意:在js中"==" 只要求值相等; "===" 要求值和类型都相等
注意:function 也支持以下的语法(匿名函数,闭包等):
var a = function (x) {
return function () { return x;}
}
var b = a(100);
console.log( 100 === b() );
9:WXSS(用于描述 WXML 的组件样式)
9.1:尺寸单位(rpx: 可以根据屏幕宽度进行自适应)
9.2:样式导入(使用@import语句可以导入外联样式表,@import后跟需要导入的外联样式表的相对路径,用;表示语句结束)
9.3:内联样式(框架组件上支持使用 style、class 属性来控制组件的样式)
9.3.1:style:静态的样式统一写到 class 中。style 接收动态的样式,在运行时会进行解析,请尽量避免将静态的样式写进 style 中,以免影响渲染速度。
9.3.2:class:用于指定样式规则,其属性值是样式规则中类选择器名(样式类名)的集合,样式类名不需要带上.,样式类名之间用空格分隔。