当前位置:   article > 正文

微信小程序开发——wx:for循环渲染元素如何修改点击样式_小程序 查找 某个元素 并修改

小程序 查找 某个元素 并修改

我们在做微信小程序的时候,往往需要做导航栏,效果是:点击导航栏的子元素,显示对应的Tab页,并且要修改点击的子元素样式用来提示用户当前位置。效果是这样:


底部导航不用说,直接在app.json中定义跳转地址和选中样式即可。关键是自定义导航,需要我们自己定义。

相信看过小程序API的人都知道导航栏怎么写:在wxml中列出每个导航栏,指定每个导航栏的url和点击样式就可以了。不清楚的童鞋可以查看API:微信小程序导航栏API

就像这样:

  1. <!-- sample.wxml -->
  2. <view class="btn-area">
  3. <navigator url="/page/navigate/navigate?title=navigate" hover-class="navigator-hover">跳转到新页面</navigator>
  4. <navigator url="../../redirect/redirect/redirect?title=redirect" open-type="redirect" hover-class="other-navigator-hover">在当前页打开</navigator>
  5. <navigator url="/page/index/index" open-type="switchTab" hover-class="other-navigator-hover">切换 Tab</navigator>
  6. </view>

但是这种做法只能算入门级,因为前台wxml视图文件没有和后台数据分离,导致导航栏不是动态加载(根据请求的JSON数据渲染导航栏)。这样的话,如果我们要修改导航栏,就只能修改wxml文件,不易维护。

好的做法是动态请求JSON数据,循环渲染出整个导航栏。如果需要修改导航栏,通过后台修改数据库中导航栏的数据即可,后台返回JSON数据给展示页面,展示页面调用this.setData({})方法即可绘制出新的导航栏。

JSON数据存储了导航栏各个子元素信息,其中goodsName对应上图的名称,goodsId用于标识每个元素,goodsClass用来定义图片路径,如下:

  1. [{
  2. "goodsName":"油烟机",
  3. "goodsId":"1",
  4. "goodsClass":"yanji"
  5. },{
  6. "goodsName":"热水器",
  7. "goodsId":"2",
  8. "goodsClass":"reshuiqi"
  9. },{
  10. "goodsName":"灶具",
  11. "goodsId":"3",
  12. "goodsClass":"zao"
  13. },{
  14. "goodsName":"浴室柜",
  15. "goodsId":"4",
  16. "goodsClass":"yushigui"
  17. },{
  18. "goodsName":"花洒",
  19. "goodsId":"5",
  20. "goodsClass":"huasa"
  21. },{
  22. "goodsName":"马桶",
  23. "goodsId":"6",
  24. "goodsClass":"matong"
  25. }]


wxml页面这样写即可循环渲染每一个导航栏,其中用到了wx:for="{{navList}}"来遍历页面data数据中的navList值,而这个navList就是我们请求的JSON。wx:for内层结构中的{{item.goodsId}}对应每个导航栏子元素的goodsId属性值,其他如{{item.goodsName}}以此类推。到这儿,你的页面应该能够渲染出整个导航栏了,但是还没有点击修改样式的功能。

  1. <view class="container clearfloat">
  2. <view class="leftNav">
  3. <block wx:for="{{navList}}" wx:key="goodsId">
  4. <view style="color:{{item.goodsId==currentItemId?'#e98f36':'#000'}}" data-num="{{item.goodsId}}" class="goodsTitle" bindtap="clickTap">
  5. <image src="/images/{{item.goodsClass}}{{item.goodsId==currentItemId?2:1}}.png"></image>
  6. <!--<image src="{{item.goodsImg}}"></image>-->
  7. <span>{{item.goodsName}}</span>
  8. </view>
  9. </block>
  10. </view>
  11. </view>

如果这些你读起来困惑,别急,之前的内容了解一下就好,再不行去看看小程序API中的wx:for你就能够做到。接下来给每个循环的子元素增加点击样式才是本文重点,看完下面的操作以后,相信你能够豁然开朗。

我们可以给每个子元素添加点击事件:上面代码中的bindtap="clickTap"就是给每个元素添加点击事件,这个点击事件处理函数在js文件中定义。下面我直接贴出这个页面的完整js文件:

  1. Page({
  2. data: {
  3. currentItemId:"1"
  4. },
  5. onLoad: function (options) {
  6. // 页面初始化 options为页面跳转所带来的参数
  7. var that = this //这一句不可少,能够调用Page对象的setData({})方法
  8. wx.request({
  9. url: 'https://www.****(你请求的域名).com/json/navList.json', //小程序要求请求的协议必须是https,所以你的服务器后台网站必须https化,而且TLS版本在1.2 以上,过程不难,后续我会写一篇如何部署服务器以及https化和TLS升级的博文
  10. header: {
  11. 'content-type': 'application/json'
  12. },
  13. success: function (res) {
  14. that.setData({
  15. navList: res.data
  16. })
  17. }
  18. })
  19. },
  20. clickTap:function(e){
  21. this.setData({
  22. currentItemId:e.currentTarget.dataset.num
  23. })
  24. },
  25. onReady: function () {
  26. // 页面渲染完成
  27. },
  28. onShow: function () {
  29. // 页面显示
  30. },
  31. onHide: function () {
  32. // 页面隐藏
  33. },
  34. onUnload: function () {
  35. // 页面关闭
  36. }
  37. })

可以看到clickTap函数的定义。参数e可以用来获取当前点击的子元素信息,e.currentTarget.dataset.num即获取了wxml中当前被点击元素的data-num="{{item.goodsId}}",这样就获取到了被点击元素的goodsId。然后通过this.setData({})方法设置页面data数据中的currentItemId为这个值(默认值为”1”,让第一个子元素是选中的样式)。最后我们在wxml页面中通过{{currentItemId}}获取这个值,用来修改对应子元素的样式。

wxml页面通过三目运算,判断每一个子元素的样式是否需要修改

style="color:{{item.goodsId==currentItemId?'#e98f36':'#000'}}" 这一句通过运算,判断每个子元素是否需要修改,如果它的goodsId等于被点击的元素的id(即currentItemId),就让颜色是#e98f36,否则就是黑色。

<image src="images/{{item.goodsClass}}{{item.goodsId==currentItemId?2:1}}.png"></image>这一句更绝,通过判断每个子元素是不是当前被点击的,直接修改图片的路径来显示不同的图片,达到已点击的样式效果。


这里贴出样式文件wxss,需要看效果的童鞋,复制对应的代码到对应的小程序文件中就行。

  1. .leftNav {
  2. float: left;
  3. width: 160rpx;
  4. }
  5. .goodsList {
  6. float: right;
  7. }
  8. .goodsTitle {
  9. min-width: 120rpx;
  10. text-align: center;
  11. line-height: 40rpx;
  12. float: left;
  13. font-size: 30rpx;
  14. padding: 20rpx 20rpx;
  15. background-color: #fafafa;
  16. border-bottom: 2rpx solid lightgray;
  17. border-right: 2rpx solid lightgray;
  18. }
  19. .goodsTitle>image {
  20. width: 64rpx;
  21. height: 64rpx;
  22. }
  23. .goodsTitle>span{
  24. display: block;
  25. }
  26. .goodsTitle>first-child{
  27. border-top: 2rpx solid lightgray;
  28. }
  29. .goodsImgView{
  30. margin: 0 auto 10rpx;
  31. width: 64rpx;
  32. height: 64rpx;
  33. background-repeat: no-repeat;
  34. }

总结:

实现的逻辑有点绕:首先通过JSON数据循环渲染导航栏,然后给每个导航栏一个统一的点击事件函数clickTap,通过这个函数修改当前页面的全局数据currentItemId为被点击元素的goodsId,最后在视图文件中判断当前元素的goodsId是否等于这个值来修改被点击元素的样式。

不得不这样做的根本原因:小程序不能像javascript或者jquery一样获取DOM元素或JQ对象来修改样式,而是通过setData({})方法刷新全局数据,然后回调渲染方法来重绘DOM(懂ReactJS的童鞋应该很熟悉)。全局数据是修改样式的唯一依据,它由点击事件函数修改,但是不像静态wxml每个导航元素都可以定义一个点击事件函数,通过循环遍历的元素只能是调用同一个事件函数(我们定义的clickTap)修改全局数据,所以我们需要获取每个元素的唯一标识(我们定义在JSON中的goodsId)来修改全局数据,最后每个元素根据这个全局数据来修改样式。

-over-


声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/笔触狂放9/article/detail/94286
推荐阅读
相关标签
  

闽ICP备14008679号