Nest博客后台接口和与React前端的交互

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接: https://blog.csdn.net/weixin_43870742/article/details/102731890

前言

最近做完博客接口,主要是文章列表和详情的接口,使用Typegoose和swagger配合Nest.js,然后用mongo express生成了一些可以操作的数据,利用axios配合前台完成了数据交互,把文章列表和详情页做了出来。下面主要是总结一下。

接口

看过我之前文章的可能知道,nest.js操作mongoDB我更喜欢使用typegoose这个ORM,不仅仅是因为和TS结合的更加好,代码提示之类的也更方便,做一个模型文件,操作起来就比较简单。
关于数据库设计,文章列表和文章详情自然是可以使用同一个MongoDB文件了,关于评论,尽管还没有实现这个功能,但是还是先把评论放在同一个文件中,毕竟应该很难做大,而既然使用了NoSQL,就没必要再建立一个新的文件硬是去和其他的文件建立联系。
关于Nest工程结构的设计,暂时也没有想太多,直接在src目录下建立了新的"posts"文件夹用来处理博客相关内容。

-> src
    -> posts
        -> posts.controller.ts
        -> ...spect.ts
        -> post.dto.ts
        -> post.model.ts
    -> main.ts
    ->app.controller.ts
    -> ...

关于model文件,我是这样定义的:

/*
 * @Date: 2019-10-23 14:10:48
 * @LastEditors: Asen Wang
 * @LastEditTime: 2019-10-23 14:35:30
 * @content: I
 */
import { getModelForClass, prop } from '@typegoose/typegoose'

export class Posts {
  @prop()
  author: string
  @prop()
  title: string
  @prop()
  intro: string
  @prop()
  content: string
  @prop()
  tags: string[]
  @prop()
  time: string
  @prop()
  readtime: number
  @prop()
  img: string
  @prop()
  views: number
  @prop()
  zan: number
  @prop()
  comments: number
}

export const PostModel = getModelForClass(Posts)

typegoose 之前讲过,这种方式个人挺喜欢的,props里面也可以传递参数,比如{default},{required}等。
这里为了测试添加数据还设置了DTO,当然这里还没有涉及到后台管理系统,所以这里先不讲。
关于控制器,由于逻辑很简单,没必要设置服务:

@Controller('posts')
@ApiUseTags('代码文章')
export class PostsController {
  @Get()
  @ApiOperation({title: '显示文章的列表界面'})
  async getPosts() {
    return await PostModel.find()
  }

  @Post()
  @ApiOperation({title: '添加文章'})
  async addPost(@Body() createPostsDto: CreatePostsDto) {
    await PostModel.create(createPostsDto)
    return {success: true}
  }

  @Get(':id')
    @ApiOperation({title: '显示文章的详情页面'})
    async getPostByID(@Param('id') id: string) {
      return await PostModel.findById(id)
    }
}

关于POST的部分暂时不需要看,typegoose使用起来还是很方便的。
最后关于main.ts的编写,注意设置一下跨域和swagger的配置编写即可,因为nest和next的默认端口都是3000,这里我把nest的端口换成了4000:

async function bootstrap() {
mongoose.connect('mongodb://localhost/myblog', {
  useNewUrlParser: true,
  useFindAndModify: false,
  useCreateIndex: true,
  useUnifiedTopology: true,
})
const app = await NestFactory.create(AppModule, {cors: true});
app.useGlobalPipes(new ValidationPipe())

const options = new DocumentBuilder()
  .setTitle('我的博客')
  .setDescription('博客API接口的Swagger文档')
  .setVersion('1.0')
  .addTag('blog')
  .build();
const document = SwaggerModule.createDocument(app, options);
SwaggerModule.setup('api-docs', app, document);

await app.listen(4000);
Logger.log(`App run in http://localhost:4000`)
}
bootstrap();

因为目前主要测试博客功能,其他的还没有编写,这里就先写成了博客部分的内容。

前后交互

整个逻辑还是比较简单的,之前讲过axios在next中的使用,这里直接写即可,拿到数据后传给子组件然后设置即可,这里举个小例子:

//index.js
const PostsContext = createContext()

const Home = ({data}) =>  (
  <>
  ...
  <PostsContext.Provider value={data}>
            <PostList />
  </PostsContext.Provider>
  ...
  </>
)

Home.getInitialProps = async() => {
  const res = await axios.get('http://localhost:4000/posts')
  return { data: res.data }
}
//组件中拿到数据
  const data = useContext(PostsContext)

Bug

数据直接使用即可,没什么需要注意的,不过我个人在这个过程中遇到了一个问题,其实之前就遇到过,只不过没怎么注意:

Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: object.

其实错误很简单,我在测试接收到的数据时,不小心在JSX的语法中直接把接收到的对象加上{}展示出来,类似:

const Home = (res) => (
 {res}
)

注意这样的错误就好了。

猜你喜欢

转载自blog.csdn.net/weixin_43870742/article/details/102731890