I. Basic structure
Use the Tabs component in views/home/index to place the list of channels
<! -- Channel Listhttps://vant-contrib.gitee.io/vant/#/zh-CN/tab#biao-qian-lan-gun-dong
-->
<template>
<div>
<van-tabs v-model="active">
<van-tab title="TAB 1">The content of 1</van-tab>
<van-tab title="Label 2">Content of the 2</van-tab>
<van-tab title="Label 3">The content of 3</van-tab>
<van-tab title="TAB 4">The content of 4</van-tab>
<van-tab title="Tag 5">The content of 5</van-tab>
<van-tab title="TAB 6">Content of 6</van-tab>
<van-tab title="TAB 7">Content of 7</van-tab>
<van-tab title="Tag 8">The content of 8</van-tab>
</van-tabs>
<! --1. tab -->
<! --2. list -->
</div>
</template>
<script>
export default {
name: 'Index',
data () {
return {
active: 1}}}</script>
Copy the code
The content should be placed in the corresponding Van-Tab slot
Get the channel and display it
Send a request to get channel list data
1. The encapsulation API
There are many related operations involving channels, and a module is encapsulated to deal with them uniformly
Create a new file SRC/API /channel.js
// Handle channel-related operations
import request from '@/utils/request'
/** * get channel list *@returns* /
export const getChannels = () = > {
return request({
url: 'v1_0/user/channels'.method: 'GET'})}Copy the code
This version of the interface allows no tokens to be passed in
2. Call the API to obtain data
In the views/home/home. In the vue:
- The import interface
- Call the interface to save the obtained data
- Data rendering
Import interface function
import { getChannels } from ‘@/api/channel.js’
Using interface functions
<script>
import { getChannels } from '@/api/channel.js'
export default {
data () {
return {
active: 2.// subscript of the selected item in tabs
channels: [] // Channel list
}
},
created () {
this.loadChannels()
},
methods: {
async loadChannels () {
try {
const res = await getChannels()
console.log(res)
this.channels = res.data.data.channels
} catch (err) {
console.log(err)
}
}
}
}
</script>
Copy the code
3. Render the view
Render through a V-for loop based on the value in channels
<van-tabs>
<van-tab
v-for="channel in channels"
:title="channel.name"
:key="channel.id">{{channel.name}}</van-tab>
</van-tabs>
Copy the code
4. Check the effect
Iii. Style of Channel Content (CV)
Adding a parent container with a fixed height and Overflow: Auto for channel content will automatically make the scrollbar appear only in the content area when there is too much content
Using layout techniques, the container automatically gets a fixed height value based on the screen size
<van-tabs>
<van-tab v-for="channel in channels" :title="channel.name" :key="channel.id">
<div style="height:300px; overflow:auto; border:1px solid red; {{channel.name}} idx in 20" :key="idx">The {{idx}} article</p>
</div>
</van-tab>
</van-tabs>
Copy the code
Van-nav-bar fixed position
<! -- Top logo search navigation area --><van-nav-bar
fixed
>Omit others....</van-nav-bar>
Copy the code
Add necessary classes
-
The root element id of app.vue is app
-
Add the Container class to the layout.vue root element
-
Add the index class to the root element of home.vue
-
The scroll wrapper is added to the channel content container
Overrides vant library styles with global styles in styles/index.less
Add a fixed-height overflow: Auto parent for channel content so that it automatically generates a vertical scroll bar when there is too much content
This global style is introduced in main.js
// Introduce global styles
import './styles/index.less'
Copy the code
Add a container to the outer layer of the channel content in home.vue and set class = scroll-wrapper
<div class="index">
<van-tabs v-model="active">
<van-tab
v-for="channel in channels"
:key="channel.id"
:title="channel.name"
>
<div class="scroll-wrapper">Content {{channel. The name}}<p
v-for="n in 20"
:key="n"
>{{n}}</p>
</div>
</van-tab>
</van-tabs>
</div>
Copy the code
But less styles:
/** Top navigation bar **/
.van-nav-bar__content {
background-color:#3196fa;
.van-nav-bar__title{
color: #fff; }}/** The outermost container fills the entire screen **/
#app{
position: absolute;
left: 0;
top: 0;
overflow: hidden;
width: 100%;
height: 100%;
}
/**. Container is the class name of the root element of the layout. vue component
.container {
width: 100%;
height: 100%;
}
/**. Index is the class name of the root element of the home/home.vue component **/
.index {
height: 100%;
// The top is fixed in the navigation bar, give the top of the navigation bar distance
padding-top: 46px;
.van-tabs {
padding-top:50px;
display: flex;
flex-direction: column;
height: 100%;
.van-tabs__wrap {
position:fixed;
top:46px;
/** follows below the top fixed navigation bar **/
left:0px;
right:30px;
/** Highlight the currently selected channel **/
.van-tabs__line {
width: 30px ! important; background-color: #3296fa; bottom: 20px; } } .van-tabs__content {flex:1;
overflow: hidden;
padding-bottom: 4rem; /** Can see the loading effect in the article list **/
.van-tab__pane{
height: 100%;
/**.scroll-wrapper is the class name of the root element of the home/ articlelist. vue component **/
.scroll-wrapper{
overflow:auto;
height: 100%;
}
}
}
}
}
Copy the code
Van – the list of componentsData loading mechanism:
-
If the current content is not enough for a screen, it will automatically call the callback function of the onLoad event to load the data and fill it in.
-
List has the following three states:
-
If loading is not in process, the loading is false. In this case, the loading event will be triggered according to the scrolling position of the list (if the list content is less than one screen, the load event will be triggered directly).
- Loading,
loading
fortrue
, indicating that an asynchronous request is being sent and will not be triggered againload
The event - When the load is complete,
finished
fortrue
, will not trigger againload
The event
- Loading,
-
After each request is complete, manually set loading to false to indicate that loading is complete