今天,继续深入学习react.js。

目录:

一、JSX介绍

二、React组件生命周期详解

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

四、React中事件的用法

五、组件的协同使用

六、React中的双向绑定

 一、JSX介绍

①定义

JSX=JavaScript XML,是一种在React组件内部构建标签的类XML语法。React在不使用JSX的情况下一样可以工作,但是使用JSX可以提高组件的可读性,增强JS语义,结构清晰,抽象程度高,代码模块化。因此推荐在React中使用JSX。

②特点

1、元素名首字母大写

2、符合嵌套规则

3、可以写入求值表达式

4、驼峰式命名

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

③使用方法

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

  1. var name=“winty”;
  2.  
  3. <p>{name}</p>

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

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

  1. var Hello=React.createClass({
  2. render:function(){
  3. return <p name="winty"> //set name
  4. Hello ,World
  5. /*
  6. 多行注释
  7. 多行注释
  8. */
  9. </p>
  10. }
  11. });

3.使用CSS内联样式

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

4.使用条件判断

  1. //方法1,三目运算符
  2. var Hello=React.createClass({
  3. render:function(){
  4. return <p>Hello,{this.props.name?this.props.name : "LuckyWinty"}</p>
  5. }
  6. });
  7.  
  8. //方法2,if-else语句
  9. var Hello1=React.createClass({
  10. getName:function(){
  11. if(this.props.name)
  12. return this.props.name;
  13. else
  14. return "LuckyWinty";
  15. render:function(){
  16. return <p>Hello,{this.getName}</p>
  17. }
  18. });
  19. //方法3,使用逻辑||运算符
  20. var Hello3=React.createClass({
  21. render:function(){
  22. return <p>Hello,{this.props.name||"LuckyWinty"}</p>
  23. }
  24. });

④非DOM属性介绍

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

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

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

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

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

ref:父组件引用子组件,你可以通过在属性中设置期望的引用名来定义一个引用。例如:

  1. ...
  2. render:function(){
  3. return <div>
  4. <input ref="MyInput" .../>
  5. </div>
  6. }
  7. ...
    //然后你就可以在组件中的任何地方使用this.refs.myInput获取这个引用了

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

  1. var Hello3=React.createClass({
  2. render:function(){
  3. return <ul>
  4. <li key="1">1</li>
  5. <li key="2">2</li>
  6. <li key="3">3</li>
  7. </ul>
  8. }
  9. });

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

二、React组件生命周期详解

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

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

属性的含义:
props=properties,属性是不可以由组件自己进行修改的,组件的属性是由父组件传递进来的。
属性的用法:
一、键值对
  1. <Hello name="winty"/> 字符串
    <Hello name={123}/> 大括号包裹的求值表达式
    <Hello name={[1,2,3]}/> 传入数组
    <Hello name={winty}/> 变量
二、展开定义(个人认为就是对象式定义)
  1. var props={
  2. one:"123",
  3. two:"22"
  4. }
这样定义的话,理论上使用应该是one={props.one}这样调用,但是这样写起来比较繁琐,而且如果数据被修改,就需要对应修改相应的赋值,并且无法动态地设置属性,所以react中添加了一种展开语法:
<Hello {...props}/>    //也就是三个点加上对象名称。
这样使用展开语法,react就会自动把对象中的变量和值当作是属性的赋值,所以Hello实际上就拿到了one、two两个属性,如果没有三个点的话,Hello拿到的实际上就是props对象,使用的时候还需要自己从中取出变量和值
三、调用react提供的setProps()函数(几乎不用)
  1. var instance=React.render(<HelloWorld></HelloWorld>,document.body);
  2. instance.setProps({name:"winty"});
状态的含义:
state,状态是由事物自行处理、不断变化的
状态的用法:
getInitialState:初始化实例的状态
setState:更新组件状态,一旦更新了状态,那么就会触发diff算法,检查内容是否发生变化,若有变化则更新组件,否则就不用。
 
属性和状态对比
相似点:都是纯JS对象、都会触发render更新、都具有确定性。
属性和状态区分:组件在运行时需要修改的数据就是状态
 
四、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
事件对象介绍
使用方法:就是在编写事件对象处理函数的时候,添加一个参数。拿到这个对象之后,就通过对象的属性来可以获取一些信息。
例如:
  1. handleChange:function(event){
  2. console.log(event.target.value);
  3. }
示例中,event就是事件对象,event.target就是事件对象的属性,就是对应的DOM元素,拿到这个元素之后再获取它的值。
事件对象属性
通用属性:

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

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

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

  1. <script type="text/jsx">
  2. var HelloWorld = React.createClass({
  3. getInitialState: function () {
  4. return {
  5. x: 0,
  6. y: 0
  7. }
  8. },
  9. handleMouseMove: function (event) {
  10. this.setState({
  11. x: event.clientX,
  12. y: event.clientY
  13. });
  14. },
  15. render: function () {
  16. return <div onMouseMove={this.handleMouseMove} style={{
  17. height: '500px',
  18. width: '500px',
  19. backgroundColor: 'gray'
  20. }}>
  21. {this.state.x + ', ' + this.state.y}
  22. </div>;
  23. },
  24. });
  25. React.render(<HelloWorld></HelloWorld>, document.body);
  26. </script>

五、组件的协同使用

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

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

实例代码:

  1. var React = require('react');
  2. var CommentList=require('./CommentList.jsx');
  3. var CommentForm=require('./commentFrom.jsx');
  4.  
  5. var CommentBox = React.createClass({
  6. render: function() {
  7. return (
  8. <div className="commentBox">
  9. <h1>Comments</h1>
  10. <CommentList /> //这是一个组件
  11. <CommentForm /> //这是另一个组件
  12. </div>
  13. );
  14. }
  15. });
  16.  
  17. module.exports = CommentBox;
父子组件之间的通信:
父组件->子组件:通过属性,父组件把数据通过属性来传递给子组件
子组件->父组件:本质上,子组件不能向父组件通信。但是可以间接地通过触发事件来通信,也就是委托。
嵌套组合缺点:
父子关系的具体实现需要经过深思熟虑,贸然编写将导致关系混乱、代码难以维护
无法掌握所有细节,使用者只知道组件用法,不知道实现细节,遇到问题难以修复

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

Mixin的目的:横向抽离出组件的相似代码
相似概念:面向切向面编程、插件
实例代码:
  1. var Time=React.createClass({
  2. mixins:[IntervalMixin(1000)],
  3. getInitialState:function(){
  4. return {secondElapsed:0};
  5. },
  6. onTick:function(){
  7. this.setState({secondElapsed:this.state.secondElapsed+1});
  8. },
  9. render:function(){
  10. return (
  11. <div>Seconds Elapsed:{this.state.secondsElapsed}</div>
  12. );
  13. }
  14. });

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

  1. React.createClass({
  2. mixins:[{
  3. getInitialState:function(){ return {a:1}}
  4. }],
  5. getInitialState:function(){ return {b:2}}
  6. });

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

 六、React中的双向绑定

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

  1. <!DOCTYPE html>
  2. <html lang="zh-cn">
  3. <head>
  4. <meta charset="UTF-8">
  5. <title>React中的双向数据绑定</title>
  6. </head>
  7. <body>
  8. <script src="./react-0.13.2/react-0.13.2/build/react-with-addons.js"></script>
  9. <script src="./react-0.13.2/react-0.13.2/build/JSXTransformer.js"></script>
  10. <script type="text/jsx">
  11. var BindingMixin = {
  12. handleChange: function(key) {
  13. var that = this
  14. var newState = {}
  15. return function(event) {
  16. newState[key] = event.target.value
  17. that.setState(newState)
  18. }
  19. }
  20. }
  21. var BindingExample = React.createClass({
  22. mixins: [React.addons.LinkedStateMixin],
  23. getInitialState: function() {
  24. return {
  25. text: '',
  26. comment: '',
  27. }
  28. },
  29. render: function() {
  30. return <div>
  31. <input type="text" placeholder="请输入内容" valueLink={this.linkState('text')} />
  32. <textarea valueLink={this.linkState('comment')}></textarea>
  33. <h3>{this.state.text}</h3>
  34. <h3>{this.state.comment}</h3>
  35. </div>
  36. }
  37. })
  38. React.render(<BindingExample></BindingExample>, document.body);
  39. </script>
  40. </body>
  41. </html>

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

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

参考资料:

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

极客学院视频课程

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

React.js深入学习详细解析的更多相关文章

  1. jQuery与直接写JS的区别详细解析

    jQuery代码具体的写法和原生的Javascript写法在执行常见操作时的区别如下所示.需要的朋友可以过来参考下     要使用jQuery,首先要在HTML代码最前面加上对jQuery库的引用,比 ...

  2. react.js学习之路一

    今天新老大来了,我们要学习他使用的框架react.js,现在是两眼一抹黑,对于我这个前端菜鸟来说,是真正的重新开始,好了,不说那么多了,开始随便记录我的学习,之后再整理内容. (1)对于react来说 ...

  3. React.js学习小结

    最近一段时间都在学习React.js,感觉还不错,现在把自己的一些学习笔记记录一下,留着以后学习查看. 0.React全家桶(技术栈) 1.React主体 2.WebPack:grunt.gulp自动 ...

  4. React.js学习

    React.js学习之环境搭建 1 工欲善其事必先利其器:前端开发工具 1.1 WebStorm和Sublime Text Sublime Text:作为代码编辑器,Sublime Text的优点如下 ...

  5. React JS和React-Native学习指南

    自己在学习React-Native过程中整理的一份学习指南,包含 教程.开源app和资源网站等,还在不断更新中.欢迎pull requests! React-Native学习指南本指南汇集React- ...

  6. react.js学习之路二

    看react.js对我来说真的不是难不难的问题,问题是我的思路太难转变了,真是坑死我了,react里面的坑也很多.算了,这些抱怨没啥用,记录一下今天学习的内容. 今天看了to-do-list经典示例 ...

  7. React.js学习知识小结(一)

    学习React也有半个月了吧,这里对所学的基础知识做个简单的总结.自己先是跟着官方文档学,差不多学了四五天,也跟着入门教程做了一个简单的小栗子.然后跟着阮一峰老师的教程上手了几个小Demo,后来在网上 ...

  8. react.js学习之路四

    针对学习react.js中,我感觉最大的疑惑点就是bind(this)的绑定和指向问题了,我被这个问题弄的头昏,有时候调用组件的时候,直接显示undefined,不存在这个组件,当时的心情是崩溃的,整 ...

  9. react.js学习之路三

    学习react.js,知识点整理: 1.props和state: props是相对于父级来说,固定的不会改变的内容.一般会先定义一个变量,则在父级中进行引用, var user = "liu ...

随机推荐

  1. 03.SQLServer性能优化之---存储优化系列

    汇总篇:http://www.cnblogs.com/dunitian/p/4822808.html#tsql 概  述:http://www.cnblogs.com/dunitian/p/60413 ...

  2. Database Replay和Consolidated Database replay

    简介 在数据库的迁移和升级场景中,我们经常会遇到一个问题:在做压力测试时,如何模拟真实的业务压力,解决这个问题的方法有很多,比如:应用方开发模拟程序或者使用压力测试工具模拟,如load runner, ...

  3. transtion:过渡动画

    p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 17.0px Monaco; color: #4f5d66 } p.p2 { margin: 0.0px 0 ...

  4. HTML块级元素

    前面的话   在HTML5出现之前,人们一般把元素分为块级.内联和内联块元素.本文将详细介绍HTML块级元素 h   标题(Heading)元素有六个不同的级别,<h1>是最高级的,而&l ...

  5. MCDownloadManager ios文件下载管理器

    我们用AFNetworking小试牛刀,写一个简单的下载器来演示功能. 前言 为什么AFNetworking能够成为顶级框架?我们究竟该如何领悟它的精髓所在?这都是很难的问题.安全,高效,流畅,这3个 ...

  6. Android Studio-—使用OpenCV的配置方法和demo以及开发过程中遇到的问题解决

    前提: 1.安装Android Studio(过程略) 2.官网下载OpenCV for Android 网址:http:opencv.org/downloads.html 我下载的是下图的版本 3. ...

  7. MySQL ALTER命令

    当我们需要修改数据表名或者修改数据表字段时,就需要使用到MySQL ALTER命令. 开始本文教程前让我们先创建一张表,表名为:testalter_tbl. root@host# mysql -u r ...

  8. Linux自动共享USB设备:udev+Samba

    一.概述 公司最近要我实现USB设备插入Ubuntu后,自动共享到网络上,能像Windows共享一样(如\\192.168.1.10)访问里面的内容,不需要写入权限.当时听完这需求,我这新人表示惊呆了 ...

  9. Android快乐贪吃蛇游戏实战项目开发教程-03虚拟方向键(二)绘制一个三角形

    该系列教程概述与目录:http://www.cnblogs.com/chengyujia/p/5787111.html 一.绘制三角形 在上一篇文章中,我们已经新建了虚拟方向键的自定义控件Direct ...

  10. 打造TypeScript的Visual Studio Code开发环境

    打造TypeScript的Visual Studio Code开发环境 本文转自:https://zhuanlan.zhihu.com/p/21611724 作者: 2gua TypeScript是由 ...