- 快速开始
- 三种组件类型
- 小知识点
- 生命周期
- Mounting: componentWillMount
- Mounting: componentDidMount
- Updating: componentWillReceiveProps(nextProps)
- Updating: shouldComponentUpdate(nextProps, nextState)
- Updating: componentWillUpdate(nextProps, nextState)
- Updating: componentDidUpdate(prevProps, prevState)
- Unmounting: componentWillUnmount
- render()
因为 React 开发涉及 JSX 语法和ES6/7新语法还有开发环境和正式环境打包等等工作。建议新手可以使用 Facebook 官方推出的 create-react-app快速开始学习基础知识和代码实践。等到实际项目开发时可以再深入的进行 webpack 定制化开发。
//全局安装
npm install -g create-react-app
//创建项目
create-react-app my-app
cd my-app
//运行
npm start
//测试
npm test
//打包
npm run build
- Server rendering. 服务器端渲染
- Some experimental syntax extensions (e.g. decorators).一些实验性的语法(例如:修饰器)
- CSS Modules.
- LESS or Sass.
- Hot reloading of components.热更新 本人自己开发的支持 redux hot reloading 项目react-started
本项目就是使用create-react-app创建的一个项目。使用 ES6 实现了官方tutorial react-tutorial 项目,进行一个比较。其中省略了服务器端数据请求的逻辑。
这种方式在早期版本的 React 组件中比较常见。
import React, { Component } from 'react'
var TickTock = React.createClass({
//类属性和方法的设置
statics: {
customMethod: function(foo) {
return foo === 'bar';
}
value: 0
},
//初始化 state 值
getInitialState: function() {
return {seconds: 0};
},
//定义 props 参数类型
propTypes: {
name: React.PropTypes.string
},
//设置 props 默认值
getDefaultProps: function() {
return {
name: 'Mary'
};
},
componentDidMount: function() {
this.setInterval(this.tick, 1000); // Call a method on the mixin
},
tick: function() {
this.setState({seconds: this.state.seconds + 1});
},
render: function() {
return (
<p>
React has been running for {this.state.seconds} seconds.
</p>
);
}
});
import React, { Component, PropTypes } from 'react'
export default class App extends Component{
//静态方法
static customMethod(foo){
return foo === 'bar';
}
constructor(){
super()
//初始化 state 值
this.state = {
data: []
}
}
handleCommentSubmit(comment) {
this.setState({
data: [...this.state.data, comment]
})
}
componentDidMount() {
setTimeout(()=>{
this.setState({
data: data
})
}, 3000)
}
render() {
return (
<div className="commentBox">
<h1>Comments</h1>
<CommentList data={this.state.data} />
<CommentForm onCommentSubmit={this.handleCommentSubmit.bind(this)} />
</div>
);
}
}
//定义 props 参数类型
App.propTypes = {
name: PropTypes.string
};
//设置 props 默认值
App.defaultProps = {
name: 'Mary'
};
//类属性
App.value = 1
ES7 transform-class-properties 类的静态属性和示例属性, 需要 babel transform-class-properties 插件支持 .babelrc 配置如下两种 presets 或者 plugins
{
"presets": [
"es2015",
"react",
"stage-1"
],
"plugins": ["transform-class-properties"]
}
export default class App extends Component{
//类的静态属性 定义 props 参数类型
static propTypes = {
name: PropTypes.string
}
static defaultProps = {
name: 'Mary'
}
static value = 1;
//简化后实例属性可支持如下写法
state = {
data: []
}
//简化 bind 的写法
handleCommentSubmit = (comment) => {
this.setState({
data: [...this.state.data, comment]
})
}
...
}
适用于无 state 的组件
function Greeting(props) {
return <h1>Hello, {props.name}</h1>;
}
或者 ES6 箭头函数
const Greeting = (props) => (
<h1>Hello, {props.name}</h1>
);
ReactDOM.render(
<Greeting name="Sebastian" />,
document.getElementById('example')
);
参考链接:
render(){
return (
<div className="demo-class" style={{
height: "100px",
width: "100px",
fontSize: "12px"
}}>
</div>
)
}
render(){
const styleObj = {
height: "100px",
width: "100px",
fontSize: "12px"
}
return (
<div className="demo-class" style={styleObj}>
</div>
)
}
render(){
return (
<div>
{/* 这里面的内容都是注释 */}
</div>
)
}
export default class image extends Component {
constructor(props) {
super(props)
}
componentDidMount(){
//获取组件根 html DOM 元素对象
let dom = findDOMNode(this)
}
render() {
retrun <img/>
}
}
export default class Demo extends Component {
constructor(props) {
super(props)
}
componentDidMount(){
//这是该组件的根 DOM 对象
console.info(this.refs.comRootDom);
this._input.focus();
}
render() {
retrun (
<div ref="comRootDom">
{/* ref 还支持函数形式,函数输入参数为 DOM 对象 */}
<TextInput ref={(input) => this._input = input} />
</div>
)
}
}
要想修改 this.state 必须通过 this.setState 函数进行设置
constructor(){
super()
this.state = {
data: [],
counter: 0,
other: 1
}
}
onClick(){
//以下代码只会改版 this.state.counter 而不会影响 this.state.other 和 this.state.data
this.setState({counter: this.state.counter + 1;
}
render(){
<div className="commentBox">
<h1>Comments</h1>
<span>other {this.state.other}</span>
<span onClick={
//bind 是 bind 函数在 ECMA-262 第五版才被加入(即ES5) 语法中函数的新方法用于绑定函数作用域的
this.onClick.bind(this)
}>counter = {this.state.counter}</span>
<CommentList data={this.state.data} />
<CommentForm onCommentSubmit={this.handleCommentSubmit.bind(this)} />
</div>
}
JSX 中使用三元运算符
render(){
return (
<div>
{
this.state.isShow ? <span>show Text</span> : ""
}
</div>
)
}
使用变量独立处理
render(){
let content = "";
if(this.state.isShow){
content = <span>show Text</span>
}
return (
<div>
{content}
</div>
)
}
对于生命周期的理解很重要,生命周期贯彻 react 组件的整个使用过程
可以在这个函数中发情数据请求,此时进行 setState() render() 将只执行一次
第一次 render() 执行后,此时可以读取对真实DOM进行相关操作
只有当组件 props 修改(即父组件传递参数变化)时才会调用该函数,在第一次 render() 过程中不执行此函数
变量 | 说明 |
---|---|
this.props | 老的 props |
nextProps | 新的 props |
如果配置该函数的话必须明确的返回 true 或者 false ,返回决定了本次变化是否引起组件重绘(及执行 render())。 在此函数中可以进行逻辑性的判断来减少组件重绘的次数
请不要在此函数中执行修改 state 的逻辑(即调用 setState 函数),如有需要请在 componentWillReceiveProps 中进行修改设置
完成组件更新(即完成本次更新重绘 render() 执行之后),此时可以进行 DOM 操作
组件被销毁时调用,已经进行各种销毁逻辑
必须返回唯一包裹组件
render(){
retrun (
<div>
</div>
)
}
// good
render(){
retrun (
<div>
</div>
{/* */}
)
}
// error
render(){
retrun (
<div>
</div>
<div>
</div>
)
}
// error
参考链接:https://facebook.github.io/react/docs/component-specs.html
因为动态设置 HTML 存在 XSS 攻击危险,所有 React 特意使用下面的方式进行 dangerouslysetinnerhtml
function createMarkup() {
return {__html: 'First · Second'};
}
function MyComponent() {
return <div dangerouslySetInnerHTML={createMarkup()} />;
}