[email protected]官方文档翻译

简介

这是我学习[email protected]时,为了加深自己对react-router-dom的理解和帮助一些英文不好的同学,对官方文档进行了翻译,本人水平有限,如有理解和翻译错误,欢迎大家指正。官网地址

快速入门

要在web应用中开始使用React Router,您将需要一个React Web应用程序.如果您需要创建一个,我们建议您尝试Create React App。这是一个非常流行的工具,可与React Router很好地配合使用。

首先,安装create-react-app并使用它创建一个新项目。

安装

您可以使用npm或yarn从公共npm注册表中安装React Router。由于我们构建的是web app,因此在本指南中将使用react-router-dom。

npm install -g create-react-app       // 全局安装 create-react-app
create-react-app demo-app             // 创建一个react项目
cd demo-app                           // 进入react项目目录
npm install react-router-dom          // 安装react-router-dom

接下来,将以下两个示例之一复制/粘贴到src/App.js中。

第一个示例:基本路由

在此示例中,路由器处理了3个“页面”:主页、关于页面和用户页面。当您点击不同的时,这个路由会渲染匹配的

注意:其实最后渲染出来是一个有真实href的标签,因此使用键盘导航或屏幕阅读器的人也可以使用react-router-dom。

import React from 'react';
import ReactDOM from 'react-dom';
import { BrowserRouter, Switch, Route, Link } from 'react-router-dom';

function Home(props) {
    console.log('Home=>', props);
    return 

Home

} function About(props) { console.log('About=>', props); return

About

; } function Users(props) { console.log('Users=>', props); return

Users

; } function App() { return
{/* 通过查找所有的子并渲染与当前URL匹配的第一个的内容 */} }/>
} ReactDOM.render(, document.querySelector('#root'));

第二个示例:嵌套路由

此示例显示了嵌套路由的工作方式。路线/topics会加载Topics组件,在这个组件上的path:id值上有条件地渲染任何其他

import React from 'react';
import ReactDOM from 'react-dom';
import { BrowserRouter, Switch, Route, Link, useRouteMatch, useParams } from 'react-router-dom';

function Home(props) {
    console.log('Home=>', props);
    return 

Home

} function About(props) { console.log('About=>', props); return

About

; } function Topic() { let { topicId } = useParams(); return

Requested topic ID: {topicId}

} function Topics() { const match = useRouteMatch(); console.log('match=>', match); return (

Topics

  • Components
  • Props v. State
{/* Topics页面有自己的,其中包含更多的路线,建立在/topics路径之上 您可以将第二个视为所有主题的“索引”页面,或者当未选择任何主题时显示的页面 */}

Please select a topic.

); } function App() { return
  • Home
  • About
  • Topics
} ReactDOM.render(, document.querySelector('#root'));

继续

希望这些示例能让您对使用React Router创建web app有点感觉。继续阅读可以了解有关React Router中主要组件的更多信息!

主要组件

React Router中的组件主要分为三类:

  • 路由器,例如
  • 路由匹配器,例如
  • 导航,例如

在Web应用程序中使用的所有组件都应从react-router-dom导入。

路由器

每个React Router应用程序的核心应该是路由器组件。对于Web项目,react-router-dom提供路由器。两者之间的主要区别在于它们存储URL和与Web服务器通信的方式。

  1. 使用常规URL路径。 这些通常是外观最好的网址,但它们要求您的服务器配置正确。 具体来说,您的Web服务器需要在所有由React Router客户端管理的URL上提供相同的页面。Create React App在开发中即开即用地支持此功能,并附带有关如何配置生产服务器的说明。
  2. 将当前位置存储在URL的哈希部分中,因此URL看起来类似于http://example.com/#/your/page。 由于哈希从不发送到服务器,因此这意味着不需要特殊的服务器配置。

要使用路由器,只需确保将其渲染在元素层次结构的根目录下即可。 通常,您会将顶级元素包装在路由器中,如下所示:

import React from "react";
import ReactDOM from "react-dom";
import { BrowserRouter } from "react-router-dom";

function App() {
  return 

Hello React Router

; } ReactDOM.render( , document.getElementById("root") );

路线匹配器

有两个路线匹配组件:Switch和Route。渲染时,它会搜索其子元素,以查找其路径与当前URL匹配的元素。当找到一个时,它将渲染该并忽略所有其他路由。这意味着您应该将包含更多特定路径(通常较长)的路径放在不那么特定路径之前。

如果没有匹配,则不渲染任何内容(null)。

import React from 'react';
import ReactDOM from 'react-dom';
import { BrowserRouter, Switch, Route } from 'react-router-dom';

function App() {
    return 
{/* 如果当前URL是/ about,那么将渲染此路由,而其余路由将被忽略 */}

About

{/* 请注意这两个路由的顺序。 更具体的path="/contact/id"位于path="/contact"之前,因此在查看单个联系人时将显示这个 */}

Contact

AllContact

{/* 如果先前的路由均未呈现任何内容,则此路由将充当后备路径。 重要提示:路径="/"的路线将始终匹配任何路径的URL,因为所有URL均以/开头。 所以这就是为什么我们把这这个放在最后 */}

Home

} ReactDOM.render( , document.querySelector('#root'));

⚠️ 需要注意的重要一件事是匹配URL的开头,而不是整个开头。所以,将始终与任意一个URL匹配。因此,我们通常将此放在的最后。另一种可能的解决方案是使用确实与整个URL匹配的。exact属性表示精准匹配。

⚠️注意:尽管React Router确实支持在之外渲染元素,从5.1版开始,我们建议您改用useRouteMatch钩子。此外,我们不建议您渲染不带路径的,而是建议您使用钩子来访问您所使用的任何变量。

导航(或路线更改器)

React Router提供了一个组件来在您的应用程序中创建链接。 无论在何处渲染,锚点都将渲染在HTML文档中。

的一种特殊类型,当其prop与当前位置匹配时,可以将其自身设置为“active”。

任何时候要强制导航,都可以渲染。渲染时,它将会使用其props进行导航

Home
// Home


  React

// 当URL为/react的时候, 渲染出来的以下内容:
// React
// 如果是其他URL,则渲染为:
// React

// 重定向到/login

NavLink例子:

import React from 'react';
import ReactDOM from 'react-dom';
import { BrowserRouter, Switch, Route, NavLink } from 'react-router-dom';

function NavigationApp() {
    return 
        
  • React
  • redux

React

Redux

} ReactDOM.render(, document.querySelector('#root'));

服务器渲染

代码分割

网络应用的一个重要特色就是:我们无需让访问者下载整个应用程序即可使用,您可以将代码拆分视为增量下载应用程序。为此,我们将使用webpack,@babel/plugin-syntax-dynamic-import,和loadable-components做代码分割。

webpack内置了对动态导入的支持; 但是,如果您使用的是Babel(例如,将JSX编译为JavaScript),则需要使用@babel/plugin-syntax-dynamic-import插件。这是仅语法的插件,这意味着Babel不会进行任何其他转换。该插件仅允许Babel解析动态导入,因此webpack可以将它们捆绑为代码拆分。 您的.babelrc应该使用如下配置:

{
  "presets": ["@babel/preset-react"],
  "plugins": ["@babel/plugin-syntax-dynamic-import"]
}

loadable-components是用于通过动态导入加载组件的库。 它自动处理各种边缘情况,并使代码拆分变得简单! 这是有关如何使用loadable-components的示例:

import loadable from "@loadable/component";
import Loading from "./Loading.js";

const LoadableComponent = loadable(() => import("./Dashboard.js"), {
  fallback: 
});

export default class LoadableDashboard extends React.Component {
  render() {
    return ;
  }
}

这一切就是这么简单! 只需使用LoadableDashboard(或任何您命名的组件),当您在应用程序中使用它时,它将自动加载并渲染。fallback是一个占位符组件,用于在加载实际组件时显示。
完整的文档在这里

代码拆分和服务器端渲染

loadable-components包含服务器端渲染的指南。

滚动还原

在早期版本的React Router中,我们提供了对滚动恢复的开箱即用的支持,从那以后人们一直在要求它。 希望本文档可以帮助您从滚动条和路由中获得所需的信息!
浏览器开始以自己的history.pushState处理滚动还原,其处理方式与使用普通浏览器导航时的处理方式相同。它已经可以在Chrome浏览器中使用,而且非常棒,这是滚动恢复规范。
由于浏览器开始处理“默认情况”,并且应用具有不同的滚动需求(例如本网站!),因此我们不提供默认滚动管理功能。 本指南应帮助您实现任何滚动需求。

滚动到顶部

在大多数情况下,您所需要做的只是“滚动到顶部”,因为您有一个较长的内容页面,该页面在导航到该页面时始终保持向下滚动。 使用组件可以轻松处理此问题,该组件将在每次导航时向上滚动窗口:
创建滚动到顶部组件:

import { useEffect } from 'react';
import { useLocation } from 'react-router-dom';
export default function ScrollToTop() {
    const { pathname } = useLocation();
    console.log('pathname=>', pathname);
    useEffect(() => {
        window.scrollTo(0, 0);
    }, [ pathname ]);
    return null;
}

如果您尚未运行React 16.8,则可以使用React.Component子类执行相同的操作:

import React from "react";
import { withRouter } from "react-router-dom";

class ScrollToTop extends React.Component {
  componentDidUpdate(prevProps) {
    if (
      this.props.location.pathname !== prevProps.location.pathname
    ) {
      window.scrollTo(0, 0);
    }
  }

  render() {
    return null;
  }
}

export default withRouter(ScrollToTop);

然后在您的应用程序的顶部渲染它,但是要把它路由器下面:

import React from 'react'
import ReactDOM from 'react-dom';
import { BrowserRouter } from 'react-router-dom';
import ScrollToTop from './ScrollToTop'

function App() {
    return 
        
        

App

} ReactDOM.render(, document.querySelector('#root'));

如果您将标签页接口连接到路由器,那么当他们切换标签页时,您可能不想滚动到顶部。 那么,您需要在的特定位置使用

import { useEffect } from "react";

function ScrollToTopOnMount() {
  useEffect(() => {
    window.scrollTo(0, 0);
  }, []);

  return null;
}

// 使用以下代码将此内容渲染到某处:
// } />
function LongContent() {
  return (
    

Here is my long content page

...

); }

再说一次,如果您运行的React小于16.8,则可以对React.Component子类做同样的事情:

with a React.Component subclass:import React from "react";

class ScrollToTopOnMount extends React.Component {
  componentDidMount() {
    window.scrollTo(0, 0);
  }

  render() {
    return null;
  }
}

// 使用以下代码将此内容渲染到某处:
// } />
class LongContent extends React.Component {
  render() {
    return (
      

Here is my long content page

...

); } }

通用解决方案

对于通用解决方案(以及哪些浏览器已开始在本机实现),我们谈论的是两件事:
1、向上滚动导航,这样就不会启动滚动到底部的新屏幕
2、恢复窗口的滚动位置和“后退”和“前进”单击上的溢出元素(但不单击“链接”单击!)
在某一时刻,我们希望提供一个通用的API。 这就是我们要研究的方向:


  
    

App

I will overflow

首先,ScrollRestoration在导航中向上滚动窗口。其次,它将使用location.key将窗口滚动位置和RestoredScroll组件的滚动位置保存到sessionStorage。然后,在安装ScrollRestoration或RestoredScroll组件时,它们可以从sessionStorage查找其位置。

最棘手的部分是定义一个"opt-out"的API,当你不想滚动窗口时进行管理。例如,如果您在页面内容中浮动了一些选项卡导航,则可能不想滚动到顶部(选项卡可能会滚动到视图之外!)。当我们得知Chrome现在可以为我们管理滚动位置,并意识到不同的应用程序将具有不同的滚动需求时,我们有点迷失了我们需要提供某些东西的信念,尤其是当人们只想滚动到顶部时( 您可以直接将其直接添加到您的应用中)。基于此,我们不再有足够的力气自己完成工作(就像您一样,我们的时间有限!)。 但是,我们很乐意为有志于实施通用解决方案的任何人提供帮助。 一个可靠的解决方案甚至可以存在于项目中。 如果您开始使用它,请与我们联系:)

设计原理

本指南的目的是说明使用React Router时要具有的思维模型。 我们称之为“动态路由”,它与您可能更熟悉的“静态路由”完全不同。

静态路由

如果您使用过Rails,Express,Ember,Angular等,则使用了静态路由。 在这些框架中,您需要在进行任何渲染之前将路由声明为应用初始化的一部分。 React Router pre-v4也是静态的(大部分是静态的)。让我们看一下在express中如何配置路由:

Express路由配置模式:
app.get("/", handleIndex);
app.get("/invoices", handleInvoices);
app.get("/invoices/:id", handleInvoice);
app.get("/invoices/:id/edit", handleInvoiceEdit);

app.listen();

请注意在app监听之前如何声明路由。 我们使用的客户端路由器相似。 在Angular中,您先声明routes,然后在渲染之前将其导入顶级的AppModule中:

// Angular的路由配置样式:
const appRoutes: Routes = [
  {
    path: "crisis-center",
    component: CrisisListComponent
  },
  {
    path: "hero/:id",
    component: HeroDetailComponent
  },
  {
    path: "heroes",
    component: HeroListComponent,
    data: { title: "Heroes List" }
  },
  {
    path: "",
    redirectTo: "/heroes",
    pathMatch: "full"
  },
  {
    path: "**",
    component: PageNotFoundComponent
  }
];

@NgModule({
  imports: [RouterModule.forRoot(appRoutes)]
})
export class AppModule {}

Ember具有常规的route.js文件,该版本会为您读取并导入到应用程序中。 同样,这是在您的应用渲染之前发生的。

// Ember 路由配置样式:
Router.map(function() {
  this.route("about");
  this.route("contact");
  this.route("rentals", function() {
    this.route("show", { path: "/:rental_id" });
  });
});

export default Router;

虽然API是不同的,他们都有着“静态路由”的模式。 React Router也跟进了直到v4。
为了成功使用React Router,您需要忘记所有这些!

未完待续....

你可能感兴趣的:(router,react.js)