用了wepy组件 , 左右两边 分别是一个组件 (上代码了)
里面的域名是线上域名 用了sass 需要下载,拉走代码 直接出效果
1. 先上左边的组件
<style lang="scss">
page{
height: 100%;
}
::-webkit-scrollbar{
width: 0;
display: none;
}
.scroll_nav{
padding-bottom: 200rpx;
&_wrap{
height: 100%;
background: #fff;
}
&_items{
height: 100rpx;
line-height: 100rpx;
text-align: center;
font-size: 30rpx;
color: #000;
border-bottom: 1px solid #f4f6f8;
&_active{
color: #ca0707;
}
}
}
</style>
<template>
<scroll-view class="scroll_nav_wrap" scroll-y="true" scroll-top="{{navScrollTop}}" scroll-with-animation="true">
<view class="scroll_nav">
<repeat for="{{navDeails}}">
<view class="scroll_nav_items {{item.id == selectedId ? 'scroll_nav_items_active' : ''}}" id="{{item.id}}" data-index="{{index}}" @tap="selectedFn">{{item.name}}</view>
</repeat>
</view>
</scroll-view>
</template>
<script>
import wepy from 'wepy'
export default class ScrollNav extends wepy.component {
props = {
}
data = {
currentIndex: 0
}
props = {
navDeails: {
type: Array,
coerce: (res) => {
return res
}
},
selectedId:{
type: [Number, String],
coerce: (res) => {
return res
}
},
navScrollTop: {
type: [Number, String],
coerce: res => res
}
}
methods = {
selectedFn(e){
this.selectedId = e.currentTarget.id
this.currentIndex = e.currentTarget.dataset.index
this.$emit('change', this.currentIndex, this.selectedId)
}
}
}
</script>
2. 右边的组件
<style lang="scss">
.scroll_view{
&_wrap{
height: 100%;
background: #fff;
position: relative;
}
&_items{
min-height: 120rpx;
&_tit{
height: 58rpx;
view{
font-size: 30rpx;
font-weight: bold;
line-height: 58rpx;
padding-left: 1em;
border-bottom: 1px solid #eee;
}
}
// .tit_position{
// view{
// width: 100%;
// position: absolute;
// left: 0; top: 0;
// }
// }
&_children{
width: 100%;
padding: 34rpx 14rpx;
border-bottom: 1px solid #eee;
box-sizing: border-box;
display: flex;
&_img{
width: 160rpx;
height: 160rpx;
flex-shrink: 0;
background: {
size: cover;
repeat: no-repeat;
position: center center;
}
}
&_context{
margin-left: 16rpx;
font-size: 30rpx;
position: relative;
.name{
font-size: 30rpx;
overflow: hidden;
-webkit-line-clamp: 1;
white-space: normal;
display: -webkit-box;
-webkit-box-orient: vertical;
box-sizing: border-box;
}
.price_wrap{
position: absolute;
bottom: 0; left: 0;
}
}
}
}
}
</style>
<template>
<scroll-view class="scroll_view_wrap" scroll-y="true" scroll-top="{{scrollTop}}" scroll-with-animation="true" @scroll="scrollFn">
<repeat for="{{viewDeails}}">
<view class="scroll_view_items">
<view class="scroll_view_items_tit {{inx[index] == positionIndex ? 'tit_position' : ''}}">
<view>
{{item.name}}
</view>
</view>
<repeat for="{{item.children}}" item="i">
<view class="scroll_view_items_children" data-id="{{i.id}}" @tap="goTo">
<view class="scroll_view_items_children_img" style="background-image: url({{i.thumb}})"></view>
<view class="scroll_view_items_children_context">
<view class="name">{{i.name}}</view>
<view class="price_wrap">
<text class="price">{{i.price}}</text>
</view>
</view>
</view>
</repeat>
</view>
</repeat>
</scroll-view>
</template>
<script>
import wepy from 'wepy'
export default class ScrollView extends wepy.component {
props = {
viewDeails: {},
scrollTop: {
type: [Number, String],
coerce: res => res
},
titleTop: {
type: Array,
coerce: res => res
}
}
data = {
positionIndex: 0,
inx: {}
}
watch = {
viewDeails(newVal){
let index = 0
this.inx = {}
Object.keys(newVal).forEach( (item, index) => {
this.inx[item] = index
})
this.$apply()
}
}
methods = {
scrollFn(e){
let selfTop = e.detail.scrollTop
this.positionIndex = this.getScrollTopIndex(selfTop)
this.$emit('change', this.positionIndex, selfTop)
},
goTo(e){
console.log(e)
const id = e.currentTarget.dataset.id
wepy.navigateTo({
url: `goodsInfo?id=${id}`
})
}
}
getScrollTopIndex(selfTop){
let currentIndex = 0
for(let i = 0, I = this.titleTop.length; i < I; i++){
if(i == I-1){
if(selfTop => this.titleTop[i]){
currentIndex = i
}
}else {
if(selfTop >= this.titleTop[i] && selfTop < this.titleTop[i + 1]){
currentIndex = i
break
}
}
}
return currentIndex
}
onLoad(){
}
}
</script>
3. page页面 来了
<style lang="scss">
page{
background: #f4f6f8;
}
.category_deails{
height: 100%;
display: flex;
&_nav{
width: 180rpx;
height: 100%;
flex-shrink: 0;
border-left: 1px solid #eee;
}
&_view{
flex: 1;
flex-shrink: 1;
height: 100%;
margin-left: 21rpx;
}
}
</style>
<template>
<view class="category_deails">
<view class="category_deails_nav">
<left-nav :navDeails.sync="navDeails" :selectedId.sync="selectedId" :navScrollTop.sync="navScrollTop" @change.user="navChange"></left-nav>
</view>
<view class="category_deails_view">
<view-scroll :viewDeails.sync="viewDeails" :scrollTop.sync="scrollTop" :titleTop.sync="titleTop" @change.user="viewChange"></view-scroll>
</view>
</view>
</template>
<script>
import wepy from 'wepy'
import leftNav from '../components/ScrollNav'
import ScrollView from '../components/ScrollView'
// import retainedDecimalMoney from '../mixins/retainedDecimalMoney'
// import getExtJson from '../mixins/getExtJson'
export default class categoryScrollDetail extends wepy.page {
components = {
'left-nav': leftNav,
'view-scroll': ScrollView
}
data = {
api_host: 'https://www.xiaoniren.cn',
config_id: '634',
navDeails: [
{
idName: 'apply'
}
],
viewDeails: {
// apple: {
// name: '',
// children: [
// ]
// }
},
selectedId: 1,
titleTop: [],
scrollTop: 0,
navId: [],
navTop: [],
navScrollTop: 0
}
getCategoryData(){
return new Promise( (resolve, reject) => {
wepy.request({
url: `${this.api_host}/restapi/goods-category`,
data: {
config_id: this.config_id,
type: 0
},
success: res => {
if(res.data.success){
this.navDeails = res.data.data.items.filter( item => {
return item.level == 1
})
this.$apply()
resolve(this.navDeails)
}
}
})
})
}
getGoodsData(){
wepy.request({
url: `${this.api_host}/restapi/goods`,
data: {
config_id: this.config_id
},
success: res => {
this.navId = []
this.navDeails.forEach( element => {
this.viewDeails['s' + element.id] = {}
this.viewDeails['s' + element.id].name = element.name
this.navId.push(element.id)
this.viewDeails['s' + element.id].children = res.data.data.items.filter( item => {
if(item.category_id == element.id){
if(item.thumb.indexOf('http') == -1){
item.thumb = `${this.api_host}${item.thumb}`
}
// item.price = retainedDecimalMoney(item.price)
return item
}
})
})
this.$apply()
setTimeout(() => {
wx.createSelectorQuery()
.selectAll('.scroll_view_items_tit')
.boundingClientRect()
.exec( res => {
this.titleTop = res[0].map( item => {
return item.top
})
this.$apply()
this.navId.forEach( (item, index) => {
if(item == this.selectedId){
this.scrollTop = this.titleTop[index]
}
})
})
wx.createSelectorQuery()
.selectAll('.scroll_nav_items')
.boundingClientRect()
.exec( res => {
this.navTop = res[0].map( item => {
return item.top
})
this.$apply()
this.navId.forEach( (item, index) => {
if(item == this.selectedId){
wx.createSelectorQuery()
.select('.category_deails_nav')
.fields({
size: true
}).exec( res => {
if(res[0].height / 2 < this.navTop[index]){
this.navScrollTop = (43 * index - res[0].height / 2) + 120
}else{
this.navScrollTop = 0
}
})
}
})
})
}, 300)
}
})
}
methods = {
navChange(index, id){
if(this.scrollTop == this.titleTop[index]){
this.scrollTop = 0.01
return
}
this.scrollTop = this.titleTop[index]
},
viewChange(index, currentScrollTop){
this.selectedId = this.navId[index]
wx.createSelectorQuery()
.select('.category_deails_nav')
.fields({
size: true
}).exec( res => {
if(res[0].height / 2 < this.navTop[index]){
this.navScrollTop = (43 * index - res[0].height / 2) + 120
}else{
this.navScrollTop = 0
}
})
}
}
onLoad(option){
// getExtJson.call(this)
// wepy.showLoading({
// title: '加载中...',
// mask: true
// })
// wepy.setNavigationBarTitle({
// title: option.name
// })
this.getCategoryData().then( res => {
this.getGoodsData()
})
this.selectedId = +option.id
this.$apply()
}
}
</script>