React的学习之路还要继续走下去,最近一边在作未完成的项目一边学习React,项目是vue写的,后面还须要有一个后台管理系统计划使用react完成,寒假说长也不长,要抓紧时间了。javascript
不少人不喜欢React,很大程度上是由于不喜欢jsx,那么jsx究竟是什么呢?首先仍是不要忘了React的基本哲学--一切都是js,包括文档结构。因此曾经天天都会见到的html在react的世界里全都不存在,react经过一系列叫作react元素的对象来构建虚拟DOM结构,最原始的建立react元素的方式是这样的:css
const root = React.createElement('div', { className: 'main' }, '我是一个div');
最终它将返回一个大概这样子的对象(有所简化过,不表明在 React 源码中是这样):html
const root = { type: 'div', props: { className: 'main', children: '我是一个div' } };
这样一个个建立节点实际上是很麻烦的,想一想看,若是每一个整个虚拟DOM的内容都要经过React.createElement来建立,代码量会不少,并且咱们根本没法直观地看出树形结构,不管开发仍是维护性都及其不友好。为了解决这一问题,一种新型的,相似xml结构的语法扩展就诞生了,就是jsx。vue
上面的代码结构改为jsx的书写方式就是这样的:java
const root =( <div className="main"> 我是一个div </div> );
这个结构就很熟悉了,不过要记住,他不是html模板,它就是js,最终在执行以前会被彻底转义成为纯js代码,因此使用jsx是不存在任何性能问题的。react
jsx的标准语法结构和xml彻底相似,特别的,jsx中的html属性要写成小驼峰命名的形式,好比onclick就要写成onClick。另外一点须要注意的问题就是,因为class是js中的保留字,因此要用className来代替。算法
jsx使用jsx时候要时刻记住它是js表达式,因此它能够像普通的js表达式同样,赋值传参返回均可以。而在jsx内部若是想使用表达式,就须要放在{}
里面。这就是jsx语法,很是简单,也不须要记忆特殊的指令,一切均可以和处理js同样来处理,下面来看一个小例子:redux
const item = this.newsList.map((news, index) => ( <li key={index}> <span>{news.title}</span> <span>{news.desc}</span> {news.image ? <img src="{news.image}"/> : null} </li> ) ); const list = ( <ul> {item} </ul> );
这是一个在react开发中特别常见的使用场景,咱们获得了一个数组的数据,须要以列表的形式渲染出来。在react中不须要使用任何迭代判断的相关指令语法,只要会写js的都能看懂上面的逻辑:经过数组的map方法迭代数组的内容,在回调函数中处理数据,渲染成想要的样式,就获得了一条一条列表项,插到列表里面就完成数据渲染了。咱们能够发如今不管是迭代方法仍是三元表达式等等,只要是js语法就能够随意地写到里面,自由度很是高。数组
了解了jsx,下一个重要概念就是组件了。组件不是react特有的,组件化开发有不少好处,组件符合高内聚低耦合的要求,每个组件是封装了视图和逻辑的一个相对独立的个体,而整个页面是由多个组件构成的,每一个组件能够屡次复用。babel
组件能够理解为相似于函数调用同样,定义好的组件是一个抽象的视图,而咱们经过传入相关的“参数”来使它展现出咱们想要的样子,组件就是咱们复用各类独立部件的基本单位。
定义一个组件最简单的方式是使用JavaScript函数:
function Welcome(props) { return <h1>Hello, {props.name}</h1>; }
这是一个最简单的函数定义组件,整个函数调用结果实际上就是返回一个<h1>
标签,不过特别的是,标签的内容不是肯定的,它是由咱们传入的参数来决定的。这就是组件开发,在React中,最经常使用的不是函数声明组件,而是向下面同样:
class Welcome extends React.Component { render() { return <h1>Hello, {this.props.name}</h1>; } }
此处使用了ES6的类和继承,建立了一个继承自Component的类。这个组件和上一个组件效果是彻底相同的,下面来重点分析React组件中几个重要的概念。
什么是state?状态,在react组件中,state是指一个组件UI呈现的最小状态集。在react中,视图层的更新是经过处理状态的变化来实现的,而state就是对这一系列状态的定义。react的数据是单向流动的,数据只能从模型层流向视图层,对应到具体的实现,咱们对state所作的一系列处理会自动的反映到视图上,咱们想要更新视图,只更新状态便可。说的可能比较抽象,看一个具体例子:
class ClickMe extends React.Component { constructor(props) { super(props); this.state = { count: 0 }; } clicked() { this.setState({ count: this.state.count + 1 }); } render() { return ( <div onClick={() => this.clicked()}> 点我{this.state.count}次 </div> ); } }
这个组件的效果就是点击文字,会显示你的点击次数,效果很简单就不截图了,关于组件生命周期和点击事件绑定后面再看,这里重点来看state的变化。在构造函数里面初始化state的数据,把state数据放在页面上,点击时候调用setState方法改变state中的数据。
关于state有几点须要注意:
props是组件的另外一个很是重要的概念,props指的是从外部传入的属性。props是React中父组件向子组件通讯的方式,下面是一个简单的例子:
class Child extends React.Component { constructor(props) { super(props); } render() { return ( <div> {this.props.data} </div> ); } }
使用组件
<Child data="我是显示的数据"></Child>
咱们定义组件时候在构造函数中能够接收到props参数,而且要使用super传到Component的构造方法中。在整个组件的类中就可使用成员变量props了。而props的内容,是父元素在调用子元素时候以属性的形式传入的。整个props控制的就是从父元素到子元素的事件流,这样咱们在使用组件的时候就能够像函数调用同样使用组件,像传入参数同样传入props。
使用props时候要注意一点,props传递数据是单向的,数据只能从父组件传递到子组件,须要其它方向的数据传递就须要使用其余方式了。
生命周期这个概念在不少开发中都会接触,react也是如此,一个react组件从建立运行到销毁须要经历不少阶段,系统也为咱们提供了对应阶段的hook方法(hook方法翻译为钩子方法,指的是当组件运行到对应的阶段时候就会自动执行写在这些方法里面的逻辑),我从网上找到了一副描述比较清晰的图片(侵删):
下面来逐一介绍这些生命周期方法以及它们说发挥的做用
以上是react生命周期的相关内容,到此,react组件的基本概念就介绍的差很少了。
在react中绑定事件须要注意一个问题,若是是使用ES6的class方式定义的组件中事件处理函数的this默认是不会绑定的,咱们须要手动绑定this指向。来看下面一个错误的例子:
class EventTest extends React.Component { clicked() { console.log('clicked'); } render() { return ( <div onClick={this.clicked}> 点我 </div> ); } }
点击点我,确实可以正常打印出clicked,看起来好像没有问题,可是,若是试着打印一下this,就会发现结果是undefined。
这样写this没办法绑定,天然也就没办法使用各类成员变量和方法,也不能调用内置方法了,显然不是咱们预期的,因此咱们须要手动来绑定this指向,方法也很简单:
class EventTest extends React.Component { clicked() { console.log('clicked'); } render() { return ( <div onClick={this.clicked.bind(this)}> 点我 </div> ); } }
只要增长bind(this)就能实现预期效果了,这也是一种经常使用的绑定this方式。除此以外还能够采用箭头函数来自动绑定this,下面的作法也是彻底能够的:
class EventTest extends React.Component { clicked() { console.log('clicked'); } render() { return ( <div onClick={()=>this.clicked()}> 点我 </div> ); } }
把clicked做为箭头函数返回的函数来使用,利用箭头函数内部自动绑定this的特性也能够实现this绑定。另外,还有一种写法:
class EventTest extends React.Component { clicked = () => { console.log('clicked'); } render() { return ( <div onClick={this.clicked}> 点我 </div> ); } }
这种方法是新的ES标准中的实验性语法,因为有babel转译也是可使用的,官网上面也提到了这种写法,不过因为新的标准还未成熟,因此用的人也很少。
了解了这些,react算是入了门了,接下来深刻学习的路还长,虚拟DOM的原理,diff算法,css-in-js,工程化下的react项目结构,react-router,redux,还有之后要学习的react native,后面随着学习慢慢总结。