react整理(一) react组件

说起react是一个很宽泛的东西,作为一个从零开始学习react的小白,到现在懂一点react,决心将自己学的东西一一整理,从简单的开始着手,一是为了巩固知识,二也是为正在学习的同学提供一些思路,三也是希望大佬能够指出我的不妥之处,或加以补充,以更深层次的掌握react。

那么,在学习react之前,我们应该掌握哪些知识?
1.需要熟悉javascript
2.需要使用es6,箭头函数, 类, 模板字符串, let, 和 const 声明

react是什么?概括为两点:
1.用来构建UI的JS库。
2.React 不是一个MVC框架,仅仅是视图层(V)层的库。

react包括哪些概念?
1.组件
2.JSX
3.Virtual DOM
4.Data Flow

第一部分

那么接下来我们就从构建一个简单的组件开始。

在之前,我们的js,css,html都是分离的,这种方式满足不了我们要去实现代码复用。组件化,很多前框的框架都开始注重了这一点。一个组件就是一个功能模块,react框架相对来说,实现的更加彻底一些。react各个组件维护自己的状态和UI,当状态更变时,自动重新渲染整个组件。

构建react组件,可以是一个类,可以是一个函数。类与函数有什么区别?
1.类是有状态的组件,而函数是无状态的组件。
2.通过类构建一个组件,允许有内部状态存在,有完整的生命周期。可以使一个组件有生命力并且便于管理。
3.通过类构建必须要继承react内置的组件类,生命周期都是继承自react内置的组件类。
4.从性能来说,类构建要稍微慢一些。

如果是不使用生命周期是不是就可以不继承内置的组件类呢?
答案是不能,如果是使用了class来构建react的组件,必须要继承react的内置组件,因为class类中必须有一个render()方法来返回组件的实例。不写render方法它就不可能返回UI,那也就不是一个组件。render方法就是生命周期之一。

首先,我们来创建一个基于class的react组件。
类构建react组件有两种方式:
1.ES5: React.createClass
2.ES6:React.Component

React.createClass是React刚开始推荐的方式,是与ES5中原生JS来创建react组件方式。React.createClass创建一个类,接受一个对象为参数,并且需要有一个render方法来返回组件实例UI。这种方式我没有怎么使用过,不过基本的使用方式如下:

import React from 'react'
import ReactDom from 'react-dom'

const reactDom = React.createClass({
  getDefaultProp: function () {
    return { open: false }
  },
  getInitialState: function (){
    return { open: this.props.open}
  },
  handleClick: function(event){
    this.setState({
      open: !this.state.open
    })
  },
  render: function () {
    var open = this.state.open
    className = open ? 'switch-button' : 'btn-switch'
    return (
      <label className={className} onClick={this.handleClick.bind(this)}>
        <Input type="checkbox" checked={open} />
      </label>
    )
  }
})

ReactDOM.render(
  <reactDom />,
  document.getElementById('root')
)

ReactDom是React的最基本方法用于将模板转为HTML语言,并插入指定的DOM节点。
虽然没有使用过,但是它的弊端就是:
1.会自动绑定函数方法,造成不必要的性能开销
2.mixins不够直观,自然。(这一点在es6中已经没有使用了,它主要的作用就是,不同的组件之间,会使用到相同的功能,如果一个组件使用了多个 mixins,其中几个 mixins 定义了相同的“生命周期方法”,这些方法会在组件相应的方法执行完之后按 mixins 指定的数组顺序执行),可参考http://wiki.jikexueyuan.com/project/react-tutorial/mixin.html

接下来要说的就是目前正使用的方法,使用es6方式来构建react组件。按照上面的方法,应该写成以下方式。

export default class reactDom extends Component {
  constructor(props){
    super(props);
    this.state = {
      open: false
    }
  }

  getDefaultProp() {
    return { open: false }
  }

  getInitialState(){
    return { open: this.props.open}
  }

  handleClick (e){
    this.setState({
      open: !this.state.open
    })
  }

  render(){
    return (
      <label className={className} onClick={this.handleClick.bind(this)}>
        <Input type="checkbox" checked={open} />
      </label>
    )
  }
}

那么es5与es6在写法上有什么更具体的区别呢?

1.写法上的不同
React.creatClass 新创建的Class赋给一个常量,再添上render方法来构建出一个基本的组件
es5的写法:

const Contacts = React.createClass({
	render() {
		return (
			<div></div>
		)
		}
	})
export default Contacts;

es6的写法:

export default class Contacts extends React.Component({
	construct(props){
		super(this)
		this.state = {}
	}
	render(){
		return(
		<div></div>
		)
	}
})

es6的不同,我们使用super这个函数,来为React.component传递属性,所以需要引用construct()这个方法。es6的写法更加具有类的意义。

2.propType 和 getDefaultProps
他们的区别在于如何使用、声明默认属性和类型,以及如何设置类初始化状态。propType的作用是,当父组件给子组件传参时,定义父组件给子组件传值的类型;getDefaultProps/DefaultProps的任务是父组件给子组件传参没有给定默认值时,可以在getDefaultProps/DefaultProps中定义。
es5写法:

const Contacts = React.createClass({
    propType: {},
    getDefaultProps: (){
 	   return {
		  }
	    }
	render() {
		return (
			<div></div>
		)
	}
})
export default Contacts

在调用 React.createClass,定义propTypes 的对象,只要给它的属性进行赋值就能声明对应属性的类型。 getDefaultProps 这个函数返回了一个对象,这个对象的所有属性将会作为组件的初始化属性
使用es6的写法,个人更喜欢这样的写法,他更简洁直观了:

export default Contacts  extends React.Component {
// static 不继承实例,直接通过类来调用的静态方法
	static propType = {
	},
	static defaultProps = {
	}
	render() {
		return (
			<div></div>
		)
	}
}

3.state的不同
外部数据来源我们用props来储存数据,而state是用来管理内部数据状态的。使用es5,state是放在getInitialState()方法中,返回一个包含组件初始化状态的对象。
es5写法具体如下:

const Contact = React.CreateClass{
	getInitialState () {
		return  {
		}
	}
	render(){
		return (
		<div></div>
		)
	}
}
export default Contact;

在es6中,废除了getInitialState()这个方法,状态的定义在construct构造函数里。例如这样:

export default Contact extends React.Component {
	construct (props) {
		super(props);
		this.state = {}
	}
	render(){
		return (
			<div></div>
		)
	}
}

4.this的使用不同
es5中会自动绑定this,比如说

const Contact = React.createClass({
    handleClick () {
         console.log(this)
    },
	render(){
		return (
			<div onClick={this.handleClick}></div>
		)
	}
})
export default  Contact;

这里的this可以自动的找到当前执行环境的上下文,不用我们操心,但是这样我们语法结构时,可能要去改变jsx部分(支持js,css,html混合在一起的写法)结构。
如果使用的是es6的语法,this不会自动去绑定上下文,而是需要自己绑定正确的上下文,就像下面的例子一样。

export default class Contact extends React.Component {
	handleClick () {
	console.log(this)
	}
	render () {
		return (
			<div onClick={this.handleClick.bind(this)}></div>
		)
	}
}

5.mixins
es5中还保存有mixins这个特性,而es6中已废弃了这个特性,取而代之的是高阶组件,不过这一块还不了解,会继续学习。

接下来,我们创建一个无状态组件
无状态的组件我们通常是做纯UI展示。不需要去定义组件状态不用考虑组件的生命周期,就像这样:

class MessageView extends React.Component { 
	render({ 
		return(
		   <div className="container"> 
			<div className="from"> 
				<span className="label">From: </span>
				<span className="value">JohnDoe</span>
			 </div>
		      <div className="message"> 
				<span className="label">Message: </span>
			 	<span className="value">Have a great day!</span>
		 	</div>
		 </div>
	 ) } } 
export default MessageView;

因为是纯UI展示,所以也可以不考虑生命周期,不继承Component,于是可改写成:

export default function MessageView({message}) { 
	return( 
	<div className="container"> 
		<div className="from">
			 <span className="label">From: </span> 
			 <span className="value">{message.from}</span>
		</div>
		<div className="message">
		 	<span className="label">Message: </span>
		 	<span className="value">{message.content}</span>
		</div> 
	</div>
) }}

那么无状态与有状态组件,我们怎么用呢?
如果要考虑生命周期,那么就用使用类构建react实例,如果不考虑生命周期,那么使用无状态函数式构建。
一般来说,ES6的写法是优于ES5写法的。

以上是我的总结,如有疑问可留言。

参考资料:
https://www.w3cplus.com/react/stateful-vs-stateless-components.html © w3cplus.com

猜你喜欢

转载自blog.csdn.net/sinat_32206135/article/details/84963536