本人只是前端大行业中最渺小的一只,曾经一度处于阴霾迷失方向,现总结北京一些公司的前端题分享给或许也同样迷茫的你(持续更新),希望能帮助你们也是我自己慢慢拨开迷雾,这次更新的面试题是公司原题主要考察react框架,其实面试题答得好只是能通过初选,所以不要满足于面试题,一起加油。
react官网:https://reactjs.org/ 学习react我个人是建议看一遍官网的api的,会有一些感悟。
react最基础也是必须记住的就是它的生命周期(三阶段10个):
一、上树阶段(Mounting阶段)
生命周期 | 做了什么 |
---|---|
constructor() | 构造函数,写state什么的 |
componentWillMount() | 将要上树,这里发出Ajax请求 |
render() | 呈递视图 |
componentDidMount() | 上树之后,可以操作DOM |
本阶段需要注意的是,在componentDidMount()
生命周期函数中,就能操作DOM了,DOM就已经上树了;本阶段的4个函数都没有参数。
二、更新阶段(Updating阶段)
props的改变或者state的改变将触发本阶段。
生命周期 | 做了什么 |
---|---|
componentWillReceiveProps(nextProps) | 当父亲传给组件的prop改变的时候发生。在这个函数中,nextProps参数表示新的父亲传入的props对象 |
shouldComponentUpdate(nextProps, nextState) 门神 | 当父亲传入的props改变或者自己state改变发生。return true此时才会继续执行后面的声明周期;return false不执行后面的生命周期了。如果没有写门神函数,默认return true。 |
render() | |
componentDidUpdate(prevProps , prevState) | 更新之后做的事情 |
三、下树阶段(Unmounting阶段)
生命周期 | 做了什么 |
---|---|
componentWillUnmount() | 将要下树 |
React中state与props介绍与比较
- state
1.state的作用
state是React中组件的一个对象.React把用户界面当做是状态机,想象它有不同的状态然后渲染这些状态,可以轻松让用户界面与数据保持一致.
React中,更新组件的state,会导致重新渲染用户界面(不要操作DOM).简单来说,就是用户界面会随着state变化而变化.
2.state工作原理
常用的通知React数据变化的方法是调用setState(data,callback).这个方法会合并data到this.state,并重新渲染组件.渲染完成后,调用可选的
callback回调.大部分情况不需要提供callback,因为React会负责吧界面更新到最新状态.
3.那些组件应该有state?
大部分组件的工作应该是从props里取数据并渲染出来.但是,有时需要对用户输入,服务器请求或者时间变化等作出响应,这时才需要state.
组件应该尽可能的无状态化,这样能隔离state,把它放到最合理的地方(Redux做的就是这个事情?),也能减少冗余并易于解释程序运作过程.
常用的模式就是创建多个只负责渲染数据的无状态(stateless)组件,在他们的上层创建一个有状态(stateful)组件并把它的状态通过props
传给子级.有状态的组件封装了所有的用户交互逻辑,而这些无状态组件只负责声明式地渲染数据.
4.哪些应该作为state?
state应该包括那些可能被组件的事件处理器改变并触发用户界面更新的数据.这中数据一般很小且能被JSON序列化.当创建一个状态化的组件
的时候,应该保持数据的精简,然后存入this.state.在render()中在根据state来计算需要的其他数据.因为如果在state里添加冗余数据或计算
所得数据,经常需要手动保持数据同步.
5.那些不应该作为state?
this.state应该仅包括能表示用户界面状态所需要的最少数据.因此,不应该包括:
计算所得数据:
React组件:在render()里使用props和state来创建它.
基于props的重复数据:尽可能保持用props来做作为唯一的数据来源.把props保存到state中的有效的场景是需要知道它以前的值得时候,
因为未来的props可能会变化. - props
1.props的作用
组件中的props是一种父级向子级传递数据的方式.
2.复合组件
react销毁阶段
1.销毁阶段可以使用的函数:
componentWillUnmount:在删除组件之前进行清理操作,比如计时器和事件监听器。因为这些函数都是开发者手动加上去的,react不知道,必须进行手动清理。
2.实例
第一种方式:在render中,把之前已有的页面去掉,反映到页面中,就是把它删掉。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>测试触发顺序,不输入不会触发五个函数,只会触发render</title>
</head>
<body>
<script type="text/javascript" src="http://cdn.bootcss.com/react/0.13.2/react.min.js"></script>
<script type="text/javascript" src="http://cdn.bootcss.com/react/0.13.2/JSXTransformer.js"></script>
<script type="text/jsx">
var style={
color:"red",
border:"1px solid #f99",
width:"200px",
height:"50px"
};
var HelloWorld= React.createClass({
render:function(){
console.log("render,4");
return <p>Hello,{this.props.name ? this.props.name : "World"}</p>;
},
componentWillUnmount:function(){
console.log("BOOM");
},
});
var HelloUniverse=React.createClass({
getInitialState:function(){
return {name:""};
},
handleChange:function(event){
//用来响应input的输入事件
this.setState({name:event.target.value});
},
render:function(){
if(this.state.name == "123"){
return <div>123</div>
}
return <div>
<HelloWorld name={this.state.name
//这里引用了HelloWorld的组件,所以HelloUniverse是他的子组件
}></HelloWorld>
<br />
<input type="text" onChange={this.handleChange} />
</div>
},
});
React.render(<div style={style}><HelloUniverse></HelloUniverse></div>,document.body)
// 写为React.render(<div style={style}><HelloWord></HelloWorld></div>,document.body)看看效果
</script>
</body>
</html>
输入别的不会触发
当输入123的时候
第二种:就是使用react提供的一个函数unmountComponentAtNode
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title></title>
</head>
<body>
<script type="text/javascript" src="http://cdn.bootcss.com/react/0.13.2/react.min.js"></script>
<script type="text/javascript" src="http://cdn.bootcss.com/react/0.13.2/JSXTransformer.js"></script>
<script type="text/jsx">
var style={
color:"red",
border:"1px solid #f99",
width:"200px",
height:"50px"
};
var HelloWorld= React.createClass({
render:function(){
console.log("render,4");
return <p>Hello,{this.props.name ? this.props.name : "World"}</p>;
},
componentWillUnmount:function(){
console.log("BOOM");
},
});
var HelloUniverse=React.createClass({
getInitialState:function(){
return {name:""};
},
handleChange:function(event){
//判断的是input里面的值,如果是123,我们就使用unmountComponentAtNode来删除
//使用unmountComponentAtNode时,传入的必须是装载时候的节点。
if(event.target.value == "123"){
React.unmountComponentAtNode(document.getElementsByTagName("body")[0]);
return;
}
this.setState({name:event.target.value});
},
render:function(){
return <div>
<HelloWorld name={this.state.name
//这里引用了HelloWorld的组件,所以HelloUniverse是他的子组件
}></HelloWorld>
<br />
<input type="text" onChange={this.handleChange} />
</div>
},
});
React.render(<div style={style}><HelloUniverse></HelloUniverse></div>,document.body)
// 写为React.render(<div style={style}><HelloWord></HelloWorld></div>,document.body)看看效果
</script>
</body>
</html>
react-router配置
路由库React-Router。它是官方维护的,事实上也是唯一可选的路由库。它通过管理 URL,实现组件的切换和状态的变化,开发复杂的应用几乎肯定会用到。
使用详情请参考阮一峰的博客。
react的render中,return里面是不是只能有一个最外层DIV
最外层只能一个组件,但不一定是div。
可以是一个react Component
,如<A></A>
;也可以是html标签,如<div></div'/'<form></form>
;如果返回的是多个平级的react Component
,需要用html标签包裹起来,如'<div><A/><B/></div>'
。
render内的html class名
react使用JSX语法,JSX语法最终是要被转换为纯Javascript的,所以要和在Javascript DOM中一样,用className
和htmlFor
。
react行内样式
react的行内样式本质上是一个对象,比如官方文档的这个
var divStyle = {
color: 'white',
backgroundImage: 'url(' + imgUrl + ')',
WebkitTransition: 'all', // 注意这里的首字母'W'是大写
msTransition: 'all' // 'ms'是唯一一个首字母需要小写的浏览器前缀
};
React.render(<div style={divStyle}>Hello World!</div>, mountNode);
如何在React中使用数据动态生成DOM标签
我们的数据是从真实的DOM中获取来 通过事件 构建一个数组 每次点击或其他事件来把数据push到数组中 这段的代码中最重要的是我们要调用父组件中 修改数据的方法 这样数据就传递过去了 我们就可以使用上述的方法来动态生成 DOM元素了
参考详情请见:点击此处
关于Virtual DOM
React采用了Virtual DOM
虚拟DOM和DIFF算法,在内存中快速比较setState
变化前后的差异,做最小量更新!
比如下图,我们点击按钮之后,state影响界面从左侧的形式变为了右侧的形式:
方案1:删除4个li,插入5个li;
方案2:增加1个li,改变5个li的innerHTML;
很明显,方案2更加节约内存,效率高。
- React中有DIFF算法,就是可以快速比较两个DOM结构的最小化差异。
- React会将DOM结构编码(类似于数据结构中的树的结构),存储在内存中,称为Virtual DOM,虚拟DOM。
当组件有组件套组件的情况下,Virtual DOM还会自动计算子孙组件的最小化差异: