初学前端在小程序中使用for循环的一个优化案例

5,958 阅读6分钟

前言

作为前端的小白,已经学习了个把月了,for循环在微信小程序中的使用在常见不过了;在获取某个官方API数据后,如何将获取的若干条数据分别不重复的放入到不同的循环当中呢?让我们看个小小的例子去体会一波。

原界面分析

界面分析

首先我们来看一下网易云音乐其中的一个界面:

这个界面其实相对来讲时比较好做的,主要就是分为两大块内容,先说中间这块-->官方榜单:左边对应的时榜单的图片,右边则是这个榜单内的歌曲,然后每行的样式都是一样的,使用for循环遍历去做会特别简便。 然后我们再看其他的一些榜单区的内容:都是一行分布3个为上方图片加下方文字的样式,这个也可以用到循环来实现。

数据分析

这里分享一下API链接:http://neteasecloudmusicapi.zhaoboy.com/toplist/detail(如何调用API想必大家也会使用,或者也从其他的大佬的文章中学习过)

然后我们来看到获取到的数据并进行分析: 从第一张图片我们可以知道list下获取到若干条信息,每条信息中的updateFrequency对应该榜单更新时间,coverImgUrl对应该榜单的图片,还有一项是tracks也是我们需要用到(看下张图) 可以看到tracks中包含的信息就是歌单了,也就是我们官方榜单中需要用到的数据 从第三章图可以看到,从编号为4开始tracks中的信息就为空了,也就是刚才给大家展示的原界面中只有官方 榜单需要这项信息,其他的榜单是不需要的。所以循环出的若干条数据中,我们需要将前4条放进官方榜单,而后面其他的数据放进其他的榜单当中,for循环下我们会将所有拿到的数据都循环出来,并且样式还是一样的。而这个界面则是在同一数据下,分别用循环放到两个不同的样式当中,大家肯定都想得到,加个if判断就好了,接下来,让我们看看如何实现。

代码实现

wxml

<view class="body-view">
	<loading hidden="{{hidden}}">
		加载中...
	</loading>
</view>
<view class="wrapper">
	<!-- 上部分:榜单推荐容器 -->
	<view class="ranking">
		<text class="ranking-name">榜单推荐</text>
		<view class="rankingbox">
			<view  class="rankinglist" wx:for="{{rank}}"  wx:key="index">
				<image class="ranking-img" src="{{item.img}}" />
				<view class="updatetime">{{item.date}}</view>
				<view class="rankinglist-name">{{item.listname}}</view>
			</view>
		</view>
	</view>
	<!-- 中间部分:官方榜容器 -->
	<view class="officiallist">
		<text class="ranking-name">官方榜</text>
		<view class="officiallistbox">
			<view class="official-list"  wx:for="{{list}}"  wx:key="index">
				<view wx:if="{{index <= 3}}">
					<image class="ranking-img" src="{{item.coverImgUrl}}" />
					<view class="updatetime">{{item.updateFrequency}}</view>
					<view class="ranking-des">
						<block wx:for="{{item.tracks}}" wx:key="index">
							<view class="songlist">
								<text class="songname">{{index+1}}.</text>
								<text class="songname">{{item.first}}</text>
								-
								<text class="songname">{{item.second}}</text>
							</view>
						</block>
					</view>
				</view>
			</view>
		</view>
	</view>
	<!-- 下部分:其他所有榜单容器循环 -->
	<view class="otherranking">
		<text class="otherranking-name">更多榜单</text>
		<view class="otherrankingbox">
			<block  class="otherrankinglist"  wx:for="{{list}}"  wx:key="index">
				<view class="other" wx:if="{{index > 3}}">
					<image class="ranking-img" src="{{item.coverImgUrl}}" />
					<view class="updatetime">{{item.updateFrequency}}</view>
					<view class="rankinglist-name">{{item.name}}</view>
				</view>
			</block>
		</view>
	</view>
</view>

wxss

/* 上部分:榜单推荐容器 */
.wrapper {
    width: 100%;
    height: 100%;
}
.ranking {
    margin: 60rpx 0 0 40rpx;
}
.rankingbox {
    display: flex;
    flex-wrap: wrap;
}
.rankinglist {
    margin: 30rpx 30rpx  30rpx 0rpx;
}
.ranking-name {
    font-size: 35rpx;
    font-weight: 550;
}
.ranking-img {
    width: 204rpx;
    height: 204rpx;
    border-radius: 10rpx;
}
.updatetime {
    position: absolute;
    margin-top: -45rpx;
    margin-left: 15rpx;
    font-size: 18rpx;
    color: rgb(241, 241, 241);
}
.rankinglist-name {
    font-size: 20rpx;
    max-width: 180rpx;
    overflow: hidden;
    text-overflow: ellipsis;
}
.ranking-des {
    width: 530rpx;
    height: 150rpx;
    margin: 0rpx 20rpx 0 20rpx;
    float: right;
    position: absolute;
    margin-top: -200rpx;
    margin-left: 210rpx;
    display: flex;
    flex-direction: column;
    justify-content: space-around;
    flex: 1 1 0%;
    padding: 10px;
}
/*上部分榜单推荐和下部分其他所有榜单所用css一样*/
/*中间官方榜单部分的榜单名,图片和上部分一样*/
/* 中间部分:官方榜容器 */
.officiallist {
    margin: 60rpx 0 0rpx 40rpx;
}
.officiallistbox {
    margin: 30rpx 0 20rpx 0rpx;
}
.official-list {
    margin: 0rpx 0 15rpx 0rpx;
}
.songlist {
    max-width: 450rpx;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.songname {
    font-size: 25rpx;
}
.otherranking {
    margin: 60rpx 0 0rpx 0rpx;
}
.otherrankingbox {
    display: flex;
    flex-wrap: wrap;
    justify-content: space-between;
    padding: 10rpx 40rpx;
    margin: 30rpx 0 0rpx 0rpx;
}
.otherranking-name {
    margin-left: 40rpx;
    font-size: 35rpx;
    font-weight: 550;
}
.other {
    margin-bottom: 20rpx;
}

js部分

// const API = require('../../toplist/detail')
 const app = getApp();
Page({
  data: {
    hidden: false,  //加载是否隐藏
    list: [],
    rank: [
      {
        img: 'https://p2.music.126.net/c0iThrYPpnFVgFvU6JCVXQ==/109951164091703579.jpg',
        date: '每周四更新',
        listname: '云音乐欧美热歌榜',
      },
      {
        img: 'https://p2.music.126.net/WTpbsVfxeB6qDs_3_rnQtg==/109951163601178881.jpg',
        date: '每周一更新',
        listname: 'iTunes榜',
      },
      {
        img: 'https://p2.music.126.net/Zb8AL5xdl9-_7WIyAhRLbw==/109951164091690485.jpg',
        date: '每天更新',
        listname: '云音乐欧美新歌榜',
      }
    ]
  },
  /**
   * 生命周期函数--监听页面加载
   */
  onLoad: function (options) {
    wx.request({
      url:'http://neteasecloudmusicapi.zhaoboy.com/toplist/detail',
      data: {
      },
      header: {  // 加载效果
        "Content-Type": "application/json"
      },
      success: (res) => {
        console.log(res)
        this.setData({
          list: res.data.list
        })
        if(this.data.list.length>0){
          this.setData({
            hidden: true
          })
        }
      }
    })
  },
})

实现效果 分享

大家看到代码中,我们是通过 wx:if 去判断 index <= 3 时数据放在officiallist这个官方榜单中,而 index > 3 时,则放在otherranking这个其他榜单中,这样写确实也没错,也实现了功能,但是逻辑不严谨,官方数据发生变化时,又得修改代码去改变if判断的值,变化一次就得改变一次(这里说的变化是:当API数据中改变成第六或者第几条数据开始tracks中才为空,那么原来index > 3 就起不到作用,又得手动去修改这个定值)。而且这样的if判断还有一些问题,剩下没取到的数据会以空数据输出,会占用一定的位置,则又需要对css进行修改,使布局不被影响,增加了一定的麻烦。(可以具体看看调试中的显示:下图)

优化方法

简述

其实我们可以在js中进行判断,API中是只有前几条数据中的tracks中是有歌单的数据的,后面其他的数据中的tracks是空的,所以我们只需要从tracks中取下手就可以。去判断tracks何时是有数据则放在官方榜单,当tracks中为空,则将这些数据放在其他榜单中。下面我们先看具体代码(这里我们把修改部分的代码放出来)

wxml

<!-- 官方榜 -->
<view class="official-list" wx:for="{{officialList}}" wx:key="index">
        <view>
            <image class="ranking-img" src="{{item.coverImgUrl}}" />
            <view class="updatetime">{{item.updateFrequency}}</view>
            <view class="ranking-des">
                <block wx:for="{{item.tracks}}" wx:key="index">
                  //这里放的还是之前的代码,block中循环的是tracks中的歌单数据,和之前的一样不用修改
                </block>
            </view>
        </view>
    </view>
<!-- 其他榜单 -->
<block class="otherrankinglist" wx:for="{{moreList}}" wx:key="index">
    <view class="other">
        <image class="ranking-img" src="{{item.coverImgUrl}}" />
        <view class="updatetime">{{item.updateFrequency}}</view>
        <view class="rankinglist-name">{{item.name}}</view>
    </view>
</block>

js:

// 在data 中新增加两个新的空数组
  data: {
    officialList: [], //新增加
    moreList: [],  //新增加
    list: [],
    rank: [
		//这里还放之前的数据
    ],
  },
  onLoad: function (options) {
    wx.request({
     //这里还是放之前的API调用
      },
      // 重点:在回调函数中判断tracks中是否有数据并放入定义的数组中
      success: (res) => {
        const oList = res.data.list.filter(item => item.tracks.length
        )
        console.log(oList)
        const mList =  res.data.list.filter( item => !item.tracks.length
        )
        this.setData({
        // 经过判断拿到数据后,分别对应放入之前的定义的官方榜单和其他榜单的数组中
          officialList:oList,
          moreList:mList,
          list: res.data.list
        })
      }
    })
  },
})

分析

修改后将 wx:if 的语句判断去掉了,在js中的data里面我们定义了两个新的空数组,officialList: []moreList: [] 在调取API数据成功后,我们定义了一个 oListmList,并判断tracks中是否有数据,有则放在oList,没有则放在mList;最后分别将oListmList 中的数据传给数组 officialListmoreList,去达到我们之前所想要的效果。我们最后去调试可以发现,不会再有多循环出来的空数组,并且数据会根据官方API数据的更新自动区别改变,请看图

总结

这里我们通过一个界面的例子,从分析到优化,虽然只是优化其中的一个逻辑,但带来的代码效果还是很显著的。作为小白的我们,从切图开始,做假数据先把界面做出来,然后去调用真数据引入。实现一个功能的办法有很多,更强的逻辑思维,和严谨的代码风格也更应该是我们追求的,也是我们小白需要慢慢改进的地方,总体来说就是去让自己做的更好。感谢各位大佬的观赏,如果有不足的地方或者有更好的想法和建议也欢迎指出哦!