豆瓣&搜索页面布局&详情评分bug解决

项目视频演示地址


搜索页面样式布局完成

要完成样式

页面样式

  1. search.wxml
1
2
3
4
5
6
7
8
9
<view  class="item-list-group">
<view class="item-group">
<image src="https://img1.doubanio.com/view/photo/s_ratio_poster/public/p2635676317.webp" class="thumbnail"></image>
<view class="info-group">
<view class="title">六人-泰坦尼克上的中国幸存者</view>
<view class="rate-year">8.5分/2020</view>
</view>
</view>
</view>
  1. search.wxss
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
.item-list-group{
padding: 10rpx 20rpx;
}
.item-list-group .item-group{
padding:10rpx 0;
/* 底部分割线 */
border-bottom:1px solid #e4e4e4;
/* 左右分布布局 */
display: flex;
}
.item-group .thumbnail{
width: 80rpx;
height: 100rpx;
margin-right: 20rpx;
}
.item-group .info-group{
flex:1;
display:flex;
flex-direction: column;
justify-content: space-between;
}

.info-group .title{
font-size: 32rpx;
}
.info-group .rate-year{
font-size: 32rpx;
color: #7b7b7b;
}

样式渲染完成,采用flex布局

搜索功能实现

  1. 搜索请求实现

分析:1.在输入框中输入输入文字,那么就应该要获取到输入框中的文字了,但是输入框是单独放在
一个searchbar组件中,我们要获取的话没有那么方便

2.解决:在组件中监听输入框中input事件,将监听到的input输入框中输入的东西及时反馈,然后组件监听得到后再区触发另外一个事件,这样就可以传到外面了。

  1. 代码实现

bindinput事件是只要你在输入框中新增删除文字它都会去执行事件

绑定事件

searchbar.js

方法实现,组件主要复制将信息传递出去,执行在search中,这样职责划分更明确

绑定事件

search.wxml绑定查找事件

1
<searchbar  bindsearchinput="onSearchInputEvent"></searchbar>

serch.js监听事件

绑定事件

此时控制台type类型变为searchinput类型,能够得到用户输入的值

  1. 发送网路请求url

url.js

1
2
3
searchUrl: function (q) {
return "https://m.douban.com/rexxar/api/v2/search?type=movie&q=" + q
}

network.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// 搜索item
getSearch:function(params){
var q =params.q;
var url = globalurls.searchUrl(q);
wx.request({
url: url,
success:function(res){
// console.log(res);
var subjects = res.data.subjects;
if (params.success){
params.success(subjects);
}
}
})
}

search.js

1
2
3
4
5
6
7
8
9
10
11
12
13
onSearchInputEvent:function(event){
var that= this;
// console.log(event)
var value = event.detail.value;
network.getSearch({
q:value,
success:function(subjects){
that.setData({
subjects:subjects
})
}
})
},

因豆瓣Api限制访问,经常请求不到数据

能够搜索

  1. 此时能够拿到数据,我们将数据渲染到页面
1
2
3
4
5
6
7
8
9
10
11
12
13
<searchbar  bindsearchinput="onSearchInputEvent"></searchbar>
<view class="item-list-group">
<view wx:for="{{subjects}}"
class="item-group" wx:key ="{{item.id}}"
<!-- 绑定了一个点击事件,这样点击item可以跳转到详情页面中 -->
bindtap="onItemTapEvent" data-id="{{item.id}}" >
<image src="{{item.pic.normal}}" class="thumbnail"></image>
<view class="info-group">
<view class="title">{{item.title}}</view>
<view class="rate-year"> {{item.rating.value}}{{item.year}}</view>
</view>
</view>
</view>

绑定了一个点击事件,这样点击item可以跳转到详情页面中,同时获取id

1
bindtap="onItemTapEvent"  data-id="{{item.id}}"

search.js

1
2
3
4
5
6
7
8
onItemTapEvent:function(event){
// console.log(event)
var id = event.currentTarget.dataset.id;
// 跳转到某一个页面
wx.navigateTo({
url: '/pages/detail/detail?type=movie&id='+id,
})
}

至此,点击电影也可以跳转到详情页面了

历史搜索记录布局

要完成的样式

search.wxml

1
2
3
4
5
6
7
<view  class="history-list-group">
<view class="history-title">
<view class="title">历史记录</view>
<view class="clear">清除</view>
</view>
<navigator class="history-group">泰坦尼克号</navigator>
</view>

search.wxss

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
.history-list-group{
padding:10rpx 20rpx;
}
.history-list-group .history-title{
display: flex;
justify-content: space-between;
padding: 20rpx 0;
background: #f9f9f9;
font-size: 28rpx;
color: #9e9e9e;
}
.history-list-group .history-group{
font-size: 32rpx;
padding: 20rpx 0;
border-bottom:1px solid #e4e4e4
}

优化:history-group可以将它变为一个navigator组件,因为历史搜索是不需要任何操作的,可以直接从本地读取

历史记录功能实现

由于豆瓣api次数限制控制,搜索有时候请求不到,故这里并未实现

学习思路

详情评分bug解决

所有电影,综艺,电视剧评分均为9.7,因为我们这里写成固定的了

rate

代码修改

1
<stars rate="{{item.rating.value}}"></stars>

问题

评论的评分是能够接收的,同理上面的星星评分也是能设置进来的。

分析:stars.js中代码问题

1
2
3
4
5
  lifetimes:{
attached:function(){
this.updateRate();
}
}

问题原因:attached生命周期函数执行时,rate还没有设置进来,因为rate是通过网络请求加载出来的,需要时间加载进来,所以这时候rate为0默认值。

解决

stars.js

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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
  properties: {
rate:{
type:Number,
value:0,
observer: function(newVal, oldVal,changePath) {
// 属性值变化时执行,newVal就是新设置的数据,old是旧数据
this.updateRate();
}
}
},
methods: {
updateRate:function(){
var that = this;
var rate= that.properties.rate;
var inRate = parseInt(rate);
var light = parseInt(rate/2);
var half = inRate%2;
var gray = 5-light-half;
var lights = [];
var halfs = [];
var grays = [];
// for循环遍历存放到数组中
for(var index=1;index<=light;index++){
lights.push(index);
}
for(var index=1;index<=half;index++){
halfs.push(index);
}
for(var index=1;index<=gray;index++){
grays.push(index);
}
// 评分设置
var ratetext = rate && rate>0?rate.toFixed(1):"未评分"
//数组获取到后 修改 data 中的值
that.setData({
lights:lights,
halfs:halfs,
grays:grays,
ratetext:ratetext,
});
}
},

lifetimes:{
attached:function(){
this.updateRate();
}
}

至此,问题解决了

问题的核心元素是:代码之前执行是放在一个attached中,这个函数是被加载到页面中才会去执行,加载到页面中我们的数据没有从网络中请求到,这时候数据就是默认的0,我们可以用observer函数,一旦监听到改变了评分的值,就可以重新设置一下这个值。

星星加载成功

项目Github地址


本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!