前端进阶之旅前端进阶之旅
基础篇
进阶篇
高频篇
精选篇
手写篇
原理篇
面经篇
AI 面试
自检篇
每日一题
  • 综合
    • 综合题型
    • 其他问题
    • 设计模式
    • 思维导图
    • 学习路线
  • 前端基础
    • HTTP
    • 浏览器
    • 计算机基础
  • 进阶学习
    • NPM工作流
    • Docker
    • Canvas
    • Node学习指南
    • 前端综合文章
  • 其他
    • Handbook
    • 职场话题
    • CSS可视化
小程序题库
公众号动态
博客动态
开发者导航
基础篇
进阶篇
高频篇
精选篇
手写篇
原理篇
面经篇
AI 面试
自检篇
每日一题
  • 综合
    • 综合题型
    • 其他问题
    • 设计模式
    • 思维导图
    • 学习路线
  • 前端基础
    • HTTP
    • 浏览器
    • 计算机基础
  • 进阶学习
    • NPM工作流
    • Docker
    • Canvas
    • Node学习指南
    • 前端综合文章
  • 其他
    • Handbook
    • 职场话题
    • CSS可视化
小程序题库
公众号动态
博客动态
开发者导航
  • React专栏

    • React组合式开发实战

      • 前端开发的四个时代
      • 企业管理系统的前世今生
      • 可视化页面搭建工具
      • 实战篇 01:开发前准备
      • 实战篇 02:项目脚手架
      • 实战篇 03:页面布局方案
      • 实战篇 04:权限管理机制
      • 实战篇 05:菜单匹配逻辑
      • 实战篇 06:消息通知设计
      • 实战篇 07:多语言支持
      • 继往开来:可视化页面搭建工具
    • React Hooks与Immutable实战

    • React SSR服务端渲染与同构实践

    • IM聊天系统前端开发实践

    • 微前端开发实战

    • React进阶实践

  • Vue专栏

  • 移动端专栏

  • Node专栏

  • 前端工程化专栏

  • 算法专栏

  • Typescript专栏

  • 其他专栏

完整面试题地址:
作者:程序员poetry
扫码关注作者公众号:「前端进阶之旅」 每天分享技术干货
前端进阶之旅公众号二维码

# 正文

上一节我们实现了应用骨架的路由同构,这一节我们来实现非常重要的一个环节 - 数据同构。

# 什么是数据同构

整体来说,组件的一些数据需要从接口异步获取后进行渲染,数据同构就是服务端和客户端能够使用同一个数据请求处理方法(一套代码),同一份数据进行组件的渲染。

我们前面实现的组件直出只是将组件转换为了 html字符串,但是并没有具体的数据,顶多就是个静态页。

比如现在有这么一个需求,要从接口获取数据并且渲染到页面上。

以往在单页应用中,我们一般都将数据的数据的请求处理放在compoentDidMount生命周期内,得到数据后更改状态,随之渲染。

异步获取数据

  componentDidMount(){
        ...
        fetchData().then(res=>{
            this.setState({
                list:res.list
            });
        })
    }
@前端进阶之旅: 代码已经复制到剪贴板

在 render 方法内组织数据

 render() {
        ....
        let {list} = this.state;
        .....
        return <>
        {list&&list.map(item=>{
            return <div>{item.title}</div>
        })}
        </>
    }
@前端进阶之旅: 代码已经复制到剪贴板

上面的代码我们都非常熟悉,以上代码也能在 ssr 模式中执行,但是无法得到我们期望的效果,数据只能在客户端得到,达不到数据直出的效果,查看网页源代码也没有我们想要的数据。

image-20210214214245297

开始的时候我们介绍过一些原理,componentDidMount生命周期只会在浏览器端执行,所以如果想让数据也能在服务端渲染就需要做一些特殊的处理。

接下来我们来实现 react ssr 本应用骨架内的数据同构。

# 数据预取

在客户端,我们在componentDidMount生命周期内执行数据请求方法从接口拿到数据。

在服务端渲染组件的时候要想在直出的组件内容也包含数据,那就需要提前得到数据,然后将数据作为属性传递给组件,在constructor内对组件 state 进行初始化。

当组件有了数据,服务端渲染直出的时候自然就会有数据。

以上这个在服务端渲染前得到数据的过程就是数据预取。

思考两个问题:

问题1:客户端和服务端组件渲染执行的声明周期不同,双端如何使用一套代码,代码如何组织呢?

问题2:真实开发中,浏览器的 fetch api 无法在node 端使用,如何统一呢?

以上两个问题都可以通过同构来解决。

先说问题2,因为比较简单,现在已经有很多同构的库来解决。

比如:isomorphic-fetch,axios,这里我推荐使用axios,对开发者非常友好,可以无差别使用。

那现在回到问题1,解决这个问题前需要回顾下以往的知识。

js里无论是函数还是类,到底都是函数,同时都是特殊的对象。

所以我们可以为这些函数添加属性,这个属性也可以被称作为类的静态方法。

静态方法有什么特点?

不需要实例化就可以访问,像下面这样。

class Foo {
   run(){
       .....
       console.log('hello');
   }
}

Foo.method=function(){
    console.log('hello method');
}
@前端进阶之旅: 代码已经复制到剪贴板

这有什么作用呢?

上面的代码可以在浏览器端执行,当然也可在 node 端执行。

其实以上思路就是解决问题2的办法,可以把Foo想象成我们的react 组件。

我们可以在 node 端找到这个路由对应的组件,然后调用这个组件的静态方法来实现数据的预取。

梳理下完整的思路

  • 约定并为组件添加数据预取的静态方法
  • 在服务端查找到当前路由对应的组件
  • 调用组件的数据预取方法得到数据
  • 将数据作为属性传入组件
  • 组件内render做相应的处理
  • 服务端直出组件
  • 浏览器接管页面,完成渲染

# 手膜手实现数据同构

# 约定数据预取方法

首先我们模拟一个异步获取数据的方法,返回一个列表数据。

我这里准备了一份从掘金采集的信息,作为假数据。

// ./src/client/pages/list/data.js

const data = [{
    "title": "深入浅出TypeScript:从基础知识到类型编程&qu
fe
基础篇
进阶篇
高频篇
精选篇
手写篇
原理篇
面经篇
AI 面试
自检篇
每日一题
  • 综合
    • 综合题型
    • 其他问题
    • 设计模式
    • 思维导图
    • 学习路线
  • 前端基础
    • HTTP
    • 浏览器
    • 计算机基础
  • 进阶学习
    • NPM工作流
    • Docker
    • Canvas
    • Node学习指南
    • 前端综合文章
  • 其他
    • Handbook
    • 职场话题
    • CSS可视化
小程序题库
公众号动态
博客动态
开发者导航
  • React专栏

    • React组合式开发实战

      • 前端开发的四个时代
      • 企业管理系统的前世今生
      • 可视化页面搭建工具
      • 实战篇 01:开发前准备
      • 实战篇 02:项目脚手架
      • 实战篇 03:页面布局方案
      • 实战篇 04:权限管理机制
      • 实战篇 05:菜单匹配逻辑
      • 实战篇 06:消息通知设计
      • 实战篇 07:多语言支持
      • 继往开来:可视化页面搭建工具
    • React Hooks与Immutable实战

    • React SSR服务端渲染与同构实践

    • IM聊天系统前端开发实践

    • 微前端开发实战

    • React进阶实践

  • Vue专栏

  • 移动端专栏

  • Node专栏

  • 前端工程化专栏

  • 算法专栏

  • Typescript专栏

  • 其他专栏