React.js深刻学习详细解析

目录:

1、JSX介绍 javascript

2、React组件生命周期详解 html

3、属性、状态的含义和用法 java

4、React中事件的用法 react

5、组件的协同使用 git

6、React中的双向绑定 github

 1、JSX介绍 算法

①定义 编程

JSX=JavaScript XML,是一种在React组件内部构建标签的类XML语法。React在不使用JSX的状况下同样能够工做,可是使用JSX能够提升组件的可读性,加强JS语义,结构清晰,抽象程度高,代码模块化。所以推荐在React中使用JSX。 数组

②特色 安全

一、元素名首字母大写

二、符合嵌套规则

三、能够写入求值表达式

四、驼峰式命名

五、不能使用javascript原生函数的一些关键词,如for和class。须要替换成htmlFor和className

③使用方法

一、使用动态值:JSX将两个花括号之间的内容{...}渲染为动态值,花括号指明了一个javascript上下文环境,花括号里面能够是一个变量,也能够是函数。 例如:

复制代码
var name=“winty”; <p>{name}</p>

function date(d){
  return [
    d.getFullYear(),
    d.getMonth()+1,
    d.getDate()
  ].join('-);
};
<p>{date(new Date()}</p>
复制代码

2.注释:首先,在子节点中注释要用大括号包裹起来,而后就能够单行注释/**/,也能够多行注释//。

复制代码
var Hello=React.createClass({ render:function(){ return <p name="winty"> //set name  Hello ,World /* 多行注释 多行注释 */ </p>  } });
复制代码

3.使用CSS内联样式

var style={ color:#000; }; React.render(<div style={style}>....</div>,document.body);

4.使用条件判断

复制代码
//方法1,三目运算符 var Hello=React.createClass({ render:function(){ return <p>Hello,{this.props.name?this.props.name : "LuckyWinty"}</p>  } }); //方法2,if-else语句 var Hello1=React.createClass({ getName:function(){ if(this.props.name) return this.props.name; else return "LuckyWinty"; render:function(){ return <p>Hello,{this.getName}</p>  } }); //方法3,使用逻辑||运算符 var Hello3=React.createClass({ render:function(){ return <p>Hello,{this.props.name||"LuckyWinty"}</p>  } });
复制代码

④非DOM属性介绍

JSX中有3个非DOM属性,分别是:dangerouslySetInnerHTML、ref、key。

dangerouslySetInnerHTML:在JSX中直接插入HTML代码,可是若是能避免使用这个属性则尽可能避免使用。

不合时宜的使用 innerHTML 可能会致使 cross-site scripting (XSS) 攻击。 净化用户的输入来显示的时候,常常会出现错误,不合适的净化也是致使网页攻击 的缘由之一。

在完全的理解安全问题后果并正确地净化数据以后,生成只包含惟一 key __html 的对象,而且对象的值是净化后的数据。例如:

function createMarkup() { return {__html: 'First &middot; Second'}; }; <div dangerouslySetInnerHTML={createMarkup()} />

ref:父组件引用子组件,你能够经过在属性中设置指望的引用名来定义一个引用。例如:

复制代码
... render:function(){ return <div>
           <input ref="MyInput" .../>
           </div> } ... //而后你就能够在组件中的任何地方使用this.refs.myInput获取这个引用了
复制代码

key:是一个可选的惟一标识符,经过给组件设置一个独一无二的键,并确保它在一个渲染周期中保持一致,使得React可以更只能地决定应该重用一个组件仍是销毁并重建一个组件,进而提升渲染性能。例如:

复制代码
var Hello3=React.createClass({ render:function(){ return <ul>
                <li key="1">1</li>
                <li key="2">2</li>
                <li key="3">3</li>
         </ul>  } });
复制代码

更多详细信息请参考:http://facebook.github.io/jsx/

2、React组件生命周期详解

组件本质上就是状态机,输入肯定,输出必定肯定。状态和结果一一对应,从而使程序变得直观。状态发生转换时会触发不一样的钩子函数,从而让开发者有机会作出响应。能够用事件的思路来理解状态,可是事件与事件之间互相独立,可是不一样状态之间可能会互相影响。
组件的全部状态结合起来就成了组件的生命周期。即:初始化阶段->运行中阶段->销毁阶段。
 
不一样生命周期内能够自定义的函数
初始化阶段:
①getDefaultProps:获取默认属性,只调用一次,是在createClass以后调用的。实例之间共享引用
②getInitialState:初始化每一个实例的特有初始化状态
③componentWillMount:mout就是装载的意思,这个方法的意思就是说组件即将被装载到页面中,也是render以前最后一次修改状态的机会
④render:组件在render函数生成虚拟节点,最后由react将虚拟节点变成真正的节点渲染到页面上。只能访问this.props和this.state,只有一个顶层组件,最好不要修改状态和DOM输出。
⑤componentDidMount:组件被装载后才会被调用,也就是说调用这个方法的时候,组件已经被渲染到了页面上,这个时候能够修改DOM
这五个函数的执行顺序就是从上到下的。须要注意的是getDefaultProps只会在组件的第一个实例被初始化的时候被调用,也就是说第二个实例以后都是从getInitialState开始调用。同一个组件的全部实例的默认属性都是同样的。
主要测试代码:
复制代码
<script type="text/babel"> var Hello=React.createClass({ getDefaultProps:function(){ console.log("getDefaultProps, 1"); }, getInitialState:function(){ console.log("getInitialState, 2"); return null; }, componentWillMount:function(){ console.log("componentWillMount, 3"); }, render:function(){ console.log("render, 4"); return <p>Hi,LuckyWinty!</p>  }, componentDidMount:function(){ console.log("componentDidMount, 5"); }, }); React.render(<Hello></Hello>,document.body);
</script>
复制代码

运行结果:

运行中阶段:
①componentWillReceiveProps:这个函数在组件即将接收到属性时触发的,或者是父组件的属性发生变化时,属性在传送到组件以前,开发者有机会经过这个函数去处理属性。好比修改,更新内部状态等。
②shouldComponentUpdate:当组件接收到新属性或者新状态的时候触发的。这个是一个疑问函数,也就是说咱们能够告诉react不去更新某个组件。由于有时候属性或者状态并不会致使组件发生更新。在组件不须要更新的状况下,手动使shouldComponentUpdate返回false,这样react就不须要再通过render和diff算法去判断是否要更新,从而提升性能。
③componentWillUpdate:render触发以前触发,更新组件,不能修改属性和状态
④render:组件在render函数生成虚拟节点,最后由react将虚拟节点变成真正的节点渲染到页面上,只能访问this.props和this.state,只有一个顶层组件,最好不要修改状态和DOM输出。
⑤componentDidUpdate:render以后,真正的DOM被渲染以后调用
备注:这五个函数的执行顺序也是从上到下的。这个的测试代码已上传至:https://github.com/LuckyWinty/ReactStudyDemo,欢迎参考!
 
销毁阶段:
①componentWillUnmount:这个函数在销毁操做真正执行以前调用,给开发者最后的机会进行一些清理工做。

3、属性、状态的含义和用法

属性的含义:
props=properties,属性是不能够由组件本身进行修改的,组件的属性是由父组件传递进来的。
属性的用法:
1、键值对
<Hello name="winty"/>   字符串
<Hello name={123}/>    大括号包裹的求值表达式
<Hello name={[1,2,3]}/>   传入数组
<Hello name={winty}/>   变量
2、展开定义(我的认为就是对象式定义)
var props={ one:"123", two:"22" }
这样定义的话,理论上使用应该是one={props.one}这样调用,可是这样写起来比较繁琐,并且若是数据被修改,就须要对应修改相应的赋值,而且没法动态地设置属性,因此react中添加了一种展开语法:
<Hello {...props}/>    //也就是三个点加上对象名称。
这样使用展开语法,react就会自动把对象中的变量和值看成是属性的赋值,因此Hello实际上就拿到了one、two两个属性,若是没有三个点的话,Hello拿到的实际上就是props对象,使用的时候还须要本身从中取出变量和值
3、调用react提供的setProps()函数(几乎不用)
var instance=React.render(<HelloWorld></HelloWorld>,document.body);
instance.setProps({name:"winty"});
状态的含义:
state,状态是由事物自行处理、不断变化的
状态的用法:
getInitialState:初始化实例的状态
setState:更新组件状态,一旦更新了状态,那么就会触发diff算法,检查内容是否发生变化,如有变化则更新组件,不然就不用。
 
属性和状态对比
类似点:都是纯JS对象、都会触发render更新、都具备肯定性。
属性和状态区分:组件在运行时须要修改的数据就是状态
 
4、React中事件的用法
事件处理函数:React绑定事件处理器的方法和HTML语法很是相似,全部的事件在命名上与原生的javascript规范一致,而且会在相同的情境下触发。
编写函数
handleClick:function(){
...
}
绑定
onClick={this.handleClick}
 
各种事件详细说明:
①移动设备上的触摸事件:onTouchCancel、onTouchEnd、onTouchMove、onTouchStart 
②键盘类事件:onKeyDown、onKeyPress、onKeyUp
③剪切类事件:onCopy、onCut、onPaste 
④表单类:onChange//内容变化即触发、onInput//输入框、onSubmit//禁止表单默认跳转行为
⑤事件:onFocus、onBlur 
⑥UI元素类:onScroll
⑦鼠标滚动事件:onWheel
⑧鼠标类型:onClick、onContextMenu//右键菜单、onDoubleClick //双击、onMouseDown、onMouseEnter、onMouseLeave、onMouseMove、onMouseOut、onMouseOver、onMouseUp
⑨拖拽事件:onDrop、onDrag、onDragEnd、onDragEnter、onDragExit、onDragLeave、onDragOver、onDragStart
事件对象介绍
使用方法:就是在编写事件对象处理函数的时候,添加一个参数。拿到这个对象以后,就经过对象的属性来能够获取一些信息。
例如:
handleChange:function(event){ console.log(event.target.value); }
示例中,event就是事件对象,event.target就是事件对象的属性,就是对应的DOM元素,拿到这个元素以后再获取它的值。
事件对象属性
通用属性:

 其余不一样类型的事件有不一样的属性,简单了解一下

知道了事件的一些属性,咱们就能够很方便地在React中获取这些属性,进行一些逻辑的处理,实现一些复杂的业务功能、页面效果等。

例如:咱们能够利用鼠标事件属性,实时显示鼠标在某个区域的坐标:

复制代码
<script type="text/jsx"> var HelloWorld = React.createClass({ getInitialState: function () { return { x: 0, y: 0 } }, handleMouseMove: function (event) { this.setState({ x: event.clientX, y: event.clientY }); }, render: function () { return <div onMouseMove={this.handleMouseMove} style={{ height: '500px', width: '500px', backgroundColor: 'gray' }}> {this.state.x + ', ' + this.state.y} </div>;  }, }); React.render(<HelloWorld></HelloWorld>, document.body);
    </script>
复制代码

5、组件的协同使用

组件协同使用的定义:组件的协同本质上就是对组件的一种组织、管理方式。
组件协同使用的目的:逻辑清晰、代码模块化、封装细节、代码可复用。
组件协同使用的方式:

①组件嵌套使用:也就是说,用一个父组件把子组件包裹起来,本质就是父子关系。以下图描述:

实例代码:

复制代码
var React = require('react'); var CommentList=require('./CommentList.jsx'); var CommentForm=require('./commentFrom.jsx'); var CommentBox = React.createClass({ render: function() { return ( <div className="commentBox">
        <h1>Comments</h1>
        <CommentList />   //这是一个组件
        <CommentForm />    //这是另外一个组件
      </div>  ); } }); module.exports = CommentBox;
复制代码
父子组件之间的通讯:
父组件->子组件:经过属性,父组件把数据经过属性来传递给子组件
子组件->父组件:本质上,子组件不能向父组件通讯。可是能够间接地经过触发事件来通讯,也就是委托。
嵌套组合缺点:
父子关系的具体实现须要通过深思熟虑,贸然编写将致使关系混乱、代码难以维护
没法掌握全部细节,使用者只知道组件用法,不知道实现细节,遇到问题难以修复

②Mixin:也就是能够把相同的代码抽象出来,封装成一个函数,而后再调用。

Mixin的目的:横向抽离出组件的类似代码
类似概念:面向切向面编程、插件
实例代码:
复制代码
var Time=React.createClass({ mixins:[IntervalMixin(1000)], getInitialState:function(){ return {secondElapsed:0}; }, onTick:function(){ this.setState({secondElapsed:this.state.secondElapsed+1}); }, render:function(){ return ( <div>Seconds Elapsed:{this.state.secondsElapsed}</div>  ); } });
复制代码

mixin至关简单,它们就是混合进组件类中的对象而已。React在这方面实现得更加深刻,它能防止静默函数覆盖,同时还支持多个mixin混合。可是这些功能在别的系统中可能引发冲突。例如:

复制代码
React.createClass({ mixins:[{ getInitialState:function(){ return {a:1}} }], getInitialState:function(){ return {b:2}} });
复制代码

这样在mixin和组件类中同时定义了getInitialState方法,获得的初始state是{a:1,b:2}.若是mixin中的方法和组件类中的方法返回的对象中存在重复的键,React会抛出一个错误来警示这个问题。

 6、React中的双向绑定

React创立的理念跟angular那些框架就是不一样的,React是单向数据绑定的。那么怎么实现像angular那样的双向绑定效果呢?看代码:

复制代码
<!DOCTYPE html>
<html lang="zh-cn">
<head>
    <meta charset="UTF-8">
    <title>React中的双向数据绑定</title>
</head>
<body>
    <script src="./react-0.13.2/react-0.13.2/build/react-with-addons.js"></script>
    <script src="./react-0.13.2/react-0.13.2/build/JSXTransformer.js"></script>
    <script type="text/jsx"> var BindingMixin = { handleChange: function(key) { var that = this var newState = {} return function(event) { newState[key] = event.target.value that.setState(newState) } } } var BindingExample = React.createClass({ mixins: [React.addons.LinkedStateMixin], getInitialState: function() { return { text: '', comment: '', } }, render: function() { return <div>
                    <input type="text" placeholder="请输入内容" valueLink={this.linkState('text')} />
                    <textarea valueLink={this.linkState('comment')}></textarea>
                    <h3>{this.state.text}</h3>
                    <h3>{this.state.comment}</h3>
                </div>  } }) React.render(<BindingExample></BindingExample>, document.body);
    </script>
</body>
</html>
复制代码

效果图(没有CSS样式,有点不优雅,见谅):

更多学习demo已上传至:https://github.com/LuckyWinty/ReactStudyDemo,欢迎参考!

参考资料:

    《React引领将来的用户界面开发框架》

     极客学院视频课程

 

PS:react.js模块化开发及打包方式欢迎参考个人上一篇博文《React.js入门必须知道的那些事》,后续会有更多深刻的学习,欢迎你们给我学习意见^_^

相关文章
相关标签/搜索