react路由深度解析
先看一段代码能否秒懂很重要
这是app.js 全局js的入口
import React from 'react'
import { render } from 'react-dom'
import { Router, browserHistory } from 'react-router' import withExampleBasename from '../withExampleBasename'
import './stubs/COURSES' const rootRoute = {
childRoutes: [ { //子路由
path: '/',
component: require('./components/App'),
childRoutes: [
require('./routes/Calendar'), //当前目录下有这么几个子路由
require('./routes/Course'),
require('./routes/Grades'),
require('./routes/Messages'),
require('./routes/Profile')
]
} ]
} render((
<Router
history={withExampleBasename(browserHistory, __dirname)}
routes={rootRoute}
/>
), document.getElementById('example'))
以上面的calendar为例子 calendar下面有component 和index.js 同样其他如course grades等下面也一样
index.js
module.exports = {
path: 'calendar',
getComponent(nextState, cb) {
require.ensure([], (require) => {
cb(null, require('./components/Calendar'))
})
}
}
component下面有calendar.js
import React, { Component } from 'react'
class Calendar extends Component {
render() {
const events = [
{ id: 0, title: 'essay due' }
]
return (
<div>
<h2>Calendar</h2>
<ul>
{events.map(event => (
<li key={event.id}>{event.title}</li>
))}
</ul>
</div>
)
}
}
module.exports = Calendar
怎么样找到诀窍了吗 /routes/calendar/index.js +component/calendar.js /routes/grades/index.js +component/grades.js
找到规律了吧 !!
来一个稍微复杂的路由
(这是全局的变量入口) COURSE.JS
global.COURSES = [
{
id: 0,
name: 'React Fundamentals',
grade: 'B',
announcements: [
{
id: 0,
title: 'No class tomorrow',
body: 'There is no class tomorrow, please do not show up'
}
],
assignments: [
{
id: 0,
title: 'Build a router',
body: 'It will be easy, seriously, like 2 hours, 100 lines of code, no biggie',
grade: 'N/A'
}
] }, {
id: 1,
name: 'Reusable React Components',
grade: 'A-',
announcements: [
{
id: 0,
title: 'Final exam next wednesday',
body: 'You had better prepare'
}
],
assignments: [
{
id: 0,
title: 'PropTypes',
body: 'They aren\'t for you.',
grade: '80%'
},
{
id: 1,
title: 'Iterating and Cloning Children',
body: 'You can totally do it.',
grade: '95%'
}
]
}
]
Course路由下面有子路由 他的目录结构 /routes/course/index.js +component(course.js+nav.js+dashborad.js)+ routers/(assignments + announcement +grade.js)
瞬间有点凌乱 有木有 往下看就明白了
course.js
/*globals COURSES:true */
import React, { Component } from 'react'
import Dashboard from './Dashboard'
import Nav from './Nav' const styles = {} styles.sidebar = {
float: 'left',
width: 200,
padding: 20,
borderRight: '1px solid #aaa',
marginRight: 20
} class Course extends Component {
render() {
let { sidebar, main, children, params } = this.props
let course = COURSES[params.courseId] //这是啥? 根据前面导航条转过来的
let content
if (sidebar && main) { //根据条件 初始化组件内容
content = (
<div>
<div className="Sidebar" style={styles.sidebar}>
{sidebar}
</div>
<div className="Main" style={{ padding: 20 }}>
{main}
</div>
</div>
)
} else if (children) {
content = children
} else {
content = <Dashboard /> //走的是这一步
} return (
<div>
<h2>{course.name}</h2>
<Nav course={course} /> //吸进来的一个组件 确定是去哪里 announcement assignment grades
{content}
</div>
)
}
} module.exports = Course
貌似还有点迷糊 继续往下看吧
nav.js
import React, { Component } from 'react'
import { Link } from 'react-router'
const styles = {}
styles.nav = {
borderBottom: '1px solid #aaa'
}
styles.link = {
display: 'inline-block',
padding: 10,
textDecoration: 'none'
}
styles.activeLink = {
...styles.link,
color: 'red'
}
class Nav extends Component {
render() {
const { course } = this.props
const pages = [
[ 'announcements', 'Announcements' ],
[ 'assignments', 'Assignments' ],
[ 'grades', 'Grades' ]
]
return (
<nav style={styles.nav}>
{pages.map((page, index) => (
<Link
key={page[0]}
activeStyle={index === 0 ? { ...styles.activeLink, paddingLeft: 0 } : styles.activeLink}
style={index === 0 ? { ...styles.link, paddingLeft: 0 } : styles.link}
to={`/course/${course.id}/${page[0]}`} //这里是3个导航的跳转 /course/${course.id}/announcement 去往announcements assignments grades
>{page[1]}</Link>
))}
</nav>
)
}
}
export default Nav
来看一下router/announcement(index.js + component + router)
index.js 文件
module.exports = {
path: 'announcements',
getChildRoutes(partialNextState, cb) {
require.ensure([], (require) => {
cb(null, [
require('./routes/Announcement') //这又是一个子路由
])
})
},
getComponents(nextState, cb) {
require.ensure([], (require) => {
cb(null, {
sidebar: require('./components/Sidebar'),
main: require('./components/Announcements') //依赖的组件
})
})
}
}
看到这里是否有点明白了 就像洋葱一层一层拨动我的心。。。还没完呢
component/announcement.js
import React, { Component } from 'react'
class Announcements extends Component {
render() {
return (
<div>
<h3>Announcements</h3>
{this.props.children || <p>Choose an announcement from the sidebar.</p>} //这个props在哪里找呀
</div>
)
}
}
module.exports = Announcements
component/sidebar.js
import React, { Component } from 'react'
import { Link } from 'react-router'
class AnnouncementsSidebar extends Component {
render() {
let { announcements } = COURSES[this.props.params.courseId] //注意这种es6的语法 取得是里面announcements的直
return (
<div>
<h3>Sidebar Assignments</h3>
<ul>
{announcements.map(announcement => (
<li key={announcement.id}>
<Link to={`/course/${this.props.params.courseId}/announcements/${announcement.id}`}>
{announcement.title} //这个到了最后了
</Link>
</li>
))}
</ul>
</div>
)
}
}
module.exports = AnnouncementsSidebar
还没完呢 还有个 router-anouncement /index.js + announcement.js 的路由
看index.js 里面的内容
module.exports = {
path: ':announcementId', //终于真相大白了 !!
getComponent(nextState, cb) {
require.ensure([], (require) => {
cb(null, require('./components/Announcement'))
})
}
}
在看最里面的组件announcement.js
import React, { Component } from 'react'
class Announcement extends Component {
render() {
let { courseId, announcementId } = this.props.params //这个很关键 怎么着呢 说白了就是 地址的参数 ${courseId} ${announceId}
let { title, body } = COURSES[courseId].announcements[announcementId]
return (
<div>
<h4>{title}</h4>
<p>{body}</p>
</div>
)
}
}
module.exports = Announcement
我们大概可以看出来 这个路由到底是如何运作了 还有些细节问题我们继续看
整理一下思路 再出发
1. 第一个app.js 确定根目录 /
2. /calendar /course /message /profile 这都是二级目录 下面都有一个 index.js 指定当前的路径 如course/index.js 指定path:course;
3./course/${courseiD}/announcement/${announcementId} /course/${courseiD}/assignment/${assignmentId} 这是 深层次的
4./course/calendar course/grades 这是浅层次的
最后是关键的全局组件
app.js
import React, { Component } from 'react'
import Dashboard from './Dashboard'
import GlobalNav from './GlobalNav'
class App extends Component {
render() {
return (
<div>
<GlobalNav />
<div style={{ padding: 20 }}>
{this.props.children || <Dashboard courses={COURSES} />} //如果该属性没有children 就render dashboard
</div>
</div>
)
}
}
module.exports = App
dashboard.js
import React, { Component } from 'react'
import { Link } from 'react-router'
class Dashboard extends Component {
render() {
const { courses } = this.props
return (
<div>
<h2>Super Scalable Apps</h2>
<p>
Open the network tab as you navigate. Notice that only the amount of
your app that is required is actually downloaded as you navigate
around. Even the route configuration objects are loaded on the fly.
This way, a new route added deep in your app will not affect the
initial bundle of your application.
</p>
<h2>Courses</h2>{' '}
<ul>
{courses.map(course => (
<li key={course.id}>
<Link to={`/course/${course.id}`}>{course.name}</Link> //这里会根据当前id去不同的course页面
</li>
))}
</ul>
</div>
)
}
}
export default Dashboard
globalNav.js 全局导航
import React, { Component } from 'react'
import { Link } from 'react-router'
const dark = 'hsl(200, 20%, 20%)'
const light = '#fff'
const styles = {}
styles.wrapper = {
padding: '10px 20px',
overflow: 'hidden',
background: dark,
color: light
}
styles.link = {
padding: 11,
color: light,
fontWeight: 200
}
styles.activeLink = {
...styles.link,
background: light,
color: dark
}
class GlobalNav extends Component {
constructor(props, context) {
super(props, context)
this.logOut = this.logOut.bind(this)
}
logOut() {
alert('log out')
}
render() {
const { user } = this.props
return (
<div style={styles.wrapper}>
<div style={{ float: 'left' }}>
<Link to="/" style={styles.link}>Home</Link>{' '} // 回到根目录
<Link to="/calendar" style={styles.link} activeStyle={styles.activeLink}>Calendar</Link>{' '}
<Link to="/grades" style={styles.link} activeStyle={styles.activeLink}>Grades</Link>{' '}
<Link to="/messages" style={styles.link} activeStyle={styles.activeLink}>Messages</Link>{' '}
</div>
<div style={{ float: 'right' }}>
<Link style={styles.link} to="/profile">{user.name}</Link> <button onClick={this.logOut}>log out</button>
</div>
</div>
)
}
}
GlobalNav.defaultProp= {
user: {
id: 1,
name: 'Ryan Florence'
}
}
export default GlobalNav
好吧 现在头绪出来了吧 我反正有点眉目了
1.首先是index.html 有个globalnav / /calendar /grades /message /profile 分别去向 主页 日历页 年级页 信息页 详情页
2.如果 找不到props.children 就会渲染course 也会根据当前的courseid去往相应页
好吧 今天就这么多 让我好好捋捋。。。
react路由深度解析的更多相关文章
- Kafka深度解析
本文转发自Jason’s Blog,原文链接 http://www.jasongj.com/2015/01/02/Kafka深度解析 背景介绍 Kafka简介 Kafka是一种分布式的,基于发布/订阅 ...
- VueRouter 源码深度解析
VueRouter 源码深度解析 该文章内容节选自团队的开源项目 InterviewMap.项目目前内容包含了 JS.网络.浏览器相关.性能优化.安全.框架.Git.数据结构.算法等内容,无论是基础还 ...
- Kafka深度解析(如何在producer中指定partition)(转)
原文链接:Kafka深度解析 背景介绍 Kafka简介 Kafka是一种分布式的,基于发布/订阅的消息系统.主要设计目标如下: 以时间复杂度为O(1)的方式提供消息持久化能力,即使对TB级以上数据也能 ...
- React路由-基础篇
React-Router-DOM ReactRouter网址, 安装 -npmjs找到react-router-dom -yarn add react-router-dom 基本使用方法 1.创建一个 ...
- 简单的说一下react路由(逆战班)
现代前端大多数都是SPA(单页面程序),也就是只有一个HTML页面的应用程序,因为它的用户体验更好,对服务器压力更小,所以更受欢迎,为了有效的使用单个页面来管理原来多页面的功能,前端路由应运而生. 前 ...
- 七天接手react项目 系列 —— react 路由
其他章节请看: 七天接手react项目 系列 react 路由 本篇首先讲解路由原理,接着以一个基础路由示例为起点讲述路由最基础的知识,然后讲解嵌套路由.路由传参,最后讲解路由组件和一般组件的区别,以 ...
- ASP.NET路由模型解析
大家好,我又来吹牛逼了 ~-_-~ 转载请注明出处:来自吹牛逼之<ASP.NET路由模型解析> 背景:很多人知道Asp.Net中路由怎么用的,却不知道路由模型内部的运行原理,今天我就给大家 ...
- [WebKit内核] JavaScript引擎深度解析--基础篇(一)字节码生成及语法树的构建详情分析
[WebKit内核] JavaScript引擎深度解析--基础篇(一)字节码生成及语法树的构建详情分析 标签: webkit内核JavaScriptCore 2015-03-26 23:26 2285 ...
- 第37课 深度解析QMap与QHash
1. QMap深度解析 (1)QMap是一个以升序键顺序存储键值对的数据结构 ①QMap原型为 class QMap<K, T>模板 ②QMap中的键值对根据Key进行了排序 ③QMap中 ...
随机推荐
- 依赖注入的威力,.NET Core的魅力:解决MVC视图中的中文被html编码的问题
有园友在博问中提了这样一个问题 —— .NET Core 中文等非英文文字html编码输出问题,到我们的 ASP.NET Core 项目中一看,也是同样的问题. 比如下面的Razor视图代码: @{ ...
- Java虚拟机10:类加载器
类与类加载器 虚拟机设计团队把类加载阶段张的"通过一个类的全限定名来获取此类的二进制字节流"这个动作放到Java虚拟机外部去实现,以便让应用程序自己决定如何去获取所需要的类.实现这 ...
- 冲刺阶段 day11
项目进展:系部,专业,班级管理这三项没有学生,教师管理部分输入项目多,所以窗体搭建比较简单,代码也简单一些,进行的还算顺利,有了之前的编写经验,很多代码可以直接copy过来,越进行编写越顺利了,已经进 ...
- 第二次作业:Github的使用
Github的使用 一·注册: 要想使用github第一步当然是注册github账号了.之后就可以创建仓库了(免费用户只能建公共仓库),Create a New Repository,填好名称 ...
- 【读书笔记】.Net并行编程高级教程--Parallel
一直觉得自己对并发了解不够深入,特别是看了<代码整洁之道>觉得自己有必要好好学学并发编程,因为性能也是衡量代码整洁的一大标准.而且在<失控>这本书中也多次提到并发,不管是计算机 ...
- hadoop研究:mapreduce研究前的准备工作
继续研究hadoop,有童鞋问我,为啥不接着写hive的文章了,原因主要是时间不够,我对hive的研究基本结束,现在主要是hdfs和mapreduce,能写文章的时间也不多,只有周末才有时间写文章,所 ...
- 将不确定变为确定~transactionscope何时提升为分布式事务?(sql2005数据库解决提升到MSDTC的办法)
回到目录 对于transactionscope不了解的同学,可以看我的相关文章 第二十六回 将不确定变为确定~transactionscope何时提升为分布式事务? 第二十七回 将不确定变为确 ...
- Node.js入门:事件机制
Evented I/O for V8 JavaScript 基于V8引擎实现的事件驱动IO. 事件机制的实现 Node.js中大部分的模块,都继承自Event模块(http://n ...
- iOS中app启动闪退的原因
这种情况应和所谓的内存不足关系不大,很少有程序会在初始化时载入大量内容导致崩溃,并且这类问题也很容易在开发阶段被发现,所以内存不足造成秒退的可能性低(内存不足退,通常是程序用了一段时间,切换了几个画面 ...
- demo
NGUI demo:http://112.124.104.173/killer/demo/demo.html 网络游戏架构(服务器放在阿里云,有时连接不上可能是服务器没有开) 只是测试框架,美术都是本 ...