ReactJS入门学习二javascript
阅读目录css
React的背景和基本原理html
在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组件化:java
虚拟DOM不只带来了简单的UI开发逻辑,同时也带来了组件开发的思想,所谓组件,即封装起来的具备独立功能的UI部件,React推荐以组件的方式去重写思考UI构成,将UI上的每个功能相对独立的模块定义成组件。而后将小组件经过嵌套的方式变成大组件,最终构成完整的UI构建。若是说MVC的思想让咱们作到表现,数据,控制的分离,那么React则以组件化的思考方式则带来了UI模块间的分离,好比我上一篇文章介绍的网站页面同样:以下图:react
导航条,侧边栏及内容区分别为不一样的小组件经过嵌套的方式变成一个完整的UI界面构建。jquery
React组件应该有以下特征:web
下面咱们首先使用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>