Nest博客後臺接口和與React前端的交互

前言

最近做完博客接口,主要是文章列表和詳情的接口,使用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}
)

注意這樣的錯誤就好了。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章