在上一篇文章中,介绍了React为什么会被创建,但是翻译完那篇文章后,并没有解答我的问题,我为什么要用React。
在学习React一个多月之后,通过学习教程和官方API,也有了一些自己的理解。
React的优点:
简单
仅仅只要表达出你的应用程序在任一个时间点应该长的样子,当底层的数据变了,React 会自动处理所有用户界面的更新。
声明式 (Declarative)
数据变化后,React 概念上与点击“刷新”按钮类似,但仅会更新变化的部分。
构建可组合的组件
React 都是关于构建可复用的组件。事实上,通过 React 你唯一要做的事情就是构建组件。得益于其良好的封装性,组件使代码复用、测试和关注分离(separation of concerns)更加简单。
虚拟DOM
React采取了一种特立独行的操作DOM的方式,它并不直接对DOM进行操作,而是引入了虚拟DOM的概念,安插在JavaScript逻辑和实际的DOM之间。这一概念提高了Web性能。在UI渲染过程中,React通过在虚拟DOM中的微操作来实对现实际DOM的局部更新。
单向数据流让事情一目了然
Flux是一个用于在JavaScript应用中创建单向数据层的架构,它随着React视图库的开发而被Facebook概念化。它只是一个概念,而非特定工具的实现。它可以被其它框架吸纳。React中的数据从父级流向子级。
使用步骤:
1、拿到一个构建页面的时候,首先要将其转化成组件树。
意思就是,你要看一下这个页面需要拆成几个组件。秉承的原则就是,一个组件完成一个功能。我的做法是将需要做的组件写出来,连同它要完成的功能都写出来
2、用React创建构建页面的静态版本
这一步会构造一些组件,这些组件重用其它组件,并且通过 props 传递数据。 props 是一种从父级向子级传递数据的方式。 state 仅用于实现交互功能,也就是说,数据随着时间变化。因为这是一个静态的应用版本,所以这里并不需要 state 。
可以从上至下或者从下至上来构建应用。也就是说,你可以从属性结构的顶部开始构建这些组件,或者从底部开始。我选择从下至上的方式,这样也可以在构建的同时写测试代码。
注:写的时候会用到构建中的css类名,这时候要注意react中是用className来加类名的
3、实现交互功能
这一步就是要弄清楚,数据是怎么传输的。props可以让数据从父级传递到子级,而有时候我们会需要数据的反向传递,即从子组件传递用户输入给父组件,这个时候就需要回调函数了。
我的项目中,所有的state都放在了父组件中,通过props向子组件中传递数据。在子组件中会有回调函数,用该函数来向父组件中传递数据。
Demo:用react实现分页组件
详情请移步github
import React from'react';import ReactDOM from'react-dom';//分页组件
exportdefaultclassextendsReact.Component{
constructor() {super();this.state = {
showLinkNum :5//每次显示的页数
}
}//控制页码跳转的函数
pageIndexChange(event){
let target = event.target;
let index ="";
let pageIndex = target.value;
let pageInputIndex = target.value;vartype = target.getAttribute("data-type");if (type =="link") {
index = event.target.innerHTML;if (!isNaN(index)) {
pageIndex = index;
}elseif (index =="首页") {
pageIndex =1;
}elseif (index =="尾页") {
pageIndex =this.props.pageNum;
}elseif (index =="»") {
pageIndex = parseInt(this.props.pageIndex) +1;
}elseif (index =="«") {
pageIndex = parseInt(this.props.pageIndex) -1;
}this.props.pageIndexChange(pageIndex);
}elseif (type =="btn-go") {
let goIndex = document.getElementById("index-input");
pageInputIndex = goIndex.value;this.props.pageIndexChange(pageInputIndex);
}elseif (type =="input") {returnnull;
}
}
render(){var arrFirst = [];//首页和前一页var arrLast = [];//尾页和后一页var arrLinkShow = [];//每次显示的页码var prevDisplay =1 ==this.props.pageIndex ?'disabled':'';//当前页为1时,首页和前一页失效var lastDisplay =this.props.pageNum ==this.props.pageIndex ?'disabled':'';//当前页为最后一页时,尾页和后一页失效var startIndex = (Math.ceil(this.props.pageIndex/this.state.showLinkNum)-1) *this.state.showLinkNum +1;//每次显示页数的开始页var endIndex = Math.min(startIndex +this.state.showLinkNum,(this.props.pageNum+1));//每次显示页数的结束页for (var i = startIndex; i < endIndex; i++ ) {var currentIndexDisplay = i ==this.props.pageIndex ?'active' :'';
arrLinkShow.push(
<li key = {i} className = {currentIndexDisplay}>
<a href="javascript:;" data-type ="link">{i}</a>
</li>
)
}
arrFirst.push(
<li key="first" className = {prevDisplay}>
<a href="javascript:;" data-type ="link" >首页</a>
</li>
);
arrFirst.push(
<li key ="1" className = {prevDisplay}>
<a href="javascript:;" aria-label="Previous" data-type ="link" id ="pre" >
«
</a>
</li>
);
arrLast.push(
<li key ="last" className = {lastDisplay}>
<a href="javascript:;" data-type ="link">尾页</a>
</li>
);
arrLast.push(
<li key ={this.props.pageNum} className = {lastDisplay} >
<a href="javascript:;" aria-label="Next" data-type ="link" id ="next">
»
</a>
</li>
)return (
<nav className="text-right" key="page">
<ul className="pagination" onClick = {this.pageIndexChange.bind(this)}>
{arrFirst}
{arrLinkShow}
{arrLast}
<li>
<inputtype="text" data-type ="input" id="index-input" />
<a href="javascript:;" className="btn page-go" data-type ="btn-go">跳转</a>
</li>
</ul>
</nav>
)
}
}