refactor: separate data and view layers
This commit is contained in:
parent
6ccc0cda66
commit
f32fcde23a
|
|
@ -25,8 +25,6 @@
|
|||
|
||||
<script lang="ts">
|
||||
import { defineComponent, computed } from 'vue'
|
||||
import { useRoute } from 'vue-router'
|
||||
import type { AppRouteNames } from '../router'
|
||||
|
||||
import ArticlesListNavigation from './ArticlesListNavigation.vue'
|
||||
import ArticlesListArticlePreview from './ArticlesListArticlePreview.vue'
|
||||
|
|
@ -34,8 +32,6 @@ import AppPagination from './AppPagination.vue'
|
|||
|
||||
import { useArticles } from '../composable/useArticles'
|
||||
|
||||
import store from '../store'
|
||||
|
||||
export default defineComponent({
|
||||
name: 'ArticlesList',
|
||||
components: {
|
||||
|
|
@ -43,6 +39,7 @@ export default defineComponent({
|
|||
AppPagination,
|
||||
ArticlesListNavigation,
|
||||
},
|
||||
|
||||
props: {
|
||||
useGlobalFeed: { type: Boolean, default: false },
|
||||
useMyFeed: { type: Boolean, default: false },
|
||||
|
|
@ -50,35 +47,23 @@ export default defineComponent({
|
|||
useAuthor: { type: Boolean, default: false },
|
||||
useFavorited: { type: Boolean, default: false },
|
||||
},
|
||||
|
||||
async setup (props) {
|
||||
const route = useRoute()
|
||||
const routeName = computed<AppRouteNames>(() => route.name as AppRouteNames)
|
||||
const { user, isAuthorized } = store.user
|
||||
|
||||
const tag = computed<string | undefined>(() => (
|
||||
typeof route.params.tag === 'string' ? route.params.tag : undefined
|
||||
))
|
||||
|
||||
const username = computed<string | undefined>(() => (
|
||||
typeof route.params.username === 'string' ? route.params.username : undefined
|
||||
))
|
||||
|
||||
const userAuthorized = computed<boolean>(() => isAuthorized(user))
|
||||
const {
|
||||
fetchArticles, articlesDownloading,
|
||||
articlesCount, articles, updateArticle,
|
||||
page, changePage,
|
||||
articlesTypeInfo,
|
||||
} = useArticles()
|
||||
|
||||
const navigationUseProps = computed(() => ({
|
||||
useGlobalFeed: props.useGlobalFeed,
|
||||
useMyFeed: props.useMyFeed ? userAuthorized.value : false,
|
||||
useTag: props.useTag ? tag.value : '',
|
||||
useAuthor: props.useAuthor ? username.value : '',
|
||||
useFavorited: props.useFavorited ? username.value : '',
|
||||
useGlobalFeed: props.useGlobalFeed && articlesTypeInfo.value.globalFeed,
|
||||
useMyFeed: props.useMyFeed && articlesTypeInfo.value.myFeed,
|
||||
useTag: props.useTag ? articlesTypeInfo.value.tag ?? '' : '',
|
||||
useAuthor: props.useAuthor ? articlesTypeInfo.value.author ?? '' : '',
|
||||
useFavorited: props.useFavorited ? articlesTypeInfo.value.favorited ?? '' : '',
|
||||
}))
|
||||
|
||||
const { fetchArticles, articlesDownloading, articlesCount, articles, page, changePage, updateArticle } = useArticles({
|
||||
routeName,
|
||||
tag,
|
||||
username,
|
||||
})
|
||||
|
||||
await fetchArticles()
|
||||
|
||||
return {
|
||||
|
|
@ -92,5 +77,4 @@ export default defineComponent({
|
|||
}
|
||||
},
|
||||
})
|
||||
|
||||
</script>
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
import { ComputedRef, ref, watch } from 'vue'
|
||||
import type { AppRouteNames } from '../router'
|
||||
import { computed, ref, watch } from 'vue'
|
||||
import { useRoute } from 'vue-router'
|
||||
import { AppRouteNames } from '../router'
|
||||
|
||||
import createAsyncProcess from '../utils/create-async-process'
|
||||
|
||||
|
|
@ -11,34 +12,51 @@ import {
|
|||
getArticlesByTag,
|
||||
} from '../services/article/getArticles'
|
||||
|
||||
interface UseArticlesProps {
|
||||
routeName: ComputedRef<AppRouteNames>
|
||||
username?: ComputedRef<string | undefined>
|
||||
tag?: ComputedRef<string | undefined>
|
||||
}
|
||||
import store from '../store'
|
||||
|
||||
export function useArticles () {
|
||||
const route = useRoute()
|
||||
const { user, isAuthorized } = store.user
|
||||
|
||||
export function useArticles ({ routeName, username, tag }: UseArticlesProps) {
|
||||
const articles = ref<Article[]>([])
|
||||
const articlesCount = ref(0)
|
||||
const page = ref(1)
|
||||
|
||||
const tag = computed(() => (
|
||||
typeof route.params.tag === 'string' ? route.params.tag : undefined
|
||||
))
|
||||
|
||||
const username = computed(() => (
|
||||
typeof route.params.username === 'string' ? route.params.username : undefined
|
||||
))
|
||||
|
||||
const articlesType = computed(() => route.name as AppRouteNames)
|
||||
|
||||
const articlesTypeInfo = computed(() => ({
|
||||
globalFeed: true,
|
||||
myFeed: isAuthorized(user),
|
||||
tag: tag.value,
|
||||
author: username.value,
|
||||
favorited: username.value,
|
||||
}))
|
||||
|
||||
async function fetchArticles () {
|
||||
articles.value = []
|
||||
let responsePromise: null | Promise<any> = null
|
||||
let responsePromise: null | Promise<ArticlesResponse> = null
|
||||
|
||||
if (routeName.value === 'my-feed') {
|
||||
if (articlesType.value === 'my-feed') {
|
||||
responsePromise = getFeeds(page.value)
|
||||
}
|
||||
if (routeName.value === 'tag' && tag?.value !== undefined) {
|
||||
if (articlesType.value === 'tag' && tag?.value !== undefined) {
|
||||
responsePromise = getArticlesByTag(tag.value, page.value)
|
||||
}
|
||||
if (routeName.value === 'profile' && username?.value !== undefined) {
|
||||
if (articlesType.value === 'profile' && username?.value !== undefined) {
|
||||
responsePromise = getProfileArticles(username.value, page.value)
|
||||
}
|
||||
if (routeName.value === 'profile-favorites' && username?.value !== undefined) {
|
||||
if (articlesType.value === 'profile-favorites' && username?.value !== undefined) {
|
||||
responsePromise = getFavoritedArticles(username.value, page.value)
|
||||
}
|
||||
if (routeName.value === 'global-feed') {
|
||||
if (articlesType.value === 'global-feed') {
|
||||
responsePromise = getArticles(page.value)
|
||||
}
|
||||
|
||||
|
|
@ -46,6 +64,8 @@ export function useArticles ({ routeName, username, tag }: UseArticlesProps) {
|
|||
const response = await responsePromise
|
||||
articles.value = response.articles
|
||||
articlesCount.value = response.articlesCount
|
||||
} else {
|
||||
throw new Error(`Articles type "${articlesType.value}" not supported`)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -57,22 +77,23 @@ export function useArticles ({ routeName, username, tag }: UseArticlesProps) {
|
|||
articles.value[index] = article
|
||||
}
|
||||
|
||||
const { active, run } = createAsyncProcess(fetchArticles)
|
||||
const { active: articlesDownloading, run: runWrappedFetchArticles } = createAsyncProcess(fetchArticles)
|
||||
|
||||
watch(routeName, () => {
|
||||
watch(articlesType, () => {
|
||||
if (page.value !== 1) changePage(1)
|
||||
else run()
|
||||
else runWrappedFetchArticles()
|
||||
})
|
||||
|
||||
watch(page, run)
|
||||
watch(page, runWrappedFetchArticles)
|
||||
|
||||
return {
|
||||
fetchArticles: run,
|
||||
articlesDownloading: active,
|
||||
fetchArticles: runWrappedFetchArticles,
|
||||
articlesDownloading,
|
||||
articles,
|
||||
articlesCount,
|
||||
page,
|
||||
changePage,
|
||||
updateArticle,
|
||||
articlesTypeInfo,
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue