3.微信小程序-B站:wxml和wxss文件

WXML

WXML(WeiXin Markup Language)是微信的一套标签语言,结合基础组件、事件系统,可以构建出页面的结构。

(小安娜:好像很厉害的样子,那基础组件、事件系统是什么?感觉更厉害,因为必须结合它们。),基础组件类似HTML中的标签,事件系统是JavaScript中的事件,可处理逻辑反应到界面上;wxml只是一个文件格式,如果没有组件和事件它没任何用处,又如果把组件、事件写在txt文档里面也没任何用处,所以没有谁更厉害,相辅相成的关系。(小安娜:嗦嘎,就好像ap、ad、adc的关系,一起才最强)

用以下一些简单的例子来看看 WXML 具有什么能力:

数据绑定

WXML 中的动态数据均来自对应* Page 的 data 对象*

简单绑定

数据绑定使用 Mustache 语法(双大括号)将变量包起来,可以作用于以下:

(小安娜:等等,有没有点诚意,Mustache是什么都不知道!),Mustache是基于JavaScript实现的模板解析引擎,等等…总之它非常方便和好用。(小安娜:我去,你自己也不知道是什么吧)

内容

<view> {{ message }} view>
Page({
  data: {
    message: 'Hello MINA!'
  }
})

显示结果:

(小安娜:代表什么意思,记得HTML中没这样的标签啊?),这就是基础组件,view组件代表视图容器,可以理解成HTML中的DIV标签。

组件属性(需要在双引号之内)

<view id="item-{{id}}">id="item-{{id}}"view>
Page({
  data: {
    id: 0
  }
})

显示结果:

控制属性(需要在双引号之内)

<view wx:if="{{condition}}">你看得见我吗?view>
Page({
  data: {
    condition: true
  }
})

显示结果:

(小安娜:我刚刚试了,condition改成false就看不见我了!),是的,改成false就表示条件为假,view组件里面的内容就不会显示了。(小安娜:哦明白了,虽然我不想看见你,为了学好小程序还是改成true吧)

关键字(需要在双引号之内)

true:boolean 类型的 true,代表真值。

false: boolean 类型的 false,代表假值。

<checkbox checked="{{false}}" />默认没选中

特别注意:不要直接写 checked="false",这时候"false"是一个字符串,(JavaScript中非0为真、非空位真)转成boolean类型后代表真值。

(小安娜:那这个checkbox是不是和HTML的复选框一样?),没错啦,但checkbox组件更团结,更多是以组的概念存在,例如我们都会用checkbox-group包括起所有同类型的checkbox组件,后面用到自然会明白了。(小安娜:啊啊抓狂了,又多了个checkbox-group,感觉没耐心学了),可别这样想,基础都是乏味的,可是带你飞之前要先带你走,下篇文章我们做案例就会感觉很有意思了。(小安娜:知道啦,那我可以直接看下一篇不^_^),继续…

所以显示结果:

运算

可以在 {{}} 内进行简单的运算,支持的有如下几种方式:

三元运算

三元运算是:条件 ? 结果1 : 结果2;条件为ture时结果1否则结果2。

<view hidden="{{flag ? true : false}}"> 看得见吗? view>

(小安娜:flag我找了好久没见你定义啊,你确定不会报错?),不会的,这种变量即为空变量,(还记得前面提到过非空为真)flag转成 boolean类型后代表false,也就是表达式最终是这样的:hidden="{{false}}",明白了吗?(小安娜:阿拉搜,继续啦)

显示结果:

算数运算

<view> {{a + b}} + {{c}} + d view>
Page({
  data: {
    a: 1,
    b: 2,
    c: 3
  }
})

这次就先不说结果了,小安娜,你来猜猜看结果是什么?(小安娜:恩~,a=1,b=2,a+b就等于3,c=3,咦~,d没定义啊?),结果其实是:3 + 3 + d,d不是没定义,而它本来就是一个文字d,不参与任何计算。(小安娜:我这么认真回答,你居然这样坑我!!!)

显示结果:

字符串运算

<view>{{"hello " + name}}view>
Page({
  data:{
    name: 'MINA2'
  }
})

显示结果:

数据路径运算

如果data对象中包含了子对象,例如:

Page({
  data: {
    object: {
      key: 'Hello '
    },
    array: ['MINA3']
  }
})

可以这样访问:

<view>{{object.key}} {{array[0]}}view>

显示结果:

这个应该没问题吧?(小安娜:没问题,就是点操作嘛,一个是JSON对象操作,一个是数组操作),OK继续。

组合

也可以在 Mustache 内直接进行组合,构成新的对象或者数组。

数组

<view wx:for="{{[zero, 1, 2, 3, 4]}}"> {{item}} view>
Page({
  data: {
    zero: 0
  }
})

(小安娜:等等,这里我看了很久还是理解不了,再细讲解下),好,首先我们在data对象中定义zero变量并赋值为0,然后使用view组件的wx:for属性表示重复显示这个组件,wx:for属性的值是一个重新构造的数组,数组中第一个元素(也就是下标为0)的值来自于data中的zero对象,所以最终是用数组为[0, 1, 2, 3, 4]重复渲染组件。(小安娜:哦哦,完~全明白了)

显示结果:

条件渲染

wx:if

wx:if我们之前已经用过了,用来判断是否渲染该组件:

<view wx:if="{{condition}}">你看得见我吗?view>

也可以用 wx:elifwx:else 来添加其他判断:

<view wx:if="{{length > 5}}"> 1 view>
<view wx:elif="{{length > 2}}"> 2 view>
<view wx:else> 3 view>
Page({
  data: {
    length: 10
  }
})

界面显示结果:1

block wx:if

因为 wx:if 是一个控制属性,需要将它添加到一个标签上。但是如果我们想一次性判断多个组件,我们可以使用 标签将多个组件包装起来,并在block标签上用wx:if控制属性。

<block wx:if="{{true}}">
  <view> view1 view>
  <view> view2 view>
block>

这里的{{true}}是一个boolean类型的值,所以最后view1、view2都会显示。

(小安娜:我记得你说view可以看成div,那block呢,HTML中没这种控制标签?),没错啦, 并不是一个组件,它仅是一个包装元素,不会在页面中做任何渲染显示,只接受控制属性。(小安娜:明白了,block就好像文件夹,不占用空间,可设置文件夹显示和隐藏)

列表渲染

wx:for

在组件上使用 wx:for 控制属性绑定一个数组数据重复渲染该组件。

默认的当前项下标变量名为: index,数组当前项的变量名为:item(小安娜:不默认是什么样啊?)

<view wx:for="{{array}}">
  {{index}}:{{item.message}}
view>
Page({
  data: {
    array: [{
      message: 'foo',
    }, {
      message: 'bar'
    }]
  }
})

显示结果:

不使用默认可以使用 wx:for-item 可以指定当前元素的变量名,使用 wx:for-index 可以指定当前下标的变量名:

<view wx:for="{{array}}" wx:for-index="idx" wx:for-item="itemName">
  {{idx}}: {{itemName.message}}
view>

输出结果一样。

block wx:for

类似block wx:if,也可以将wx:for用在 标签上,重复渲染多组件块。例如:

<block wx:for="{{['a', 'b', 'c']}}">
  <view> {{index}}:{{item}}view>
block>

显示结果:

wx:key(可以选择跳过,但,是很重要的重点)

(小安娜:突然有种想打你的冲动,又是重点又可以跳过,下课操场见!!!),冷静、冷静,官方文档我看到这时,也是没理解这是什么意思,后来就跳过这段了,但是也完成了B站的首页,(小安娜:哈~,原来是自己傻看不懂,别把我们的智商和你比好吧!),当写到这时再去多看了一遍(小安娜:绝对不止一遍),把官方例子运行调试之后,才发现微信官方设计wx:key的用意,而且是很重要的重点。

如果列表中的项目位置会改变或者有新的项目添加到列表中,为了项目保持自己的属性和状态(如 的输入内容, 的选中状态),需要使用wx:key来指定列表中项目的唯一的标识符。

wx:key的值以两种形式提供:

  1. 字符串;代表在for循环的arrayitem的某个属性,该属性的值是列表中唯一的字符串或数字,并且不能动态改变。
  2. 保留关键字;*this 代表在for循环中的item本身,这种需要item本身是唯一的字符串或者数字。

是不是完全理解不了什么意思?(小安娜:我觉得这不是重点,重点是案例你还没讲)

案例1:wx:key的值是字符串

<switch wx:for="{{objectArray}}" wx:key="unique" style="display: block;"> {{item.id}} switch>
<button bindtap="switch"> 改变顺序 button>
<button bindtap="addToFront"> 添加到前面 button>

(小安娜:bindtap是什么意思呢?),这个是用来绑定事件的,bindtap是当用户点击的时候会执行相对于的函数,这个马上会在事件中详细讲解。

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'},
    ]
  },
  // 随机改变列表项目顺序
  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
    })
  }
})

(小安娜:天了噜,一大波代码来袭,看不懂了啦),所有函数真可以不用看懂内部实现,只需知道干什么用就行(内心的杰尔夫君:其实我知道只有她看不懂,大家照顾照顾她,假装看不懂)(小安娜:阿丘~谁在说我坏话!)

显示结果(①:初始化状态;②:打开项目2的开关;③:改变顺序后项目2依然是打开状态;④:在最前面添加项目6,项目2依然是打开状态),这就是wx:key的作用,它会利用一个唯一值保留该项状态:

案例2:wx:key的值是*this

<switch wx:for="{{numberArray}}" wx:key="*this" style="display: block;"> {{item}} switch>
<button bindtap="addNumberToFront">添加到前面button>
Page({
  data: {
    numberArray: [1, 2, 3, 4]
  },
  // 添加项目到前面
  addNumberToFront: function(e){
    this.data.numberArray = [ this.data.numberArray.length + 1 ].concat(this.data.numberArray)
    this.setData({
      numberArray: this.data.numberArray
    })
  }
})

显示结果:

模板

WXML提供模板(template),可以在模板中定义代码片段,然后在不同的地方调用。

使用模板

  1. 使用name属性作为模板的名字。然后在