从0到1完成小程序开发(3)
一,数据的绑定
一个页面只有静态数据往往是不够的,大部分情况下需要在小程序运行的过程中,动态的从服务器端去获取,然后再渲染输出到这个视图中进行显示。
之前的页面为硬解码的方式
<view class="usermotto"> <text style="font-size:60rpx">今日推荐:恋爱循环</text> <image class="img" src="/imgs/banner.png"></image> <text class="text">推荐精彩点评:</text> <text class="text">问世间情为何物,执教人生死相许</text> <view> <text>豆瓣评分:{{score}}</text> </view> </view>
这样的页面只能用来展示,如果数据变更会很不方便,所以需要用到数据绑定。
在小程序框架中,每个页面所需要的各种数据,都是集中在这个页面所注册的页面对象中进行定义
在当前页面的js文件中通过调用page函数来给这个页面注册所需要的对象函数。
比如我需要给下面的页面添加数据绑定。
在这个页面文件夹下的脚本文件中的data属性中定义一个movie的数据:
Page({ /** * 页面的初始数据 */ data: {//通过data属性来给页面定义各种需要的数据 imovie:{ name:'恋爱循环', img:'/imgs/banner.png', comment:'问世间,情为何物,直教生死相许' } }
在小程序中用{{}}来对数据进行绑定。
<view class="usermotto"> <text style="font-size:60rpx">今日推荐:{{imovie.name}}</text> <image class="img" src="{{imovie.img}}"></image> <text class="text">推荐精彩点评:</text> <text class="text">{{imovie.comment}}</text> <view> <text>豆瓣评分:</text> </view> </view>
在上面代码中标题的名字,图片的路径,评论的语句都使用{{数据对象.数据名}}来放到相应的位置。
在{{}}中可以使用表达式
例如:创建一个数据名为score 和number数据变量
data: {//通过data属性来给页面定义各种需要的数据 imovie:{ name:'恋爱循环', img:'/imgs/banner.png', comment:'问世间,情为何物,直教生死相许' }, number:18,//创建一个数字为18 score:58//创建一个评分数为58 },
在WXML中使用表达式相加
<text>豆瓣评分:{{score + number}}</text>
页面展示为76。
在例如如果相加的和超过或者等于60的时候显示及格否则显示为不及格。
<text>豆瓣评分:{{(score + number>=60)?"及格":"不及格"}}</text>
为true显示及格
在调试框的AppData中可快速找到对应的内部变量和取值。
可以快速修改取值,当你修改后脚本内数据也会变化。
二,条件渲染
类似于编程语言中的条件语句,只有当某种条件成立的时候组件才会渲染生成。
使用WX:if做数据绑定来实现条件成立后组件渲染生成
小例子:
<view wx:if="{{recommend}}">
<text style="color:red;">强烈推荐</text> </view>
当recommend为false时,不渲染这段话,当recommend为true时渲染。
条件成立时渲染了这个视图。
也可以用 wx:elif
和 wx:else
来添加一个 else 块:
<view wx:if="{{length > 5}}"> 1 </view> <view wx:elif="{{length > 2}}"> 2 </view> <view wx:else> 3 </view>
使用条件渲染与使用hidden属性有什么区别
<view hidden="{{recommend}}">//使用hidden属性 <text style="color:red;">强烈推荐</text> </view>
recommend:true//hidden和if不同它是要取反的
使用hidden属性时,,这个元素总是要先被渲染生成的。hidden属性只是控制了它的可见性而已。
从使用的角度该如何选择?
使用hidden属性时,当控制条件发生切换,其节点数时没有任何变化的。所以它的开销会比较小,但是它的初始化开销会比较大。
当使用条件渲染的时候,当渲染条件发生切换的时候,其节点数会有对应的变化。所以对于可见性需要频繁切换的时候,我们就不建议使用条件渲染。因为它的开销会比较大。
三,列表渲染
列表渲染类似于编程语言中的循环语句。它重复的来渲染生成组件。
通过wx:for属性来实现列表渲染。
首先需要将之前的recommend页的内容修改为一个紧凑的块状的展示界面。
.recommend{ display: flex; } .recommend-content{ display: flex; flex-direction: column; } .img{ width: 30vh; height: 20vh; } .font-title{ font-size: 20px; color: hotpink; }
<view class="font-title"> <text>本周推荐</text> </view> <view class="recommend"> <image class="img" src="{{imovie.img}}"></image> <view class="recommend-content"> <text>{{imovie.name}}</text> <text class="text">推荐精彩点评:{{imovie.comment}}</text> <text>{{(number + score>=80)?"分数优秀":"分数低"}}</text> <text style="color:red;">强烈推荐</text> <view hidden="{{recommend}}"> </view> </view> </view>
假如需要在这个页面上展示许多个块状界面
第一步,需要把脚本文件内的imovie数据更改为数据对象。
data: {//通过data属性来给页面定义各种需要的数据 imovie:[ { name:'恋爱循环', img:'/imgs/banner.png', comment:'论世间情为核武,直教人生死相许', }, { name: '恋爱循环2', img: '/imgs/banner.png', comment: '论世间情为核武,直教人生死相许', }, { name: '恋爱循环3', img: '/imgs/banner.png', comment: '论世间情为核武,直教人生死相许', }], number:18, score:78, recommend:true },
在页面的视图中插入wx:for属性
<view class="recommend" wx:for="{{imovie}}">
这里不需要固定取出数组内某一个数据,需要有一个抽象的item概念。
<view class="font-title"> <text>本周推荐</text> </view> <view class="recommend" wx:for="{{imovie}}"> <image class="img" src="{{item.img}}"></image> <view class="recommend-content"> <text>{{item.name}}</text> <text class="text">推荐精彩点评:{{item.comment}}</text> <text>{{(number + score>=80)?"分数优秀":"分数低"}}</text> <text style="color:red;">强烈推荐</text> <view hidden="{{recommend}}"> </view> </view> </view>
这个时候就通过对imovie中的每一个值item的遍历和对应的渲染生成这个元素。
如何查看这是第几个渲染的值?
框架中所内置的index值是这个数组的下标,从0开始。
可以进行数据绑定来实现显示第几天推荐。
但是index的值从0开始 所以要index+1
使用swiper组件(轮播图效果)
使用swiper组件添加一个轮播图效果,使用方法如下:
<view> <swiper style="background: #eee"> <swiper-item>123</swiper-item> <swiper-item>456</swiper-item> <swiper-item>789</swiper-item> </swiper> </view>
swiper元素用来表示一个滑动容器。常用来实现幻灯片轮播或者轮播图效果。其中每一页幻灯片都是通过swiper-item元素来表示的。
现在给swiper元素添加上图片:
<view> <swiper style="background: #eee"> <swiper-item> <text>王牌对王牌</text>//文字标题 <image src="https://p.ssl.qhimg.com/t01b0121d51643a361c.jpg"></image> </swiper-item> <swiper-item> <text>朋友请听好</text>//文字标题 <image src="https://p.ssl.qhimg.com/t01f92341c61300cc74.jpg"></image> </swiper-item> <swiper-item> <text>特工007</text>//文字标题 <image src="https://p.ssl.qhimg.com/t01c55c28fa53f1d79b.jpg"></image> </swiper-item> </swiper> </view>
由于高度不够所以导致图片没用显示完整。添加高度样式。
现在显示正常。那么问题来了 如何把之前的列表渲染为swiper幻灯片元素呢。
看代码
把原来的view元素改为swoper-item元素即可
<swiper> <swiper-item class="recommend" wx:for="{{imovie}}"> <image class="img" src="{{item.img}}"></image> <view class="recommend-content"> <text>第{{index + 1}}天:{{item.name}}</text> <text class="text">推荐精彩点评:{{item.comment}}</text> <text>{{(number + score>=80)?"分数优秀":"分数低"}}</text> <text style="color:red;">强烈推荐</text> </view> </swiper-item> </swiper>
现在给列表幻灯片添加一些样式优化。
添加列表指示:
<swiper indicator-dots="{{true}}">
如果希望幻灯片的每一页都露出一部分的效果,引起用户触摸交互。
对swiper元素设置previous-margin和next-margin来实现
<swiper class="swiper" previous-margin="25px" next-margin="25px">//上一页露出25像素内容。下一页露出25像素内容
修改默认显示的幻灯片为第x页。
在swiper标签中添加current="x"
<swiper indicator-dots="{{true}}" current="1">
既默认显示为第一页。
更新数据
this.setData()方法
- 小程序并没有提供类似DOM的JS API来直接更新视图
- this.setData()方法-更新数据并让框架自动更新相关视图
- 更新是增量式的
- 单向绑定
在小程序中对内部状态数据进行更新,不能采用直接赋值写入的方式。必须通过调用小程序提供的this.setData()这个方法
下面来看一下实例 ,实现一个点击按钮更新视图文字的功能。
<text style="color:red;">推荐分数 : {{count}}</text> <view> <button bindtap="fnumb" style="height:40px">👍+1</button> </view> //添加一个按钮 当点击按钮时调用函数fnum给conunt+1并更新视图
在js文件的page中增加一个函数fnumb
fnumb: function (event) { this.setData({ count: this.data.count + 1 }) }//在this.setData中定义更新哪些数据。
这样点击按钮视图层也会更新。
this.setData()方法还可以对某一小部分进行局部的更新。
例如更改轮播图本周推荐第三页的电影名字。
在this.setData()中添加需要修改的局部数据对应的路径
需要注意的是这个表达式不是一个有效标识符需要放在双引号中来定义。
fnumb: function (event) { this.setData({ count: this.data.count + 1, //name属性赋值 "imovie[2].name":"梧桐树下的天空已泛白" })
点击按钮时只更改第三页幻灯片内容。
那么问题来了。视图层的更新会不会引起数据的自动更新?
答案是不会。因为小程序的数据是单向绑定,
事件机制
事件机制主要是用来对用户的事件交互进行响应。也是视图层向逻辑层进行通讯的一种方式。