【vue-blog】从SCF改为tsx

发布时间 2023-03-22 21:11:30作者: 东方来客

修改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}})
  })
}

参考链接

本次代码提交记录
vue setup文档
vue jsx/tsx 文档