目录
1、script。
2、jsx语法
3、绑定事件
4、函数组件
5、解析html
6、遍历
7、判断
8、slot插值
9、jsx编译
10、创建组件---createClass
11、创建组件---component(es6)
12、组件通信
13、表单内容
14、性能优化
15、路由
16、路由传参
17、生命周期
18、key的作用
19、状态(state)和属性(props)之间有何不同
20、虚拟dom
21、为什么说虚拟dom会提高性能?
22、diff算法
23、dva:js和jsx的区别
24、dva:路由跳转
25、刷新拦截
正文
1、script。默认type='text/javascript'
- <script type='text/babel'>,页面在加载时会被browser.js编译成真正的js插入页面中。
2、jsx语法
- jsx是js和html混合的写法,遇到<>以html形式进行解析,遇到{}以js形式进行解析。
3、绑定事件
- 不传参:例:<div onClick={f1}></div>
- 传参:例:<div onClick={(e)=>{f2(100,e)}}></div>
4、函数组件(将模板return出去)
普通函数调用:例:{Ipt()}
组件形式调用:例:<Ipt a='10' b={20}></Ipt>。参数用props接收。定义时首字母大写。
5、解析html
dangerouslySetInnerHTML(==v-html):例:
<div dangerouslySetInnerHTML={{__html:str_x}}></div>
6、遍历
7、判断
8、slot插值
- 通过props.children获得。
9、jsx编译
var x = <div id="box"> hello </div>
var x = React.createElement("div",{id:"box"},[React.createElement("em",{key:1},"hello"),React.createElement("span",{key:2},"span")])
10、创建组件---createClass
- createClass:React.createClass({})
- getInitialState:组件内部的状态,可相应的,是一个function返回对象。例:
getInitialState(){
return {
num:0
}
}
- render:定义模板。this指向组件实例。例:
render(){
return(
<div>
<button onClick={()=>{this.increase(100)}}></button>
</div>
)
}
- 方法。方法内部本身为null,改变this指向后,this指向组件实例。例:
increase(a){
this.setState({ // 修改状态;访问状态:this.state.val
num:this.state.num+a
},()=>{ // 数据变化,DOM更新之后执行函数,类似于Vue nextTick
console.log(this.refs.txt.innerHTML) // 操作DOM
})
}
因为setState是一个异步的过程,所以说执行完setState之后不能立刻更改state里面的值。如果需要对state数据更改监听,setState提供第二个参数,就是用来监听state里面数据的更改,当数据更改完成,调用回调函数。
11、创建组件---component(es6)
class App extends React.Component{}
- constructor:定义自身的方法和属性。例:
constructor(props){
super(props); // 继承
this.state={
num:100
}
}
12、组件通信 原文链接
- 父--->子:父组件通过向子组件传递props,子组件得到props后进行相应的处理。
- 子--->父:利用回调函数,可以实现子组件向父组件通信:父组件将一个函数作为props传递给子组件,子组件调用该回调函数,便可以向父组件通信。
- 兄弟:react-redux 原文链接 redux是react中常用的一个进行集中状态管理的工具,当一个状态被多个状态所访问时,传统组件通信过于繁琐,可以将状态放入redux。
13、表单内容
<input type="text" value={this.state.val} onChange={(e)=>{this.setState({val:e.target.value})}}/>
14、性能优化
- 组件内部调用setState,当前组件及子组件都会重新渲染,生命周期并不会重复执行。
- shouldComponentUpdate:决定组件是否重新渲染,return true 渲染。可以避免不必要的dom操作。
- PureComponent:class Index extends React.PureComponent{}
- 使用路由懒加载。
- 使用key来帮助React识别列表中所有子组件的最小变化。
15、路由
路由暴露对象是ReactRouterDom。例:
let { HashRouter, Route, Link, Redirect, Switch, withRouter} = ReactRouterDom
- Route包裹路由组件。例:<Route path='/' component={Index}/>
- Link类似于vue中 router-link。例:<Link to='/'> 首页 </Link>
- NavLink:是Link的一个特定版本,会在匹配上当前的url的时候,给已经渲染的元素添加 样式 参数。原文链接
- BrowserRouter(路径不带#)、HashRouter(路径带#)限定路由使用区域 原文链接。
- withRouter:对普通组件进行包裹,将路由相关对象注入到组件。只有路由组件上props内部包含路由相关信息及方法。需要使用withRouter将路由对象注入 非路由 组件的props上。
- Redirect:路由重定向。
- Switch:确保包含的Route组件只匹配一个。
16、路由传参 原文链接
- 方式一:params(刷新页面数据不会丢失)
路由配置:例:<Route path='/detail/:id' component={Detail}></Route>
路由跳转:例:this.props.history.push('/detail/10');<Link to='/detail/10'></Link>
注意:js跳转时,需要使用withRouter。例:export default withRouter(connect(getProps,getDis)(List)) 父组件
路由页面接收参数:例:this.props.history.match.params.id
当前路由:例:localhost:3000/detail/10 - 方式二:state(刷新页面数据不会丢失)
路由配置:例:<Route path='detail' component={Detail}></Route>
路由跳转:例:this.props.history.push({pathname:'/detail',state:{id:10}});<Link to={{pathname:'detail',state:{id:10}}}></Link>
注意:js跳转时,需要使用withRouter。例:export default withRouter(connect(getProps,getDis)(List)) 父组件
路由页面接收参数:例:this.props.location.state.id
当前路由:例:localhost:3000/detail - 方式三:query(刷新页面数据丢失)
路由配置:例:<Route path='detail' component={Detail}></Route>
路由跳转:例:this.props.history.push({pathname:'/detail',query:{id:10}});<Link to={{pathname:'detail',query:{id:10}}}></Link>
注意:js跳转时,需要使用withRouter。例:export default withRouter(connect(getProps,getDis)(List)) 父组件
路由页面接收参数:例:this.props.location.query.id
当前路由:例:localhost:3000/detail
17、生命周期 原文链接
声明周期里的this指向组件实例。
- 1、getDefaultProps
这个方法是用来设置组件默认的props,组件生命周期只会调用一次。只适用于React.createClass直接创建组件。 - 2、getInitialState
设置state初始值,可以访问到this.props。只适用于React.createClass。 - 3、componentWillMount
这个方法在组件首次渲染之前调用,这个是在render方法调用之前可以修改state的最后一次机会。这个很少用到。 - 4、render
JSX通过这里,可以解析成对应的虚拟DOM,渲染成最终结果。 - 5、componentDidMount
这个方法在首次真实的DOM渲染后调用(仅此一次)。当我们需要访问真实的DOM时,在这个方法中访问。 - 6、componentWillReceiveProps
每当我们通过父组件更新子组件props时(这个也是唯一途径),这个方法被调用。 - 7、shouldComponentUpdate
字面意思,是否应该更新组件,默认返回 true。当返回 false 时,后期函数就不会调用,组件不会在次渲染。 - 8、componentWillUpdate
组件将会更新,props和state改变后必调用。 - 9、render
跟实例化的render一样。 - 10、componentDidUpdate
这个方法在更新真实的DOM成功后调用,当我们需要访问真实的DOM时,这个方法也经常用到。 - 11、componentWillUnmount
每当组件调用,这个组件就必须从DOM中销毁,此时该方法就会被调用。当我们在组件中使用了setInterval,那我们就需要在这个方法中调用clearInterval。如果手动使用了addEventListener绑定事件,也需要解绑事件。
18、key的作用
- Keys 是 React 用于追踪哪些列表中元素被修改、被添加或者被移除的辅助标识。
19、状态(state)和属性(props)之间有何不同
- state:是一种数据结构,用于组件挂载时所需数据的默认值。state可能会随着时间的推移而发生突变,但多数时候,是作为用于事件行为的结果。
- props(properties):是组件的配置。props由父组件传递给子组件,并且就子组件而言,props是不可变得。组件不能改变自身的props,但是可以把其子组件的props放在一起(统一管理)。props也不仅仅是数据,回调函数也可以通过props传递。
20、虚拟dom
- 本质:用js对象,来模拟DOM元素的嵌套关系;
- 目的:就是为了实现页面元素的高效更新。
21、为什么说虚拟dom会提高性能?
- 说Virtual(虚拟) DOM高效的一个理由就是它不会直接操作原生的DOM节点,因为这个很消耗性能。当组件状态变化时它会通过某些diff算法去计算出本次数据更新真实的视图变化,然后只改变“需要改变”的DOM节点。
- 虚拟 dom 相当于在 js 和真实 dom 中间加了一个缓存,利用 dom diff 算法避免了没有必要的 dom 操作,从而提高性能。
22、diff算法
- tree diff:新旧两棵DOM树,逐层对比的过程,就是Tree Diff;当整棵DOM逐层对比完毕,则所有需要按需更新的元素,必然能够找到。
- component diff:在进行Tree Diff的时候,每一层中,组件级别的对比,叫做Component Diff。
如果对比前后,组件类型相同,则暂时认为组件不需要被更新。
如果对比前后,组件类型不同,则需要移除旧组件。创建新组建,并追加到页面上。 - element diff:在进行组件对比的时候,如果两个组件类型相同,则需要进行元素级别的对比,这叫做Element Diff。
23、dva:js和jsx的区别
- JS:即JavaScript,一种直译式脚本语言。
- JSX:即JavaScript XML——一种在React组建内部构建标签的类XML语法。(增强React程序组件的可读性)。
- 区别:浏览器只能识别普通的js,普通的css,并不能识别scss,或者jsx(scss是css的拓展,jsx可以看做是js的拓展),所以webpack的作用是把scss转换为css,把jsx转换为浏览器可以识别的js,然后浏览器才能正常使用。
JSX语法,像是在Javascript代码里直接写XML的语法,实质上这只是一个语法糖,每一个XML标签都会被JSX转换工具转换成纯Javascript代码,React 官方推荐使用JSX, 当然你想直接使用纯Javascript代码写也是可以的,只是使用JSX,组件的结构和组件之间的关系看上去更加清晰。
24、dva:路由跳转
- 1、'dva/router'下引入Link;
布局中使用<Link to='/'>去首页</Link> - 2、this.props.history.push('/') // 注:需要将父级页面的history传递过来。
- 3、组件文件引入:import {withRouter} from 'dva/router'
export default withRouter(ListBtn) - 4、组件文件引入:import {routerRedux} from 'dva/router'
this.props.dispatch(routerRedux.push('/'))
25、刷新拦截(参考文件)
componentWillMount () {
// 拦截判断是否离开当前页面
window.addEventListener('beforeunload', this.beforeunload);
}
componentWillUnmount () {
// 销毁拦截判断是否离开当前页面
window.removeEventListener('beforeunload', this.beforeunload);
}
beforeunload (e) {
let confirmationMessage = '你确定离开此页面吗?';
(e || window.event).returnValue = confirmationMessage;
return confirmationMessage;
}