====== 2.小程序的代码构成 ======
一个小程序
{
"pages":[
"pages/index/index",
"pages/logs/logs"
],
"window":{
"backgroundTextStyle":"light",
"navigationBarBackgroundColor": "#fff",
"navigationBarTitleText": "WeChat",
"navigationBarTextStyle":"black"
}
}
{
"navigationBarBackgroundColor": "#ffffff",
"navigationBarTextStyle": "black",
"navigationBarTitleText": "微信接口功能演示",
"backgroundColor": "#eeeeee",
"backgroundTextStyle": "light"
}
===== -#2 WXML 模板 =====
WXML由标签、属性等等构成,充当的就是类似 HTML 的角色。不同之处 \\
- 小程序的 WXML 用的标签是 view, button, text 等等[[https://developers.weixin.qq.com/miniprogram/dev/framework/quickstart/framework.html|小程序的能力]]
- 多了一些'' wx:if'' 这样的属性以及'' { { } }'' 这样的表达式
小程序采用MVVM的开发模式,提倡把
JS 只需要管理状态即可: \\
this.setData({ msg: "Hello World" })
==== - 数据绑定 ====
通过''{{}}''的语法把一个
// page.js
Page({
data: {
message: 'Hello MINA!'
}
})
=== - 组件属性 ===
(需要在双引号之内)
Page({
data: {
id: 0
}
})
=== - 控制属性 ===
(需要在双引号之内)
Page({
data: {
condition: true
}
})
=== - 数据路径运算 ===
Page({
data: {
object: {
key: 'Hello '
},
array: ['MINA']
}
})
也可以用扩展运算符...来将一个对象展开 \\
Page({
data: {
obj1: {
a: 1,
b: 2
},
obj2: {
c: 3,
d: 4
}
}
})
{a: 1, b: 2, c: 3, d: 4, e: 5}
仅仅通过数据绑定还不够完整的描述状态和界面的关系,还需要 if/else, for等控制能力,在小程序里边,这些控制能力都用 wx: 开头的属性来表达。[[https://developers.weixin.qq.com/miniprogram/dev/framework/view/wxml/|WXML]] \\
=== - 双向绑定语法 ===
如果使用 this.setData({ value: 'leaf' }) 来更新 value ,this.data.value 和输入框的中显示的值都会被更新为 leaf ;但如果用户修改了输入框里的值,却不会同时改变 this.data.value 。
如果需要在用户输入的同时改变 this.data.value ,需要借助简易双向绑定机制。此时,可以在对应项目之前加入 model: 前缀
双向绑定的表达式有如下限制:
只能是一个
Page({
data: {
array: [{
message: 'foo',
}, {
message: 'bar'
}]
}
})
输出: \\
0:foo
1:bar
使用 wx:for-item 可以指定数组当前元素的变量名, \\
使用 wx:for-index 可以指定数组当前下标的变量名:\\
输出: \\
0:foo
1:bar
:!: 当 wx:for 的值为字符串时,会将字符串解析成字符串数组 \\
等同于 \\
=== - wx:key ===
如果列表中项目的
Page({
data: {
objectArray: [
{id: 5, unique: 'unique_5'},
{id: 4, unique: 'unique_4'},
{id: 3, unique: 'unique_3'},
{id: 2, unique: 'unique_2'},
{id: 1, unique: 'unique_1'},
{id: 0, unique: 'unique_0'},
],
numberArray: [1, 2, 3, 4]
},
switch: 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 temp = this.data.objectArray[x]
this.data.objectArray[x] = this.data.objectArray[y]
this.data.objectArray[y] = temp
}
this.setData({
objectArray: this.data.objectArray
})
},
addToFront: function(e) {
const length = this.data.objectArray.length
this.data.objectArray = [{id: length, unique: 'unique_' + length}].concat(this.data.objectArray)
this.setData({
objectArray: this.data.objectArray
})
},
addNumberToFront: function(e){
this.data.numberArray = [ this.data.numberArray.length + 1 ].concat(this.data.numberArray)
this.setData({
numberArray: this.data.numberArray
})
}
})
{{ :微信小程序:wxkey.png?400 |}}
[[https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Math/random|Math.random()]] 函数返回一个浮点, 伪随机数在范围从0到小于1 \\
[[https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Math/floor|Math.floor()]] 返回小于或等于一个给定数字的最大整数。 \\
[[https://www.w3school.com.cn/js/jsref_concat_array.asp|concat()]] 方法用于连接两个或多个数组,该方法不会改变现有的数组,而仅仅会返回被连接数组的一个副本。 \\
==== - 条件渲染 ====
=== - wx:if ===
在框架中,我们用 '' wx:if="{ {condition} }" ''来判断是
也可以用'' wx:elif ''和'' wx:else''来添加一个else块: \\
=== - block wx:if ===
因为''wx:if''是一个控制属性,需要将它添加到一个标签上。 \\
但是
===== - WXSS 样式 =====
WXSS 具有 CSS 大部分的特性,小程序在 WXSS 也做了一些扩充和修改。[[https://developers.weixin.qq.com/miniprogram/dev/framework/view/wxss.html|WXSS]] \\
- app.wxss 作为全局样式,会作用于当前小程序的所有页面 \\
- 局部页面样式 page.wxss 仅对当前页面生效。 \\
==== - 样式导入 ====
/** common.wxss 局部样式 **/
.small-p {
padding:5px;
}
:!:使用@import语句可以导入外联样式表,@import后跟需要导入的外联样式表的
/** app.wxss 全局样式**/
@import "common.wxss";
.middle-p {
padding:15px;
}
==== - 内联样式 ====
*style:静态的样式统一写到 class 中。style 接收动态的样式,在运行时会进行解析,请尽量避免将静态的样式写进 style 中,以免影响渲染速度。
*class:用于指定样式规则,其属性值是样式规则中类选择器名(样式类名)的集合,样式类名不需要带上.,样式类名之间用空格分隔。
===== - JS 逻辑交互(事件) =====
用户做交互:响应用户的点击、获取用户的位置等等。在小程序里边,我们就通过编写 JS 脚本文件来处理用户的操作。
==== - 代码案例 ====
编写 JS 脚本文件来
点击 button 按钮的时候,我们希望把界面上 msg 显示成 "Hello World",于是我们在 button 上声明一个属性: bindtap ,在 JS 文件里边声明了 clickMe 方法来响应这次点击操作: \\
//app.js
Page({
clickMe: function() {
this.setData({ msg: "Hello World" })
}
})
==== - 什么是事件 ====
[[https://www.w3cschool.cn/weixinapp/weixinapp-event.html|微信小程序 事件]] \\
* 事件是视图层到逻辑层的通讯方式。
* 事件可以将用户的行为反馈到逻辑层进行处理。
* 事件可以绑定在组件上,当达到触发事件,就会执行逻辑层中对应的事件处理函数。
* 事件对象可以携带额外信息,如id, dataset, touches。
在组件中绑定一个事件处理函数。\\
如''bindtap'',当用户点击该组件的时候会在该页面对应的Page中找到相应的事件处理函数。 \\
//与index.wxml文件同目录下index.js,参数是event。
Page({
tapName: function(event) {
console.log(event)
}
})
''console.log(event)''打印数据
{
"type": "tap",
"timeStamp":895,
"target": {
"id": "tapTest",
"dataset": {
"hi": "WeChat"
}
},
"currentTarget": {
"id": "tapTest",
"dataset": {
"hi": "WeChat"
}
},
"detail": {
"x":53,
"y":14
},
"touches": [{
"identifier":0,
"pageX":53,
"pageY":14,
"clientX":53,
"clientY":14,
}],
"changedTouches": [{
"identifier":0,
"pageX":53,
"pageY":14,
"clientX":53,
"clientY":14,
}],
}
==== - 事件分类 ====
事件分为冒泡事件和非冒泡事件 \\
* 冒泡事件:当一个组件上的事件被触发后,该事件
outer view
middle view
inner view
如在上边这个例子中,点击inner view会先后触发handleTap3和handleTap2(因为tap事件会冒泡到middle view,而middle view阻止了tap事件冒泡,不再向父节点传递),点击middle view会触发handleTap2,点击outter view会触发handleTap1。
:!: mut-bind 来绑定事件。一个 mut-bind 触发后,如果事件冒泡到其他节点上,其他节点上的 mut-bind 绑定函数不会被触发,但 bind 绑定函数和 catch 绑定函数依旧会被触发。
==== - 数据绑定 ====
Click here!
* 此时,页面的 this.data.handlerName 必须是一个字符串,指定事件处理函数名;
* 如果它是个空字符串,则这个绑定会失效。
==== - 事件的捕获阶段 ====
捕获阶段位于冒泡阶段之前,且在捕获阶段中,事件到达节点的顺序与冒泡阶段恰好相反。
可以采用''capture-bind''、''capture-catch''关键字,后者将中断捕获阶段和取消冒泡阶段。
在下面的代码中,点击 inner view 会先后调用handleTap2、handleTap4、handleTap3、handleTap1。
outer view
inner view
==== - 事件对象 ====
如无特殊说明,当组件触发事件时,逻辑层绑定该事件的
DataSet Test
Page({
bindViewTap:function(event){
event.target.dataset.alphaBeta === 1 // - 会转为驼峰写法
event.target.dataset.alphabeta === 2 // 大写会转为小写
}
})
=== CustomEvent 自定义事件对象属性列表(继承 BaseEvent) ===
^ 属性 | 类型 ^ 说明 ^
| detail | Object | 额外的信息 |
detail \\
//所有页面都会被微信索引(默认情况)
{
"rules":[{
"action": "allow", //允许
"page": "*"
}]
}
//配置 path/to/page 页面被索引,其余页面不被索引
{
{
"rules":[{
"action": "allow", //允许
"page": "path/to/page"
}, {
"action": "disallow",//不允许
"page": "*"
}]
}
}