Open LingYanSi opened 8 years ago
react-router 为react提供路由管理,看起来如下伪代码
import { createHistory, useBasename } from 'history'
import {Router , Link, Route, } from 'react-router'
// history的作用在于,使用html5的history api 而不是使用hash
const history = useBasename(createHistory)({
basename: ''
});
class App extends Component{
constructor(){
super(...arguments)
}
render(){
return <div>
<Nav />
<div className="main">
<Sidebar/>
<div className="content">
{this.props.children}
</div>
</div>
<Footer />
</div>
}
}
render((
<Router history={history}>
<Route path='/' component={ App }>
<Route path='home' component={ Home } />
<Route path='article' component={ Article } />
<Route path='article/:id' component={ ArticleInfo } />
<Route path='message' component={ Message } />
<Route path='about' component={ About } />
{/* path='*' 表示默认路由 */}
<Route path='*' component={ NotFound } />
</Route>
</Router>
) ,
document.getElementById('app')
)
redux是flux的实现,主要用于解决store -> view -> action -> store单向数据流的问题 在react中,通常的做法是每个组建都有很多的state,当应用比较小的时候,做起来好像没有什么问题 一旦应用打起来后,就比较麻烦了,比如说子组件去更改兄弟组件、父组件、关系不太大的组建的状态,最终会导致逻辑混乱,不易管理
其实,我们应该明白,view只是数据的展现,用户可以通过view触发一个action,整个action可能会修改数据,数据修改后view可能会发生改变 store -> view -> action -> store
从函数式编程的角度来讲,我们期望任何时间,同样的输入会得到同样的输出
对于react来讲,我么可以把store通过父组件注入,子组件的数据通过props由父组件传递过来 不过总是写props是不是有点太恶心呢? 可以不可以子组件的数据也是从store获取呢? 这样做的话,也是会变得混乱起来,因为数据来源不统一?有待观察
整个应用的数据来源
action经过reducer返回一个新的store
reducer其实就是一个action的switch,返回一个新的store
action通过dispatch派发
中间件,通过修改dispatch而获得,因为action是通过dispatch派发的,因此我们可以在dispatch内拦截action,在action被reducer会里后,还可以对返回值进行处理,不过一般我们是不会通过中间件对store进行修改的,更多的是做logger之类的事情,也可以通过中间件完成异步任务
import React,{Component} from 'react'
class Router extends Component{
componentDidMount(){
Router.self = this
}
getChild(children){
// return this.props.children
return React.Children.map( children, Item => {
// 这里是一个路由的匹配校验
if(Item.props.path === Router.currentURL){
let Com = Item.props.component
// 把url参数传递给组件
return <Com params={'111'}>
{this.getChild(Item.props.children)}
</Com>
}
})
}
render(){
return <div>
{this.getChild(this.props.children)}
</div>
}
}
Router.urlChange = function ( url) {
// url变化后,强制更新Router
Router.currentURL = url
Router.self.forceUpdate()
}
Router.currentURL = '/'
class Link extends Component{
constructor(){
super()
}
render(){
let props = this.props
return <a onClick={Router.urlChange.bind(this, props.to)}>
{props.title}
{props.children}
</a>
}
}
class Route extends Component{
render() {
// 匹配路由,如果匹配的上就渲染,不然就return null
return null
}
}
export {Router, Route, Link}
import { Router, Route, Link } from 'module/router/index.js'
class Step1 extends Component{
render(){
return <div>
念去去,千里烟波
<Link to="/step2">下一步</Link>
{this.props.children}
</div>
}
}
class Step2 extends Component{
render(){
console.log(this.props.params);
return <div>
哈哈哈哈哈
<Link to="/">下一步</Link>
</div>
}
}
class Home extends Component{
render(){
return <Router>
<Route path="/" component={Step1}>
<Route path="/" component={Step2}></Route>
</Route>
<Route path="/step2" component={Step2}></Route>
</Router>
}
}
import Fuck from './fuck'
class You extends Component{
render(){
let data = {
name: '薄熙来',
job: '平西王'
}
return <div id="shenfen" color="red">
<Fuck {...data}/>
</div>
}
}
其中的
...data
属于es6的spread[解构赋值]语法
首先从react的jsx语法说起 上面的代码会被babel转译成如下伪代码
let You = React.createElement(
'div',
{id:'shenfen', color:'red'},
React.createElement(
Fuck,
{name:'薄熙来', job:'平西王'}
)
)
也就是说
{...data} => {name: '薄熙来', data: '平西王'}
再说spread语法
let sth = {a: 111, b:6666}
let data = {...sth, {b:22}}
data // {a:111, b:22} 前面的属性会被后面的属性覆盖
写react也有一段时间,但发现其实并没有完全理解React,甚至对于其原理也是理解的比较模糊
class Fuck extends Component{
render(){
return <div className="fuck">
达到反革命
</div>
}
}
//Fuck是一个组建component
// 渲染
React.render(Fuck, rootElement)
//render方法接收到Fuck,执行后,会得到render方法返回的对象
//render方法会被转译成如下代码
React.createElement('div'
,{'class': 'fuck'},
React.createElement(
'text',
{}
)
)
class A extends Component{
fuck(){
console.log(this) // this指向div
}
// 属性
state = {
name: '嘿嘿'
}
static ni = '静态属性'
static you = ()=>{
console.log('静态方法')
}
// 方法
fuck = () => {
console.log(this) // this指向组件的实例
}
render(){
return <div onClick={this.fuck}></div>
}
}
function tap(func){
// 判断及其类型
if(window.navigator.userAgent.toLowerCase().match(/phone|android|ipad|ipod/g)){
var notMove = true
return {
onTouchEnd(...args){
notMove && func(...args)
notMove = true
},
onTouchMove(){
notMove = false
}
}
} else {
return {
onClick: func
}
}
}
export default tap
import onTap from 'tap'
class A extends Component{
tap = ()=>{
alert('被点击了')
}
render(){
return <div {...onTap(this.tap)}></div>
}
}
如果在a标签上绑定了Tap事件,而在父元素上也绑定了Tap事件 如果没有组织事件冒泡,在切换到新页面之前,老页面会被销毁,但此时React的时间系统依然会向父元素派发事件 当然,react会先校验下,这个元素是否存在,如果不在,会throw一个错误
Uncaught Invariant Violation: React DOM tree root should always have a node reference.
对于切换页面的Tap事件,请阻止事件冒泡!!!!
React 代码在这里