van-tab van-pull-refresh下拉加载(网上抄

2022-06-24  本文已影响0人  糖醋里脊120625
image.png

watch
const emit = defineEmits(['changeLabel'])
const labelList = store.getters['label/labelList']

主要van-tabs.vue



<template>
  <div class="app-container">
    <form action="/">
      <van-search
        v-model="keyword"
        input-align="center"
        :clearable="false"
        :show-action="!!keyword"
        placeholder="请输入搜索关键词"
        @search="() => (params.keyword = keyword)"
        @cancel="() => (params.keyword = '')"
      />
    </form>
    <LabelSelect
      @changeLabel="(val) => (params.type = val)"
      ref="label"
    ></LabelSelect>
    <van-tabs
      v-model:active="params.sortBy"
      color="#009688"
      title-active-color="#009688"
      title-inactive-color="#595959"
      line-width="24px"
      line-height="2px"
    >
      <van-tab title="全部" name=""></van-tab>
      <van-tab title="推荐" name="level"></van-tab>
      <van-tab title="最新" name="releaseTime"></van-tab>
      <van-tab title="最热" name="pv"></van-tab>
      <van-tab title="最赞" name="likes"></van-tab>

      <List :showTitle="false" :params="params"></List>
    </van-tabs>
  </div>
</template>

<script setup lang="ts">
import LabelSelect from './components/labelSelect.vue'
import List from '@/views/home/components/list.vue'
import { reactive, ref } from 'vue'
import SvgIcon from '@/components/svgIcon'

let params = reactive({
  keyword: '',
  sortBy: '',
  type: '',
  isMobile: true,
})
let keyword = ref('')
</script>

主要LabelSelect.vue

<template>
  <div class="label-box">
    <div
      class="label-text"
      :class="{ 'label-text__active': activeIndex === index && labelName }"
      :style="{
        backgroundColor:
          activeIndex === index && labelName ? item.bgColor : '#fff',
      }"
      v-for="(item, index) in labelList"
      :key="item.label"
      @click="handleLabel(index, item.label)"
    >
      {{ item.label }}
    </div>
  </div>
</template>

<script setup lang="ts">
import { useStore } from 'vuex'
import { ref } from 'vue'

const store = useStore()
const emit = defineEmits(['changeLabel'])
const labelList = store.getters['label/labelList']
console.log(labelList)
let activeIndex = ref(-1)
let labelName = ref('')

// 选择label类别
// index的类型有可能是 string | number | symbol,不能写 number,打包编译会报错
const handleLabel = (index: any, label: string) => {
  labelName.value = activeIndex.value === index && labelName.value ? '' : label
  activeIndex.value = index
  emit('changeLabel', labelName)
}
</script>

主要list.vue

<template>
  <div
    :class="{ 'list-container': true, 'list-container__pt': !props.showTitle }"
    v-if="hasLoad"
  >
    <van-pull-refresh
      v-model="refreshing"
      @refresh="handleRefresh"
      v-if="total"
    >
      <div class="list-title" v-if="props.showTitle">
        <SvgIcon name="icon-label01"></SvgIcon>
        <span>最新文章({{ total }})</span>
      </div>
      <van-list
        v-model:loading="loading"
        :finished="finished"
        :immediate-check="false"
        :finished-text="total > 10 ? '--我是有底线的--' : ''"
        @load="handleLoad"
      >
        <div
          class="list-item"
          v-for="item in list"
          :key="item._id"
          @click.stop="gotoDetail(item._id)"
        >
          <div class="item-content">
            <img :src="item.imageUrl" />
            <div class="content-box">
              <div class="content-top">
                <div class="content-title">{{ item.name }}</div>
                <div class="content-desc">{{ item.specification }}</div>
              </div>
              <div class="content-label">
                <div
                  class="label-text"
                  :style="{ backgroundColor: getLabelColor(label) }"
                  v-for="label in item.type"
                  :key="label"
                >
                  {{ label }}
                </div>
              </div>
            </div>
          </div>
          <div class="item-footer">
            <div class="footer-item">
              <SvgIcon name="icon-date02"></SvgIcon>
              <div class="footer-text">
                2020-12-30
              </div>
            </div>
            <div class="footer-item">
              <SvgIcon name="icon-browse02"></SvgIcon>
              <div class="footer-text">800</div>
            </div>
            <div
              class="footer-item"
              :class="{ 'icon-likes': getLikesColor(item._id) }"
              @click.stop="handleLikes(item._id)"
            >
              <SvgIcon name="icon-like02"></SvgIcon>
              <div class="footer-text">
                1000
                {{ formatNumber(getLikesNumber(item._id, item.likes)) }}
              </div>
            </div>
          </div>
        </div>
      </van-list>
    </van-pull-refresh>
    <NoData v-else></NoData>
  </div>
</template>

<script setup lang="ts">
import base from '@/utils/base'
import NoData from '@/components/noData'
import SvgIcon from '@/components/svgIcon'
import { apiGetBlogList, apiUpdateLikes } from '@/api/blog'
import { formatTime, formatNumber } from '@/filters/index'
import useClickLike from '@/useMixin/useClickLike'
import useGetLabelColor from '@/useMixin/useGetLabelColor'
import { ref, watch } from 'vue'
import { useRouter } from 'vue-router'
import { articleModel } from '@/models/index'

interface Props {
  showTitle?: boolean
  params?: object
}
// 定义props默认值
const props = withDefaults(defineProps<Props>(), {
  showTitle: true,
  params: undefined,
})
const { getLikesNumber, getLikesColor, handleLikes, likeList } =
  useClickLike(apiUpdateLikes)
const { getLabelColor } = useGetLabelColor()
const route = useRouter()

let loading = ref(false)
let finished = ref(false)
let refreshing = ref(false)
let hasLoad = ref(false)
let pageindex = ref(1)
let pagesize = ref(10)
let total = ref(0)
let list = ref<Array<articleModel>>([])

// 监听label页传下来的参数
if (props.params) {
  watch(props.params, () => {
    pageindex.value = 1
    hasLoad.value = false
    loading.value = false
    finished.value = false
    list.value = []
    likeList.value = []
    getBlogList()
  })
}
// 获取文章列表
const getBlogList = (reload = true) => {
  reload && base.showLoading()
  return apiGetBlogList({
    pageindex: pageindex.value,
    pagesize: pagesize.value,
    ...props.params,
  })
    .then((res) => {
      list.value = [...list.value, ...res?.data?.list]
      total.value = res?.data?.total
      finished.value = pageindex.value * pagesize.value >= total.value
    })
    .catch((err) => console.log(err))
    .finally(() => {
      hasLoad.value = true
      loading.value = false
      refreshing.value = false
      reload && base.hideLoading()
    })
}
getBlogList()

// 下拉刷新
const handleRefresh = () => {
  pageindex.value = 1
  list.value = []
  likeList.value = []
  getBlogList()
}
// 滚动加载
const handleLoad = () => {
  if (!refreshing.value) {
    pageindex.value++
    getBlogList(false)
  }
}
// 去详情页
const gotoDetail = (id: string) => {
  route.push({ path: '/article/detail', query: { id } })
}
</script>

vuex.main

import { createStore } from "vuex";
import label from "./modules/label";

export default createStore({
  state: {},
  mutations: {},
  actions: {},
  modules: {
    label,
  },
});

vuex label.ts

import { apiGetLabelList } from "@/api/label";
import { labelModel } from "@/models/index";

type State = {
  labelList: Array<labelModel>;
};
export default {
  namespaced: true,
  state: {
    labelList: [ {
      _id: "1",
      label: "查询记录_蘑菇",
      bgColor: "string",
      createTime: "string",
    }],
  },
  mutations: {
    setLabelList(state: State, data: Array<labelModel>) {
      state.labelList = data;
    },
  },
  actions: {
    getLabelList(context: { commit: (arg0: string, arg1: any) => void }) {
      let params = {
        pageindex: 1,
        pagesize: 50,
      };
      return apiGetLabelList(params)
        .then((res) => {
          context.commit("setLabelList", res?.data?.list);
        })
        .catch((err) => {
          console.log(err);
        })
        .finally(()=>{
          alert(2)
        })
        ;
    },
  },
  getters: {
    labelList(state: State) {
      return state.labelList;
    },
  },
};

引用段落
actions中
getLabelList方法触发

<script lang="ts">
import { useStore } from 'vuex'
import { defineComponent } from 'vue'
export default defineComponent({
  name: 'App',
  setup() {
    const store = useStore()
    const getLabelList = () => store.dispatch('label/getLabelList')
    getLabelList()
  },
})
</script>
上一篇 下一篇

猜你喜欢

热点阅读