You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

205 lines
4.6 KiB

<template>
<div v-for="article in articles" :key="article.url" id="articles">
<!-- 增加了这个 span -->
<span v-if="article.category !== null" class="category">
{{ article.category.title }}
</span>
<span v-for="tag in article.tags" v-bind:key="tag" class="tag">
{{ tag }}
</span>
<!-- 路由链接:to的两个参数分别是: 路由名称和传入的id -->
<router-link :to="{ name: 'detail', params: { id: article.id } }">
<div class="article-title">{{ article.title }}</div>
</router-link>
<div>
{{ formatted_time(article.created) }}
</div>
</div>
<!-- 实现分页 -->
<div id="paginator">
<span v-if="is_page_exists('previous')">
<router-link :to="get_path('previous')"> Prev </router-link>
</span>
<span class="current-page">
{{ get_page_param("current") }}
</span>
<span v-if="is_page_exists('next')">
<router-link :to="get_path('next')"> Next </router-link>
</span>
</div>
</template>
<script>
import $ from "jquery";
import { onMounted, ref } from "vue";
import { useRoute } from "vue-router";
export default {
name: "ArticleList",
setup() {
onMounted(() => {
get_article_data();
});
let articles = ref([]); // 保存当前页的所有文章
let previous = ref(null); // 保存上一页的url
let next = ref(null); // 保存下一页的url
let router = useRoute();
// 格式化创建时间
const formatted_time = (iso_date_string) => {
const date = new Date(iso_date_string);
return date.toLocaleDateString();
};
// 判断页面是否存在
const is_page_exists = (direction) => {
if (direction === "next") {
return next.value !== null;
}
return previous.value !== null;
};
// 获取页码
const get_page_param = (direction) => {
try {
let url_string;
switch (direction) {
case "next":
url_string = next.value;
break;
case "previous":
url_string = previous.value;
if (
url_string === "http://127.0.0.1:6789/api/article/"
) {
url_string =
"http://127.0.0.1:6789/api/article/?page=1";
}
break;
default:
// 首页需要特殊处理
if (!("page" in router.query)) return 1;
if (router.query.page === null) return 1;
return router.query.page;
}
const url = new URL(url_string);
return url.searchParams.get("page");
} catch (error) {
return;
}
};
const get_article_data = () => {
let article_url = "http://127.0.0.1:6789/api/article"; // BaseUrl
let params = new URLSearchParams();
// 注意 appendIfExists 方法是原生没有的
// 原生只有 append 方法,但此方法不能判断值是否存在
// 只有这两种参数存在时才加入url
params.appendIfExists("page", router.query.page);
params.appendIfExists("search", router.query.search);
// 这下可以同时传入多种参数
const paramsString = params.toString();
if (paramsString.charAt(0) !== "") {
article_url += "/?" + paramsString;
}
$.ajax({
url: article_url,
type: "GET",
success: (resp) => {
articles.value = resp.results; // 获取当前页面的文章列表
previous.value = resp.previous; // 获取前一页的链接
next.value = resp.next; // 获取后一页的链接
},
});
};
// 在翻页后取得包括page和search的正确路径
const get_path = (direction) => {
let url = "";
try {
switch (direction) {
case "next":
if (next.value !== undefined) {
url += new URL(next.value).search;
}
break;
case "previous":
if (previous.value !== undefined) {
url += new URL(previous.value).search;
}
break;
}
} catch {
return url;
}
return url;
};
return {
articles,
formatted_time,
is_page_exists,
get_page_param,
get_article_data,
get_path,
};
},
watch: {
// 监听路由是否有变化
$route() {
this.get_article_data();
},
},
};
</script>
<style scoped>
#articles {
padding: 1rem;
}
.article-title {
font-size: 1.2rem;
font-weight: bolder;
text-decoration: none;
color: blue;
padding: 5px 0 5px 0;
}
.tag {
padding: 2px 5px 2px 5px;
margin: 5px 5px 5px 0;
font-family: Georgia, Arial, sans-serif;
font-size: small;
background-color: #4e4e4e;
color: whitesmoke;
border-radius: 5px;
}
#paginator {
text-align: center;
padding-bottom: 4rem;
}
#paginator a {
color: black;
}
.current-page {
font-size: x-large;
font-weight: bold;
padding-left: 10px;
padding-right: 10px;
}
.category {
padding: 5px 10px 5px 10px;
margin: 5px 5px 5px 0;
font-family: Georgia, Arial, sans-serif;
font-size: small;
background-color: darkred;
color: whitesmoke;
border-radius: 15px;
}
</style>