【vue-blog】从SCF改为tsx
修改tsconfig.json
{
// ...
"compilerOptions": {
// 增加对jsx的支持
"jsx": "preserve"
},
// ...
}
创建tsx文件
1. index.tsx
import {defineComponent} from 'vue';
export default defineComponent({
name: '首页',
setup: () => {
// 相当于() => { return <div>...</div> }
return () => (
<div>...</div>
)
}
});
后面的代码都写在setup
函数中。
2. 请求数据
// 引入封装的请求
import apiBlog from '@/api/blog'
// ...
// 从vue中引入ref
const page = ref(1);
const total = ref(0);
const blogs = ref<Blog[]>([])
const getBlogs = async () => {
const res = await apiBlog.getBlogs({page: page.value})
if (res.status == "ok") {
blogs.value.push(...res.data)
total.value = res.total
page.value = res.page
}
}
// ...
3. 在env.d.ts
中添加Blog
的数据类型
interface User {
username: string;
avatar: string
}
interface Blog {
id: number;
title: string;
description: string;
createdAt: string;
user: User
}
添加类型后可以更好的进行提示与类型检查。
4. 选择生命周期发送请求
import {onMounted} from 'vue';
onMounted(getBlogs)
5. html
html分为两部分,一部分是带路由的文章列表,另一部分是分页,分页我们这里使用element-plus
的组件。
文章列表
<section class="blog-posts">
// 判断有无数据
{ blogs.value.length != 0 && blogs.value.map( (blog, index) => (
// 在 JSX 表达式中,使用单对大括号来嵌入动态值
// 在vue-router中引入RouterLink
<RouterLink class="item" key={blog.id} to={`/detail/${blog.id}`}>
<figure class="avatar">
<img src={blog.user.avatar} alt={blog.user.username}/>
<figcaption>{blog.user.username}</figcaption>
</figure>
<h3>{blog.title}<span>
{proxy.friendlyDate(blog.createdAt)}</span></h3>
<p>{blog.description}</p>
</RouterLink>
) ) }
</section>
分页html
<section class="pagination">
<el-pagination
layout="prev, pager, next"
total={total.value}
current-page={page.value}
onUpdate:current-page={onPageChange}>
</el-pagination>
</section>
这里要注意total 和 page-count 必须传一个,
如果传入了 current-page,必须监听 current-page 变更。
监听current-page
变更官网提到了@update:current-page
,我们这里使用了jsx,正确的写法是onUpdate:current-page={onPageChange}
。
如果在写代码的过程中找不到正确的写法,可以查找它们的xxx.d.ts
来解决。
下面是pagination
组件的部分类型声明,可以看到其中就有我们要找到代码。
{
"onUpdate:current-page"?: ((val: number) => any) | undefined;
"onUpdate:page-size"?: ((val: number) => any) | undefined;
"onSize-change"?: ((val: number) => any) | undefined;
"onCurrent-change"?: ((val: number) => any) | undefined;
"onPrev-click"?: ((val: number) => any) | undefined;
"onNext-click"?: ((val: number) => any) | undefined;
}
分页处理
// 从vue-router中引入useRouter
var router = useRouter();
const onPageChange = (newPage: number) => {
apiBlog.getIndexBlogs({page: newPage}).then((res: any) => {
blogs.value.push(...res.data)
total.value = res.total
page.value = res.page
router.push({path: '/', query: {page: newPage}})
})
}