1.JSX引用一个组件,实际上调用了React.createElement
<MyButton color="blue" shadowSize={2}>Click Me</MyButton>
编译为
React.createElement(
MyButton,
{color: 'blue', shadowSize: 2},
'Click Me'
)
2.PropTypes 类型检查
React v16 之前可用 React.PropTypes
class Greeting extends React.Component {
render() {
return (<h1>Hello, {this.props.name}</h1>);
}
}
Greeting.propTypes = {
name: React.PropTypes.string
};
React v16 之后React.PropTypes弃用,需使用prop-types库
import PropTypes from 'prop-types';
class Greeting extends React.Component {
render() {
return (<h1>Hello, {this.props.name}</h1>);
}
}
Greeting.propTypes = {
name: PropTypes.string
};
当给属性传递了无效值时,JavsScript 控制台将会打印警告。出于性能原因,propTypes 只在开发模式下进行检查。
3.Ref属性访问组件
组件并不是真实的 DOM 节点,而是存在于内存之中的一种数据结构,叫做虚拟 DOM (virtual DOM)。只有当它插入文档以后,才会变成真实的 DOM 。根据 React 的设计,所有的 DOM 变动,都先在虚拟 DOM 上发生,然后再将实际发生变动的部分,反映在真实 DOM上,这种算法叫做DOM diff,它可以极大提高网页的性能表现。
this.refs.[refName] 属性可以获取真实 DOM ,但是必须等到虚拟 DOM 插入文档以后(componentDidMount),才能使用这个属性,否则会报错。
能用state状态提升解决的,尽量不要用ref
1) 使用React.createRef()创建ref
class A extends React.Component{
constructor(props){
super(props);
this.textInput = React.createRef();
}
componentDidMount(){
this.textInput.current.focusTextInput();
}
render(){
return (
<B ref={this.textInput} />
);
}
}
这种方法仅对 class 声明的 B(组件) 有效,对函数式声明的B无效,因为函数式声明没有产生实例。
class B extends React.Component {
// class申明
//...
render(){
return (<input />);
}
}
function B(){
// 函数申明
return (<input />);
}
2) Ref回调
React 将在组件挂载时将 DOM 元素传入ref 回调函数并调用,当卸载时传入 null 并调用它。
ref 回调函数会在 componentDidMout 和 componentDidUpdate 生命周期函数前被调用
class A extends React.Component{
constructor(props){
super(props);
}
saveFormRef = (form) => {
this.form = form; //将子组件Dom
}
render(){
return (
<BForm ref={ this.saveFormRef } />
);
}
}
class B extends React.Component{
render(){
return (<Form>...</Form>);
}
}
const BForm = Form.create()(B);
export default B;
Ref可以读取组件的DOM,例子中由于BForm是一个Form组件,所以在A中可以直接读取B的表单数据。
4.React.createClass和extends Component的区别
1) 语法区别
//ES5的语法
var Hello = React.createClass({
componentWillMount : function(){
......
},
render: function(){
return (<div>Hello</div>);
},
})
module.exports = Hello;
//ES6的语法
class Hello extends React.Component{
constructor(props){
super(props);
}
componentWillMount(){
...
}
render(){
return (<div>Hello</div>);
}
}
export default Hello;
2)状态的区别
React.createClass:通过getInitialState()方法返回一个包含初始值的对象
const Hello = React.createClass({
// return an object 返回的结果在state里
getInitialState(){
return {
isEditing: false
}
}
render(){
return <div></div>
}
})
React.Component:通过constructor设置初始状态
class Hello extends React.Component{
constructor(props){
super(props);
this.state = { // define this.state in constructor
isEditing: false
}
}
render(){
return <div></div>
}
}
3)this区别
React.createClass:会自动绑定this
const Hello = React.createClass({
handleClick() {
console.log(this); // React Component instance
},
render() {
return (
<div onClick={this.handleClick}></div>//会切换到正确的this上下文
);
}
});
React.Component:this属性并不会自动绑定到 React 类的实例上,默认的函数或者生命周期函数才会自动绑定this
class Hello extends React.Component{
constructor(props){
super(props);
}
handleClick(){
console.log(this); // null
}
handleFocus(){ // manually bind this
console.log(this);
}
handleBlur: ()=>{ // use arrow function
console.log(this);
}
render(){
return <input onClick={this.handleClick}
onFocus={this.handleFocus.bind(this)}
onBlur={this.handleBlur}/>
}
}
也可以在constructor中绑定this (推荐使用这种方法)
constructor(props){
super(props);
this.handleClick = this.handleClick.bind(this);
}
网友评论