zoukankan      html  css  js  c++  java
  • 使用react-router实现单页面应用路由

    这是Webpack+React系列配置过程记录的第二篇。其他内容请参考:

    上一篇文章讲述了如何搭建单页面应用的开发环境。本文接着介绍如何实现单页面应用。

    实际上,单页面应用利用js实现了页面的动态化,用户使用时基本感知不到网页是如何实现的,开发也不应该让用户感知到。为了实现这一步,react提供了一个官方的路由组件react-router,让你的单页面应用支持页面的跳转以及动态渲染。

    使用react-router的前端实现

    安装react-router
    npm install --save react-router-dom  

    我使用的是最新版本4.1.1,这个版本的react-router针对浏览器、原生应用等环境已经做了区分。我做的是基于web的单页面应用,因此安装的时候我使用的是react-router-dom这个依赖。

    使用react-router

    还是基于上一篇文章搭建的开发环境,我们使用官方示例简单入门对react-router的使用方法。

    回顾一下上一篇文章的开发环境:

    开发环境目录

    这里主要需要修改index.js,其内容改为官方示例代码:

    import React from 'react';  
    import ReactDOM from 'react-dom';  
    import {  
      BrowserRouter as Router,
      Route,
      Link
    } from 'react-router-dom';
    
    const BasicExample = () => (  
      <Router>
        <div>
          <ul>
            <li><Link to="/">Home</Link></li>
            <li><Link to="/about">About</Link></li>
            <li><Link to="/topics">Topics</Link></li>
          </ul>
    
          <hr/>
    
          <Route exact path="/" component={Home}/>
          <Route path="/about" component={About}/>
          <Route path="/topics" component={Topics}/>
        </div>
      </Router>
    )
    
    const Home = () => (  
      <div>
        <h2>Home</h2>
      </div>
    )
    
    const About = () => (  
      <div>
        <h2>About</h2>
      </div>
    )
    
    const Topics = ({ match }) => (  
      <div>
        <h2>Topics</h2>
        <ul>
          <li>
            <Link to={`${match.url}/rendering`}>
              Rendering with React
            </Link>
          </li>
          <li>
            <Link to={`${match.url}/components`}>
              Components
            </Link>
          </li>
          <li>
            <Link to={`${match.url}/props-v-state`}>
              Props v. State
            </Link>
          </li>
        </ul>
    
        <Route path={`${match.url}/:topicId`} component={Topic}/>
        <Route exact path={match.url} render={() => (
          <h3>Please select a topic.</h3>
        )}/>
      </div>
    )
    
    const Topic = ({ match }) => (  
      <div>
        <h3>{match.params.topicId}</h3>
      </div>
    )
    
    ReactDOM.render(<BasicExample/>, document.getElementById('main'));  

    注意到上面的代码引入了react-router的BrowserRouter(重命名为Router),Route,Link三个组件。新版本的react-router提出了一切都以Component实现的原则,因此这些组件实际上都是React.Component的实现。

    BrowserRouter是一个容器Component,其内部实现了路由跳转的逻辑。旧版本直接使用Router就可以,新版本根据环境不同有不同的实现,Web环境使用BrowserRouter。

    Route也是一个Component,配置了页面路径以及当用户输入的路径命中时需要渲染的组件。

    Link用于跳转,有点像HTML的a标签。不一样的是Link是需要在后端进行编译,最终可能以a标签的形式呈现给用户。

    验证react-router

    使用下面命令编译并运行应用:

    npm run build  
    npm start 

    访问http://localhost:2000 可以看到页面已经可以正常访问,且点击可以实现页面跳转。

    react-router效果

    如果你细心一点,你会发现刚刚访问的页面链接是使用a标签出发了页面的跳转。但是跳转后页面并没有向后端发送页面请求。事实上,这就是单页面应用为了解耦前后端实现的目标之一。Link在页面的呈现

    我在index.js中使用Link组件,编译后在浏览器上以a标签呈现给用户。而react-router连接了这些a标签的事件处理,动态的实现组件的渲染和浏览器地址栏内容的修改。因此这个过程不需要重新加载内容也不会向后端发出网络请求。

    使用react-router的后端实现

    单页面是为了实现前后端的业务解耦,但绝对的解耦是不存在的。有两个方面佐证这个观点。首先是api协议的约定,这必须要前端与后端的同时支持;其次就是本文的主要内容——路由实现。

    缺少后端支持的问题

    通过上面内容我们知道单页面应用的路由是通过js实现的,相对于传统网站而言是“伪跳转”。那么如果用户直接在浏览器上输入http://localhost:2000/about 然后回车会有什么效果。

    使用我的demo环境,会看到下图:缺少后端支持的效果

    果断的404响应。因为我的服务器根本没有/about这个目录或者文件。

    增加后端支持

    为了解决这个问题,我需要增加这样一个依赖:

    npm install --save connect-history-api-fallback 

    并且在项目根目录的index.js(注意不是public目录的index.js,这里应该重新命名一下的,当前将就一下)。

    内容改为:

    var express = require('express');  
    var app = express();
    
    app.use('/', require('connect-history-api-fallback')()); // Add  
    app.use('/', express.static('public'));
    
    var server = app.listen(2000, function() {  
      var port = server.address().port;
      console.log('Open http://localhost:%s', port);
    });

    另外需要修改一下public目录下的index.html文件的内容。这是使用相对路径获取js文件,属于上次留下来的bug,不改的话会存在问题。内容如下:

    <html>  
      <head>
      </head>
      <body>
        <p>Hello world</p>
        <div id='main'></div>
        <script src="/out.js"></script><!-- 改动行 -->
      </body>
    </html>  

    这样就可以解决问题了。重新在浏览器输入http://localhost:2000/about 可以看到页面显示正常了。

    需要注意增加的代码必须放在express.static行的上方。这涉及的express框架的原理,不在这里深究,只要知道connect-history-api-fallback组件根据配置,帮我们把public目录下的index.html作为所有不存在的路径的请求的响应返回给浏览器。

    同步博客原文链接

  • 相关阅读:
    常用C# 6.0 常用 新特性
    VS 编译总是出现错误: "LC.EXE 已退出,代码为1"
    C# XML封装
    VS 2015秘钥
    写入Txt文本信息
    C# 7.0 新特性
    Winform 弹框增加确定按钮并点击确定后进行下一步操作
    VS 代码过长自动换行
    C# 6.0 新特性
    string::npos 是什么 c++ /STL
  • 原文地址:https://www.cnblogs.com/developerdaily/p/6795448.html
Copyright © 2011-2022 走看看