React 入门基础

React 入门基础

目录

快速开始

因为 React 开发涉及 JSX 语法和ES6/7新语法还有开发环境和正式环境打包等等工作。建议新手可以使用 Facebook 官方推出的 create-react-app快速开始学习基础知识和代码实践。等到实际项目开发时可以再深入的进行 webpack 定制化开发。

  1. //全局安装
  2. npm install -g create-react-app
  3. //创建项目
  4. create-react-app my-app
  5. cd my-app
  6. //运行
  7. npm start
  8. //测试
  9. npm test
  10. //打包
  11. 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.createClass

这种方式在早期版本的 React 组件中比较常见。

  1. import React, { Component } from 'react'
  2. var TickTock = React.createClass({
  3. //类属性和方法的设置
  4. statics: {
  5. customMethod: function(foo) {
  6. return foo === 'bar';
  7. }
  8. value: 0
  9. },
  10. //初始化 state 值
  11. getInitialState: function() {
  12. return {seconds: 0};
  13. },
  14. //定义 props 参数类型
  15. propTypes: {
  16. name: React.PropTypes.string
  17. },
  18. //设置 props 默认值
  19. getDefaultProps: function() {
  20. return {
  21. name: 'Mary'
  22. };
  23. },
  24. componentDidMount: function() {
  25. this.setInterval(this.tick, 1000); // Call a method on the mixin
  26. },
  27. tick: function() {
  28. this.setState({seconds: this.state.seconds + 1});
  29. },
  30. render: function() {
  31. return (
  32. <p>
  33. React has been running for {this.state.seconds} seconds.
  34. </p>
  35. );
  36. }
  37. });

ES6 Classes export class Name extends React.Component

  1. import React, { Component, PropTypes } from 'react'
  2. export default class App extends Component{
  3. //静态方法
  4. static customMethod(foo){
  5. return foo === 'bar';
  6. }
  7. constructor(){
  8. super()
  9. //初始化 state 值
  10. this.state = {
  11. data: []
  12. }
  13. }
  14. handleCommentSubmit(comment) {
  15. this.setState({
  16. data: [...this.state.data, comment]
  17. })
  18. }
  19. componentDidMount() {
  20. setTimeout(()=>{
  21. this.setState({
  22. data: data
  23. })
  24. }, 3000)
  25. }
  26. render() {
  27. return (
  28. <div className="commentBox">
  29. <h1>Comments</h1>
  30. <CommentList data={this.state.data} />
  31. <CommentForm onCommentSubmit={this.handleCommentSubmit.bind(this)} />
  32. </div>
  33. );
  34. }
  35. }
  36. //定义 props 参数类型
  37. App.propTypes = {
  38. name: PropTypes.string
  39. };
  40. //设置 props 默认值
  41. App.defaultProps = {
  42. name: 'Mary'
  43. };
  44. //类属性
  45. App.value = 1

ES7 transform-class-properties 类的静态属性和示例属性, 需要 babel transform-class-properties 插件支持
.babelrc 配置如下两种 presets 或者 plugins

  1. {
  2. "presets": [
  3. "es2015",
  4. "react",
  5. "stage-1"
  6. ],
  7. "plugins": ["transform-class-properties"]
  8. }
  1. export default class App extends Component{
  2. //类的静态属性 定义 props 参数类型
  3. static propTypes = {
  4. name: PropTypes.string
  5. }
  6. static defaultProps = {
  7. name: 'Mary'
  8. }
  9. static value = 1;
  10. //简化后实例属性可支持如下写法
  11. state = {
  12. data: []
  13. }
  14. //简化 bind 的写法
  15. handleCommentSubmit = (comment) => {
  16. this.setState({
  17. data: [...this.state.data, comment]
  18. })
  19. }
  20. ...
  21. }

纯函数(pure funciton) stateless-functions

适用于无 state 的组件

  1. function Greeting(props) {
  2. return <h1>Hello, {props.name}</h1>;
  3. }
  4. 或者 ES6 箭头函数
  5. const Greeting = (props) => (
  6. <h1>Hello, {props.name}</h1>
  7. );
  8. ReactDOM.render(
  9. <Greeting name="Sebastian" />,
  10. document.getElementById('example')
  11. );

参考链接:

component-specs

reusable-components

选择组件类型

阮一峰 ES6 教程 class

小知识点

className 和 style

  1. render(){
  2. return (
  3. <div className="demo-class" style={{
  4. height: "100px",
  5. width: "100px",
  6. fontSize: "12px"
  7. }}>
  8. </div>
  9. )
  10. }
  11. render(){
  12. const styleObj = {
  13. height: "100px",
  14. width: "100px",
  15. fontSize: "12px"
  16. }
  17. return (
  18. <div className="demo-class" style={styleObj}>
  19. </div>
  20. )
  21. }

JXS 注释

  1. render(){
  2. return (
  3. <div>
  4. {/* 这里面的内容都是注释 */}
  5. </div>
  6. )
  7. }

DOM 操作

ReactDOM.findDOMNode

  1. export default class image extends Component {
  2. constructor(props) {
  3. super(props)
  4. }
  5. componentDidMount(){
  6. //获取组件根 html DOM 元素对象
  7. let dom = findDOMNode(this)
  8. }
  9. render() {
  10. retrun <img/>
  11. }
  12. }

Refs to Comments

  1. export default class Demo extends Component {
  2. constructor(props) {
  3. super(props)
  4. }
  5. componentDidMount(){
  6. //这是该组件的根 DOM 对象
  7. console.info(this.refs.comRootDom);
  8. this._input.focus();
  9. }
  10. render() {
  11. retrun (
  12. <div ref="comRootDom">
  13. {/* ref 还支持函数形式,函数输入参数为 DOM 对象 */}
  14. <TextInput ref={(input) => this._input = input} />
  15. </div>
  16. )
  17. }
  18. }

修改组件 state

要想修改 this.state 必须通过 this.setState 函数进行设置

  1. constructor(){
  2. super()
  3. this.state = {
  4. data: [],
  5. counter: 0,
  6. other: 1
  7. }
  8. }
  9. onClick(){
  10. //以下代码只会改版 this.state.counter 而不会影响 this.state.other 和 this.state.data
  11. this.setState({counter: this.state.counter + 1;
  12. }
  13. render(){
  14. <div className="commentBox">
  15. <h1>Comments</h1>
  16. <span>other {this.state.other}</span>
  17. <span onClick={
  18. //bind 是 bind 函数在 ECMA-262 第五版才被加入(即ES5) 语法中函数的新方法用于绑定函数作用域的
  19. this.onClick.bind(this)
  20. }>counter = {this.state.counter}</span>
  21. <CommentList data={this.state.data} />
  22. <CommentForm onCommentSubmit={this.handleCommentSubmit.bind(this)} />
  23. </div>
  24. }

MDN 对于 bind 的介绍

JSX 语法不支持 IF-ELSE 使用三元运算符或者使用变量独立处理

JSX 中使用三元运算符

  1. render(){
  2. return (
  3. <div>
  4. {
  5. this.state.isShow ? <span>show Text</span> : ""
  6. }
  7. </div>
  8. )
  9. }

使用变量独立处理

  1. render(){
  2. let content = "";
  3. if(this.state.isShow){
  4. content = <span>show Text</span>
  5. }
  6. return (
  7. <div>
  8. {content}
  9. </div>
  10. )
  11. }

生命周期

对于生命周期的理解很重要,生命周期贯彻 react 组件的整个使用过程

Mounting: componentWillMount

可以在这个函数中发情数据请求,此时进行 setState() render() 将只执行一次

Mounting: componentDidMount

第一次 render() 执行后,此时可以读取对真实DOM进行相关操作

Updating: componentWillReceiveProps(nextProps)

只有当组件 props 修改(即父组件传递参数变化)时才会调用该函数,在第一次 render() 过程中不执行此函数

变量 说明
this.props 老的 props
nextProps 新的 props

Updating: shouldComponentUpdate(nextProps, nextState)

如果配置该函数的话必须明确的返回 true 或者 false ,返回决定了本次变化是否引起组件重绘(及执行 render())。
在此函数中可以进行逻辑性的判断来减少组件重绘的次数

Updating: componentWillUpdate(nextProps, nextState)

请不要在此函数中执行修改 state 的逻辑(即调用 setState 函数),如有需要请在 componentWillReceiveProps 中进行修改设置

Updating: componentDidUpdate(prevProps, prevState)

完成组件更新(即完成本次更新重绘 render() 执行之后),此时可以进行 DOM 操作

Unmounting: componentWillUnmount

组件被销毁时调用,已经进行各种销毁逻辑

render()

必须返回唯一包裹组件

  1. render(){
  2. retrun (
  3. <div>
  4. </div>
  5. )
  6. }
  7. // good
  8. render(){
  9. retrun (
  10. <div>
  11. </div>
  12. {/* */}
  13. )
  14. }
  15. // error
  16. render(){
  17. retrun (
  18. <div>
  19. </div>
  20. <div>
  21. </div>
  22. )
  23. }
  24. // error

参考链接:https://facebook.github.io/react/docs/component-specs.html

Set innerHtml TODO

因为动态设置 HTML 存在 XSS 攻击危险,所有 React 特意使用下面的方式进行
dangerouslysetinnerhtml

  1. function createMarkup() {
  2. return {__html: 'First &middot; Second'};
  3. }
  4. function MyComponent() {
  5. return <div dangerouslySetInnerHTML={createMarkup()} />;
  6. }

Event TODO

context