GVKun编程网logo

温习react-router(ran温)

1

本文将分享温习react-router的详细内容,并且还将对ran温进行详尽解释,此外,我们还将为大家带来关于''react-router-redux''到''connected-react-rout

本文将分享温习react-router的详细内容,并且还将对ran温进行详尽解释,此外,我们还将为大家带来关于''react-router-redux''到''connected-react-router''、./node_modules/react-router-dom/react-router-dom.js尝试导入错误:未从“ react-router”导出“ Navigate”、Angular 2 router.navigate - Angular 2 router.navigate、angular-ui-router – Angular UI Router – 允许任何查询字符串参数的相关知识,希望对你有所帮助。

本文目录一览:

温习react-router(ran温)

温习react-router(ran温)

原文链接:https://react-guide.github.io...

react-router是一个基于react的路由库,它可以让你向应用中快速的添加视图数据流,同时保持页面与URL之间的同步。

路由配置

1. 不使用React-Router的情形

import React from 'react'
import {render} from 'react-dom'

const About = React.createClass({...})
const InBox = React.createClass({...})
const Home = React.createClass({...})

const App = React.createClass({
    getinitialState() {
        return {
            route: window.location.hash.substr(1)
        }
    },componentDidMount() {
        window.addEventListener('hashchage',()=> {
            this.setState({
                route: window.location.hash.substr(1)
            })
        })
    },render() {
        let Child
        switch (this.state.route) {
          case '/about': Child = About; break;
          case '/inBox': Child = InBox; break;
          default:      Child = Home;
        }
        return (
            <div>
                <h1>App</h1>
                <ul>
                  <li><a href="#/about">About</a></li>
                  <li><a href="#/inBox">InBox</a></li>
                </ul>
                <Child/>
             </div>
        )
    }
})

React.render(<App />,document.body)

如上,当URL的hash部分(指的是#后的部分)变化后,<App>会根据this.state.route来渲染不同的<Child>。现在看起来很直观,但是当你的路由结构复杂,项目变的比较庞大的时候,这种方法可能就不太适合了。
我们看下在使用react-router后的编码结构:

import React from 'react'
import { render } from 'react-dom'

// 首先我们需要导入一些组件...
import { Router,Route,Link } from 'react-router'

const App = React.createClass({
  render() {
    return (
      <div>
        <h1>App</h1>
        {/* 把 <a> 变成 <Link> */}
        <ul>
          <li><Link to="/about">About</Link></li>
          <li><Link to="/inBox">InBox</Link></li>
        </ul>

        {/*
          接着用 `this.props.children` 替换 `<Child>`
          router 会帮我们找到这个 children
        */}
        {this.props.children}
      </div>
    )
  }
})

// 最后,我们用一些 <Route> 来渲染 <Router>。
// 这些就是路由提供的我们想要的东西。
React.render((
  <Router>
    <Route path="/" component={App}>
      <Route path="about" component={About} />
      <Route path="inBox" component={InBox} />
    </Route>
  </Router>
),document.body)

看上面代码我们除去了对hash路由的判断,取而代之的是通过react-router控制了视图的显示。在内部,router会将你树级嵌套格式的<Route>转变成路由配置。我们也可以通过普通对象的方式来替代路由配置:

const routes = {
    path: '/',component: App,childRoutes: [
        {path: 'about',component: About},{path: 'inBox',component: InBox}
    ]
}
React.render(<Router routes={routes}>)

2. 获取URL参数

当渲染组件时,React Router会自动向Route组件中注入一些有用的信息,尤其是路径中动态部分的参数。

const Message = React.createClass({

  componentDidMount() {
    // 来自于路径 `/inBox/messages/:id`
    const id = this.props.params.id

    fetchMessage(id,function (err,message) {
      this.setState({ message: message })
    })
  },// ...

})

3. 路由配置

路由配置是一组指令,用来告诉router如何匹配URL以及匹配后如何执行代码。

import React from 'react'
import { Router,Link } from 'react-router'

const App = React.createClass({
  render() {
    return (
      <div>
        <h1>App</h1>
        <ul>
          <li><Link to="/about">About</Link></li>
          <li><Link to="/inBox">InBox</Link></li>
        </ul>
        {this.props.children}
      </div>
    )
  }
})

const About = React.createClass({
  render() {
    return <h3>About</h3>
  }
})

const InBox = React.createClass({
  render() {
    return (
      <div>
        <h2>InBox</h2>
        {this.props.children || "Welcome to your InBox"}
      </div>
    )
  }
})

const Message = React.createClass({
  render() {
    return <h3>Message {this.props.params.id}</h3>
  }
})

React.render((
  <Router>
    <Route path="/" component={App}>
      <Route path="about" component={About} />
      <Route path="inBox" component={InBox}>
        <Route path="messages/:id" component={Message} />
      </Route>
    </Route>
  </Router>
),document.body)

通过上面的配置,可以看到路由是怎么渲染的:

URL 组件
/ App
/about App->About
/inBox App->InBox
/inBox/messages/:id App->InBox->Message

4. 添加首页

设想一下,当url为/时,我们想渲染一个在App中组件,不过此时App的render中的this.props.children还是undefined。这种情况下,可以使用IndexRoute来设置一个默认页面。

import { IndexRoute } from 'react-router'

const Dashboard = React.createClass({
  render() {
    return <div>Welcome to the app!</div>
  }
})

React.render((
  <Router>
    <Route path="/" component={App}>
      {/* 当 url 为/时渲染 Dashboard */}
      <IndexRoute component={Dashboard} />
      <Route path="about" component={About} />
      <Route path="inBox" component={InBox}>
        <Route path="messages/:id" component={Message} />
      </Route>
    </Route>
  </Router>
),document.body)

此时,App的render中的this.props.children会将是<Dashboard>这个元素。

URL 组件
/ App->Dashboard
/about App->About
/inBox App->InBox
/inBox/messages/:id App->InBox->Message

5. 让UI从URL中解耦出来

如果我们可以将/inBox从/inBox/messages/:id中去除,并且能够让Message嵌套在App-InBox。那我们可以通过绝对路径实现。

React.render((
  <Router>
    <Route path="/" component={App}>
      <IndexRoute component={Dashboard} />
      <Route path="about" component={About} />
      <Route path="inBox" component={InBox}>
        {/* 使用 /messages/:id 替换 messages/:id */}
        <Route path="/messages/:id" component={Message} />
      </Route>
    </Route>
  </Router>
),document.body)

绝对路径可能在动态路由中无法使用

6. 兼容旧的URL

如果改为/inBox/messages/5,这样都会匹配不到路径,会返回一个错误页面,我们可以通过<Redirect>使URL重新正常工作。

import { Redirect } from 'react-router'

React.render((
  <Router>
    <Route path="/" component={App}>
      <IndexRoute component={Dashboard} />
      <Route path="about" component={About} />
      <Route path="inBox" component={InBox}>
        <Route path="/messages/:id" component={Message} />

        {/* 跳转 /inBox/messages/:id 到 /messages/:id */}
        <Redirect from="messages/:id" to="/messages/:id" />
      </Route>
    </Route>
  </Router>
),document.body)

现在,当有人惦记/inBox/message/5这个链接,他们会自动跳转到/message/5。

7. 替换的配置方式

因为route一般被嵌套使用,所以使用JSX这种天然具有简洁嵌套型语法的结构来描它们的关系非常方便。我们也可以使用原生route数组对象。

const routeConfig = [
    {
        path: '/',indexRoute: {
            component: Dashboard
        },childRoutes: [
            { path: 'about',{ path: 'inBox',component: InBox,childRoutes: [
                {path: '/messages/:id',component: Message },{path: 'message/:id',onEnter: function(nextState,replaceState) {
                    replaceState(null,'/messages/' + nextState.params.id)
                }}
            ]}
        ]
    }
]

路由匹配原理

路由由三个属性来决定是否匹配一个URL:

1. 嵌套关系
2. 路径语法
3. 优先级

1. 嵌套关系

React Router使用路由嵌套的概念让你定义view的嵌套集合,当一个URL调用时,整个路由集合中(匹配的部分)都会被渲染。嵌套路由被描述成一种属性结构,Reat-Router会深度优先遍历整个路由配置来寻找一个给定的URL相匹配的路由。

2. 路径语法

路由路径是匹配一个URL的一个字符串模式,大部分的路由路径都可以直接按照字面量理解,但是以下有几个特殊的符号:

1. :paramName -- 匹配一段位于/,?或者#之后的URL.命中的部分将被作为一个参数。
2. () -- 在它内部的内容被认为是可选的
3. * --匹配任意字符串直到命中下一个字符或者整个URL的末尾,并创建要给splat参数。

例子:

<Route path="/hello/:name">         // 匹配 /hello/michael 和 /hello/ryan
<Route path="/hello(/:name)">       // 匹配 /hello,/hello/michael 和 /hello/ryan
<Route path="/files/*.*">           // 匹配 /files/hello.jpg 和 /files/path/to/hello.jpg

3. 优先级

路由算法会根据定义的顺序自顶向下匹配路由,因此,当你拥有两个兄弟路由节点匹配时,你必须确认前一个路由不会匹配后一个路由中的路径。

Histories

React Router时建立在history上的,简而言之,一个history知道如何去监听浏览器地址的变化,并解析这个URL转为location对象,然后router使用它匹配到路由,最后正确的渲染对应组件。

1. borwserHistory
2. hashHistory
3. createMemoryHistory
import {browserHistory} from 'react-router'
render(
  <Router history={browserHistory} routes={routes} />,document.getElementById('app')
)

1. browserHistory

browser history 是使用 React Router 的应用推荐的 history。它使用浏览器中的 History API 用于处理 URL,创建一个像example.com/some/path这样真实的 URL 。

2. hashHistory

Hash history 使用 URL 中的 hash(#)部分去创建形如 example.com/#/some/path 的路由。

默认路由(IndexRoute)与 IndexLink

1. 默认路由

首先,我们看下不使用默认路由的情形:

<Router>
  <Route path="/" component={App}>
    <Route path="accounts" component={Accounts}/>
    <Route path="statements" component={Statements}/>
  </Route>
</Router>

当用户访问/时,App组件被渲染,但组件内的子元素却没有,App内部的this.props.children为undefined。你可以简单的使用{this.props.chidlren || ''}来渲染默认组件。
但现在,Home 无法参与到比如 onEnter hook 这些路由机制中来。 在 Home 的位置,渲染的是 Accounts 和 Statements。 由此,router 允许你使用 IndexRoute ,以使 Home 作为最高层级的路由出现.

<Router>
  <Route path="/" component={App}>
    <IndexRoute component={Home}/>
    <Route path="accounts" component={Accounts}/>
    <Route path="statements" component={Statements}/>
  </Route>
</Router>

现在 App 能够渲染 {this.props.children} 了, 我们也有了一个最高层级的路由,使 Home 可以参与进来。

2. Index Links

如果你在这个 app 中使用 <Link to="/">Home</Link>,它会一直处于激活状态,因为所有的 URL 的开头都是 / 。 这确实是个问题,因为我们仅仅希望在 Home 被渲染后,激活并链接到它。

如果需要在 Home 路由被渲染后才激活的指向 / 的链接,请使用 <IndexLink to="/">Home</IndexLink>

动态路由

对于大型应用来说,一个首当其冲的问题就是所需加载的 JavaScript 的大小。程序应当只加载当前渲染页所需的 JavaScript。有些开发者将这种方式称之为“代码分拆” —— 将所有的代码分拆成多个小包,在用户浏览过程中按需加载。
路由是个非常适于做代码分拆的地方:它的责任就是配置好每个 view。
React Router 里的路径匹配以及组件加载都是异步完成的,不仅允许你延迟加载组件,并且可以延迟加载路由配置。在首次加载包中你只需要有一个路径定义,路由会自动解析剩下的路径。
Route 可以定义 getChildRoutes,getIndexRoute 和 getComponents 这几个函数。它们都是异步执行,并且只有在需要时才被调用。我们将这种方式称之为 “逐渐匹配”。 React Router 会逐渐的匹配 URL 并只加载该 URL 对应页面所需的路径配置和组件。

''react-router-redux''到''connected-react-router''

''react-router-redux''到''connected-react-router''

背景:
redux和react-router两者协同工作会出现,路由变化而store无法感知到,的问题。

react-router-redux :
一. 作用:
react-router-redux 是 redux 的一个中间件,加强了React Router库中history这个实例,以允许将history中接受到的变化反应到state中去。

使用方法1:

使用syncHistoryWithStore包裹browserHistory,当url改变时,会自动触发 LOCATION_CHANGE action,更改store中维护的 locationBeforeTransitions 状态对象,实现store状态的更新。

// 只需要传入react-router中的history以及redux中的store,就可以获得一个增强后的history对象。
// 将这个history对象传给react-router中的Router组件作为props,就给应用提供了观察路由变化并改变store的能力。
import { syncHistoryWithStore, routerReducer } from ''react-router-redux''
const store = createStore(
  combineReducers({
    ...reducers,
    routing: routerReducer
  })
)
const history = syncHistoryWithStore(browserHistory, store)
ReactDOM.render(
  <Provider store={store}>
    <Router history={history}>
      <Route path="/" component={App} />
    </Router>
  </Provider>,
  document.getElementById(‘app'')
)

// 对应的reducer.js
export const LOCATION_CHANGE = ''@@router/LOCATION_CHANGE''

const initialState = {
  locationBeforeTransitions: null
}
  1. 使用方法2:

    手动触发路由的跳转,同时需要。

    直接store.dispatch(push(''/foo'')),会触发 CALL_HISTORY_METHOD 这个action,调用中间件,等同于调用 browserHistory上相应的push方法。

// 触发路由跳转(使用redux action的方式来触发)
import { createStore, combineReducers, applyMiddleware } from ''redux'';
import { routerMiddleware, push } from ''react-router-redux''
// Apply the middleware to the store
const middleware = routerMiddleware(browserHistory)
const store = createStore(
  reducers,
  applyMiddleware(middleware)
)
// 使用dispatch手动触发 push 等操作
store.dispatch(push(''/foo''))

源码的具体实现:

// import 的 push, replace, go, goBack, goForward之类的方法出自: action.js
export const push = updateLocation(''push'')

function updateLocation(method) {
  return (...args) => ({
    type: CALL_HISTORY_METHOD,
    payload: { method, args }
  })
}

//中间件代码
export default function routerMiddleware(history) {
  return () => next => action => {
    if (action.type !== CALL_HISTORY_METHOD) {
      return next(action)
    }

    const { payload: { method, args } } = action
    history[method](...args)       //这里直接改变browserHistory
  }
}

二. react-router-redux原理图

CALL_HISTORY_METHOD,这类 action 一般会在组件内派发,它不负责 state 的修改,通过 routerMiddleware 后,会被转去调用 history。

面临的问题:
react-router-redux 只兼容 react-router 2.x and 3.x,所以要改成使用 connected-react-router 来兼容 react-router 4.x。

解决:

把之前 react-router-redux 中 store.dispatch(push(''/foo'')) 这么使用的,直接改成 history.push(''/foo'') 之类的。

参考文章:
https://blog.csdn.net/weixin_... React 的路由状态管理

./node_modules/react-router-dom/react-router-dom.js尝试导入错误:未从“ react-router”导出“ Navigate”

如何解决./node_modules/react-router-dom/react-router-dom.js尝试导入错误:未从“ react-router”导出“ Navigate”

./node_modules/react-router-dom/react-router-dom.js Attempted import error: ''Navigate'' is not exported from ''react-router''.

react-router-dom的版本是6.0.0-alpha.2,而react-router是5.2.0。 两者均已正确安装。我不确定如何解决此错误。有人可以给我任何可能的解决方法吗?

我的代码中甚至没有<Navigate to=?>行。

解决方法

为什么只安装两个都需要,这可以工作

  1. 执行npm删除react-router
  2. 删除node_modules
  3. 纱线安装或npm安装和
  4. 启动纱线或启动npm

Angular 2 router.navigate - Angular 2 router.navigate

Angular 2 router.navigate - Angular 2 router.navigate

问题:

I''m trying to navigate to a route in Angular 2 with a mix of route and query parameters. 我正在尝试使用路由和查询参数的组合导航到 Angular 2 中的路由。

Here is an example route where the route is the last part of the path: 这是一个示例路线,其中路线是路径的最后一部分:

{ path: '':foo/:bar/:baz/page'', component: AComponent }

Attempting to link using the array like so: 尝试使用数组进行链接,如下所示:

this.router.navigate([''foo-content'', ''bar-contents'', ''baz-content'', ''page''], this.params.queryParams)

I''m not getting any errors and from what I can understand this should work. 我没有收到任何错误,据我所知,这应该可行。

The Angular 2 docs (at the moment) have the following as an example: Angular 2 文档(目前)具有以下示例:

{ path: ''hero/:id'', component: HeroDetailComponent }

[''/hero'', hero.id] // { 15 }

Can anyone see where I''m going wrong? 谁能看到我哪里出错了? I''m on router 3. 我在路由器 3 上。


解决方案:

参考: https://stackoom.com/en/question/2Zzgr

angular-ui-router – Angular UI Router – 允许任何查询字符串参数

angular-ui-router – Angular UI Router – 允许任何查询字符串参数

我使用的是Angular UI路由器,这在大多数情况下效果很好.但是,我有一种情况,我不知道提前查询字符串参数的名称.

通常使用UI路由器,您可以定义类似这样的路由:

$stateProvider.state('test',{
	url: '/test?testQueryStringParam',templateUrl: 'Test.html',controller: 'TestController'
});

然后在我的控制器中,我可以使用$stateParams访问testQueryStringParam.

但是,使用UI路由器,您无法访问路径定义中未指定的任何查询字符串参数.

Angular框架附带的路由器确实允许您这样做.所以我尝试使用我的UI路由器定义的$location服务.这确实很有效.

当我想添加查询字符串参数时,我使用:

$location.search("paramName","paramValue");

当我想获取查询字符串值时,我只是使用:

$location.search()

这会更新URL,但不会重新实例化控制器(如$state.go($state.current,{},{reload:true})).这似乎不是一个大问题,因为我可以自己重新加载数据.但是,如果您在浏览器中使用后退按钮,它将再次更改URL,但不会重新实例化控制器.

无论如何还有

>我可以使用UI路由器来实现这一点吗?
>获取使用$location实际重新实例化控制器的解决方法.

作为最后的手段,我也尝试指导更新window.location,但这会刷新整个页面,这是不可接受的.

谢谢

您可以传递未在URL中显示的非url参数
$stateProvider.state('test',{
    url: '/test?testQueryStringParam',params: {
    optParam: null,},controller: 'TestController'
});

如您所见,optParam是一个可选参数,其默认值为null,在URL中不可见

您可以使用$stateParams在控制器中访问此参数

$stateParams.optParam

这是一个有用的blog

关于温习react-routerran温的介绍已经告一段落,感谢您的耐心阅读,如果想了解更多关于''react-router-redux''到''connected-react-router''、./node_modules/react-router-dom/react-router-dom.js尝试导入错误:未从“ react-router”导出“ Navigate”、Angular 2 router.navigate - Angular 2 router.navigate、angular-ui-router – Angular UI Router – 允许任何查询字符串参数的相关信息,请在本站寻找。

本文标签: