React简单介绍
react 背景知识
react 是一个用于构建用户界面的 javascript 库,主要用于构建 ui,而不是一个 mvc 框架,但可以使用 react 作为 mvc 架构的 view 层轻易的在已有项目中使用,它是一个用于构建用户界面的 javascript 库,起源于 facebook 的内部项目,用来架设 instagram 的网站,于 2013 年 5 月开源。react 拥有较高的性能,代码逻辑非常简单,越来越多的人已开始关注和使用它。
以前没有 ajax 技术的时候,web 页面从服务端整体渲染出 html 输出到浏览器端进行渲染,同样的,用户的一个改变页面的操作也会刷新整个页面来完成。直到有了 ajax 出现,实现页面局部刷新,带来的高效和分离让 web 开发者们惊叹不已。但随之而来的问题是,复杂的用户交互及展现需要通过大量的 dom 操作来完成,这让页面的性能以及开发的效率又出现了新的瓶颈。
时至今日,谈到前端性能优化,减少 dom 元素、减少 reflow 和 repaint、编码过程中尽量减少 dom 的查询等手段是大家耳熟能详的。而页面任何ui的变化都是通过整体刷新来完成的。幸运的是,react 通过自己实现的 dom diff 算法,计算出虚拟页面当前版本和新版本之间的差异,最小化重绘,避免不必要的 dom 操作,解决了这两个公认的前端性能瓶颈,实现高效 dom 渲染。
我们知道,频繁的操作 dom 所带来的性能消耗是很大的,而 react 之所以快,是因为它不直接操作 dom,而是引进虚拟 dom 的实现来解决这个问题
对于页面的更新,react 通过自己实现的 dom diff 算法来进行差异对比、差异更新,反映到页面上就是只重绘了更新的部分,从而提高渲染效率。
备注:以下性能阐述参考自尤雨溪。
对于 react 的性能方面,想啰嗦几句:
1. react 从来没有说过 “react 比原生操作 dom 快”。react 的基本思维模式是每次有变动就整个重新渲染整个应用。如果没有 virtual dom,简单来讲就是直接重置 innerhtml。
2. 在比较性能的时候,要分清楚初始渲染、小量数据更新、大量数据更新这些不同的场合。
3. 不要天真地以为 virtual dom 就是快,diff 不是免费的,virtual dom 真正的价值从来都不是性能,而是它
1) 为函数式的 ui 编程方式打开了大门;
2) 可以渲染到 dom 以外的其他场景,如 backend、native。
组件化
在业务开发中,遇到公共的模板部分,我们不得不将模板和规定的数据格式耦合在一起来实现组件。而在 react 中,我们可以使用 jsx 语法来封装组件,将组件的结构、数据逻辑甚至样式都聚合在一起,更加简单、明了、直观的定义组件。
有了组件化的实现,我们可以很直观的将一个复杂的页面分割成若干个独立组件,再将这些独立组件组合完成一个复杂的页面。这样既减少了逻辑复杂度,又实现了代码的重用。
react 基础
模板
<!doctype html> <html> <head> <script src=“js/react.js”></script> <script src=“js/react-dom.js”></script> <script src=“js/browser.min.js”></script> </head> <body> <div id=“example”></div> <script type=“text/babel”> /* * reactdom.render 是 react 的最基本方法,用于将模板转为 html 语言, * 并插入指定的 dom 节点。 * */ reactdom.render( <h1>hello, 博看文思!</h1>, document.getelementbyid(‘example') ); </script> </body> </html>
jsx
上一节的代码, html 语言直接写在 javascript 语言之中,不加任何引号,这就是 jsx 的语法,它允许 html 与 javascript 的混写
jsx的好处:
1.使用jsx语法来封装组件有什么好处:
1)熟悉的代码
2)更加语义化
3)更加抽象且直观
2.几个注意点:
1)render的方法中return的*元素只能是一个;
2)如果要定义样式的时候,不能这样去写
// 不要出现类似的错误,style=“opacity:{this.state.opacity};”
3)使用 classname 和 htmlfor 来替代对应的class 和 for
提示:关于组件化的话题,感兴趣的话可以继续关注vuejs、web components等对组件的写法。/**随着更为复杂的多端环境的出现,组件标准化还有着更大的想象空间,react的组件定义不是终点,也不一定是标准,但会在组件化的道路上留下深刻de影响。**/
jsx 基本语法:
var names = [‘alice', ‘emily', ‘kate']; reactdom.render( <div> { names.map(function (name,key) { return <div key={key}>hello, {name}!</div> }) } </div>, document.getelementbyid(‘example') );
上面代码体现了 jsx 的基本语法规则:遇到 html 标签(以 < 开头),就用 html 规则解析;遇到代码块(以 { 开头),就用 javascript 规则解析。
jsx 允许直接在模板插入 javascript 变量。如果这个变量是一个数组,则会展开这个数组的所有成员。
var arr = [ <h1>hello world!</h1>, <h2>react is awesome</h2>, ]; reactdom.render( <div>{arr}</div>, document.getelementbyid(‘example') );
组件
1.概念
react 允许将代码封装成组件(component),然后像插入普通 html 标签一样,在网页中插入这个组件。react.createclass 方法就用于生成一个组件类
2.代码示例
var hellomessage = react.createclass({ render: function() { return <h1>hello {this.props.name}</h1>; } }); reactdom.render( <hellomessage name=“john” />, document.getelementbyid(‘example') ); var hellomessage = react.createclass({ render: function() { return <h1 classname=“green”>hello {this.props.name}</h1>; } }); reactdom.render( <hellomessage name=“john” />, document.getelementbyid(‘example') );
this.props.children
this.props 对象的属性与组件的属性一一对应,但是有一个例外,就是 this.props.children 属性。它表示组件的所有子节点
var noteslist = react.createclass({ render: function() { return ( <ol> { /* * 因为this.props.children的返回值会根据子节点的数量返回undefined,object,array. * 所以react提供了一个react.children的方法专门处理this.props.children * */ react.children.map(this.props.children, function (child) { return <li>{child}</li>; }) } </ol> ); } }); reactdom.render( <noteslist> <span>hello</span> <span>world</span> </noteslist>, document.getelementbyid(“example”) );
proptypes
组件的属性可以接受任意值,字符串、对象、函数等等都可以。有时,我们需要一种机制,验证别人使用组件时,提供的参数是否符合要求。组件类的proptypes属性,就是用来验证组件实例的属性是否符合要求。
var mytitle = react.createclass({ proptypes: { /* * 声明title属性是必须的,并且数据类型要为字符串,相当于是规范化的接口文档 * */ title: react.proptypes.string.isrequired, }, render: function() { return <h1> {this.props.title} </h1>; } }); var data = “123”; reactdom.render( <mytitle title={data} />, document.getelementbyid(“example”) );
错误示范:
var data = 123; reactdom.render( <mytitle title={data} />, document.body );
getdefaultprops
getdefaultprops 方法可以用来设置组件属性的默认值
var mytitle = react.createclass({ getdefaultprops: function () { return { title:”hello world” } }, render: function() { return <h1> {this.props.title} </h1>; } }); // var data = “123”; reactdom.render( <mytitle />, document.getelementbyid(“example”) );
获取真实的 dom 节点
组件并不是真实的 dom 节点,而是存在于内存之中的一种数据结构,叫做虚拟 dom (virtual dom)。只有当它插入文档以后,才会变成真实的 dom 。根据 react 的设计,所有的 dom 变动,都先在虚拟 dom 上发生,然后再将实际发生变动的部分,反映在真实 dom上,这种算法叫做 dom diff ,它可以极大提高网页的性能表现。
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') );
this.state
组件免不了要与用户互动,react 的一大创新,就是将组件看成是一个状态机,一开始有一个初始状态,然后用户互动,导致状态变化,从而触发重新渲染 ui。react 把组件看成是一个状态机(state machines)。通过与用户的交互,实现不同状态,然后渲染 ui,让用户界面和数据保持一致。react 里,只需更新组件的 state,然后根据新的 state 重新渲染用户界面
var likebutton = react.createclass({ getinitialstate: function() { /* * 设置状态的初始值 * */ return {liked: false}; }, handleclick: function() { /* * 更改状态 * */ this.setstate({liked: !this.state.liked}); }, render: function() { var text = this.state.liked ? ‘喜欢' : ‘不喜欢'; return ( <p onclick={this.handleclick}> 你 {text} 他. 点击切换. </p> ); } }); reactdom.render( <likebutton />, document.getelementbyid(‘example') );
由于 this.props 和 this.state 都用于描述组件的特性,可能会产生混淆。一个简单的区分方法是,this.props 表示那些一旦定义,就不再改变的特性,而 this.state 是会随着用户互动而产生变化的特性。
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);
组件 api
组件的7个方法:
设置状态:setstate;
替换状态:replacestate;
设置属性setprops;
替换属性replaceprops;
强制更新:forceupdate;
获取dom节点:getdomnode;
判断组件挂载状态:ismounted。
组件生命周期
初始化
getdefaultprops:设置默认性的值
getinitialstate:设置初始的状态
componentwillmount:(组件即将被装载)
render(渲染)
componentdidmount:组件已经被装载,只会在第一个组件被调用的时候出发
运行中
componentwillreceiveprops 在组件将要接收到属性的时候,接收属性前
shouldcomponentupdate 在接收到新的 props 或者 state,将要渲染之前调用。该方法在初始化渲染的时候不会调用
componentwillupdate render 触发之前,更新
render 渲染
componentwillunmount 在组件从 dom 中移除的时候立刻被调用
销毁
componentwillunmount 在组件从 dom 中移除的时候被立刻调用
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 );
因为 react 组件样式是一个对象第一重大括号表示这是 javascript 语法,第二重大括号表示样式对象
ajax
上面代码没有使用 jquery 完成 ajax 请求,这是为了便于说明。react 本身没有任何依赖,完全可以不用jquery,而使用其他库。
var input = react.createclass({ getinitialstate: function () { return {users:[]} }, componentdidmount:function(){ var _this = this; $.get(“http://localhost:8080/users?act=get”,function (data){ console.log(data); _this.setstate({ users:data }); }); }, render: function () { var users = this.state.users; console.log(users); return <table> { users.map(function (user,key){ return <tr key={key}><td>{user.firstname}</td><td>{user.lastname}</td></tr> }) } </table> } }); reactdom.render(<input/>,document.getelementbyid(“test”));
以上所述是小编给大家介绍的react的相关知识,希望对大家有所帮助