微信小程序-封装原生垂直滚动菜单(类似外卖商品菜单)
就是根据左侧菜单点击,切换右侧显示的内容,可以上下滚动
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