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>
网友评论