项目构建
- git && github
- nodejs
- webstrom
- chrome
- shell
- babel es6 plugin preset
- webpack
跑通项目
- 使用es6语法和react,需要babe来编译;npm i babel-core babel-loader babel-preset-es2015 babel-preset-react --save-dev
babel-preset-stage-0 用来解决尖头函数不兼容的问题; - index.html作为模版,需下载:html-webpack-plugin
jsx语法
- 就是js+xml语法的混合;
- 顶层标签只允许出现一个;
- 注释的写法:{/这是jsx中的注释/}
- class需要写为 className
- label中的for,需要改为htmlFor
- jsx样式的写法
render(){
const name="圆梦源123";
const styles={
fontSize:'30px',
color:'red'
};
return(
<div style={styles}>
{/*这是jsx中的注释*/}
<h1>你好,{name}!</h1>
</div>
)
}
react虚拟DOM
- 什么是虚拟DOM(Virtual DOM)
虚拟DOM保存了真实DOM的层次关系和一些基本属性,与真实DOM一一对应。虚拟DOM的工作原理是:数据 -> 全新的虚拟DOM -> 与上一个状态的虚拟DOM进行diff算法比较,得到一个Patch -> 把这个Patch打到浏览器的DOM上。所以虚拟DOM叫的挺高端,其实就有点类似DocumentFragment,把多次DOM操作做一个批处理。 - 什么是diff算法?
- 现在前端框架比的是算法。diff算法说白了就是比较两个文件不同的算法。
- 比较前后两个状态虚拟DOM的diff算法,可以简单分为三部分,我总结了三句话
- 虚拟DOM树同一位置不同类型(标签不同)的节点:删除前一状态节点,插入后一状态节点,哪怕节点有子节点也这样做;
- 虚拟DOM树同一位置相同类型但个别属性不同的节点,对前一状态节点进行属性重设;
- 列表节点(就是我们用循环创建的类似Array的节点),如果没有unique key(没有控制台会报警告的)就按照前面两种方式解决,如果有unique key就找到key相应的位置插入节点。
- 虚拟DOM快在哪里?
- js计算肯定要比DOM操作快啊,每次DOM操作都很有可能引起回流(Reflow)和重绘(Repaint)啊。当然浏览器也不傻,不是你每次操作DOM浏览器都重绘一次,一般浏览器会按照时间或次数间隔进行DOM操作的批处理。
- 到底是浏览器优化后的DOM批处理快,还是React的虚拟DOM+优化diff算法快?这个不清楚,根据博客上内容,React的优化更人性化、也更快。速度快肯定是虚拟DOM的一个优点;
- 主要是主动权不同:浏览器对DOM操作批处理的主动权不在前端人员手中,React将这种批处理的时机选择交到了我们手中,看我们什么时候想render页面。
对react组件添加样式
- 写在css文件中,通过import导入,给标签className赋值;
react中的属性props
-
组件定义和导出
-
props 组件间的数据流动
- 定义参数规则 prop-types模块的运用
- 默认参数的设置 defaultProps
//参数规格的设定 Profile.propTypes={ url:propTypes.string, name:propTypes.string, id:propTypes.number.isRequired }; //参数默认值;可传可不传 Profile.defaultProps={ name:'leilei' };
-
state 管理组件自己内部的数据
var MyComponent=function(props){
var state={
}
return "v dom"
}
refs引用DOM元素:range举例
update=(e)=>{
console.log(findDOMNode(this.refs.one).value)
this.setState({
name:e.target.value
})
}
子组件children属性
-
this.props.children
- 可以拿到我们传给该组件下的所有的元素;
比如该组件叫List,我们就能拿到h1和h2
<List> <h1>12233</h1> <h2>12233</h2> </List>
- 可以拿到我们传给该组件下的所有的元素;
-
React.children
- forEach
- map
//先导入children: import {Children} from React let node=Children.map(this.props.children,(item)=>{ return <li>{item}</li> });
react生命周期图
react-router内容介绍,我们使用3.0.5版本
-
打通基本开发环境
-
基于react-router跑通基本路由
- Router:整个路由相关的配置
- Route:具体的路由
- hashHistory:在前端通过路由展现UI
<Router history={hashHistory}> <Route path="/" components={App}></Route> <Route path="/contact" components={Contact}></Route> </Router>
-
使用Link组件进行导航切换:类似于a链接
-
组件和路由的嵌套使用
- 多个组件的嵌套组合,构成一个路由对应的页面;
index->App page1->App+Contact page2->App+About
- 结合
this.props.children
; 它拿的是当前组件下的子组件;
-
activeClassName和activeStyle设置路由激活状态
- 当你访问一个路由,通过路由的设置,可以实现页面的跳转;
- activeClassName - 相当于外链的css样式
- activeStyle - 相当于行内样式
- 小实战:封装导航组件
-
params路由参数
- 路由变量设置和获取
/concat/footer /concat/header /concat/:message/:haha
通过{this.props.params.message} {this.props.params.haha} 获取对应的路由参数; 以后传路由,必须按我们提前设置好的规则传递;
-
更复杂的路由嵌套结合
-
IndexRoute的使用
- 在解释默认路由(IndexRoute)的用例之前,我们来设想一下,一个不使用默认路由的路由配置是什么样的?
<Router> <Route path="/" component={App}> <Route path="/about" component={About}></Route> <Route path="/contact" component={contact}></Route> </Route> </Router>
当用户访问/时,App组件被渲染,但组件內的子元素却没有,App内部的this.props.children为undefined,这个时候,我们只可以简单的使用
{this.props.children||}
来渲染一些默认的UI组件;- IndexRoute
<Router history={hashHistory}> <Route path="/" components={App}> {/*设置默认路由*/} <IndexRoute components={Home}/> <Route path="/contact" components={Contact}/> <Route path="/about" components={About}/> </Route> </Router>
-
IndexLink的使用
<IndexLink to="/" activeStyle={{color:'pink'}}>首页</IndexLink> <Link to="/">Home</Link>
会匹配任何以/开始的子路由,但是,我们访问的/路由,只希望展示Home组件;
-
路由重定向 Redirect
<Redirect from="/about" to="/about/react"></Redirect>
-
如何使用browserHistory
- react-router 是基于history构建的,利用history属性来监听浏览器地址栏的变化,并且,将URL进行解析后放入到location对象中,从而给react-router提供UI和路由之间的匹配;
- 三种history属性类型
- hashHistory
- 不需要你配置服务器即可使用
- 不支持服务端渲染
- 不建议在生产环境使用
- browserHistory 棒棒!!
- 通过URL变化来改变路由的,调用的是浏览器的History
- 一般用于线上生产环境
- createMemoryHistory
- Memory history 并不会从地址栏中操作或读取,它能够帮助我们完成服务器端的渲染,或者用于测试以及其他渲染环境(比如React Native),和其他两种不一样的是,我们需要在内存中创建history对象来使用
- createHashHistory & createBrowserHistory
- hashHistory
-
webpack后段服务器
- 在package.json中配置上 --history-api-fallback
"start": "webpack-dev-server --progress --colors --content-base dist --history-api-fallback"
-
navigating 路由之间的切换
- Link
- browserHistory
//handleSubmit通过form的onSubmit={this.handleSubmit} handleSubmit(e){ e.preventDefault();//阻止form表单同步的提交; const username=e.target.elements[0].value; const repo=e.target.elements[1].value; const path=`/about/${username}/${repo}`; browserHistory.push(path); }
- this.context.router
//1:表单的 onSubmit提交后出发的handleSubmit事件; handleSubmit(e){ e.preventDefault();//阻止form表单同步的提交; const username=e.target.elements[0].value; const repo=e.target.elements[1].value; const path=`/about/${username}/${repo}`; this.context.router.push(path) }
//2:设置contextTypes;注意,这里不兼容react.PropTypes;必须下载prop-types插件; App.contextTypes={ router:PropTypes.object }; export default App;
Confirm Navigation
- 路由跳转前确认,场景:询问是否保存数据,转场动画等;
this.context.router.setRouteLeaveHook
//组件中
componentDidMount(){
this.context.router.setRouteLeaveHook(this.props.route,this.leaveHook)
}
leaveHook(nextLocation){
console.log(nextLocation)
return 'you want leave?'
}
//contextTypes的设置
Contact.contextTypes={
router:propTypes.object
};
网友评论