基于微信小程序wepy中 scroll-view滚动到指定位置(定位到id位置,使用 scroll-into-view)附带三层下拉框例子
·
<scroll-view style="height:500rpx"
scroll-y="true"
scroll-with-animation="true"
scroll-into-view="bottomView{{selectedObj[currentTab.value][1].value}}">
<view wx:if="{{item.label}}"
wx:for="{{ selectedObj[currentTab.value][0].children }}"
wx:for-item="item"
wx:for-index="index"
wx:key="index"
bindtap="handleMenuR"
data-params="{{ item }}"
class="content-category-item {{item.value === selectedObj[currentTab.value][1].value?'active':''}}">
<view id="bottomView{{item.value}}"
wx:if="{{item.value === selectedObj[currentTab.value][1].value}}">
<view> {{item.label || '-'}}</view>
</view>
<view wx:else> {{item.label || '-'}}</view>
</view>
</scroll-view>
重点:scroll-into-view(值应为某子元素id(id不能以数字开头)。设置哪个方向可滚动,则在哪个方向滚动到该元素,如bottomView111)
style="height:500rpx" 高度必须指定,
scroll-y="true" Y轴 scroll-with-animation="true" 动画过渡

下面是三层筛选下拉框,(基于小程序框架wepy)
1,新建文件TreeSelect3.wpy,把下面代码复制到这个文件
<template>
<view class="xx-tree-select">
<view wx:for="{{tabList}}"
wx:for-item="item"
wx:for-index="index"
wx:key="index"
class="xx-select-item"
bind:tap="handleTab"
data-params="{{item}}"
data-index="{{index}}">
<text class="{{currentTabIdx === index ? 'active' : ''}} txt_wid">{{ item.label }}</text>
<image wx:if="{{ currentTabIdx !== index }}"
class="default"
src="https://cdn.ylnhome.com/tuike/triangle.png"></image>
<image wx:else
src="https://cdn.ylnhome.com/tuike/triangle_act.png"></image>
</view>
<!-- 标签选择弹出框 -->
<!-- 注: 这样布局目的是为了避免 `catchtouchmove` 属性影响子元素滚动 -->
<view wx:if="{{ showPopup }}"
class="xx-wrap {{noSearchbar ? 'no-searchbar' : ''}}">
<view class="xx-list-wrap"
bindtap="handleShade"
catchtouchmove="catchTouch"></view>
<view class="tree-select-wrap">
<view class="goods-tree-select">
<view class="tree-select-menu">
<scroll-view style="height:500rpx"
scroll-with-animation="true"
scroll-into-view="bottomView{{selectedObj[currentTab.value][0].value}}"
scroll-y="true">
<view bindtap="handleMenuL"
data-params="{{ {value: null, label: ''} }}"
class="tree-select-menu-item {{!selectedObj[currentTab.value][0].value ? 'active' : ''}}">
<view class="tree-select-menu-item-text">{{setAllName || '全部'}}</view>
</view>
<view wx:if="{{item.label}}"
wx:for="{{ currentTab.children || [] }}"
wx:for-item="item"
wx:for-index="index"
wx:key="index"
bindtap="handleMenuL"
data-params="{{ item }}"
class="tree-select-menu-item {{item.value === selectedObj[currentTab.value][0].value ? 'active' : ''}}">
<view id="bottomView{{item.value}}"
class="tree-select-menu-item"
wx:if="{{item.value === selectedObj[currentTab.value][0].value}}">{{item.label || '-'}}</view>
<view wx:else>{{item.label || '-'}}</view>
</view>
</scroll-view>
</view>
<view wx:if="{{selectedObj[currentTab.value][0].children}}"
class="tree-select-content">
<view class="content-category">
<scroll-view style="height:500rpx"
scroll-y="true"
scroll-with-animation="true"
scroll-into-view="bottomView{{selectedObj[currentTab.value][1].value}}">
<view wx:if="{{item.label}}"
wx:for="{{ selectedObj[currentTab.value][0].children }}"
wx:for-item="item"
wx:for-index="index"
wx:key="index"
bindtap="handleMenuR"
data-params="{{ item }}"
class="content-category-item {{item.value === selectedObj[currentTab.value][1].value?'active':''}}">
<view id="bottomView{{item.value}}"
wx:if="{{item.value === selectedObj[currentTab.value][1].value}}">
<view> {{item.label || '-'}}</view>
</view>
<view wx:else> {{item.label || '-'}}</view>
</view>
</scroll-view>
</view>
</view>
<view wx:if="{{selectedObj[currentTab.value][1].children}}"
class="tree-select-content tree-select-content1">
<view class="content-category">
<scroll-view style="height:500rpx"
scroll-y="true"
scroll-with-animation="true"
scroll-into-view="bottomView{{selectedObj[currentTab.value][2].value}}">
<view class="content-category-item {{ selectedMenu.length < 3 ? 'active' : '' }}"
bindtap="handleMenuR"
data-params="{{ selectedMenu[1] }}">
全部
</view>
<view wx:if="{{item.label}}"
wx:for="{{ selectedObj[currentTab.value][1].children }}"
wx:for-item="item"
wx:for-index="index"
wx:key="index"
bindtap="handleMenuR1"
data-params="{{ item }}"
class="content-category-item {{item.value === selectedObj[currentTab.value][2].value ? 'active' : ''}}">
<view id="bottomView{{item.value}}"
wx:if="{{item.value === selectedObj[currentTab.value][2].value}}"> {{item.label || '-'}}</view>
<view wx:else> {{item.label || '-'}}</view>
</view>
</scroll-view>
</view>
</view>
</view>
</view>
</view>
</view>
</template>
<script>
import wepy from 'wepy';
import axios from '@/utils/http';
import { myLogin } from '@/utils/userLogin.js';
export default class XxTreeSelect3 extends wepy.component {
config = {}
components = {}
watch = {
dataList () {
if (this.isGetData) return;
this.isGetData = true;
this.$apply();
this._getList();
}
}
props = {
noSearchbar: Boolean,
currentObj: Object,
dataList: Array,
chenpin: {
type: Boolean,
default: false
}
}
mixins = []
data = {
isGetData: false,
currentTabIdx: -1,
currentTab: {},
selectedObj: {}, // 每个tabbar当前已选
selectedMenu: [], // 当前已选
tabList: [],
tabListDeep: [],
showPopup: false, // 选择下拉框
}
computed = {
setAllName () {
let name = '';
if (this.currentTab.value === 'sort') {
return '综合排序'
} else {
// 品类
if (this.selectedMenu.length && (this.currentTab.value === 'category')) {
name = '品类';
}
// 系列
if (this.selectedMenu.length && (this.currentTab.value === 'series')) {
name = '系列';
}
// 风格
if (this.selectedMenu.length && (this.currentTab.value === 'style')) {
name = '风格';
}
if (this.selectedMenu.length && (this.currentTab.value === 'sort')) {
name = '排序';
}
return '全部' + name;
}
}
}
methods = {
handleTab (data) {
let params = data.currentTarget.dataset.params;
let paramsIdx = data.currentTarget.dataset.index;
this.currentTab = params;
if (this.currentTabIdx !== paramsIdx) {
// this.currentTab = params;
this.currentTabIdx = paramsIdx;
this.showPopup = true;
} else {
// this.currentTab = {};
this.currentTabIdx = -1;
this.showPopup = false;
}
this.$apply();
this.$emit('handle-tab', params);
},
handleMenuL (data) {
let params = data.currentTarget.dataset.params;
this.selectedMenu = [params];
this.selectedObj[this.currentTab.value] = this.selectedMenu;
this.tabList.map((item, index) => {
if (item.value === this.currentTab.value) {
item.label = params.label || this.tabListDeep[index].label;
}
});
this.$apply();
this.showPopup = false;//点一下回弹
this.currentTabIdx = -1;//点一下回弹
this.$emit('handle-menu', this.selectedObj);
},
handleMenuR (data) {
let params = data.currentTarget.dataset.params;
this.selectedMenu.length = 2;
this.selectedMenu[1] = params;
this.selectedObj[this.currentTab.value] = this.selectedMenu;
this.tabList.map((item, index) => {
if (item.value === this.currentTab.value) {
item.label = params.label || this.tabListDeep[index].label;
}
});
this.$apply();
this.showPopup = false;//点一下回弹
this.currentTabIdx = -1;//点一下回弹
this.$emit('handle-menu', this.selectedObj);
},
handleMenuR1 (data) {
let params = data.currentTarget.dataset.params;
this.selectedMenu[2] = params;
this.selectedObj[this.currentTab.value] = this.selectedMenu;
this.tabList.map((item, index) => {
if (item.value === this.currentTab.value) {
item.label = params.label || this.tabListDeep[index].label;
}
});
this.$apply();
this.showPopup = false;
this.currentTabIdx = -1;//点一下回弹
this.$emit('handle-menu', this.selectedObj);
},
// 点击框遮罩层
handleShade () {
this.showPopup = false;
// this.currentTab = {};
this.currentTabIdx = -1;
this.$apply();
},
// 阻止冒泡
handleContent (evt) {
return;
},
// 阻止滚动穿透
catchTouch () {
return;
},
}
events = {}
/* 生命周期 */
onLoad () {
// this._getList();
}
/* 函数 */
_getList () {
if (!this.dataList) return;
this.tabList = this.dataList;
this.tabListDeep = JSON.parse(JSON.stringify(this.dataList));
if (this.currentObj && JSON.stringify(this.currentObj) !== '{}') {
this.selectedObj = this.currentObj;
this.currentTab.value = Object.keys(this.currentObj)[0];
this.selectedMenu = Object.values(this.currentObj)[0];
this._setList();
setTimeout(() => {
this._setList();
}, 200);
setTimeout(() => {
this._setList();
}, 500);
setTimeout(() => {
this._setList();
}, 1000);
setTimeout(() => {
this._setList();
}, 2000);
}
this.$apply();
}
_setList () {
let tabLabel;
if (this.chenpin) {
// 从爆款商品进默认选择成品家具
this.tabLabel = this.selectedMenu[0].label
this.currentTabIdx = -1;
this.tabList[0].label = '成品家具'
// this.selectedObj[this.currentTab.value] = this.selectedMenu;
} else {
this.tabList.map(item => {
if (item.value === this.currentTab.value) {
// 改变 tab 名称
if (!tabLabel) {
if (this.selectedMenu[1]) {
tabLabel = this.selectedMenu[1].label
}
}
item.label = tabLabel;
// console.log('item', item);
// 设置当前已选路径
if (item.children) {
item.children.map(item1 => {
if (item1.value === this.selectedObj[this.currentTab.value][0].value) {
if (this.selectedMenu.length > 2) {
tabLabel = this.selectedMenu[2].label
item.label = tabLabel;
}
this.selectedObj[this.currentTab.value][0].children = item1.children;
this.$apply();
if (item1.children) {
item1.children.map(item2 => {
if (item2.value === this.selectedObj[this.currentTab.value][1].value) {
this.selectedObj[this.currentTab.value][1].children = item2.children;
this.$apply();
}
})
}
}
})
}
}
if (item.value === Object.keys(this.currentObj)[1]) {
item.label = Object.values(this.currentObj)[1][0].label;
this.$apply();
}
});
}
this.$apply();
}
}
</script>
<style lang="less" scoped>
.xx-tree-select {
display: flex;
align-items: center;
justify-content: center;
width: 100%;
height: 100rpx;
.xx-select-item {
display: flex;
align-items: center;
justify-content: center;
width: 40%;
height: 100%;
text {
display: block;
font-size: 26rpx;
color: #393939;
margin-right: 10rpx;
&.active {
color: #d8b191;
}
}
image {
width: 20rpx;
height: 18rpx;
&.default {
transform: rotate(180deg);
}
}
}
.txt_wid {
max-width: 200rpx;
overflow: hidden;
text-overflow: ellipsis; //超出部分以省略号显示
white-space: nowrap;
}
.xx-wrap {
position: absolute;
top: 190rpx;
width: 100%;
height: 100vh;
z-index: 999;
&.no-searchbar {
top: 100rpx;
}
.xx-list-wrap {
position: absolute;
top: 0;
width: 100%;
height: 100%;
background-color: #00000066;
}
.tree-select-wrap {
position: absolute;
top: 0;
width: 100%;
height: 500rpx;
.goods-tree-select {
display: flex;
height: 100%;
background: #fff;
border-top: 1px solid #f2f2f2;
.tree-select-menu {
width: 100%;
height: 100%;
// border-right: 1px solid #f2f2f2;
overflow-y: auto;
.tree-select-menu-item {
position: relative;
display: flex;
align-items: center;
justify-content: center;
width: 100%;
height: 80rpx;
&.active {
background: #f2f2f2;
font-weight: bold;
&::after {
position: absolute;
content: '';
display: block;
width: 8rpx;
height: 100%;
background-color: #dc143c;
left: 0;
}
}
}
}
.tree-select-content {
width: 100%;
background: #fff;
overflow-y: auto;
border-left: 1px solid #f2f2f2;
.content-category {
box-sizing: border-box;
display: flex;
flex-direction: column;
align-items: center;
width: 100%;
// padding: 20rpx;
.content-category-item {
text-align: center;
width: 100%;
height: 80rpx;
line-height: 80rpx;
background: #fff;
&.active {
background: #f2f2f2;
font-weight: bold;
}
}
}
&.tree-select-content1 {
background-color: #f2f2f2;
.content-category-item {
color: #666;
background-color: #f2f2f2;
&.active {
color: #000;
font-weight: bold;
}
}
}
}
}
}
}
}
</style>
2.使用
如果我在b.wpy页面使用,那么在b.wpy页面引用并使用
import wepy from 'wepy';
import XxTreeSelect3 from '@/components/tree-select/TreeSelect3';
components = {
XxTreeSelect3,
};
data = {
tabList: [
{
label: '品类',
value: 'category'
},
{
label: '系列',
value: 'series'
},
{
label: '风格',
value: 'style'
},
{
label: '综合排序',
value: 'sort'
}
],
chenpin: false,//可不用
selectedTab: {},
}
<template>
<view>
<XxTreeSelect3 :dataList.sync="tabList"
:chenpin.sync="chenpin"
:currentObj.sync="selectedTab"
@handle-menu.user="handleMenu">
</XxTreeSelect3>
<view>
</template>
methods = {
// 选中标签
handleMenu (data) {
this.showLoading = true
this.currentPage = 1;
this.dataList = [];
this.selectedTab = data;
if (this.selectedTab.sort) {
this.sort = this.selectedTab.sort.length > 0 ? this.selectedTab.sort[0].value : 3
if (this.selectedTab.sort.length > 0) {
if (this.selectedTab.sort[0].value) {
this.sort = this.selectedTab.sort[0].value
} else {
this.sort = 3
}
} else {
this.sort = 3
}
}
this.getStoreGoods();
this.$apply();
}
}
tabList数组格式

可以这么组成需要数组格式
methods = { _getGoodsTress (list) { if (!list || !list.length) return []; return list.map(item => { return { label: item.content, value: item.id, children: this._getGoodsTress(item.subCategories) } }) } getGoodsCategory () { axios.get(`/jzx/jzxStoreSupplier/getGoodsCategory`, { params: { storeId } }).then(res => { if (res && res.length) { this.getCategorylist = res this.tabList.map((item, index) => { if (item.value === 'category') { this.tabList[index].children = this._getGoodsTress(res); } }) console.log(this.good_category) var good_category = this.good_category let category = JSON.parse(good_category.category).category; if (good_category.type == 123) { // 是首页icon跳转进来的 var that = this this.getCategorylist.forEach(item => { if (category[0].value == item.id) { that.selectedTab.category[0].value = Number(item.id) that.selectedTab.category[0].children = item.subCategories } }) } // 注意selectedTab.category[0].value只能传Number类型。 console.log(this.selectedTab, ' this.selectedTab2') } this.$apply(); }).catch(err => { console.log(err); }); }) }; // 风格列表 getStyleList () { axios.get(`/article/get-style-tag-list`).then(res => { if (res) { this.tabList.map(item => { if (item.value === 'style') { item.children = res.map(item1 => { return { label: item1.name, value: item1.id } }); } }) } var tabList2 = JSON.stringify(this.tabList) wx.setStorage({ key: "tabList2", data: tabList2 }) this.$apply(); }); }; // 排序列表 getSortList () { // axios.get(`/article/get-style-tag-list`).then(res => { // if (res) { var res = [{ name: '价格升序', id: 2 }, { name: '价格降序', id: 1 }] this.tabList.map(item => { if (item.value === 'sort') { item.children = res.map(item1 => { return { label: item1.name, value: item1.id } }); } }) // } this.$apply(); // }); }; }
更多推荐
所有评论(0)