前端|微信小程序开发学习笔记(二)

前端|微信小程序开发学习笔记(二)

五月 04, 2019

七. 列表渲染

wx:for

1
2
3
4
5
6
7
8
9
<view class="movie" wx:for= "{{thisWeekMovie}}">
<image class="movie-image" src="{{item.imagePath}}"></image>
<view class="movie-details">
<text style="" >{{index+1}}{{item.name}}</text> <!--/*style 用于文本类型-->
<text>点评: {{item.comment}}</text>
<text wx:if= "{{!item.ishighlyRecommended}}" style="font-size:16px; color:red;">强烈推荐</text>
<text>{{count}}</text>
</view>
</view>

重复渲染thisWeekMovie中的元素
item是指数组中的值
index的值为当前所遍历到的item值的下标
默认数组的当前项的下标变量名默认为 index,数组当前项的变量名默认为 item

weekly.js文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
thisWeekMovie: [
{
name: "教父3",
comment: "最精彩的剧本,最真实的黑帮电影",
imagePath: "/images/42.jpg",
ishighlyRecommended: true
},
{
name: "逃避虽可耻但有用",
comment: "程序员纯情的爱",
imagePath: "/images/42.jpg",
ishighlyRecommended: true
},
{
name: "今生第一次",
comment: "韩国程序员的恋爱春天",
imagePath: "/images/42.jpg",
ishighlyRecommended: true
},
],

定义了一个列表为 thisWeekMovie结果为

图像10

八. 使用swiper组件 从列表展示变为幻灯片轮播展示

swiper元素用来表示一个滑动容器, 常用来实现幻灯片轮播

每一个幻灯片用 表示

1
2
3
4
5
6
7
8
9
10
11
<swiper class='movie-swiper' indicator-dots='{{true}}' previous-margin='50rpx' next-margin='50rpx'>           <!---->
<swiper-item class="movie" wx:for= "{{thisWeekMovie}}">
<image class="movie-image" src="{{item.imagePath}}"></image>
<view class="movie-details">
<text style="" >{{index+1}}{{item.name}}</text> <!--/*style 用于文本类型-->
<text>点评: {{item.comment}}</text>
<text wx:if= "{{!item.ishighlyRecommended}}" style="font-size:16px; color:red;">强烈推荐</text>
<text>{{count}}</text>
</view>
</swiper-item>
</swiper>

indicator-dots='true' 表示是否显示底部滑动
previous-margin='50rpx' next-margin='50rpx' 予显示出一部分上一个和下一个的页面内容

{
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
  height: 100%;
width: 100%;
background: #eee;
margin: 0 20rpx;
}
```


margin: 0 20rpx; 设置页面的左右外边距 每一个view元素距离它的副元素,也就是所在的幻灯片页左右都有10像素的间隔,从而两个相邻幻灯片页有20像素间隔.

### 九.页面的生命周期

1.swiper中如何默认切换到最后一页幻灯片
2.非本周幻灯片页添加"返回本周"按钮
页面状态数据如何初始化.onLoad(options)
onHide,onUnload
onShow,onReady


1
2

current 选项可以选择首张幻灯片为第几页 默认为'0'

current=’NaN‘

1
2
3
表示将数组thisWeekMovie的最后一个数绑定到第一张幻灯片中  .length为数组的长度
加一个返回本周按钮
在幻灯片view页面中

返回本周

1
2


.movie-card {
height: 100%;
width: 100%;
background: #eee;
margin: 0 20rpx;
position: relative;
}

1
`position: relative`;  将view做一个相对定位

.return-button{
position: absolute;
}

1
2
将控制按钮做一个相对定位    
添加一些基本的样式

.return-button{
position: absolute;
right: 0;
top: 40rpx;
font-size: 26rpx;
font-style: italic;
border: 1px solid blue;
border-right: 0;
border-radius: 10%;
}

1
按钮返回本周只有在本周其他页面中才会出现,因此添加条件渲染

返回本周

1
#### 如何实现按键的功能加入

返回本周

1
2
3
4
5
6
7
"bindtap='f0'"绑定一个按钮事件,按下按钮后执行f0事件
绑定事件处理函数f0 之后在f0事件处理函数中将swiper元素切换到最后一页 而
#### swiper元素通过current来切换页面因此切换到最后一页时就是要将current更新成最后一页的页码,
但是在小程序中并没有在逻辑层提供一个类似于DOM的api来直接对视图层的元素属性进行设置,我们能做的就是current所绑定的内部状态变量或者时对应的表达式进行更新,我们看到current所绑定的内部状态变量是"thisWeekMovie.length -1"

一旦我们从服务器中获取到thisWeekMovie这个数组之后,在小程序中对页面操作时, 对这个数组不改变属性,长度也不变,所以这个表达式"thisWeekMovie.length -1"的值是不变的,因此这样绑定无法通过在逻辑层通过对所绑定的表达式的值进行改变来改变current值,所以我们需要对current属性绑定一个新的单独的内部变量上,让这个内部变量的初始值定义为数组长度减一,然后在事件处理的过程中,在逻辑层对新内部变量的取值进行更新,进而让框架自动更新current属性对应的取值.
首先定义新的内部变量


1
然后在data属性中定义这个变量

currentIndex: 0,

1
此时不能直接将data数据中的"thisWeekMovie.length -1"直接赋值给currentIndex,因为currentIndex与thisWeekMovie在同一个对象中定义的另一个属性,因此会报错误为thisWeekMovie没有定义,因此我们必须将这一初始化操作在另一个地方完成,而且必须在视图文件被渲染之前完成,因为在渲染时就会使用currentIndex的值,对current属性进行设置,那么在什么地方完成呢,就需要引入onload生命周期回调函数,也是在这个页面所注册的页面对象中所定义,当页面被打开加载时,框架会自动调用页面所注册的页面对象中onload方法,来完成初始化,

onLoad: function (options) {
this.setData({
currentIndex: this.data.thisWeekMovie.length -1
})
},

1
2
3
4
5
6
7
8
定义一个this.setData  来在加载时进行初始化设置,通过在onLoad中调用this.data.thisWeekMovie.length
来获取thisWeekMovie数组的长度.需注意,onLoad函数是与data函数并列,也就是说调用data中的数据时,需要用类来引用 "this.data."

onShow 每一次页面从隐藏状态变为显现状态时就要被调用一次

this.setData()方法-更新数据并让框架自动更新相关视图

首先为了实现按钮功能定义了一个事件f0,因此定义f0函数.

f0: function(event){
console.log(this.data.count)
},

1
2
"console.log(this.data.count)"指在console中显示count的值.
在小程序中对内部变量更新,不能采用直接赋值写入的方式.因此使用this.setData()方法,如将

f0: function(event){
this.setData({
currentIndex: this.data.thisWeekMovie.length - 1
})
},

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
当用户在视图层进行相应更新时(如手动切换页面),无论current的值变成了几,currentIndex的值都不会进行变化,说明小程序中的视图层的更新不会自动引起内部状态数据的变化,也就说明视图层对内部变量绑定是单项绑定(只能允许逻辑层向视图层更新)

#### `注意`
在onload中,var变量定义时前后都不能有`,`

### 十. 事件机制

事件绑定
冒泡事件与非冒泡事件
bind绑定 VS catch绑定
时间对象简介

1.冒泡事件: 当一个组件上的事件被触发后,该事件会向父节点传递. 对应 bindtap
2.非冒泡事件: 当一个组件上的事件被触发后,该事件不会向父节点传送. 对应catchtap

当我们使用的是bindtap时,点击这个内容,就会触发一个事件,之后这个事件会向上传递,通过在事件函数中执行console.log(event)观察事件向上传的什么内容.

图像11
![ ](https://zzufire.github.io/img/1.11.png)
如点击的是view中的一个元素(返回本周),事件执行后,调用这个元素的事件处理函数,之后这个触发又冒泡到了view又触发了view的tap事件.
target指定的时事件触发的源头文件(view内部的元素)currentTarget指定的是页面元素的文件

### 十一. 组件的自定义数据属性

需求: 从weekly页上的电影卡片跳转到电影详情页
新增detail页
wx.navigateTo()
参数化的page path
组件的自定义数据属性: 像逻辑层的业务数据传递

wx.navigateTo() & 保留当前页面,跳转到应用内的某个页面。但是不能跳到 tabbar 页面。使用 wx.navigateBack 可以返回到原页面。小程序中页面栈最多十层。


1
2


f1: function (event) {
this.setData({

}),
console.log(this.data.count),
wx.navigateTo({
  url: '/pages/detail/detail',
})

},

1
2
3
4
5
6
7
url定义页面的地址 "url: '/pages/detail/detail?id=77'  "加一个"?id=77 "来指明跳转到哪一个页面
我们可以通过将每一个页面设置一个id参数来区分页面,然后通过从currentTarget中取出这个元素所对应的id值
首先我们测试一下currentTarget中都包含哪些东西,使用 ` console.log(event.currentTarget)` 来查看.

图像12
![w](https://zzufire.github.io/img/1.12.png 'pia!你死啦')
我们在view中添加设置 数据用户名

观察

1
2
3
4
5
6
图像13
![w](https://zzufire.github.io/img/1.13.png 'pia!你死啦')
以" data- "起始的设置数据参数为事件参数的dataset选项中因此,我们定义一个数据参数 data-movie-id

得到一个数据" movieId: "
因此" data- "这种声明就是用户自定义的数据属性 ,这些自定义的属性就会在事件发生时,被抽取出来,然后封装在事件对象中,传递给对应的事件处理函数来使用.因此在事件处理函数中调用event.


1
2
3
4
5
6
7
8
```
f1: function (event) {
var movieId = event.currentTarget.dataset.movieId;
console.log(movieId),
wx.navigateTo({
url: '/pages/detail/detail?id='+ movieId,
})
},

输出为在console中显示movieId的值也就是对应的页面的id值.

问题: 在此情况下,

,而```view```内部又有一个"```返回本周```"的文本按钮跳转到本周的页面,而此时点击```返回本周```后就直接跳转到了```detail```页面中,这是因为```bindtap``` 的冒泡机制.当点击返回本周按钮后,点击触发```f0```事件,处理后向上传数据,给``````,之后view又触发了f1事件.因此会进入detail页面中.
1
解决方法就是将 "返回本周"中的```bindtap```改成```catchtap```.

onLoad: function (options) {
console.log(options),
this.setData({
mid: options.id,
})
},

1
2
在detail页面的js文件中配置加载页面生命周期函数(每次加载detail页面时就会执行这个函数```onLoad:```)
option中存放的就是在上一个页面触发事件后

url: ‘/pages/detail/detail?id=’+ movieId,

1
2
3
4
5
6
url页面信息的后缀id.

### `十二. 发起请求API`

小程序网络相关API
wx.request 等

$.ajax({

})

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
```      
wx.request({
url: 'https://api.douban.com/a/b.jsp',
method: "GET",
data: {
x: 1, y: 2
},
header: {

},
success: function (res){
console.log(res)
},
fail: function (){

},
complete: function (){

},
})

异步调用,每一次调用后,不阻塞,而是立马返回,返回后执行后面的程序,而只是小程序后台去监听什么时候能收到response.测试一下,在request函数后面加入语句

1
console.log("OK")

结果如图
图像14
w
发现先输出的是OK,之后是 success回调函数中的内容 说明调用request后立马返回,同时后台监听服务器是否响应,此时继续执行下一条语句,等有响应后,执行回调函数.

调用豆瓣电影API

调用详细数据并展示
豆瓣Restful API简介
通过wx:request来调用豆瓣的获取电影条目信息API
403 Forbidden的问题

  • 原因
  • 解决办法
    detail页具体展示
    1
    url: 'https://douban.uieee.com/v2/movie/subject/' + options.id,

因为原豆瓣API接口被禁止,可以使用上述url进行访问,同时要在右上角详情中将不校验合法域名勾选上.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
wx.request({
url: 'http://t.yushu.im/v2/movie/subject/' + options.id,
method: "GET",
header: {
"content-type":"json"
},
success: function (res){
console.log(res)
that.setData({
movie: res.data
})
},
fail: function (){

},
complete: function (){

},
}),
console.log("OK")
},

将在豆瓣上的教父页面数据保存在内部变量movie中

1
2
3
header: {
"content-type":"json"
},

定义这样的文本类型为json,否则会报错.

通过新增变量movie 来对电影详情数据进行绑定显示

显示加载动画

在调用api时request立即返回,紧接着就执行渲染程序,但此时还没有收到服务器发来的相应数据,movie中也是空的,因此detail中调用的movie中的数据都是空白,过一会收到数据后才加载出来.因此中间空余事件放置loading动画.使用wx.showNavigationBarLoading()显示动画,放在request之后, wx.hideNavigationBarLoading()放在回调函数执行中,也就是接收到数据并保存在movie中之后就将加载动画隐藏.

1
2
3
wx.setNavigationBarTitle({
title: res.data.rating.average + '分: '+res.data.title,
})

将页面打印成页面内容的名字和评分.