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,loadingfortrue, indicating that an asynchronous request is being sent and will not be triggered againloadThe event
    • When the load is complete,finishedfortrue, will not trigger againloadThe event
  • After each request is complete, manually set loading to false to indicate that loading is complete