Vue implements left and right menu linkage.
- Vue
- Top: 100 Copyright: true
zhihu
Personal blog
Github
Source portal: Rain120/ VUe-study
According to theThe nuggets commentsRequirements, updated data interface and fixed some issues
I saw the effect of left and right linkage on the food delivery software and found it very interesting, so I tried to realize it by using Vue, and separated the linkage into a separate component. Without further ado, here is an effect picture first.
This component is divided into two parts: 1. Left menu; 2. Right menu.
Dynamic data structure
menus: [
{
name: Menu '1',
data: [
{
name: '1.1'
},
{
name: '1.2'
},
{
name: '1.3'
},
{
name: '1.4'
},
{
name: '1.5'
},
{
name: '1.6'}}]]Copy the code
Data data is user-defined to add some content and render DOM
DOM structure of the left menu
<scroll
class="left-menu"
:data="menus"
ref="leftMenu">
<div class="left-menu-container">
<ul>
<li
class="left-item"
ref="leftItem"
:class="{'current': currentIndex === index}"
@click="selectLeft(index, $event)"
v-for="(menu, index) in menus"
:key="index">
<p class="text">{{menu.name}}</p>
</li>
</ul>
</div>
</scroll>
Copy the code
The DOM structure of the right menu
<scroll
class="right-menu"
:data="menus"
ref="rightMenu"
@scroll="scrollHeight"
:listenScroll="true"
:probeType="3">
<div class="right-menu-container">
<ul>
<li class="right-item" ref="rightItem" v-for="(menu, i) in menus" :key="i">
<div class="title">{{menu.name}}</div>
<ul>
<li v-for="(item, j) in menu.data" :key="j">
<div class="data-wrapper">
<div class="data">{{item.name}}</div>
</div>
</li>
</ul>
</li>
</ul>
</div>
</scroll>
Copy the code
This is for demo purposes, so the data is pure fudge.
Of course, since this is a child component, we are going to pass props through the parent component, so define props
props: {
menus: {
required: true.type: Array,
default () {
return[]}}},Copy the code
In this business scenario, our implementation method is to calculate the position of the left menu according to the scrolling height of the right menu. Of course, the left menu can also be clicked to determine how high the scrolling distance of the right menu needs to be. Then how do we obtain the scrolling distance of the container? We’ve been using better Scroll, and we know from reading the document that it has an Scroll event, and we can listen for that event to get the pos of the scroll
if (this.listenScroll) {
let me = this
this.scroll.on('scroll', (pos) => {
me.$emit('scroll', pos)
})
}
Copy the code
So we listen for the Scroll event on the Scroll component in the right menu
@scroll="scrollHeight"
Copy the code
method
scrollHeight (pos) {
console.log(pos);
this.scrollY = Math.abs(Math.round(pos.y))
},
Copy the code
Let’s type out the POS obtained by monitoring
We can see that the console has the pos information of the current scroll, because in mobile development, the coordinate axis is opposite to our mathematical coordinate axis, so the Y-axis value is negative when sliding up
So we need to get the height of each piece of Li, and we can do that by getting their DOM
_calculateHeight() {
let lis = this.$refs.rightItem;
let height = 0
this.rightHeight.push(height)
Array.prototype.slice.call(lis).forEach(li => {
height += li.clientHeight
this.rightHeight.push(height)
})
console.log(this.rightHeight)
}
Copy the code
We call the height calculation function after creating the hook
_calculateHeight() {
let lis = this.$refs.rightItem;
let height = 0
this.rightHeight.push(height)
Array.prototype.slice.call(lis).forEach(li => {
height += li.clientHeight
this.rightHeight.push(height)
})
console.log(this.rightHeight)
}
Copy the code
When the user is scrolling, we need to calculate the current scrolling distance within that range and get his index
computed: {
currentIndex () {
const { scrollY, rightHeight } = this
const index = rightHeight.findIndex((height, index) => {
return scrollY >= rightHeight[index] && scrollY < rightHeight[index + 1]
})
return index > 0 ? index : 0
}
}
Copy the code
So the current menu item should be the left menu item index = 1 active above is the left menu according to the right menu sliding linkage implementation, users can also click the left menu to realize the right menu linkage, at this time, we add a click event to the menu item
@click="selectLeft(index, $event)"
Copy the code
$event is added here to distinguish between native click events and events distributed by better Scroll
selectLeft (index, event) {
if(! event._constructed) {return
}
let rightItem = this.$refs.rightItem
let el = rightItem[index]
this.$refs.rightMenu.scrollToElement(el, 300)
},
Copy the code
use
<cascad-menu :menus="menus"></cascad-menu>
Copy the code
At this point, we’re pretty much done with these requirements