refactor: separate data and view layers

This commit is contained in:
Sándor Levcsák 2020-11-02 11:50:19 +02:00 committed by Sándor Levcsák
parent 6ccc0cda66
commit f32fcde23a
2 changed files with 54 additions and 49 deletions

View File

@ -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>

View File

@ -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,
}
}