评论

微信小程序-封装原生垂直滚动菜单(类似外卖商品菜单)

封装一个竖向的滚动菜单,类似外卖程序的菜单

微信小程序-封装原生垂直滚动菜单(类似外卖商品菜单)

 就是根据左侧菜单点击,切换右侧显示的内容,可以上下滚动

colorUI组件库——垂直导航栏 

        这种是通过原生的微信小程序制作的垂直导航栏,如果想要更好看的样式和效果,这里推荐一款小程序UI组件库——colorUI,我这里就放个它的效果演示图,有需要可以去下载它的源码,直接复制就能用了

1.通过微信小程序开发者工具,快速新建组件文件夹

创建一个叫做CategoryRolling的组件,方便调用,你也可以叫其他名字

如何快速创建组件请参考:

https://blog.csdn.net/black_cat7/article/details/120349836

2.组件基础内容的编写

页面内容:CategoryRolling.wxml

<view class="cates_container">
  <!-- 左侧菜单 -->
  <scroll-view scroll-y class="left_menu">
    <!-- wx:key="*this"  表示用自身item来当作key
    当数据类型是比较简单的情况下使用==》 比如循环出的item是 单个字符串或数字  如果item是个很大的对象,就不要用这个了
    -->
    <!-- {{index===currentIndex?'active':''}}  ==》这个index就是for循环中的index
    ==》当跟currentIndex(也就是js中data设置的数据)相同时,表示选中,那就添加一个激活的样式名
    -->
    <view wx:for="{{leftMenuList}}" wx:key="*this" class="menu_item {{index===nowActiveCurrentIndex?'active':''}}"
      bindtap="leftHandleItemTap" data-index="{{index}}">
      {{item}}
    </view>
  </scroll-view>
  <!-- 右侧商品内容 
  scroll-top  ==》设置滚动条的位置,防止切换菜单后滚动条不在顶部
  -->
  <scroll-view scroll-top="{{scrollTopWhere}}" scroll-y class="right_content">
    <view class="goods_group" wx:for="{{rightContent}}" wx:for-index="index" wx:for-item="item">
      <view class="goods_title">
        <text class="delimiter">/</text>
        <text class="title">{{item.cat_name}}</text>
        <text class="delimiter">/</text>
      </view>
    </view>
  </scroll-view>
</view>

wxml页面中这里只是做了个简陋的样子,具体想要展示成什么效果请根据需求进行编写,比如右侧加上展示的图片、可跳转的<navigator>等操作

例如:增加图片显示

 wxss样式文件:CategoryRolling.wxss

/* pages/category/category.wxss */
// 设置整个页面高度
page{
  height: 100%;
}
  .cates_container{
    // ?设置滚动区域的高度==》要减去顶部搜索框组件的高度90rpx ==》底部tab栏目不用减去
    /* less中使用calc的时候要注意    ~'calc( 100vh - 90rpx )'  ==> 能不进行计算,完成地转换到wxss中去
    直接使用calc,会先计算完成,在生成wxss文件
    height: calc( 100vh - 90rpx )===>会先计算==>变成 100vh-90=10vh ==>再转到wxss里,得到 height:10vh;
    */
    // !height: ~'calc( 100vh - 90rpx )';
    // !注意:当顶部有东西占了一定高度后,就要减去高出的部分,否则会挤出去一定的高度导致需要二次滚动才能看见全部内容
    // height:calc( 100vh - 90rpx );
    height: 100vh;
    display: flex;
    .left_menu{
      /* 子项 高度 100% flex */
      // 占据整个宽度的2份 2 / 5+2
      flex: 2;
      // 左侧菜单的样式
      .menu_item{
        height: 80rpx;
        display: flex;
        justify-content: center;
        align-items: center;
        font-size: 30rpx;
      }
      // 左侧菜单选中时的样式
      .active{
        // 设置文字样式为全局设置的红色变量
        color: #eb4450;
        // 设置选中时左侧出现边框
        // currentColor ===》 代表了当前元素应用的color颜色值 ==》也就是设置的红色
        border-left: 5rpx solid currentColor;
      }
    }
    // 右侧内容数据
    .right_content{
       /* 子项 高度 100% flex */
      // 占据整个宽度的5份 5 / 5+2
      flex: 5;
      .goods_group{
        // 商品大标题
        .goods_title{
          height: 80rpx;
          display: flex;
          justify-content: center;
          align-items: center;
          // 文字分隔符
          .delimiter{
            color: #ccc;
            padding: 0 10rpx;
          }
          .title{}
        }
       
      }
    }
  }

样式文件我使用的是less格式,如何使用less插件、快速编写样式,请查看以下博客:

https://blog.csdn.net/black_cat7/article/details/120288835

https://blog.csdn.net/black_cat7/article/details/120450524

3. js操作:CategoryRolling.js

// components/CategoryRolling/CategoryRolling.js
Component({
  /**
   * 组件的属性列表
   */
  properties: {
    // 左侧菜单数据
    leftMenuList: {
      // 类型
      type: Array,
      // 默认值
      value: []
    },
    // 右侧菜单数据(包含所有的右侧待展示数据)
    //!想要在方法中使用传入的参数,需要用【 this.data.rightMenuList】 来调用获取,但是不用在data中再声明一次
    rightMenuList: {
      type: Array,
      value: []
    }
  },
  /**
   * 监听传入的参数的变化,每次传入的数据变化变化,都会触发一次
   * ?注意:监听有点延时,所以第一下监听到的数据可能【为空】,然后拿到数据后再次触发就正常了
   *  */
  observers: {
    'rightMenuList': function (val) {
      // val=》就是父组件传入组件中的rightMenuList数据
      console.log(val);
      //!监听传入的右侧菜单数据,赋值给右侧数据变量,用于默认展示页面第一次打开时加载的右侧数据
      this.setData({
        // TODO:不同数据源,就要改一下这里的格式,比如叫childrens
        rightContent: val[0].children
      })
      // console.log(this.data.rightContent);
    }
  },
  /**
   * 组件的初始数据
   */
  data: {
    // 默认 当前选中的index,用于判断是否添加激活的样式名
    nowActiveCurrentIndex: 0,
    // 默认 右侧内容的滚动条距离顶部的距离
    scrollTopWhere: 0,
    // 右侧的商品数据,当前选择的左侧菜单对应的右侧数据
    rightContent: [],
  },
 
  /**
   * 组件的方法列表
   */
  methods: {
    // 左侧菜单的点击事件
    leftHandleItemTap (e) {
      /* 
      1 获取被点击的标题身上的索引
      2 给data中的nowActiveCurrentIndex赋值就可以了
      3 根据不同的索引来渲染右侧的商品内容
       */
      const { index } = e.currentTarget.dataset;
      console.log('当前点击的元素在数组的位置==》', index);
      // 设置右侧的商品数据,根据设置数组中不同位置的数据 this.rightMenuList[index] 就能有不同的数据了
      // TODO:不同数据源,就要改一下这里的格式,比如叫childrens
      let rightContent = this.data.rightMenuList[index].children;
      // 点击左侧菜单后,现在右侧对应要展示的数据
      // console.log(rightContent);
      this.setData({
        // 设置data中选中项index为传进来的index,用于wxml页面匹配并对应添加active样式
        nowActiveCurrentIndex: index,
        // 重新设置data中商品的数据,以展示不同的右侧商品内容
        rightContent,
        // 重新设置 右侧内容的scroll-view标签的距离顶部的距离
        scrollTopWhere: 0,
      });
    },
  }
})

其中TODO注释的两处是需要根据你的数据格式来调整以下的,不然wxml页面中没有数据可以渲染

4.父页面中使用封装好的CategoryRolling组件

 然后,在父页面中使用封装好的组件

<!--父页面-->
......
  <!-- 引用封装好的组件 -->
  <CategoryRolling leftMenuList="{{leftMenuList}}" rightMenuList="{{rightContent}}"></CategoryRolling>
......

注意:要传入父页面通过接口获取到的数据给封装好的组件

到此,就能得到开头的那种效果了,如果需要进一步封装,可以增加一些功能。 

 参考:黑马微信小程序教程:https://www.bilibili.com/video/BV1nE41117BQ?p=3


最后一次编辑于  2023-10-19  
点赞 1
收藏
评论
登录 后发表内容