壹 ❀ 引

我在从零开始的微信小程序入门教程(二),初识WXML与WXSS一文中简单介绍了小程序组件与小程序样式相关概念,在了解这两者之后,其实我们已经可以搭建出简单的静态页面,与书写HTML页面一样,小程序页面也只能通过多写多练提升。在构建完页面后就出现了一个问题,我们该如何获取组件元素让数据与之关联呢?

在网页开发中,我们同样使用JS操作DOM,包括数据渲染,事件监听等,比如我现在要通过点击一个按钮后,替换段落中的本文信息,使用JS可以这么做:

<p>我是谁?</p>
<button>点我点我</button>
let btn = document.querySelector("button"),
p = document.querySelector("p");
btn.onclick = function () {
p.innerHTML = '我是听风是风啊!'
};

没问题,效果虽然实现了,但是类似的操作我们总是得获取并操作DOM,逻辑层与渲染层高度耦合,每一份数据我们似乎都得找到对应的DOM所在,并帮助它们相互关联,这很明显不太友好。伴随发展,angularjs,vue,react的出现,我们知道了MVVM模式的存在,在开发中逻辑层与渲染也得以分离,微信小程序在开发模式上也借鉴了这一点,比如还是上面的效果,用小程序就可以这么做,我们分别在index.wxmlindex.js中添加如下代码:

<text>{{myName}}</text>
<button bindtap="setName">点我点我</button>
const app = getApp()

Page({
data: {
myName:'我是谁?'
},
setName() {
this.setData({ myName: "喷火龙" })
}
})

接下来我们解释下小程序数据绑定到底怎么玩,以及其它几种常见的数据交互方式。

贰 ❀ 数据交互

贰 ❀ 壹 数据绑定{

熟悉vue等相关框架的同学对于上述例子一定十分熟悉,对于第一次了解这种用法的同学也不用担心,并不复杂,我们来解释下到底什么是意思。

首先看WXML,小程序使用{{}}表达式来绑定解析JS文件中定义的变量,而在JS文件的data对象中一般用于定义小程序初始化所需数据,比如例子中的变量myName有一个初始值。

Page({
data: {
/* 页面初始数据写在这*/
}
})

接下来就是如何通过点击事件让myName发生变化,在组件button上我们通过点击事件bindtap绑定了一个setName方法,注意,这个方法同样定义在JS文件Page对象中,与data对象同级,以往我们绑定方法一般会给方法名后带括号,小程序的方法绑定并没有括号,比如上面的bindtap="setName"

Page({
data: {
/* 页面初始数据写在这 */
},
方法名() {
/* do something */
}
});

数据绑定除了能用于解决组件文本内容的变更,还有一大作用就是支持组件属性动态变更,什么是组件属性?样式class是属性,组件内连样式style也是属性,比如我们可以有这样一个组件:

<text class="name" style="color:#fff;background:#e4393c">{{myName}}</text>

那么通过数据绑定表达式,我们可以让样式也动起来,比如下面这个例子:

<text class="{{defaultClass}}" style="color:#fff;background:{{backgroudColor}};display:block">{{myName}}</text>
<button bindtap="setName">点我</button>
.my-name {
height: 30px;
width: 100px;
text-align: center;
line-height: 30px;
} .my-name-new{
height: 40px;
width: 200px;
text-align: center;
line-height: 40px;
}
const app = getApp()

Page({
data: {
myName: '我是谁?',
defaultClass: 'my-name',
backgroudColor: '#e4393c'
},
setName() {
this.setData({
myName: "喷火龙",
defaultClass:'my-name-new',
backgroudColor:'#bbded6'
})
}
})

在这个例子中,我们定义了一个class变量,此class默认值由JS文件中提供,除此之外,在内联样式style中的background属性也是变量,当点击按钮,我们切换了class的值以及background的值,在为属性使用数据绑定时,唯一需要注意的是{{}}始终被包裹在一对双引号中,关于数据绑定先说到这里,也算是WXSS的一部分补充。

贰 ❀ 贰 基本逻辑语法

{{}}中除了单纯的解析变量,还能做简单的逻辑运算,比如算术计算:

<text>{{num1+num2}}</text>
Page({
data: {
num1: 1,
num2: 2
},
})

我们还能用于字符串拼接,比如下面的例子:

<text>听风是风{{str}}</text>
<text>{{"听风是风"+str}}</text>
Page({
data: {
str: '很酷'
},
})

这两种拼接方式都是可以的,因为在{{}}中解析的是变量,所以本身是字符时得加上引号。

另外,{{}}中还能使用三元表达式,也就是根据条件决定使用不同的结果:

<text>{{userName?userName:'登录'}}</text>
Page({
data: {
userName: ''
},
})

比如上面这个例子就是一个简单的用户信息展示,如果有数据展示用户名,如果没有提示登录。

三元的用途还很多,比如结合样式使用,通过条件判断来决定使用哪种样式,这在实际开发中都非常实用,待大家执行探索。

贰 ❀ 叁 条件逻辑

控制模板是否显示方面,在vue中有v-if,在angular中有ng-if,而在小程序中我们可以使用wx:if来达到同样的效果,当然我们还是得结合{{}}使用,比如:

<text wx:if="{{bool}}">我叫听风是风</text>

注意,wx:if与我们以往使用框架中的效果一样,一旦变量为false,整个组件不会加载,在小程序解析的wxml模板中你都找不到它,这和组件加载但display:none是有区别的。

问题来了,假设我们希望wx:if不仅是控制一个组件,而是好几个组件的显示隐藏怎么办?这时候我们可以结合block组件使用,看下面的例子:

<block wx:if="{{bool}}">
<text>我叫听风是风,</text>
<text>听风是风你加点油好不好,真的是!</text>
</block>

block虽然是个组件,但它本身并不会被渲染,只是单纯起到容器的作用,比如当bool为true可以看到wxml中并没有渲染block组件,所以大家不用担心会不会增加无用组件层级的问题。

实际开发中有这样一种情况,比如购物车页面,如果当前用户能请求回购物车数据,我们自然是展示购物车信息,如果请求回来没数据,我们肯定得给出购物车为空的友好提示,以angualrjs为例,我一般是提供2个盒子,大致这么个意思:

<div class="cart">
<div ng-if="bool"></div>
<div ng-if="!bool"></div>
</div>

因为angularjs只提供了ng-if情况,这里通过 ! 取反值,模拟了if else的情况。

值得庆幸的是小程序不仅提供了wx:if,还提供了wx:elif以及wx:else,所以条件情况再多,我们都能应对自如,比如:

<text wx:if="{{num > 0}}"> 大于0 </text>
<text wx:elif="{{num < 0}}"> 小于0 </text>
<text wx:else> 等于0 </text>

既然谈到了wx:if,用过vue的同学一定会想问小程序有没有类似v-show的指令呢?当然有,我们可以给组件添加hidden属性来达到v-show的效果,hidden接受一个Boolean值。wx:ifhidden的区别是,wx:if值为假时组件直接就不渲染,而hidden为真时组件还是会渲染,只是display为none。

2020.7.7 更新修改

另外关于hidden有个小坑,比如下面这个例子:

<text hidden="false">1</text>

你会发现这个组件并不会显示,而正确的写法是这样:

<text hidden="{{false}}">1</text>

出于angularjs以及其它框架的习惯,我一直觉得{{}}中应该解析变量,没想到这里小程序居然要使用{{}}包裹一个明确的布尔值。感谢HZz.D.25'11指出。

所以站在我的角度,我还是推荐使用变量表示布尔值,这样更符合使用习惯,比如下面的例子:

<view hidden="{{bool}}">1</view>
Page({
data: {
bool: false
},
})

贰 ❀ 肆 列表渲染

在上面的例子中我们提及购物车有数据以及无数据时的实现场景,如果有数据,我们其实就得将数据结合模板遍历出来,在angular中我们可以使用ng-repeat,vue中有v-for,很巧,小程序也提供了wx:for,我们先来看一个简单的例子:

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

不难猜测,这里的indexitem就是小程序默认给我们提供的,当遍历数组时,当前元素的索引与当前元素自身。

那么假设数组中的每个元素都是对象呢?其实还是一样的访问,比如下面这样:

Page({
data: {
array: [{
name:'echo'
},{
name:'听风是风'
},{
name:'时间跳跃'
}]
},
})
<view wx:for="{{array}}">
{{item.name}}
</view>

有同学肯定要问了,小程序默认把索引和元素自身命名成了indexitem,那我自己能不能改个名字呢?能,看下面例子:

<view wx:for="{{array}}" wx:for-index="a" wx:for-item="b">
{{a}}: {{b}}
</view>

我们可以使用wx:for-indexwx:for-item来自定义indexitem的名字,想取什么随你开心。

上面的例子都是将wx:for加在了一个组件上面,比如我们要遍历购物车数据,那就有购物车图片,价格,总价,删除等等对应的组件,这么多组件怎么办?还记得前面提到的无私奉献的block组件吗?没错,我们可以用它将重要的组件包裹起来,像这样:

<block wx:for="{{array}}">
<view>{{index}}</view>
<view>{{item}}</view>
</block>

最后,关于wx:for性能方法,我们不得不提wx:key,这玩意有啥用呢?打个比方,我们现在有数组[1,2,3,4],小程序将这四项渲染了出来,现在我们修改重排了数组,变成了[4,3,2,1],如果我们没添加wx:key,小程序会重新渲染,再次遍历新增四个组件。

而如果我们在遍历时添加了wx:key,小程序会以key作为一个查找标准,判断当前已经渲染出来的组件还有没有用,我们仔细看数组变化,它只是重新排了序,内容无变化,所以小程序会将之前已经创建好的组件直接再利用进行重排,而不是直接完全重新渲染一遍,这样就提升了渲染过程。

再比如[1,2,3,4]变成了[1,2,3,4,5],有key就是在原有基础上新增一个即可,而不用重新遍历五个组件,大概就这么个意思。

OK,我们解释了wx:key作用之后,来说说wx:key接受什么做参数,这里直接引用官方介绍:

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

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

我们分别对应这两种值给出两个例子:

字符串情况,表示item中的一个属性,且属性的值在整个数组中都是独一无二的数组或字符串:

<view wx:for="{{array}}" wx:key="id" > {{item.name}} </view>
Page({
data: {
array: [
{id: 0, name: 'echo'},
{id: 1, name: '听风是风'},
{id: 2, name: '时间跳跃'},
{id: 3, name: '行星飞行'},
]
}
})

this情况,表示item自身,item应该是独一无二的数值或者字符串:

<view wx:for="{{array}}" wx:key="*this" > {{item}} </view>
Page({
data: {
array: [1, 2, 3, 4]
}
})

注意,使用过程中this前有个星号,虽然不加也没报错,但官方是加了所以还是加吧。

肆 ❀ 总

好了,那么到这里,我们大致介绍完了常见数据绑定的几种用法,只要有数据,我们现在能利用各种手段将这些数据渲染到WXML中,这非常棒!

在上文中,我们在了解数据绑定的同时,也知道了第一个事件bindtap,它属于点击事件,那么在小程序中还有哪些好玩的事件呢?这个问题我们在下篇教程中揭晓,通过学习事件,让我们的小程序页面更具交互性。

那么到这里,本文正式结束。

教程第四篇已更新:从零开始的微信小程序入门教程(四),理解小程序事件与冒泡机制

从零开始的微信小程序入门教程(三),有趣且好玩的数据绑定的更多相关文章

  1. 从零开始的微信小程序入门教程(一)

    之前说要和同事一起开发个微信小程序项目,现在也在界面设计,功能定位等需求上开始实施了.所以在还未正式写项目前,打算在空闲时间学习下小程序.本意是在学习过程中结合实践整理出一个较为入门且不是很厚的教程, ...

  2. 微信小程序入门教程之四:API 使用

    今天是这个系列教程的最后一篇. 上一篇教程介绍了,小程序页面如何使用 JavaScript 脚本.有了脚本以后,就可以调用微信提供的各种能力(即微信 API),从而做出千变万化的页面.本篇就介绍怎么使 ...

  3. 天河微信小程序入门《三》:打通任督二脉,前后台互通

    原文链接:http://www.wxapp-union.com/forum.php?mod=viewthread&tid=505&extra=page%3D1 天河君在申请到https ...

  4. 开发微信小程序入门教程,含破解工具

    2016年09月21日晚 微信发不了微信“小程序”的内测版,一时间整个互联网都炸了锅.个大新闻.论坛都在讨论这个事情. 作为互联网的一猿,我们怎能不紧跟时代的脚步.于是第二天上午也对微信发布的“小程序 ...

  5. 微信小程序入门教程

    首先请看demo 很简单的静态js就可以实现一款小程序开发. js.json.html.css四个核心文件 序言 开始开发应用号之前,先看看官方公布的「小程序」教程吧!(以下内容来自微信官方公布的「小 ...

  6. 微信小程序入门教程之一:初次上手

    微信是中国使用量最大的手机 App 之一,日活跃用户超过3亿,月活跃用户超过11亿(2019年底统计),市场极大. 2017年,微信正式推出了小程序,允许外部开发者在微信内部运行自己的代码,开展业务. ...

  7. 微信小程序入门教程之三:脚本编程

    这个系列教程的前两篇,介绍了小程序的项目结构和页面样式. 今天,接着往下讲,教大家为小程序加入 JavaScript 脚本,做出动态效果,以及如何跟用户互动.学会了脚本,就能做出复杂的页面了. 本篇的 ...

  8. 微信小程序入门教程(一)API接口数据记录

    今天测试用小程序调用API接口,发现有些数据打印都是对象,怎么全部打印详细点来 小程序代码: httpsearch: function (name, offset, type, cb) { wx.re ...

  9. 微信小程序入门(三)

    11.开发框架基本介绍 四个组成部分,其它三个前面介绍过了,主要WXS: WXS:对wxml增强的一种脚本语言,可以对请求的数据进行filter或者做计算处理,帮助wxml快速构建出页面结构. 12. ...

  10. 天河微信小程序入门《四》:融会贯通,form表单提交数据库

    天河在阔别了十几天之后终于又回来了.其实这篇文章里的demo是接着(天河微信小程序入门<三>)后面就做了的,但是因为最近在做别的项目,所以就偷懒没有发出来.放到今天来看,从前台提交数据到数 ...

随机推荐

  1. 05_二叉树的层次遍历II

    二叉树的层序遍历 II 给你二叉树的根节点 root ,返回其节点值 自底向上的层序遍历 . (即按从叶子节点所在层到根节点所在的层,逐层从左向右遍历) 示例 1: 输入:root = [3,9,20 ...

  2. KVM 核心功能:磁盘虚拟化

    1 磁盘虚拟化简介 QEMU-KVM 提供磁盘虚拟化,从虚拟机角度看其自身拥有的磁盘即是实际的物理磁盘.实际上,虚拟机读写的磁盘数据保存在 host 上的物理磁盘.   QEMU-KVM 主要有如下几 ...

  3. 每天学五分钟 Liunx 0001 | 存储篇:swap

    swap swap ,内存交换空间,它是磁盘上的一块空间,主要作用是为了防止物理内存不足. CPU 从内存中读取数据.当内存的空间不足时, CPU 难以读取到数据,导致程序无法正常工作.所以诞生了 s ...

  4. Scan Synthesis Review

    Review scan replacement - 将normal DFF替换为mux gate DFF scan stitching - 将DFF连接起来 scan的作用:将测试困难的时序逻辑转变为 ...

  5. [java] - 获取上传到服务器上的文件路径

    request.getSession().getServletContext().getRealPath("upload/" );

  6. [转帖]Xargs用法详解

    https://www.cnblogs.com/cheyunhua/p/8796433.html 1. 简介 之所以能用到这个命令,关键是由于很多命令不支持|管道来传递参数,而日常工作中有有这个必要, ...

  7. [转帖]Linux命令拾遗-动态追踪工具

      原创:打码日记(微信公众号ID:codelogs),欢迎分享,转载请保留出处. 简介# 这是Linux命令拾遗系列的第六篇,本篇主要介绍工作中常用的动态追踪工具strace.arthas.bpft ...

  8. 使用smem 计算Oracle用户下内存占用情况.

    1. 本来计划使用 ps 命令进行查看, 但是发现ps 最多查询出来的是 RSS的内存数据, 会多添加很多冗余的内存数据量进来, 于是作罢 2. 找了下公司的方神, 说可以使用smem 然后简单看了下 ...

  9. ESXi查看底层存储磁盘厂商型号的方式与方法

    ESXi查看底层存储磁盘厂商型号的方式与方法 背景 公司一台过保的服务器出现了磁盘告警 Vendor不太靠谱. 过保的机器就不管了 不买他们的服务器也不说一下是啥硬盘. 想自己替换,需要先获取磁盘的型 ...

  10. 加快ios的出包速度

    在导出ipa时,通过这几种方法,可以更快地导出ipa来进行测试 不勾选bitcode 在导出ipa时,不勾选bitcode,这样会加快出包的速度,但导出来的ipa会大一些,关于bitcode可查看:& ...