React元素和组件

670 阅读3分钟

一、React元素

React元素用来构建虚拟DOM(React DOM),与真实DOM有相同的树状结构,而真实DOM由DOMElement组成。

1、创建

React.createElement(
  type, // 必传,要创建的HTML元素标签名的字符串('div','span')
  [props],// 可传,元素的属性
  [...children]// 可传,元素的下一层嵌套,通过React.createElement嵌套元素
)

// 示例
var child1 = React.createElement('li', null, 'one');
var child2 = React.createElement('li', null, 'two');
var content = React.createElement('ul', { className: 'teststyle' }, child1, child2); // 第三个参数可以分开也可以写成一个数组
ReactDOM.render(
    content,
    document.getElementById('example')
);

2、JSX

使用React.createElement创建元素会造多层嵌套,JSX使创建元素更简易。

JSX:JS的一种类XML的语法扩展,提供给预处理器使用,预处理器再将其转换成React.createElement。提供{}用于编写JavaScript表达式。

class CreateComment extends Component {
    render() {
        <input value={this.state.user} />
    }
}

二、React组件

将React元素组织在一起,有助于将功能、标记、样式等进行封装,方便复用。

1、有状态的React组件(React类)

创建

通过声明一个继承自 React.Component 抽象基类的JavaScript类来代表一个组件,至少需要定义render 方法,在 render 方法里面返回需要渲染的元素。

render方法可以嵌套但最高层只有一个节点,可以访问持久化的组件状态、组件方法、继承React.Component 抽象基类的方法;

class Todo extends React.Component {
  render() {
    return <li>Hello, {this.props.content}</li>;
  }
}

<Todo content="图雀" />

// 旧方式
import createReactClass from 'create-react-class';
const HelloWorld = createReactClass({
    render() { return(<p>Hello, world!</p>) }
})
状态
  • state:可变,在组件类定义,类实例通过this.state访问,
  • props:不可变不可修改,来自父组件或组件自身的defaultProps静态方法,通过this.props访问,
state的初始化和更新

state在constructor方法中进行初始化;

class CreateComment extends Component {
    constructor(props) {
        super(props);
        this.state = {
            user: ""
        };
    }
    render() {
        <input value={this.state.user} />
    }
}

React需要追踪状态并确保虚拟DOM和实际DOM同步,使用setState更新状态;调用setState更新时,无需立即执行,而是创建一个挂起的状态转换,React选择批量更新提高效率。

React实现了一个合成事件系统作为虚拟DOM的一部分,将浏览器事件转换为React事件,这些事件设置在React元素上。

setState(
    updater,// 设置新状态 (prevState,props)=> stateChange
    [callback]// 回调函数
)
// 实例
class CreateComment extends Component {
    constructor(props) {
        super(props);
        this.state = {
            user: ""
        };
        this.hanleUserChange =this.hanleUserChange.bind(this);
    }
    hanleUserChange(event){
        const val = event.target.value;
        this.setState({// 浅合并
            user:val
        })
    }
    render() {
        <input value={this.state.user} onChange={this.handleUserChange}/>
    }
}
props的验证器PropTypes

PropTypes验证器使React类组件具有验证属性数据类型和是否必传的功能,使用时需安装prop-types包,通过将类的静态属性或通过类定义后的简单属性赋值添加验证。

var title = 123;// 属性 title 是必须的且是字符串,非字符串类型会自动转换为字符串 
class MyTitle extends React.Component {
  static propTypes = {// 通过类的静态属性
      title: PropTypes.string
  };
  render() {
    return (
      <h1>Hello, {this.props.title}</h1>
    );
      }
}
MyTitle.propTypes = {// 或通过类定义后的简单属性赋值(string为类型,isRequired为必传)
  title: PropTypes.string.isRequired
};
ReactDOM.render(
    <MyTitle title={title} />,
    document.getElementById('example')
);
默认属性

通过为类定义一个defaultProps静态属性添加默认属性

class MyTitle extends React.Component {
  static defaultProps = {// 默认属性
      title: '标题'
  };
  render() {
    return (
      <h1>Hello, {this.props.title}</h1>
    );
      }
}
ReactDOM.render(
    <MyTitle />,
    document.getElementById('example')
);

2、无状态的函数组件

创建
// 普通函数
function HelloMessage(props) { 
    return <h1>Hello {props.name}!</h1>; 
} 
// 箭头函数
const HelloMessage = (props)  => {
    return <h1>Hello {props.name}!</h1>; 
}
<HelloMessage name="Runoob"/>;
  • setState执行数据的浅合并,保留任何没有被覆盖的顶级属性;
  • 单向数据流:属性从父组件流向子组件,子组件通过回调函数将数据回送给父组件,但不能直接修改父组件的状态,父组件也无法直接修改子组件状态。组件通过属性完成组件交互。

三、ReactDOM渲染元素

ReactDOM.render(
    ReactElement element,// React元素
    DOMElement container,// DOM元素,容器
)
<!--创建一个id为root的div元素,用于渲染容器-->
<div id="root"></div>
import React from "react";
import ReactDOM from "react-dom";// React渲染器,利用render方法渲染
import App from "./components/App";

ReactDOM.render(
  <App>,
  document.getElementById("root")
);