ReactJS入门二

ReactJS入门学习二

ReactJS入门学习二

阅读目录

回到顶部

React的背景和基本原理

在web开发中,我们总需要将变化的数据实时反应到UI上,这时就需要对DOM进行操作,复杂或频繁的对DOM操作是性能瓶颈产生的原因,React为此引入了虚拟的DOM的机制,在浏览器端使用javascript实现了一套DOM API,基于React开发时所有的DOM构造都是通过虚拟的DOM进行的,每当数据有变化时,React都会重新构建整个DOM树,然后React将当前的整个DOM树与之前的DOM树进行对比,得到变化的部分,然后将变化的部分进行实际的浏览器的DOM更新,而且React能够批处理虚拟的DOM刷新,在一个事件循环内的两次数据的变化会被合并,比如你连续先将节点内容A变成B,然后将B变成A,React会认为UI不发生任何变化。尽管每一次都需要构造完整的虚拟DOM树,但是虚拟DOM树是内存数据,性能是非常高的,而对实际的DOM进行操作仅仅是Diff部分,因此可以提高性能。在保证性能的同时,我们将不再需要关注某个数据的变化如何更新到一个或者多个具体的DOM元素,而只需要关心在任意一个数据状态下,整个界面是如何Render的。

React组件化:

虚拟DOM不仅带来了简单的UI开发逻辑,同时也带来了组件开发的思想,所谓组件,即封装起来的具有独立功能的UI部件,React推荐以组件的方式去重写思考UI构成,将UI上的每一个功能相对独立的模块定义成组件。然后将小组件通过嵌套的方式变成大组件,最终构成完整的UI构建。如果说MVC的思想让我们做到表现,数据,控制的分离,那么React则以组件化的思考方式则带来了UI模块间的分离,比如我上一篇文章介绍的网站页面一样:如下图:

导航条,侧边栏及内容区分别为不同的小组件通过嵌套的方式变成一个完整的UI界面构建。

React组件应该有如下特征:

  1. 可组合:一个组件易于与其他组件一起使用,或者说嵌套在另一个组件内部。
  2. 可重用:每个组件都具有独立的功能,它可以被使用在多个UI场景。
  3. 可维护:每个小的组件仅仅包含自身的逻辑,更容易理解及维护。

下面我们首先使用React时候需要引用如下JS,react.js和JSXTransformer.js,下面的HTML代码如下:

<!doctype html>
<html lang="en">
 <head>
  <meta charset="UTF-8">
  <title>Document</title>
  <script src="js/react.js"></script>
  <script src="js/JSXTransformer.js"></script>
 </head>
 <body>
    <div id = "demo"></div>
    <script type="text/jsx">
        // code
    </script>
 </body>
</html>

回到顶部

理解React.render()

React.render()是用于将模版转为HTML语言,并且插入指定的DOM节点。

如下代码:

React.render(
    <h1>hello,world!</h1>,
    document.getElementById("demo")
);

页面生成HTML结构如下:

页面显示如下:

回到顶部

什么是JSX?

React的核心机制就是实现了一个虚拟DOM,利用虚拟DOM来减少对实际DOM的操作从而提升性能,组件DOM结构就是映射到这个虚拟的DOM上,React在这个虚拟DOM上实现了一个diff算法,当要更新组件的时候,会通过diff寻找要变更的DOM节点,再把这个修改更新到浏览器实际的DOM节点上,所以实际上不是真的渲染整个DOM树,这个虚拟的DOM是一个纯粹的JS数据结构,所以性能比原生DOM会提高很多;

虚拟DOM也可以通过Javascript来创建,比如如下代码:

var child1 = React.createElement(‘li‘,null,‘First Text Content‘);
var child2 = React.createElement(‘li‘,null,‘second Text Content‘);
var root = React.createElement(‘ul‘,{className:‘test‘},child1,child2);

React.render(root,document.getElementById("demo"));

在页面中渲染成结构变成如下:

在页面显示如下:

但是这样编写代码可读性不好,于是React就出现了JSX,使用如下的方式创建虚拟DOM;

var root = (
        <ul className="test">
            <li>First Text Content</li>
            <li>second Text Content</li>
        </ul>
);
React.render(root,document.getElementById("demo"));

上面2种方式实现的效果都一样,可能很多人会认为引入一个JSX的源码进来会影响页面性能,在这里我们只是为了测试而已,如果真的在开发项目中,JSX在产品打包阶段会编译成纯粹的javascript,JSX语法不会带来任何性能影响的。

回到顶部

为什么要使用JSX?

前端开发最基本的功能是展示数据,因此很多框架都引入了模版引擎,如果我们不使用模版的话,那么我们需要手动并接一个很长的html字符串,并且这样并接很容易出错,代码也不太美观,且最重要的是展示逻辑和业务逻辑没有得到足够的分离(使用MVC思想考虑);因此React就发明了JSX;

回到顶部

JSX的语法

JSX允许HTML与javascript混写,如下代码:

var names = [‘longen1‘,‘longen2‘,‘longen3‘];
React.render(
    <div className="aa">
        {
            names.map(function(name){
                return <p>Hello,{name}</p>
            })
        }
        </div>,document.getElementById("demo")
);

JSX的语法规则是:遇到HTML标签(以<开头),就是用HTML的规则解析,遇到代码块(以{开头),就用jSX的语法规则解析;上面的代码生成如下:

理解this.props

Props表示的是组件自身的属性,是父层节点传递给子层节点的一些属性或者数据,如下代码:

var HelloMessage = React.createClass({
    render: function() {
        return <div>Hello {this.props.name}</div>;
    }
});
React.render(<HelloMessage name="John" />, document.getElementById("demo"));

理解this.props.children

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

如下代码:

var NotesList = React.createClass({
    render: function() {
        return (
            <ol>
              {
                this.props.children.map(function (child) {
                  return <li>{child}</li>
                })
              }
             </ol>
        );
     }
});
React.render(
     <NotesList>
        <span>hello</span>
        <span>world</span>
    </NotesList>,
    document.getElementById("demo")
);

在页面显示如下:

理解React.createClass方法

React允许将代码封装成组件,然后像普通的HTML一样插入,React.createClass方法用于生成一个组件类;如下代码:

var NodeList = React.createClass({
    render: function() {
        return <h1>Hello {this.props.name}</h1>;
    }
});
React.render(
    <NodeList name="John" />,
    document.getElementById(‘demo‘)
);

如上代码;NodeList就是一个组件类,模版插入<NodeList />时,会自动生成一个NodeList的实列;所有组件都必须有一个render()方法,用于输出组件;如上<NodeList name=”John”/>就是加入了一个属性name,组件上的属性我们可以使用this.props对象上获取,比如上面的name属性就可以通过this.props.name读取;

在页面显示如下:

理解this.state

this.state是组件私有的,我们可以通过this.setState()来改变它,那么组件会重新渲染下自己;如下代码:

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>
        );
    }
});
React.render(
    <LikeButton />,
    document.getElementById(‘demo‘)
);

如上代码 先使用 getInitialState() 方法用于定义初始状态(且只执行一次),当用户点击时候,调用handleClick函数,使用this.setState来动态的更改值,每次更改后,会自动调用render()进行渲染组件。

this.props与this.state的区别?

this.props是指属性从父节点元素继承过来的,且属性不可以更改的。

this.state 是指可以动态更改的;是组件的私有的;

Refs和findDOMNode()

为了同浏览器交互,我们有时候需要获取真实的DOM节点,我们可以通过React的 React.findDOMNode(component)获取到组件中真实的DOM;

如下代码:

var MyComponent = React.createClass({
    handleClick: function() {
        React.findDOMNode(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>
            );
        }
    });
    React.render(
        <MyComponent />,
        document.getElementById(‘demo‘)
    );

组件MyComponent的子节点有一个文本输入框,点击按钮后,把焦点放在输入框内,这时候我们需要先获取到MyComponent组件内的真实的DOM节点,为了做到这点,文本输入框必须有一个ref属性,然后 this.refs.[refName]就指向与这个虚拟的DOM子节点,最后通过React.findDOMNode获取真实的DOM节点。

理解React.createElement

参数:type(string), config(object), children(子节点)

如下代码

var CommentBox = React.createClass({
    displayName: ‘CommentBox‘,
    render: function(){
        return (
            React.createElement(‘div‘,{className:‘commentBox‘},"Hello,world!I am a CommentBox")
        );
    }
});
React.render(
    React.createElement(CommentBox,null),document.getElementById("demo")
);

在页面上显示如下:

理解React.PropTypes

验证使用组件时,提供的参数是否符合要求,组件的属性可以接受任意值,字符串,对象,函数都可以;比如如下代码,验证组件中的 title属性是否是字符串;如下代码:

var MyTitle = React.createClass({
  propTypes: {
    title: React.PropTypes.string.isRequired
  },
  render: function() {
     return  this.props.title == 1234 ? <p>是一个字符串</p> : null
   }
});
var data = "123";
React.render(
  <MyTitle title="1234" />,document.getElementById("demo")
);

可以看到,在页面打印出是一个字符串;

理解React.isValidElement

参数object

判断参数是否是一个合法的的ReactElement,并返回Boolean值;如下代码测试

var Longen = React.createClass({
    render: function() {
        return <p>123</p>
}
});
var test = <Longen/>,
test2 = ‘<Longen/>‘;
console.log(React.isValidElement(test));  //true
console.log(React.isValidElement(test2));  //false

回到顶部

如何在JSX中如何使用事件

我们以前编写事件如下:

<button onclick="checkAndSubmit(this.form)">Submit</button>

这样编写代码对于简单的html页面时没有问题,但是对于复杂的的页面,我们可以使用如下javascript来绑定事件:我们可以引用jquery;

$(‘#id‘).on(‘click‘, this.checkAndSubmit.bind(this));

但是在JSX中我们可以如下绑定事件:

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

在JSX中我们不需要关心什么时候去移除事件绑定,因为React会在对应的真实的DOM节点移除就自动解除了事件绑定;

React并不会真正绑定事件到每一个元素上,而是采用事件代理的方式,在根节点document上为每种事件添加唯一的listener,然后通过事件的target找到真实的触发目标元素,这样从触发元素到顶层节点之间的所有节点如果有绑定这个事件的话,React都会触发对应的事件函数,这就是React模拟事件系统的基本原理。

尽管整个事件系统由React管理,但是其API和使用方法与原生事件一致。这种机制确保了跨浏览器的一致性:在所有浏览器(IE9及以上)都可以使用符合W3C标准的API,包括stopPropagation(),preventDefault()等等。对于事件的冒泡(bubble)和捕获(capture)模式也都完全支持。

下面我们来做一个demo,来使用下JSX下的事件如下使用:

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>
    );
  }
});
React.render(<Input/>, document.getElementById("demo"));

如上是一个input输入框,当我们不断在输入框的值的时候,<p>标签的内容也会跟随的变化;

回到顶部

如何在JSX中如何使用样式

大部分的时候我们都是把样式写到css文件内,但是有时候我们也可以将样式写到JSX中,在JSX中使用样式和真实的样式也很类似,也是通过style属性来定义的,但是和真实DOM不同的是,属性值不能是字符串,而一定要是对象,比如如下:

<div style={{color: ‘#ff0000‘, fontSize: ‘14px‘}}>Hello World.</div>

我们可以看到JSX中使用的双大括号,其实第一个大括号的含义是JSX的语法,第二个大括号的含义是一个对象;我们也可以如下写:

var style = {

color: ‘#ff0000‘,

fontSize: ‘14px‘

};

<div style={style}>HelloWorld.</div>

时间: 08-23

ReactJS入门二的相关文章

ReactJS入门

ReactJS入门学习一 阅读目录 React是什么? React如何制作组件? 理解组件属性props 理解页面中如何渲染数据的 理解从服务器端获取数据及理解state的 回到顶部 React是什么? React仅仅是VIEW层,而我们经常看到Angular是一个完整的框架,而React不是,因此我们看到他们两个的侧重点不一样,所以也不能比较的,React提供了模板语法及一些函数钩子用于HTML的渲染,只用于View层. React的优点?       1. 虚拟DOM 在DOM树的状态发生改

[WebGL入门]二十,绘制立体模型(圆环体)

注:文章译自http://wgld.org/,原作者杉本雅広(doxas),文章中如果有我的额外说明,我会加上[lufy:],另外,鄙人webgl研究还不够深入,一些专业词语,如果翻译有误,欢迎大家指正. 本次的demo的运行结果 立体的模型 这次稍微喘口气,开始绘制立体模型.这里说的[喘口气]是指本次的文章中没有出现任何新的技术知识点.只是利用到现在为止所介绍过的内容,来绘制一个立体的圆环体.到现在为止,只绘制了三角形和四边形,当然,在三维空间中绘制简单的多边形也没什么不对,但是缺点儿说服力.

kafka入门二:Kafka的设计思想、理念

本节主要从整体角度介绍Kafka的设计思想,其中的每个理念都可以深入研究,以后我可能会发专题文章做深入介绍,在这里只做较概括的描述以便大家更好的理解Kafka的独特之处.本节主要涉及到如下主要内容: Kafka设计基本思想 Kafka中的数据压缩 Kafka消息转运过程中的可靠性 Kafka集群镜像复制 Kafka 备份机制 一.kafka由来 由于对JMS日常管理的过度开支和传统JMS可扩展性方面的局限,LinkedIn(www.linkedin.com)开发了Kafka以满足他们对实时数据流

Netty入门二:开发第一个Netty应用程序

    既然是入门,那我们就在这里写一个简单的Demo,客户端发送一个字符串到服务器端,服务器端接收字符串后再发送回客户端. 2.1.配置开发环境 1.安装JDK 2.去官网下载jar包 (或者通过pom构建) 2.2.认识下Netty的Client和Server 一个Netty应用模型,如下图所示,但需要明白一点的是,我们写的Server会自动处理多客户端请求,理论上讲,处理并发的能力决定于我们的系统配置及JDK的极限. Client连接到Server端 建立链接发送/接收数据 Server端

Thinkphp入门 二 —空操作、空模块、模块分组、前置操作、后置操作、跨模块调用(46)

原文:Thinkphp入门 二 -空操作.空模块.模块分组.前置操作.后置操作.跨模块调用(46) [空操作处理] 看下列图: 实际情况:我们的User控制器没有hello()这个方法 一个对象去访问这个类不存在的方法,那么它会去访问”魔术方法__call()” 用户访问一个不存在的操作—>解决:给每个控制器都定义个_empty()方法来处理 第二个解决方法:定义一个空操作 [空模块处理] 我们使用一个类,但是现在这个类还没有被include进来. 我们可以通过自动加载机制处理__autoloa

转 Python爬虫入门二之爬虫基础了解

静觅 » Python爬虫入门二之爬虫基础了解 2.浏览网页的过程 在用户浏览网页的过程中,我们可能会看到许多好看的图片,比如 http://image.baidu.com/ ,我们会看到几张的图片以及百度搜索框,这个过程其实就是用户输入网址之后,经过DNS服务器,找到服务器主机,向服务器发出一个请求,服务器经过解析之后,发送给用户的浏览器 HTML.JS.CSS 等文件,浏览器解析出来,用户便可以看到形形色色的图片了. 因此,用户看到的网页实质是由 HTML 代码构成的,爬虫爬来的便是这些内容

Redbean:入门(二) - Find

<?php require_once 'rb.php'; $tableName = 'link'; //连接数据库 R::setup('mysql:host=localhost;dbname=hwibs_model','root',''); //链接表 R::dispense($tableName); //1.获取对象记录句柄,如果不存在id的情况下就无法使用load,那么可以使用find方法进行查找 $result = R::find($tableName,'id > 4');//普通使用

DevExpress XtraReports 入门二 创建 data-aware(数据感知) 报表

原文:DevExpress XtraReports 入门二 创建 data-aware(数据感知) 报表 本文只是为了帮助初次接触或是需要DevExpress XtraReports报表的人群使用的,为了帮助更多的人不会像我这样浪费时间才写的这篇文章,高手不想的看请路过 本文内容来DevExpress XtraReports帮助文档,如看过类似的请略过. 废话少说 开始正事 一.创建应用程序并添加报表 启动 MS Visual Studio (2005.2008.或 2010). 在 Visua

MongooooooooooooooooooooDB入门二:基本概念介绍

前言 工欲善其事必先利其器.在学习MongoDB之前,需要对MongoDB的一些基本概念有系统的了解. 所以,本篇文章主要介绍MongoDB的一些基本概念,这些概念的定义均来自<MongoDB权威指南>,关于此书想要了解更多,请点击此处. 我尽量使用最简洁的语言来尽可能完整地描述这些基本概念,如有遗漏或不妥之处欢迎指正. 文档 文档是MongoDB的核心概念之一.多个键值对有序地放在一起便是文档.例如: {"name":"Jerry","sco