作者:水落斜阳
链接:https://www.jianshu.com/p/4fb47009c330
来源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
1.react component有几种写法?各有什么特点
① 函数式定义的无状态组件(Stateless Functional)
性能更高效、代码更简洁
没有 state,也就是无状态
不需要管理/维护 组件的生命周期
纯函数,相同的 props 会得到同样的UI渲染结果
组件不会被实例化,整体渲染性能得到提升
组件不能访问this对象
②.
ES5原生方式React.createClass定义的组件
是react刚开始推荐的创建组件的方式,这是ES5的原生的JavaScript来实现的React组件
是创建有状态的组件
些组件是要被实例化的,并且可以访问组件的生命周期方法
创建的组件,其每一个成员函数的this都有React自动绑定
③.ES6 方式定义的组件(Class Components)
ES6的形式来创建react的组件的,是React目前极为推荐的创建有状态组件的方式
创建的组件,其成员函数不会自动绑定this,需要开发者手动绑定,否则this不能获取当前组件实例对象
有三种手动绑定方法:可以在构造函数中完成绑定,也可以在调用时使用method.bind(this)来完成绑定,还可以使用arrow function来绑定
2.写个受控表单组件更新state的流程?
class App extends Component {
constructor(props) {
super(props)
this.state = { value: 'hi' }
}
onInputChange = (e) => {
this.setState({ value: e.target.value })
}
render() {
const { value } = this.state
return (
<input value={value} onChange={this.onInputChange} />
)
}
}
文本描述
1.初始化state设置表单的默认值,例如 this.state = { value: 'hi' }
2.每当表单值发生变化时,调用onChange事件
3.通过对象e拿到改变的状态,例如e.target.value
4.通过setState更新应用value 并 触发视图重新渲染,最终完成表单组件的更新
3下面两种写法的得到的this.state.text值是一样吗?为什么?
...
this.state = { text : '这是一个栗子' }
...
// 使用传递对象的写法
handleClick = () => {
this.setState({ text: this.state.text + '111' })
this.setState({ text: this.state.text + '222' })
}
// 使用传递函数的写法
handleClick = () => {
this.setState((prevState) => {
return { text: prevState.text + '111' }
})
this.setState((prevState) => {
return { text: prevState.text + '222' }
})
}
render() {
return <div onClick={this.handleClick}>{this.state.text}</div>
}
两种传递方式,得到的结果是不一样的。
传递对象 => this.state.text => '这是一个栗子222'
传递函数 => this.state.text => '这是一个栗子111222'
setState为了提升性能,在批量执行 state 改变在做统一的DOM渲染。而在这个批量执行的过程中,如果你多次传递的是一堆对象,它就会做一些对象合并或者组合的操作,例如Object.assign({}, { a: '111' }, { a: '222' })。如果key值一样的话,后面的值会覆盖掉前面的值。
但多次传递函数方式,每次 React 从 setState 执行函数,并通过传递已更新的状态来更新你的状态。这使得功能 setState 可以基于先前状态设置状态。
4.为什么我们利用循环产生的组件中要用上key这个特殊的prop?
render() {
return (
<ul>
list.map((item, index) => {
return <li key={item.id}>{item.name} - {item.age}</li>
})
</ul>
)
}
5.keys 是 React 用于追踪哪些列表中元素被修改、被添加或者被移除的辅助标识
之所以需要key,因为react 是非常高效的,它会借助元素的 key 值来判断该元素是新创建的,或者移动(交换位置)而来的,从而减少不必要的元素重渲染
如果上面代码改成 key={index} 呢,有啥区别
这样做的效率是非常非常非常低的,只有list变化了, 每个元素对应的key都变了,react Virtual DOM就不论有没有相同的项,更新都会重新渲染了。所以我们要保证某个元素的 key 在其同级元素中具有唯一性, 这个key 的值可以直接后台数据返回的 id
6.react组件间的通信有哪些
- 父组件向子组件通信
react 中数据是单向传递的,父组件可以向子组件通过传 props 的方式,
子组件拿到 props 之后做相应的处理
2.子组件向父组件通信
子组件向父组件传递数据(通信) 也是要通过 props 传递一个函数,子组件调用这个函数,并将子组件需要传递的数据作为参数,传递给父组件
3.兄弟组件之间通信
可以通过他们的共同父组件来实现,
7.跨n级组件之间通信或者,非嵌套组件的通信有什么好的办法
- 利用 react 提供的 context , 它类似一个全局大容器,我们把想传递的信息放在里面,需要的往里面取便是
2.自定义事件的方式。自定义事件是典型的发布/订阅模式,通过向事件对象上添加监听器和触发事件来实现组件间通信
3.状态管理工具 mobx redux 等
8.简要说说React中虚拟DOM原理
在React中,也有一个render函数来将虚拟DOM树,并且,React中有state转移的过程,所以每次state有变化之后,就会触发render函数,重新构造一个虚拟DOM树。对比新旧虚拟DOM树的差别,记录下差异,然后只针对差异部分对应的真实DOM进行操作。
如何进行新旧虚拟DOM树的对比呢?
这里采用的是Diff算法。Diff算法比较复杂,主要的思路是这样的。
首先,每一次生成的虚拟DOM树上的各个节点都对应唯一的一个id,当第二次生成了新的DOM树时,对原来树上的每一个节点对比新树上对应节点,如果不同,就记录下来这个差异。同时,差异也分为很多种:
替换节点;
修改属性;
对文本内容修改
移动、删除、增加节点;
比如,替换节点就需要调原生JS的repaceChild()接口;
对于修改属性,则要调setAttribute()接口等等。