澳门新萄京官方网站-www.8455.com-澳门新萄京赌场网址

澳门新萄京官方网站:REACT急迅入门,js深入学习

2019-11-16 作者:澳门新萄京赌场网址   |   浏览(85)

React.js深入学习详细解析

2016/07/16 · JavaScript · ReactJS

本文作者: 伯乐在线 - winty 。未经作者许可,禁止转载!
欢迎加入伯乐在线 专栏作者。

今天,继续深入学习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上下文环境,花括号里面可以是一个变量,也可以是函数。 例如:

JavaScript

var name=“winty”; <p>{name}</p>

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

JavaScript

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

1
2
3
4
5
6
7
8
function date(d){
  return [
    d.getFullYear(),
    d.getMonth() 1,
    d.getDate()
  ].join('-);
};
<p>{date(new Date()}</p>

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

JavaScript

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

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

3.使用CSS内联样式

JavaScript

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

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

4.使用条件判断

JavaScript

//方法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> } });

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
//方法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 的对象,并且对象的值是净化后的数据。例如:

JavaScript

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

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

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

JavaScript

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

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

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

JavaScript

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

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

更多详细信息请参考:

 

二、React组件生命周期详解

组件本质上就是状态机,输入确定,输出一定确定。状态和结果一一对应,从而使程序变得直观。状态发生转换时会触发不同的钩子函数,从而让开发者有机会做出响应。可以用事件的思路来理解状态,但是事件与事件之间互相独立,但是不同状态之间可能会互相影响。

组件的所有状态结合起来就成了组件的生命周期。即:初始化阶段->运行中阶段->销毁阶段。

不同生命周期内可以自定义的函数

初始化阶段:

①getDefaultProps:获取默认属性,只调用一次,是在createClass之后调用的。实例之间共享引用

②getInitialState:初始化每个实例的特有初始化状态

③componentWillMount:mout就是装载的意思,这个方法的意思就是说组件即将被装载到页面中,也是render之前最后一次修改状态的机会

④render:组件在render函数生成虚拟节点,最后由react将虚拟节点变成真正的节点渲染到页面上。只能访问this.props和this.state,只有一个顶层组件,最好不要修改状态和DOM输出。

⑤componentDidMount:组件被装载后才会被调用,也就是说调用这个方法的时候,组件已经被渲染到了页面上,这个时候可以修改DOM

这五个函数的执行顺序就是从上到下的。需要注意的是getDefaultProps只会在组件的第一个实例被初始化的时候被调用,也就是说第二个实例之后都是从getInitialState开始调用。同一个组件的所有实例的默认属性都是一样的。

主要测试代码:

JavaScript

<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>

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<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>

运行结果:

澳门新萄京官方网站 1

运行中阶段:

①componentWillReceiveProps:这个函数在组件即将接收到属性时触发的,或者是父组件的属性发生变化时,属性在传送到组件之前,开发者有机会通过这个函数去处理属性。比如修改,更新内部状态等。

②shouldComponentUpdate:当组件接收到新属性或者新状态的时候触发的。这个是一个疑问函数,也就是说我们可以告诉react不去更新某个组件。因为有时候属性或者状态并不会导致组件发生更新。在组件不需要更新的情况下,手动使shouldComponentUpdate返回false,这样react就不需要再经过render和diff算法去判断是否要更新,从而提高性能。

③componentWillUpdate:render触发之前触发,更新组件,不能修改属性和状态

④render:组件在render函数生成虚拟节点,最后由react将虚拟节点变成真正的节点渲染到页面上,只能访问this.props和this.state,只有一个顶层组件,最好不要修改状态和DOM输出。

⑤componentDidUpdate:render之后,真正的DOM被渲染之后调用

备注:这五个函数的执行顺序也是从上到下的。这个的测试代码已上传至:

销毁阶段:

①componentWillUnmount:这个函数在销毁操作真正执行之前调用,给开发者最后的机会进行一些清理工作。

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

属性的含义:

props=properties,属性是不可以由组件自己进行修改的,组件的属性是由父组件传递进来的。

属性的用法:

一、键值对

XHTML

<Hello name="winty"/> 字符串 <Hello name={123}/> 大括号包裹的求值表达式 <Hello name={[1,2,3]}/> 传入数组 <Hello name={winty}/> 变量

1
2
3
4
<Hello name="winty"/>   字符串
<Hello name={123}/>    大括号包裹的求值表达式
<Hello name={[1,2,3]}/>   传入数组
<Hello name={winty}/>   变量

二、展开定义(个人认为就是对象式定义)

JavaScript

var props={ one:"123", two:"22" }

1
2
3
4
var props={
   one:"123",
   two:"22"
}

这样定义的话,理论上使用应该是one={props.one}这样调用,但是这样写起来比较繁琐,而且如果数据被修改,就需要对应修改相应的赋值,并且无法动态地设置属性,所以react中添加了一种展开语法:

<Hello {…props}/>    //也就是三个点加上对象名称。

这样使用展开语法,react就会自动把对象中的变量和值当作是属性的赋值,所以Hello实际上就拿到了one、two两个属性,如果没有三个点的话,Hello拿到的实际上就是props对象,使用的时候还需要自己从中取出变量和值

三、调用react提供的setProps()函数(几乎不用)

JavaScript

var instance=React.render(<HelloWorld></HelloWorld>,document.body); instance.setProps({name:"winty"});

1
2
var instance=React.render(<HelloWorld></HelloWorld>,document.body);
instance.setProps({name:"winty"});

状态的含义:

state,状态是由事物自行处理、不断变化的

状态的用法:

getInitialState:初始化实例的状态

setState:更新组件状态,一旦更新了状态,那么就会触发diff算法,检查内容是否发生变化,若有变化则更新组件,否则就不用。

属性和状态对比

相似点:都是纯JS对象、都会触发render更新、都具有确定性。

澳门新萄京官方网站 2

属性和状态区分:组件在运行时需要修改的数据就是状态

四、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

事件对象介绍

使用方法:就是在编写事件对象处理函数的时候,添加一个参数。拿到这个对象之后,就通过对象的属性来可以获取一些信息。

例如:

JavaScript

handleChange:function(event){ console.log(event.target.value); }

1
2
3
handleChange:function(event){
    console.log(event.target.value);
}

示例中,event就是事件对象,event.target就是事件对象的属性,就是对应的DOM元素,拿到这个元素之后再获取它的值。

事件对象属性

通用属性:

澳门新萄京官方网站 3

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

澳门新萄京官方网站 4

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

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

JavaScript

<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>

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
<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

实例代码:

JavaScript

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;

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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的目的:横向抽离出组件的相似代码

相似概念:面向切向面编程、插件

实例代码:

JavaScript

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> ); } });

1
2
3
4
5
6
7
8
9
10
11
12
13
14
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混合。但是这些功能在别的系统中可能引起冲突。例如:

JavaScript

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

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

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

 六、React中的双向绑定

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

XHTML

<!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>

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
<!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样式,有点不优雅,见谅):

澳门新萄京官方网站 6

更多学习demo已上传至:

参考资料:

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

极客学院视频课程

打赏支持我写出更多好文章,谢谢!

打赏作者

一、HTML 模板

零、安装
React 的安装包,可以到官网下载。不过,React Demos 已经自带 React 源码,不用另外安装,只需把这个库拷贝到你的硬盘就行了。

<!DOCTYPE html>
<html>
<head>
<script src="../build/react.js"></script>
<script src="../build/react-dom.js"></script>
<script src="../build/browser.min.js"></script>
</head>
<body>
<div id="example"></div>
<script type="text/babel">
// ** Our code goes here! **
</script>
</body>
</html>
a). 注意点最后一个<script>标签的type属性为text/label,这是因为React独有的JSX语法和JS不兼容。凡是使用JSX的地方,都要加上type="text/label";

*通过createElement创建元素 HELLO Word

打赏支持我写出更多好文章,谢谢!

任选一种支付方式

澳门新萄京官方网站 7 澳门新萄京官方网站 8

1 赞 3 收藏 评论

使用 React 的网页源码,结构大致如下。

$ git clone git@github.com:ruanyf/react-demos.git
如果你没安装 git, 那就直接下载 zip 压缩包。

b). 上面的代码使用了三个库:react.js/react-dom.js/Browser.js,它们都是必须首先加载。其中react.js是React的核心库,react-dom.js是提供与DOM相关的功能,Browser.js的作用是将JSX语法转为javascript语法。(这一步是很耗时间的,在实际上线的时候,应该将它放到服务器完成)
1.ReactDOM.render()
ReactDOM.render是React的最基本的方法,用于将模板转为HTML语言,并插入指定的DOM节点,如:
ReactDOM.render(
<h1>Hello,world</h1>,
document.getElementById('example')
);
//上面代码将一个 h1 标题,插入 example 节点
2.JSX语法
JSX的语法允许HTML语言直接写在JavaScript语言之中,不加任何引号具体点来说:JSX遇到HTML标签(以<开头),就用HTML规则解析;遇到代码块(以{开头),就用JavaScript规则解析
3.组件
React运毒将代码封装成组件(Component),然后想插入普通HTML标签一样,在网页中插入这个组件。React.createClass方法就是用于生成一个组件类,如:
var HelloMessage=React.createClass({
render:function(){
return <h1>Hello {this.props.name}</h1>;
}
});

var el=React.createElement(type,[props],[children...]) 标签 属性 内容
React.render(el,document.getElementById("..."))

关于作者:winty

澳门新萄京官方网站 9

前端工程师,前端爱好者。博客: 个人主页 · 我的文章 · 1 ·  

澳门新萄京官方网站 10

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="../build/react.js"></script>
    <script src="../build/react-dom.js"></script>
    <script src="../build/browser.min.js"></script>
</head>
<body>
    <div id="example"></div>
    <script type="text/babel">
        // ** Our code goes here! **
    </script>
</body>
</html>

下面要讲解的12个例子在各个 Demo 子目录,每个目录都有一个 index.html 文件,在浏览器打开这个文件(大多数情况下双击即可),就能立刻看到效果。
需要说明的是,React 可以在浏览器运行,也可以在服务器运行,但是本教程只涉及浏览器。一方面是为了尽量保持简单,另一方面 React 的语法是一致的,服务器的用法与浏览器差别不大。Demo13 是服务器首屏渲染的例子,有兴趣的朋友可以自己去看源码。
一、HTML 模板
澳门新萄京官方网站,使用 React 的网页源码,结构大致如下。

ReactDOM.render(<HelloMessage name="John" />,
document.getElementById('example')
)
==>组件的属性可以在组件类的this.props对象上获取,
比如name属性就可以通过this.props.name读取补充:this.props.children表示组件的左右子节点;
组件类的PropTypes属性用来验证组件实例的属性是否符合要求
4.获取真实的DOM节点
组件并不是真实的DOM节点,而是存在于内存之中的一种数据结构,叫作虚拟DOM(virtual DOM).只有当它插入文档之后才会变成真实的DOM。更加React的设计,所有的DOM变动都是现在虚拟DOM上发生,然后再将实际发生变动的部分,反应在正式DOM上,
这种算法叫作DOM Diff,它可以极大提高网页的性能表现
如果需要从组件获取真实DOM的节点,要用到ref属性
5.this.state
组件避免不了和用户交互,React将组件看成一个状态机,开始有一个初始状态,然后用户互动,导致状态变化,从而触发重新渲染UI
var LikeButton = React.createClass({
getInitialState: function() {
return {liked: false};
},
handleClick: function(event) {
this.setState({liked: !this.state.liked});
},
render: function() {
var text = this.state.liked ? 'like' : 'haven't liked';
return (
<p onClick={this.handleClick}>
You {text} this. Click to toggle.
</p>
);
}
});
分析:getInitialState方法用于定义初始状态,它就是一个对象,这个对象可以通过this.state属性读取,当喻户点击组件,导致状态变化。this.setState方法就会修改状态值,每次修改以后,自动调用this.render方法,再次渲染组件
补充:
this.props和this.state都用于描述组件的特性,前者表示那些一旦定义,就不再改变的特性,而后者会随着用户互动而放生变化的特性

*虚拟DOM

上面代码有两个地方需要注意。首先,最后一个 <script> 标签的 type 属性为 text/babel 。这是因为 React 独有的 JSX 语法,跟 JavaScript 不兼容。凡是使用 JSX 的地方,都要加上 type="text/babel"

<!DOCTYPE html>
<html>
<head>
<script src="../build/react.js"></script>
<script src="../build/react-dom.js"></script>
<script src="../build/browser.min.js"></script>
</head>
<body>
<div id="example"></div>
<script type="text/babel">
// ** Our code goes here! **
</script>
</body>
</html>
上面代码有两个地方需要注意。首先,最后一个 <script> 标签的 type 属性为 text/babel 。这是因为 React 独有的 JSX 语法,跟 JavaScript 不兼容。凡是使用 JSX 的地方,都要加上 type="text/babel" 。
其次,上面代码一共用了三个库: react.js 、react-dom.js 和 Browser.js ,它们必须首先加载。其中,react.js 是 React 的核心库,react-dom.js 是提供与 DOM 相关的功能,Browser.js 的作用是将 JSX 语法转为 JavaScript 语法,这一步很消耗时间,实际上线的时候,应该将它放到服务器完成。

6.组件的生命周期
组件的生命周期分为三个状态:
Mounting:已插入真实DOM===>Updating:正在被重新渲染===>Unmounting:已移出真实DOMReact为每个状态都提供了两个处理函数,
will函数再进入状态之间调用,did函数再进入状态之后调用,三种状态攻击五种处理函数:
componentWillMount()
componentDidMount()
componentWillUpdate(object nextProps, object nextState)
componentDidUpdate(object prevProps, object prevState)
componentWillUnmount()React 还提供两种特殊状态的处理函数:componentWillReceiveProps(object nextProps):已加载组件收到新的参数时调用shouldComponentUpdate(object nextProps, object nextState):组件判断是否重新渲染时调用,如:
var Hello = React.createClass({
getInitialState: function () {
return {
opacity: 1.0
};
},

在虚拟DOM上操作 通过render来挂载到真实的DOM
组件
React.createClass(meta)
内部需要render函数

其次,上面代码一共用了三个库: react.js 、react-dom.js 和 Browser.js ,它们必须首先加载。其中,react.js 是 React 的核心库,react-dom.js 是提供与 DOM 相关的功能,Browser.js 的作用是将 JSX 语法转为 JavaScript 语法,这一步很消耗时间,实际上线的时候,应该将它放到服务器完成。

$ babel src --out-dir build
上面命令可以将 src 子目录的 js 文件进行语法转换,转码后的文件全部放在 build 子目录。
二、ReactDOM.render()
ReactDOM.render 是 React 的最基本方法,用于将模板转为 HTML 语言,并插入指定的 DOM 节点。

componentDidMount: function () {
this.timer = setInterval(function () {
var opacity = this.state.opacity;
opacity -= .05;
if (opacity < 0.1) {
opacity = 1.0;
}
this.setState({
opacity: opacity
});
}.bind(this), 100);
},

*JSX

$ babel src --out-dir build

ReactDOM.render(
<h1>Hello, world!</h1>,
document.getElementById('example')
);
上面代码将一个 h1 标题,插入 example 节点(查看 demo01),运行结果如下。

render: function () {
return (
<div style={{opacity: this.state.opacity}}>
Hello {this.props.name}
</div>
);
}
});

JSX是对JavaScript语法的扩展,它让我们可以在JavaScript代码中以类似HTML 的方式创建React元素。
var Jsxdemo=React.createClass({
render:function(){
var html=<div>
<div className="ez-led">Hello, React!</div>
<div className="ez-led">2015-04-15</div>
<div className="ez-led">我是第三排</div>
</div>;
return html;
}
JSX 能让我们像是拼写字符串一样去写HTML、

上面命令可以将 src 子目录的 js 文件进行语法转换,转码后的文件全部放在 build 子目录。

三、JSX 语法
上一节的代码, HTML 语言直接写在 JavaScript 语言之中,不加任何引号,这就是 JSX 的语法,它允许 HTML 与 JavaScript 的混写(查看 Demo02 )。

ReactDOM.render(
<Hello name="world"/>,
document.body
);
注意style={{opacity:this.state.opacity}},因为一重大括号表示JavaScript语法,第二重大括号表示样式对象

*props

二、ReactDOM.render()

var names = ['Alice', 'Emily', 'Kate'];

props 称之为 无状态组件 组件的表现都是通过外部传入的props属性 根据自身的状态来做出不同的反应
var Jsxdemo=React.createClass({
render:function(){
var number=this.props.setid;
alert(number); 这里能直接输出对象里的汉字
var style={
"color":"red",
"fontSize":"12px"//这里是要求内联样式需要按照驼峰写法去写
}
var html=<div>
<div className="ez-led" style={style}>Hello, React!</div>
<div className="ez-led">2015-04-15</div>
<div className="ez-led">我是第三排</div>
</div>;
return html;
}
});

ReactDOM.render 是 React 的最基本方法,用于将模板转为 HTML 语言,并插入指定的 DOM 节点。

ReactDOM.render(
<div>
{
names.map(function (name) {
return <div>Hello, {name}!</div>
})
}
</div>,
document.getElementById('example')
);
上面代码体现了 JSX 的基本语法规则:遇到 HTML 标签(以 < 开头),就用 HTML 规则解析;遇到代码块(以 { 开头),就用 JavaScript 规则解析。上面代码的运行结果如下。

    ReactDOM.render(<Jsxdemo setid="11"/>,document.getElementById("jsxdemobox"));

ReactDOM.render(

JSX 允许直接在模板插入 JavaScript 变量。如果这个变量是一个数组,则会展开这个数组的所有成员(查看 demo03 )。

*内联样式

  <h1>Hello, world!</h1>,

var arr = [
<h1>Hello world!</h1>,
<h2>React is awesome</h2>,
];
ReactDOM.render(
<div>{arr}</div>,
document.getElementById('example')
);
上面代码的arr变量是一个数组,结果 JSX 会把它的所有成员,添加到模板,运行结果如下。

var Jsxdemo=React.createClass({
render:function(){
var style={
"color":"red",
"fontSize":"12px"//这里是要求内联样式需要按照驼峰写法去写
}
var html=<div>
<div className="ez-led" style={style}>Hello, React!</div>
<div className="ez-led">2015-04-15</div>
<div className="ez-led">我是第三排</div>
</div>;
return html;
}
});

  document.getElementById('example')

四、组件
React 允许将代码封装成组件(component),然后像插入普通 HTML 标签一样,在网页中插入这个组件。React.createClass 方法就用于生成一个组件类(查看 demo04)。

*state 状态机

);

var HelloMessage = React.createClass({
render: function() {
return <h1>Hello {this.props.name}</h1>;
}
});

state - 组件的状态变量 保存组件的当前状态,可以再任何时候通过this.state来获取到当前状态
getInitialState() - 设置组件初始状态
setState(currentState) - 设置组件当前状态 会重新渲染
//getInitialState方法来设置初始化状态 也就是设置我们的 state {key:value} 其中key代表state指向的状态变量 value代表状态
getInitialState : function(){
return {open : true};
},
//这里是通过一个点击事件来重新设定状态机 必须要通过this.setState({option:!this.state.open}) 意思就是设置状态机的另一种状态
onClick : function(){
//读取并重设状态,这将触发重新渲染
this.setState({open : !this.state.open});
},
//在render来操控我们的虚拟DOM 记得return HTML代码
render : function(){
//根据状态设置样式
img = this.state.open ? "img/switch-on.png" : img = "img/switch-off.png";

上面代码将一个 h1 标题,插入 example 节点

ReactDOM.render(
<HelloMessage name="John" />,
document.getElementById('example')
);
上面代码中,变量 HelloMessage 就是一个组件类。模板插入 <HelloMessage /> 时,会自动生成 HelloMessage 的一个实例(下文的"组件"都指组件类的实例)。所有组件类都必须有自己的 render 方法,用于输出组件。
注意,组件类的第一个字母必须大写,否则会报错,比如HelloMessage不能写成helloMessage。另外,组件类只能包含一个顶层标签,否则也会报错。

            //返回元素
            return <img src = {img} style={{width:"150px"}} onClick={this.onClick}/>;
        }

三、JSX 语法

var HelloMessage = React.createClass({
render: function() {
return <h1>
Hello {this.props.name}
</h1><p>
some text
</p>;
}
});
上面代码会报错,因为HelloMessage组件包含了两个顶层标签:h1和p。
组件的用法与原生的 HTML 标签完全一致,可以任意加入属性,比如 <HelloMessage name="John"> ,就是 HelloMessage 组件加入一个 name 属性,值为 John。组件的属性可以在组件类的 this.props 对象上获取,比如 name 属性就可以通过 this.props.name 读取。上面代码的运行结果如下。

  • 生命周期

上一节的代码, HTML 语言直接写在 JavaScript 语言之中,不加任何引号,这就是 JSX 的语法,它允许 HTML 与 JavaScript 的混写

添加组件属性,有一个地方需要注意,就是 class 属性需要写成 className ,for 属性需要写成 htmlFor ,这是因为 class 和 for 是 JavaScript 的保留字。
五、this.props.children
this.props 对象的属性与组件的属性一一对应,但是有一个例外,就是 this.props.children 属性。它表示组件的所有子节点(查看 demo05)。

componentWillMount() - 组件实例即将挂接(初次渲染)时被调用
这个方法在整个生命周期中只会被调用一次。
componentDidMount() - 组件实例挂接(初次渲染)后被调用
这个方法在整个生命周期中只会被调用一次。
componentWillReceiveProps(nextProps) - 组件实例即将设置新属性时被调用
参数nextProps表示即将应用到组件实例上的新属性值。
这个方法在初次渲染时不会被调用。在此方法内调用setState()不会引起重新渲染。
shouldComponentUpdate(nextProps, nextState) - 组件实例即将重新渲染时被调用
参数nextProps传入即将应用到组件实例上的新属性值,参数nextState传入组件实例即将被 设置的状态值。如果这个方法返回false,那么组件实例就不会被重新渲染。除非我们明确地 知道,新的属性和状态不需要进行重新渲染,否则这个方法都应该返回true。
这个方法在初次渲染时或通过forceUpdate()方法进行渲染时不会被调用。
componentWillUpdate(nextProps, nextState) - 组件实例即将重新渲染时被调用
这个方法在初次渲染时不会被调用。注意:不能在此方法内调用setState()。
componentDidUpdate(prevProps, prevState) - 组件实例重新渲染后被调用
这个方法在初次渲染时不会被调用。
componentWillUnmount() - 组件实例即将从DOM树移除时被调用
这个方法在整个生命周期中只会被调用一次。

var names = ['Alice', 'Emily', 'Kate'];

var NotesList = React.createClass({
render: function() {
return (
<ol>
{
React.Children.map(this.props.children, function (child) {
return <li>{child}</li>;
})
}
</ol>
);
}
});

(访问DOM v0.14 版中 refs 指向的就是 DOM 节点,同时也会保留 .getDOMNode() 方法(带 warning),最终在 v0.15 版中去除该方法。)
首先要给你想获得DOM对象设定 ref=“q” ref 必须是全局唯一的
var el = React.findDOMNode(this.refs.q),
this.refs.q获取到的是虚拟DOM,在render方法执行之后,并且react已经完成了DOM的更新,才能通过 this.refs.city.getDOMNode() 来拿到原生的DOM元素。
使用 this.refs.xxx.getDOMNode() 或React.findDOMNode(this.refs.xxx) 可以获取到真正的 DOM 节点。

ReactDOM.render(

ReactDOM.render(
<NotesList>
<span>hello</span>
<span>world</span>
</NotesList>,
document.body
);
上面代码的 NoteList 组件有两个 span 子节点,它们都可以通过 this.props.children 读取,运行结果如下。

// 之前:
// var input = this.refs.giraffe.getDOMNode();
//
// v0.14 版:0.15版本以后
var input = this.refs.giraffe;
alert(input.value);

  <div>

这里需要注意, this.props.children 的值有三种可能:如果当前组件没有子节点,它就是 undefined ;如果有一个子节点,数据类型是 object ;如果有多个子节点,数据类型就是 array 。所以,处理 this.props.children 的时候要小心。
React 提供一个工具方法 React.Children 来处理 this.props.children 。我们可以用 React.Children.map 来遍历子节点,而不用担心 this.props.children 的数据类型是 undefined 还是 object。更多的 React.Children 的方法,请参考官方文档。
六、PropTypes
组件的属性可以接受任意值,字符串、对象、函数等等都可以。有时,我们需要一种机制,验证别人使用组件时,提供的参数是否符合要求。
组件类的PropTypes属性,就是用来验证组件实例的属性是否符合要求(查看 demo06)。

*表单

  {

var MyTitle = React.createClass({
propTypes: {
title: React.PropTypes.string.isRequired,
},

文本输入框
不要使用value属性设置文本输入框元素的初值,应当使用defaultValue:
//JSX
<input type ="text" defaultValue ="demo"/>
复选按钮
不要使用checked属性设置复选按钮的初始选中状态,应当使用defaultChecked:
//JSX
<input type ="checkbox" defaultChecked/>
单选按钮组
不要使用option元素的selected属性设置单选按钮组的初始选中状态,应当使用 select元素的defaultValue:
//JSX
<select defaultValue="A">
<option value="A">China</option>
<option value="B">India</option>
<option value="C">Japan</option>
</select>

    names.map(function (name) {

render: function() {
return <h1> {this.props.title} </h1>;
}
});
上面的Mytitle组件有一个title属性。PropTypes 告诉 React,这个 title 属性是必须的,而且它的值必须是字符串。现在,我们设置 title 属性的值是一个数值。

*容器组件

      return <div>Hello, {name}!</div>

var data = 123;

在ReactDOM.render里面 ,组件要成双标签 {this.props.children}用于获取到我们的React的 子元素

    })

ReactDOM.render(
<MyTitle title={data} />,
document.body
);
这样一来,title属性就通不过验证了。控制台会显示一行错误信息。

ReactDOM.render(<Jsxdemo setid="11">我是容器组件</Jsxdemo>,document.getElementById("jsxdemobox"));
var Jsxdemo=React.createClass({
componentDidMount:function(){
var message=this.refs.bbbb;
// alert(message.value);
},
render:function(){
var number=this.props.setid;
// alert(number);
var style={
"color":"red",
"fontSize":"12px"//这里是要求内联样式需要按照驼峰写法去写
}
var html=<div>
<div className="ez-led" style={style}>{this.props.children}</div>
<div className="ez-led" ref="aaaa">2015-04-15</div>
<input type="text" className="ez-led" ref="bbbb" defaultValue="我是第三排"/>
</div>;
return html;
}
});

  }

Warning: Failed propType: Invalid prop `title` of type `number` supplied to `MyTitle`, expected `string`.
更多的PropTypes设置,可以查看官方文档。
此外,getDefaultProps 方法可以用来设置组件属性的默认值。

ReactDOM.render(<Jsxdemo setid="11">我是容器组件</Jsxdemo>,document.getElementById("jsxdemobox"));

  </div>,

var MyTitle = React.createClass({
getDefaultProps : function () {
return {
title : 'Hello World'
};
},

*JSX可展开属性

  document.getElementById('example')

render: function() {
return <h1> {this.props.title} </h1>;
}
});

我们可以再render里面

);

ReactDOM.render(
<MyTitle />,
document.body
);
上面代码会输出"Hello World"。
七、获取真实的DOM节点
组件并不是真实的 DOM 节点,而是存在于内存之中的一种数据结构,叫做虚拟 DOM (virtual DOM)。只有当它插入文档以后,才会变成真实的 DOM 。根据 React 的设计,所有的 DOM 变动,都先在虚拟 DOM 上发生,然后再将实际发生变动的部分,反映在真实 DOM上,这种算法叫做 DOM diff ,它可以极大提高网页的性能表现。
但是,有时需要从组件获取真实 DOM 的节点,这时就要用到 ref 属性(查看 demo07 )。

<div className="ez-slider" onMouseDown ={this.onMouseDown} onMouseMove ={this.onMouseMove} onMouseUp ={this.onMouseUp}/>
相等于
var props ={
className :"ez-slider",
onMouseDown :this.onMouseDown,
onMouseUp :this.onMouseUp,
onMouseMove :this.onMouseMove
};

上面代码体现了 JSX 的基本语法规则:遇到 HTML 标签(以 < 开头),就用 HTML 规则解析;遇到代码块(以 { 开头),就用 JavaScript 规则解析。

var MyComponent = React.createClass({
handleClick: function() {
this.refs.myTextInput.focus();
},
render: function() {
return (
<div>
<input type="text" ref="myTextInput" />
<input type="button" value="Focus the text input" onClick={this.handleClick} />
</div>
);
}
});

//传入属性包
var rel =<div {...props}></div>;

JSX 允许直接在模板插入 JavaScript 变量。如果这个变量是一个数组,则会展开这个数组的所有成员。

ReactDOM.render(
<MyComponent />,
document.getElementById('example')
);
上面代码中,组件 MyComponent 的子节点有一个文本输入框,用于获取用户的输入。这时就必须获取真实的 DOM 节点,虚拟 DOM 是拿不到用户输入的。为了做到这一点,文本输入框必须有一个 ref 属性,然后 this.refs.[refName] 就会返回这个真实的 DOM 节点。
需要注意的是,由于 this.refs.[refName] 属性获取的是真实 DOM ,所以必须等到虚拟 DOM 插入文档以后,才能使用这个属性,否则会报错。上面代码中,通过为组件指定 Click 事件的回调函数,确保了只有等到真实 DOM 发生 Click 事件之后,才会读取 this.refs.[refName] 属性。
React 组件支持很多事件,除了 Click 事件以外,还有 KeyDown 、Copy、Scroll 等,完整的事件清单请查看官方文档。
八、this.state
组件免不了要与用户互动,React 的一大创新,就是将组件看成是一个状态机,一开始有一个初始状态,然后用户互动,导致状态变化,从而触发重新渲染 UI (查看 demo08 )。

var Jsxdemo=React.createClass({
// getInitialState:function(){

var arr = [

var LikeButton = React.createClass({
getInitialState: function() {
return {liked: false};
},
handleClick: function(event) {
this.setState({liked: !this.state.liked});
},
render: function() {
var text = this.state.liked ? 'like' : 'haven't liked';
return (
<p onClick={this.handleClick}>
You {text} this. Click to toggle.
</p>
);
}
});

        // },
        componentDidMount:function(){
            var message=this.refs.bbbb;
            // alert(message.value);
        },
        onClick:function(){
            alert(0);
        },
        render:function(){
            var number=this.props.setid;
            // alert(number);
            var style={
                "color":"red",
                "fontSize":"12px"//这里是要求内联样式需要按照驼峰写法去写
            }
            var options={
                className:"ez-led",
                onClick:this.onClick
            }
            var newhtml=<div {...options}>22222</div>;
            return newhtml;
        }
    });

ReactDOM.render(<Jsxdemo setid="11">我是容器组件</Jsxdemo>,document.getElementById("jsxdemobox"));

  <h1>Hello world!</h1>,

ReactDOM.render(
<LikeButton />,
document.getElementById('example')
);
上面代码是一个 LikeButton 组件,它的 getInitialState 方法用于定义初始状态,也就是一个对象,这个对象可以通过 this.state 属性读取。当用户点击组件,导致状态变化,this.setState 方法就修改状态值,每次修改以后,自动调用 this.render 方法,再次渲染组件。
由于 this.props 和 this.state 都用于描述组件的特性,可能会产生混淆。一个简单的区分方法是,this.props 表示那些一旦定义,就不再改变的特性,而 this.state 是会随着用户互动而产生变化的特性。
九、表单
用户在表单填入的内容,属于用户跟组件的互动,所以不能用 this.props 读取(查看 demo9 )。

动画 CSS3 transition 思路就是利用状态机来判断 DOM状态
为元素声明transition样式
设置属性初始值,第一次渲染元素
设置属性目标值,第二次渲染元素

  <h2>React is awesome</h2>,

var Input = React.createClass({
getInitialState: function() {
return {value: 'Hello!'};
},
handleChange: function(event) {
this.setState({value: event.target.value});
},
render: function () {
var value = this.state.value;
return (
<div>
<input type="text" value={value} onChange={this.handleChange} />
<p>{value}</p>
</div>
);
}
});

*默认属性

];

ReactDOM.render(<Input/>, document.body);
上面代码中,文本输入框的值,不能用 this.props.value 读取,而要定义一个 onChange 事件的回调函数,通过 event.target.value 读取用户输入的值。textarea 元素、select元素、radio元素都属于这种情况,更多介绍请参考官方文档。
十、组件的生命周期
组件的生命周期分成三个状态:
Mounting:已插入真实 DOM
Updating:正在被重新渲染
Unmounting:已移出真实 DOM
React 为每个状态都提供了两种处理函数,will 函数在进入状态之前调用,did 函数在进入状态之后调用,三种状态共计五种处理函数。
componentWillMount()
componentDidMount()
componentWillUpdate(object nextProps, object nextState)
componentDidUpdate(object prevProps, object prevState)
componentWillUnmount()
此外,React 还提供两种特殊状态的处理函数。
componentWillReceiveProps(object nextProps):已加载组件收到新的参数时调用
shouldComponentUpdate(object nextProps, object nextState):组件判断是否重新渲染时调用
这些方法的详细说明,可以参考官方文档。下面是一个例子(查看 demo10 )。

getDefaultProps:是设置默认属性 红色为相关代码
如果设置了value 则 弹出 10 如果没有设置 则 弹出 20

ReactDOM.render(

var Hello = React.createClass({
getInitialState: function () {
return {
opacity: 1.0
};
},

var ZZ=React.createClass({
    getDefaultProps:function(){
        return {
            value:20
        }
    },
    onClick:function(){
        alert(0);
    },
    render:function(){
        alert(this.props.value);
        var option={
            className:"maincsss",
            onClick:this.onClick
        }
        var html=<div {...option}>111111</div>;
        return html;    
    }
});
ReactDOM.render(<ZZ value="10"/>,document.getElementById("mainbox"));

mixin复用代码      meisen发音  混合柔和的意思  专门用来写公共模块的对象 并且通过minxins指向您的 mixin对象 来拷贝你的React组件中

  <div>{arr}</div>,

componentDidMount: function () {
this.timer = setInterval(function () {
var opacity = this.state.opacity;
opacity -= .05;
if (opacity < 0.1) {
opacity = 1.0;
}
this.setState({
opacity: opacity
});
}.bind(this), 100);
},

varEzLoggerMixin={
log:function(){
//sth. happened here.
}
};
React.createClass({
mixins:[EzLoggerMixin],
render:function(){
//your render stuff.
}
});

  document.getElementById('example')

render: function () {
return (
<div style={{opacity: this.state.opacity}}>
Hello {this.props.name}
</div>
);
}
});

//mixin就是存放公共能力的一个简单的对象而已。首字母可不大写 但是为了养成习惯 首字母还是大写的好 哦
var Minxintext={
log:function(){
alert("我是mixin");
}
};
mixins : [Minxintext],
然后在React实例里面的生命周期或者事件函数里面 通过 this. 你定义的mixin对象内部的函数

);

ReactDOM.render(
<Hello name="world"/>,
document.body
);
上面代码在hello组件加载以后,通过 componentDidMount 方法设置一个定时器,每隔100毫秒,就重新设置组件的透明度,从而引发重新渲染。
另外,组件的style属性的设置方式也值得注意,不能写成

var Minxintext={
log:function(){
alert("我是mixin");
}
};
var ZZ=React.createClass({
mixins : [Minxintext],
getDefaultProps:function(){
return {
value:20
}
},
onClick:function(){
this.log();
},
render:function(){
// alert(this.props.value);
var option={
className:"maincsss",
onClick:this.onClick
}
var html=<div {...option}>111111</div>;
return html;
}
});
ReactDOM.render(<ZZ value="10"/>,document.getElementById("mainbox"));

上面代码的arr变量是一个数组,结果 JSX 会把它的所有成员,添加到模板

style="opacity:{this.state.opacity};"
而要写成

map 循环

四、组件

style={{opacity: this.state.opacity}}
这是因为 React 组件样式是一个对象,所以第一重大括号表示这是 JavaScript 语法,第二重大括号表示样式对象。
十一、Ajax
组件的数据来源,通常是通过 Ajax 请求从服务器获取,可以使用 componentDidMount 方法设置 Ajax 请求,等到请求成功,再用 this.setState 方法重新渲染 UI (查看 demo11 )。

return (
<span>
{
datas.map(function(i){
return <span {...option} key={i.id}>我是{i.name}a a a </span>;
})
}
</span>
)

React 允许将代码封装成组件(component),然后像插入普通 HTML 标签一样,在网页中插入这个组件。React.createClass 方法就用于生成一个组件类。

var UserGist = React.createClass({
getInitialState: function() {
return {
username: '',
lastGistUrl: ''
};
},

var HelloMessage = React.createClass({

componentDidMount: function() {
$.get(this.props.source, function(result) {
var lastGist = result[0];
if (this.isMounted()) {
this.setState({
username: lastGist.owner.login,
lastGistUrl: lastGist.html_url
});
}
}.bind(this));
},

  render: function() {

render: function() {
return (
<div>
{this.state.username}'s last gist is
<a href={this.state.lastGistUrl}>here</a>.
</div>
);
}
});

    return <h1>Hello {this.props.name}</h1>;

ReactDOM.render(
<UserGist source="" />,
document.body
);
上面代码使用 jQuery 完成 Ajax 请求,这是为了便于说明。React 本身没有任何依赖,完全可以不用jQuery,而使用其他库。
我们甚至可以把一个Promise对象传入组件,请看Demo12。

  }

ReactDOM.render(
<RepoList
promise={$.getJSON('
/>,
document.body
);
上面代码从Github的API抓取数据,然后将Promise对象作为属性,传给RepoList组件。
如果Promise对象正在抓取数据(pending状态),组件显示"正在加载";如果Promise对象报错(rejected状态),组件显示报错信息;如果Promise对象抓取数据成功(fulfilled状态),组件显示获取的数据。

});

var RepoList = React.createClass({
getInitialState: function() {
return { loading: true, error: null, data: null};
},

ReactDOM.render(

componentDidMount() {
this.props.promise.then(
value => this.setState({loading: false, data: value}),
error => this.setState({loading: false, error: error}));
},

  <HelloMessage name="John" />,

render: function() {
if (this.state.loading) {
return <span>Loading...</span>;
}
else if (this.state.error !== null) {
return <span>Error: {this.state.error.message}</span>;
}
else {
var repos = this.state.data.items;
var repoList = repos.map(function (repo) {
return (
<li>
<a href={repo.html_url}>{repo.name}</a> ({repo.stargazers_count} stars) <br/> {repo.description}
</li>
);
});
return (
<main>
<h1>Most Popular JavaScript Projects in Github</h1>
<ol>{repoList}</ol>
</main>
);
}
}
});
十二、参考链接
React's official site
React's official examples
React (Virtual) DOM Terminology, by Sebastian Markbåge
The React Quick Start Guide, by Jack Callister
Learning React.js: Getting Started and Concepts, by Ken Wheeler
Getting started with React, by Ryan Clark
React JS Tutorial and Guide to the Gotchas, by Justin Deal
React Primer, by Binary Muse
jQuery versus React.js thinking, by zigomir

  document.getElementById('example')

);

上面代码中,变量 HelloMessage 就是一个组件类。模板插入 <HelloMessage /> 时,会自动生成 HelloMessage 的一个实例(下文的"组件"都指组件类的实例)。所有组件类都必须有自己的 render 方法,用于输出组件。

注意,组件类的第一个字母必须大写,否则会报错,比如HelloMessage不能写成helloMessage。另外,组件类只能包含一个顶层标签,否则也会报错。

var HelloMessage = React.createClass({

  render: function() {

    return <h1>

      Hello {this.props.name}

    </h1><p>

      some text

    </p>;

  }

});

上面代码会报错,因为HelloMessage组件包含了两个顶层标签:h1和p。

组件的用法与原生的 HTML 标签完全一致,可以任意加入属性,比如 <HelloMessage name="John"> ,就是 HelloMessage 组件加入一个 name 属性,值为 John。组件的属性可以在组件类的 this.props 对象上获取,比如 name 属性就可以通过 this.props.name 读取。

添加组件属性,有一个地方需要注意,就是 class 属性需要写成 className ,for 属性需要写成 htmlFor ,这是因为 class 和 for 是 JavaScript 的保留字。

五、this.props.children

this.props 对象的属性与组件的属性一一对应,但是有一个例外,就是 this.props.children 属性。它表示组件的所有子节点。

var NotesList = React.createClass({

  render: function() {

    return (

      <ol>

      {

        React.Children.map(this.props.children, function (child) {

          return <li>{child}</li>;

        })

      }

      </ol>

    );

  }

});

 

ReactDOM.render(

  <NotesList>

    <span>hello</span>

    <span>world</span>

  </NotesList>,

  document.body

);

上面代码的 NoteList 组件有两个 span 子节点,它们都可以通过 this.props.children 读取

这里需要注意, this.props.children 的值有三种可能:如果当前组件没有子节点,它就是 undefined ;如果有一个子节点,数据类型是 object ;如果有多个子节点,数据类型就是 array 。所以,处理 this.props.children 的时候要小心。

React 提供一个工具方法 React.Children 来处理 this.props.children 。我们可以用 React.Children.map 来遍历子节点,而不用担心 this.props.children 的数据类型是 undefined 还是 object。更多的 React.Children 的方法,请参考官方文档。

六、PropTypes

组件的属性可以接受任意值,字符串、对象、函数等等都可以。有时,我们需要一种机制,验证别人使用组件时,提供的参数是否符合要求。

组件类的PropTypes属性,就是用来验证组件实例的属性是否符合要求。

var MyTitle = React.createClass({

  propTypes: {

    title: React.PropTypes.string.isRequired,

  },

  render: function() {

     return <h1> {this.props.title} </h1>;

   }

});

上面的Mytitle组件有一个title属性。PropTypes 告诉 React,这个 title 属性是必须的,而且它的值必须是字符串。现在,我们设置 title 属性的值是一个数值。

var data = 123;

ReactDOM.render(

  <MyTitle title={data} />,

  document.body

);

这样一来,title属性就通不过验证了。控制台会显示一行错误信息。

Warning: Failed propType: Invalid prop `title` of type `number` supplied to `MyTitle`, expected `string`.

更多的PropTypes设置,可以查看官方文档。

此外,getDefaultProps 方法可以用来设置组件属性的默认值。

var MyTitle = React.createClass({

  getDefaultProps : function () {

    return {

      title : 'Hello World'

    };

  },

  render: function() {

     return <h1> {this.props.title} </h1>;

   }

});

ReactDOM.render(

  <MyTitle />,

  document.body

);

上面代码会输出"Hello World"。

七、获取真实的DOM节点

组件并不是真实的 DOM 节点,而是存在于内存之中的一种数据结构,叫做虚拟 DOM (virtual DOM)。只有当它插入文档以后,才会变成真实的 DOM 。根据 React 的设计,所有的 DOM 变动,都先在虚拟 DOM 上发生,然后再将实际发生变动的部分,反映在真实 DOM上,这种算法叫做 DOM diff ,它可以极大提高网页的性能表现。

但是,有时需要从组件获取真实 DOM 的节点,这时就要用到 ref 属性。

var MyComponent = React.createClass({

  handleClick: function() {

    this.refs.myTextInput.focus();

  },

  render: function() {

    return (

      <div>

        <input type="text" ref="myTextInput" />

        <input type="button" value="Focus the text input" onClick={this.handleClick} />

      </div>

    );

  }

});

ReactDOM.render(

  <MyComponent />,

  document.getElementById('example')

);

上面代码中,组件 MyComponent 的子节点有一个文本输入框,用于获取用户的输入。这时就必须获取真实的 DOM 节点,虚拟 DOM 是拿不到用户输入的。为了做到这一点,文本输入框必须有一个 ref 属性,然后 this.refs.[refName] 就会返回这个真实的 DOM 节点。

需要注意的是,由于 this.refs.[refName] 属性获取的是真实 DOM ,所以必须等到虚拟 DOM 插入文档以后,才能使用这个属性,否则会报错。上面代码中,通过为组件指定 Click 事件的回调函数,确保了只有等到真实 DOM 发生 Click 事件之后,才会读取 this.refs.[refName] 属性。

React 组件支持很多事件,除了 Click 事件以外,还有 KeyDown 、Copy、Scroll 等,完整的事件清单请查看官方文档。

八、this.state

组件免不了要与用户互动,React 的一大创新,就是将组件看成是一个状态机,一开始有一个初始状态,然后用户互动,导致状态变化,从而触发重新渲染 UI。

var LikeButton = React.createClass({

  getInitialState: function() {

    return {liked: false};

  },

  handleClick: function(event) {

    this.setState({liked: !this.state.liked});

  },

  render: function() {

    var text = this.state.liked ? 'like' : 'haven't liked';

    return (

      <p onClick={this.handleClick}>

        You {text} this. Click to toggle.

      </p>

    );

  }

});

ReactDOM.render(

  <LikeButton />,

  document.getElementById('example')

);

上面代码是一个 LikeButton 组件,它的 getInitialState 方法用于定义初始状态,也就是一个对象,这个对象可以通过 this.state 属性读取。当用户点击组件,导致状态变化,this.setState 方法就修改状态值,每次修改以后,自动调用 this.render 方法,再次渲染组件。

由于 this.props 和 this.state 都用于描述组件的特性,可能会产生混淆。一个简单的区分方法是,this.props 表示那些一旦定义,就不再改变的特性,而 this.state 是会随着用户互动而产生变化的特性。

九、表单

用户在表单填入的内容,属于用户跟组件的互动,所以不能用 this.props 读取。

var Input = React.createClass({

  getInitialState: function() {

    return {value: 'Hello!'};

  },

  handleChange: function(event) {

    this.setState({value: event.target.value});

  },

  render: function () {

    var value = this.state.value;

    return (

      <div>

        <input type="text" value={value} onChange={this.handleChange} />

        <p>{value}</p>

      </div>

    );

  }

});

 

ReactDOM.render(<Input/>, document.body);

上面代码中,文本输入框的值,不能用 this.props.value 读取,而要定义一个 onChange 事件的回调函数,通过 event.target.value 读取用户输入的值。textarea 元素、select元素、radio元素都属于这种情况,更多介绍请参考官方文档。

澳门新萄京官方网站:REACT急迅入门,js深入学习详细深入分析。十、组件的生命周期

组件的生命周期分成三个状态:

Mounting:已插入真实 DOM

Updating:正在被重新渲染

Unmounting:已移出真实 DOM

React 为每个状态都提供了两种处理函数,will 函数在进入状态之前调用,did 函数在进入状态之后调用,三种状态共计五种处理函数。

componentWillMount()

componentDidMount()

componentWillUpdate(object nextProps, object nextState)

componentDidUpdate(object prevProps, object prevState)

componentWillUnmount()

此外,React 还提供两种特殊状态的处理函数。

componentWillReceiveProps(object nextProps):已加载组件收到新的参数时调用

shouldComponentUpdate(object nextProps, object nextState):组件判断是否重新渲染时调用

这些方法的详细说明,可以参考官方文档。下面是一个例子。

var Hello = React.createClass({

  getInitialState: function () {

    return {

      opacity: 1.0

    };

  },

 

  componentDidMount: function () {

    this.timer = setInterval(function () {

      var opacity = this.state.opacity;

      opacity -= .05;

      if (opacity < 0.1) {

        opacity = 1.0;

      }

      this.setState({

        opacity: opacity

      });

    }.bind(this), 100);

  },

 

  render: function () {

    return (

      <div style={{opacity: this.state.opacity}}>

        Hello {this.props.name}

      </div>

    );

  }

});

 

ReactDOM.render(

  <Hello name="world"/>,

  document.body

);

上面代码在hello组件加载以后,通过 componentDidMount 方法设置一个定时器,每隔100毫秒,就重新设置组件的透明度,从而引发重新渲染。

另外,组件的style属性的设置方式也值得注意,不能写成

style="opacity:{this.state.opacity};"

而要写成

style={{opacity: this.state.opacity}}

这是因为 React 组件样式是一个对象,所以第一重大括号表示这是 JavaScript 语法,第二重大括号表示样式对象。

十一、Ajax

组件的数据来源,通常是通过 Ajax 请求从服务器获取,可以使用 componentDidMount 方法设置 Ajax 请求,等到请求成功,再用 this.setState 方法重新渲染 UI。

var UserGist = React.createClass({

  getInitialState: function() {

    return {

      username: '',

      lastGistUrl: ''

    };

  },

  componentDidMount: function() {

    $.get(this.props.source, function(result) {

      var lastGist = result[0];

      if (this.isMounted()) {

        this.setState({

          username: lastGist.owner.login,

          lastGistUrl: lastGist.html_url

        });

      }

    }.bind(this));

  },

 

  render: function() {

    return (

      <div>

        {this.state.username}'s last gist is

        <a href={this.state.lastGistUrl}>here</a>.

      </div>

    );

  }

});

 

ReactDOM.render(

  <UserGist source="" />,

  document.body

);

上面代码使用 jQuery 完成 Ajax 请求,这是为了便于说明。React 本身没有任何依赖,完全可以不用jQuery,而使用其他库。

我们甚至可以把一个Promise对象传入组件

ReactDOM.render(

  <RepoList

promise={$.getJSON('?q=javascript&sort=stars')}

  />,

  document.body

);

上面代码从Github的API抓取数据,然后将Promise对象作为属性,传给RepoList组件。

如果Promise对象正在抓取数据(pending状态),组件显示"正在加载";如果Promise对象报错(rejected状态),组件显示报错信息;如果Promise对象抓取数据成功(fulfilled状态),组件显示获取的数据。

var RepoList = React.createClass({

  getInitialState: function() {

    return { loading: true, error: null, data: null};

  },

  componentDidMount() {

    this.props.promise.then(

      value => this.setState({loading: false, data: value}),

      error => this.setState({loading: false, error: error}));

  },

  render: function() {

    if (this.state.loading) {

      return <span>Loading...</span>;

    }

    else if (this.state.error !== null) {

      return <span>Error: {this.state.error.message}</span>;

    }

    else {

      var repos = this.state.data.items;

      var repoList = repos.map(function (repo) {

        return (

          <li>

            <a href={repo.html_url}>{repo.name}</a> ({repo.stargazers_count} stars) <br/> {repo.description}

          </li>

        );

      });

      return (

        <main>

          <h1>Most Popular JavaScript Projects in Github</h1>

          <ol>{repoList}</ol>

        </main>

      );

    }

  }

});

最后

因为ReactJS的大名一直如雷贯耳,所以便花了些时间了解一下。原本以为只是简单的不同于JQuery的封装,但实际上却是完全打破了以前HTML开发的模式。
从使用HTML属性到HTML和CSS分离,再到JavaScript处理逻辑,用了不短的时间。现在很少看到杂糅着各种语言的页面代码。
所以,最初看到ReactJs代码的时候,简直不敢相信眼睛,这么多年分离的结果,又活生生地杂糅到了一起。
未来前端肯定会有更好的方向和发展,但绝对不会是ReactJS。

我是Vue的死忠粉,脑残粉。

本文由澳门新萄京官方网站发布于澳门新萄京赌场网址,转载请注明出处:澳门新萄京官方网站:REACT急迅入门,js深入学习

关键词:

  • 上一篇:没有了
  • 下一篇:没有了