React服务端渲染,子组件的数据预获取遇到坑了

没用框架自己实现了服务端渲染,现在在数据预获取放面遇到了问题

场景

每个路由对应的页面组件,会挂载一个loadData方法(类似于next.js的getInitialProps),这样,在服务端渲染的时候,会根据路由匹配出当前页面组件,调用loadData方法,扩充store,完成数据预获取。但这个页面内如果有子组件需要独立获取自身的数据,我这样实现就有问题了,因为只能根据路由匹配出当前页面,无法匹配出其内部组件,具体场景如下:

假设有文章详情页,路由是/article/:id,对应路由页面是<ArticleDetail/>

详情页内一般都会有文章评论,抽象为一个组件<CommentList/>,且评论组件是其他页面也会用到,接收id请求评论数据。

这样<ArticleDetail/>内嵌套了<CommentList/>组件。


遇到的问题

<CommentList/>不是路由内的组件,服务端根据路由无法匹配到它,所以其中的loadData方法无法被调用。也就是说评论列表的数据无法预获取,也就无法放入store。


我的思路

针对这种情况,我想了可以在它的父组件<ArticleDetail/>的loadData方法内请求评论数据放到store,<CommentList/>再取出来显示。也就是父组件请求子组件内的数据,子组件只负责展示。
但是感觉这种方法有缺点:

  • 违背了低耦合的原则,组件内的数据交互最好是由它自己独立完成。
  • 被复用的组件这样搞会很麻烦,每个用到这个组件的时候都要在其所在的路由页面的loadData方法写一个请求。本质上是还是耦合度比较高的问题

还有一种办法,就是直接为这个<CommentList/>组件也配置路由,对应/article/:id,这样这个路由就会对应两个组件:<ArticleDetail/><CommentList/>,也就不存在上述问题了。

  • 但每用一次就要配置一次路由,有点麻烦

请问大家有什么思路指点一下吗?不胜感激

阅读 2.1k
1 个回答

next与nuxt也并没发现有什么办法,自己找了个方法保持了组件的低耦合,就是loadData方法返回一个promise,其内部是路由页面的loadData方法与其子组件页面的loadData方法,再用Promise.all()执行,待执行完毕(无论成功失败),resolve外层promise。代码如下:

{
  path: '/article/article-detail/:id',
  component: ArticalDetail,
  loadData: (store, id) => {
    return new Promise(resolve => {
      const loadDataList = [ ArticalDetail.loadData(store, id), Message.loadData(store, id)]
      Promise.all(loadDataList).then(() => resolve()).catch(() => resolve())
    })
  }
}

可以将这个方法做个封装:

export const multiLoadData = (store, id) => (...components) => {
  const loadDataArr = [...components].map(component => component.loadData(store, id))
  return new Promise(resolve => Promise.all(loadDataArr).then(() => resolve()).catch(() => resolve()))
}

使用时将store,以及路由页面和其所有的子组件传入即可:

  {
    path: '/article/article-detail/:id',
    component: ArticalDetail,
    loadData: store => multiLoadData(store, id)(ArticalDetail, Message)
  }
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题