zoukankan      html  css  js  c++  java
  • React 同构

    React 同构

    搬运
    https://segmentfault.com/a/1190000004671209

    究竟什么是同构呢?

    同构就是希望前端 后端都使用同一套逻辑 同一套代码
    Nodejs出现后 这一设计方式的实现更加容易了 后端同样可以根据路径来加载js文件渲染指定的页面 而React又拥有renderToString 以及 renderToStaticMarkup方法
    可以将react组建渲染成html字串

    renderToString VS renderToStaticMarkup
    这两者都是将 React元素变成原始的HTML, 且都是服务端在使用, 不同的是renderToStaticMarkup不会创建出额外的React的属性 比如 data-react-id等 主要是用于创建一个纯粹的静态页, 这样可以节省很多带宽

    实现一个最简单的同构

    就是希望服务器在响应某个请求所调用的逻辑
    客户端对于该路径的处理也是使用同一套逻辑 (客户端对于路径处理 指的是运用了Hash或者Histroy State的SPA页面 对不同路径的处理)
    更通俗一点的说法, 客户端和服务端对于同一个路径所作出的响应会使用到共同的文件(但并不表示对于同一个路径 他们处理的逻辑完全相同)

    关于react-router的browserHistroy

    如果你设置某个页面的router为 / 的话
    访问这个页面的路径应该是 domian.xx:port/
    之前没有理解browserHistroy 目标app是在一个很深的路径下
    当时使用这个路径去访问
    localhost/ReactStudy/RouterStudy/
    自然就会出现 Location / Not match

    Server端

    我们知道Server端对于一个请求的处理, 就是根据不同的路径做出不同的响应 所以Server端的响应应该是一个完整的页面 之后在页面上发生的任何路径的改变, 都应该交给react route处理 Server不再参与后续的任务

    这里Server使用koa来实现 服务端的路径处理使用koa-router

      let app = koa();
      let router = koaRouter();
      router.get(['/', '/home'], function*() {
    
        // 执行view插件
        // 调用render方法  this是app的context
        // 所以调用的this.render 也就是
        this.body = this.render('Home', {
          microdata: microdata,
          mydata: {
            nick: 'server render body'
          }
        },1);
      });
      app.use(router.routes()).use(router.allowedMethods());
    
    

    可以看到整个响应体this.body的渲染由一个render方法完成
    这个render调用了一个文件专门渲染服务端的页面 这个页面请求一个js文件 这个js文件就是整个客户端的逻辑

    可能这个页面的一些渲染就是由和客户端通的组件得到的 但是并不一定会有共同的部分
    这样服务器可以直接将一些信息渲染到页面中 解决了SEO的问题
    但是这个过程非常的慢

    慢的原因是因为这个render需要根据路径动态的require一些组件 然后解析等等
    这些被require的组件如果是采用了ES6的方式编写 需要用 'babel-register' 来处理
    它是一个Hook, 可以在require一个组件的时候做一些处理, 将ES6编译成ES5
    由于这里是动态的处理这个编译的过程 这个服务端的响应就更加慢了

    
      render() {
        // 对象的解构赋值
        const { microdata, title, children } = this.props;
        return (
          <html>
            <head>
              <meta charSet='utf-8' />
              <meta httpEquiv='X-UA-Compatible' content='IE=edge' />
              <meta httpEquiv='Cache-Control' content='no-siteapp' />
              <meta name='renderer' content='webkit' />
              <meta name='keywords' content='demo' />
              <meta name='description' content='demo' />
              <meta name='viewport' content='width=device-width, initial-scale=1' />
              <title>{title}</title>
            </head>
            <body>
              {children}
              {this.renderScripts()}
            </body>
          </html>
        );
      }
    

    需要注意的是, 并不是有了babel-loader 所有的ES6都可以顺利的变成ES5, Babel Online上可以看到关于ES6的语法有不同的presets的设置 默认情况下 class 的static 不能直接通过babel-loader编译 解决方案在这里http://jsrocks.org/2016/01/configuring-babel-6-for-node-js/
    需要参数 你可以在.babelrc中加入下面的配置或者在webpack.config.js中添加params参数

    {
     "plugins": ["es2015", "stage-0"]
    }
    

    客户端

    客户端最终的结果是一个OR多个js文件, 它包含了所有的页面上的逻辑以及页面之间的跳转(这里用的是react-router)
    服务端生成了页面之后, 可以将一些参数(比如路径的参数) 直接写在页面中, 然后客户端从页面中获取这些参数值然后执行,

    客户端主要逻辑

      render() {
        let { isServer, mydata } = this.props;
        return (
          <Router history={browserHistory}>
            <Route path="/" component={Nav}>
              <Route path="/device/:deviceID" component={DeviceView}/>
            </Route>
          </Router>
        );
      }
    

    等客户端的逻辑一开始执行 就会根据当前的url做匹配 执行特定的组件逻辑

  • 相关阅读:
    Install Failed Insufficient Storage, 解决 ADB 安装APK失败问题
    finding-the-smallest-circle-that-encompasses-other-circles
    PyTorch for Semantic Segmentation
    Semantic-Segmentation-DL
    Awesome Semantic Segmentation
    应用于语义分割问题的深度学习技术综述
    JS打开浏览器
    Overcoming iOS HTML5 audio limitations
    Android APP Testing Tutorial with Automation Framework
    基于方向包围盒投影转换的轮廓线拼接算法
  • 原文地址:https://www.cnblogs.com/cart55free99/p/5357508.html
Copyright © 2011-2022 走看看