案例一、聊天室案例

/**
* This file provided by Facebook is for non-commercial testing and evaluation
* purposes only. Facebook reserves all rights not expressly granted.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* FACEBOOK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/

//定义Comment整体组件
var Comment = React.createClass({
//调用 marked 库,转义出HTML标签
rawMarkup: function() {
var rawMarkup = marked(this.props.children.toString(), {sanitize: true});
return { __html: rawMarkup };
},
//输出HTML
render: function() {
return (
<div className="comment">
<h2 className="commentAuthor">
{this.props.author}
</h2>
<span dangerouslySetInnerHTML={this.rawMarkup()} />
</div>
);
}
}); var CommentBox = React.createClass({
//从服务器获取数据
loadCommentsFromServer: function() {
$.ajax({
url: this.props.url,
dataType: 'json',
cache: false,
//存储Ajax返回的状态数据
success: function(data) {
this.setState({data: data});
//绑定到CommentBox的上下文
}.bind(this),
error: function(xhr, status, err) {
console.error(this.props.url, status, err.toString());
}.bind(this)//绑定到CommentBox的上下文
});
},
//数据提交事件
handleCommentSubmit: function(comment) {
var comments = this.state.data;
// Optimistically set an id on the new comment. It will be replaced by an
// id generated by the server. In a production application you would likely
// not use Date.now() for this and would have a more robust system in place.
//设置提交数据的id属性
comment.id = Date.now();
//链接新的数组评论对象
var newComments = comments.concat([comment]);
//设置评论列表,更新组件状态数据
this.setState({data: newComments});
//发送Ajax请求,更新评论数据列表
$.ajax({
url: this.props.url,
dataType: 'json',
type: 'POST',
data: comment,
//更新数据成功执行
success: function(data) {
//动态更新界面的关键点就是调用 this.setState() 。更新界面。
//我们用新的从服务器拿到的评论数组来替换掉老的评论数组,然后 UI 自动更新。有了这种反应机制,实时更新就仅需要一小点改动。在这里我们使用简单的轮询
this.setState({data: data});
}.bind(this),
//更新数据失败执行
error: function(xhr, status, err) {
//执行失败更新回state
this.setState({data: comments});
console.error(this.props.url, status, err.toString());
}.bind(this)//绑定到CommentBox的上下文
});
},
//getInitialState() 在组件的生命周期中仅执行一次,用于设置组件的初始化 state 。
getInitialState: function() {
//初始化设置data为空
return {data: []};
},
//componentDidMount 是一个组件渲染的时候被 React 自动调用的方法。
componentDidMount: function() {
//首次渲染调用此方法,获取列表
this.loadCommentsFromServer();
//计时器循环更新组件的state,更新页面的评论列表
setInterval(this.loadCommentsFromServer, this.props.pollInterval);
},
render: function() {
//设置Comment组件,设置CommentList组件的data属性,将获取的data值传递给它
//传递一个新的回调函数( handleCommentSubmit )到子组件CommentForm,设置子组件“onCommentSubmit”属性
return (
<div className="commentBox">
<h1>Comments</h1>
<CommentList data={this.state.data} />
<CommentForm onCommentSubmit={this.handleCommentSubmit} />
</div>
);
}
}); //定义CommentList组件
var CommentList = React.createClass({
render: function() {
//映射数据列表,传入Comment组件需要的author属性和id属性,并显示内容
var commentNodes = this.props.data.map(function(comment) {
return (
<Comment author={comment.author} key={comment.id}>
{comment.text}
</Comment>
);
});
//返回节点信息
return (
<div className="commentList">
{commentNodes}
</div>
);
}
});
//定义用户提交表单
var CommentForm = React.createClass({
//初始化组件,设置属性的初始值
getInitialState: function() {
return {author: '', text: ''};
},
//更新作者状态
handleAuthorChange: function(e) {
this.setState({author: e.target.value});
},
//更新文本状态
handleTextChange: function(e) {
this.setState({text: e.target.value});
},
//提交事件
handleSubmit: function(e) {
e.preventDefault();
var author = this.state.author.trim();
var text = this.state.text.trim();
//获取作者和文本
if (!text || !author) {
return;
}
//调用父组件的提交事件
this.props.onCommentSubmit({author: author, text: text});
//重置状态数据
this.setState({author: '', text: ''});
},
render: function() {
//渲染form表单。设置元素值到HTML元素,并绑定事件
return (
<form className="commentForm" onSubmit={this.handleSubmit}>
<input
type="text"
placeholder="Your name"
value={this.state.author}
onChange={this.handleAuthorChange}
/>
<input
type="text"
placeholder="Say something..."
value={this.state.text}
onChange={this.handleTextChange}
/>
<input type="submit" value="Post" />
</form>
);
}
}); //渲染Dom组件
ReactDOM.render(
<CommentBox url="/api/comments" pollInterval={2000} />,
document.getElementById('content')
);

案例二、检索列表

 <!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<script src="../../build/react.min.js"></script>
<script src="../../build/JSXTransformer.js"></script>
</head>
<body>
<div id="content"></div>
<script type="text/jsx">
//目录行表头
var ProductCategoryRow = React.createClass({
render: function() {
return (<tr><th colSpan="2">{this.props.category}</th></tr>);
}
}); //产品行
var ProductRow = React.createClass({
render: function() {
//判断name的值红色,还是黑色。return前面可以写应用逻辑
var name = this.props.product.stocked ?
this.props.product.name :
<span style={{color: 'red'}}>
{this.props.product.name}
</span>;
return (
<tr>
<td>{name}</td>
<td>{this.props.product.price}</td>
</tr>
);
}
}); // 产品列表组件,根据 “用户输入( user input )” 过滤和展示 “数据集合( data collection )”
var ProductTable = React.createClass({
render: function() {
//定义列表数组
var rows = [];
//记录最后一条目录
var lastCategory = null;
//遍历产品数组,将产品记录到数组
this.props.products.forEach(function(product) {
//判断记录,如果不等将“产品目录”压入“数组”中
// if (product.category !== lastCategory) {
// rows.push(<ProductCategoryRow category={product.category} key={product.category} />);
// }
//
// 判断过滤条件
if (product.name.indexOf(this.props.filterText) === -1 || (!product.stocked && this.props.inStockOnly)) {
return;
} //否则压入产品组件
// rows.push(<ProductRow product={product} key={product.name} />);
if (product.category !== lastCategory) {
rows.push(<ProductCategoryRow category={product.category} key={product.category} />);
} //
//
//记录最后一个目录
lastCategory = product.category;
}.bind(this));
//渲染出table
return (
<table>
<thead>
<tr>
<th>Name</th>
<th>Price</th>
</tr>
</thead>
<tbody>{rows}</tbody>
</table>
);
}
}); //搜索框子组件,接受所有用户输入( user input )
var SearchBar = React.createClass({
//定义搜索框组件内部内容
render: function() {
return (
<form>
<input type="text" placeholder={this.props.filterText} />
<p>
<input type="checkbox" checked={this.props.inStockOnly}/>
{' '}
Only show products in stock
</p>
</form>
);
}
}); //整个产品列表容器
var FilterableProductTable = React.createClass({
//设置初始State,标示json数据
getInitialState: function() {
return {
filterText: '',
inStockOnly: false
};
}, //设置更新State,更新Dom,这个一般和State的初始化一起存在
handleUserInput: function(filterText, inStockOnly) {
this.setState({
filterText: filterText,
inStockOnly: inStockOnly
});
}, //Div层输出子组件,单纯定义。
//将自己的state状态传递给子组件。如果products是ajax,那么它也是state.
render: function() {
return (
<div>
<SearchBar
filterText={this.state.filterText}
inStockOnly={this.state.inStockOnly}
onUserInput={this.handleUserInput}
/>
<ProductTable
products={this.props.products}
filterText={this.state.filterText}
inStockOnly={this.state.inStockOnly}
/>
</div>
);
}
}); var PRODUCTS = [
{category: 'Sporting Goods', price: '$49.99', stocked: true, name: 'Football'},
{category: 'Sporting Goods', price: '$9.99', stocked: true, name: 'Baseball'},
{category: 'Sporting Goods', price: '$29.99', stocked: false, name: 'Basketball'},
{category: 'Electronics', price: '$99.99', stocked: true, name: 'iPod Touch'},
{category: 'Electronics', price: '$399.99', stocked: false, name: 'iPhone 5'},
{category: 'Electronics', price: '$199.99', stocked: true, name: 'Nexus 7'}
]; //渲染HTML
React.render(
<FilterableProductTable products={PRODUCTS} />,
document.getElementById('content')
); </script>
</body>
</html>

//1、(思考数据片段,找出state数据)思考示例应用中的所有数据片段,有:
//state组件的状态判断,识别出最小的(但是完整的)代表 UI 的 state.此处关键点在于精简:不要存储重复的数据。
//让我们分析每一项,指出哪一个是 state 。简单地对每一项数据提出三个问题:
//是否是从父级通过 props 传入的?如果是,可能不是 state 。
//是否会随着时间改变?如果不是,可能不是 state 。
//能根据组件中其它 state 数据或者 props 计算出来吗?如果是,就不是 state 。

//2、(产生数据片段的组件)
//最初的 products 列表(不是state,传入)
//用户输入的搜索文本(是,随时间变化)
//复选框的值(是,随时间变化)
//过滤后的 products 列表(不是,可以计算出)
//初始的 products 列表通过 props 传入,所以不是 state 。
//搜索文本和复选框看起来像是 state ,因为它们随着时间改变,也不能根据其它数据计算出来。
//最后,过滤的 products 列表不是 state ,因为可以通过搜索文本和复选框的值从初始的 products 列表计算出来。
//所以最终, state 是:用户输入的搜索文本,复选框的值

//3、(判断state在那个组件上更新最为合适,即数据独立更新的Dom组件)
//我们辨别出了应用的 state 数据模型的最小集合。接下来,需要指出哪个组件会改变或者说拥有这个 state 数据模型。
//记住: React 中数据是沿着组件树从上到下单向流动的。可能不会立刻明白哪个组件应该拥有哪些 state 数据模型。
//这对新手通常是最难理解和最具挑战的,因此跟随以下步骤来弄清楚这点:
//对于应用中的每一个 state 数据:

//找出每一个基于那个 state 渲染界面的组件。(ProductTable 需要基于 state 过滤产品列表,SearchBar 需要显示搜索文本和复选框状态。
//所以选择它们共同的父亲,ProductTable。)

//找出state所在组件的原则:
//找出共同的祖先组件(某个单个的组件,在组件树中位于需要这个 state 的所有组件的上面)。共同的需要State组件的上面父组件。
//要么是共同的祖先组件,要么是另外一个在组件树中位于更高层级的组件应该拥有这个 state 。
//如果找不出拥有这个 state 数据模型的合适的组件,创建一个新的组件来维护这个 state ,然后添加到组件树中,层级位于所有共同拥有者组件的上面。
//让我们在应用中应用这个策略:
//ProductTable 需要基于 state 过滤产品列表,SearchBar 需要显示搜索文本和复选框状态。
//共同拥有者组件是 FilterableProductTable 。
//理论上,过滤文本和复选框值位于 FilterableProductTable 中是合适的。
//我们决定了 state 数据模型位于 FilterableProductTable 之中。

//4、(设置state)
//给 FilterableProductTable 添加 getInitialState() 方法,该方法返回 {filterText: '', inStockOnly: false} 来反映应用的初始化状态。
//传递 filterText 和 inStockOnly 给 ProductTable 和 SearchBar 作为 prop 。
//使用这些 props 来过滤 ProductTable 中的行,设置在 SearchBar 中表单字段的值。
//开始观察应用将会如何运行:设置 filterText 为 "ball" ,然后刷新应用。将会看到数据表格被正确更新了。

案例三、更新事件触发

 <!DOCTYPE html>

<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<script src="../../build/react.min.js"></script>
<script src="../../build/JSXTransformer.js"></script>
</head>
<body>
<div id="content"></div> <script type="text/jsx">
//富交互性的动态用户界面
var LikeButton = React.createClass({
//设置初始化状态
getInitialState: function() {
return {liked: false};
},
//调用事件
handleClick: function(event) {
//切换事件状态
//工作是从 props 里取数据并渲染出来。用户输入、服务器请求或者时间变化等作出响应,这时才需要使用 State。
//
this.setState({liked: !this.state.liked});
},
render: function() {
//渲染时候的处理逻辑
//常用的模式:创建多个只负责渲染数据的无状态(stateless)组件,在它们的上层创建一个有状态(stateful)组件并把它的状态通过 props
//传给子级。这个有状态的组件封装了所有用户的交互逻辑,而这些无状态组件则负责声明式地渲染数据。
var text = this.state.liked ? 'like' : 'haven\'t liked';
//绑定并调用组件的方法
return (
<p onClick={this.handleClick}>
You {text} this. Click to toggle.
</p>
);
//State 应该包括那些可能被组件的事件处理器改变并触发用户界面更新的数据。真实的应用中这种数据一般都很小且能被JSON序列化。当创建一个状态化的组件时,想象一下表示它
//的状态最少需要哪些数据,并只把这些数据存入 this.state。在 render()
//里再根据state来计算你需要的其它数据。你会发现以这种方式思考和开发程序最终往往是正确的,因为如果在 state
// 里添加冗余数据或计算所得数据,需要你经常手动保持数据同步,不能让 React 来帮你处理。
// this.state 应该仅包括能表示用户界面状态所需的最少数据。因此,它不应该包括:计算所得数据: 不要担心根据 state 来预先计算数据 —— 把所有的计算都放到
// render() 里更容易保证用户界面和数据的一致性。例如,在 state 里有一个数组(listItems),我们要把数组长度渲染成字符串, 直接在 render() 里使用 this.state
// .listItems.length + ' list items' 比把它放到 state 里好的多。React 组件: 在 render() 里使用当前 props 和 state 来创建它。基于 props
// 的重复数据: 尽可能使用 props 来作为惟一数据来源。把 props 保存到 state 的一个有效的场景是需要知道它以前值的时候,因为未来的 props 可能会变化。
}
}); React.render(
<LikeButton />,
document.getElementById('content')
);
</script>
</body>
</html>

  

ReactJS 官网案例分析的更多相关文章

  1. MXNet官网案例分析--Train MLP on MNIST

    本文是MXNet的官网案例: Train MLP on MNIST. MXNet所有的模块如下图所示: 第一步: 准备数据 从下面程序可以看出,MXNet里面的数据是一个4维NDArray. impo ...

  2. Django官网案例教程

    1.注意:python manage.py runserver 0:8000(侧任何IP均可访问)

  3. Yeoman 官网教学案例:使用 Yeoman 构建 WebApp

    STEP 1:设置开发环境 与yeoman的所有交互都是通过命令行.Mac系统使用terminal.app,Linux系统使用shell,windows系统可以使用cmder/PowerShell/c ...

  4. 对石家庄铁道大学官网UI设计的分析

    在这一周周一,老师给我们讲了PM,通过对PM的学习,我知道了PM 对项目所有功能的把握, 特别是UI.最差的UI, 体现了团队的组织架构:其次, 体现了产品的内部结构:最好, 体现了用户的自然需求.在 ...

  5. 【官网翻译】性能篇(四)为电池寿命做优化——使用Battery Historian分析电源使用情况

    前言 本文翻译自“为电池寿命做优化”系列文档中的其中一篇,用于介绍如何使用Battery Historian分析电源使用情况. 中国版官网原文地址为:https://developer.android ...

  6. spring原理案例-基本项目搭建 01 spring framework 下载 官网下载spring jar包

    下载spring http://spring.io/ 最重要是在特征下面的这段话,需要注意: All avaible features and modules are described in the ...

  7. 针对石家庄铁道大学官网首页的UI分析

    身为一名光荣的铁大铮铮学子,我对铁大的网站首页非常的情有独钟,下面我就石家庄铁道大学的官网首页进行UI分析: 1.在首页最醒目的地方赫然写着石家庄铁道大学七个大字,让人一眼就豁然开朗. 2.网站有EN ...

  8. Maccms后门分析复现(并非官网的Maccms){10.15 第二十二天}

    该复现参考网络中的文章,该漏洞复现仅仅是为了学习交流,严禁非法使用!!!! Maccms官网:http://www.maccms.cn/ Maccms网站基于PHP+MYSQL的系统,易用性.功能良好 ...

  9. “深度评测官”——记2020BUAA软工软件案例分析作业

    项目 内容 这个作业属于哪个课程 2020春季计算机学院软件工程(罗杰 任建) 这个作业的要求在哪里 个人博客作业-软件案例分析 我在这个课程的目标是 完成一次完整的软件开发经历并以博客的方式记录开发 ...

随机推荐

  1. where T:new() 是什么意思

    经常看到方法后面加where T:new() ,下面来解释下 比如如下这个方法   protected static T CreateNewInstance<T>() where T :  ...

  2. joinablequeue模块 生产者消费者模型 Manager模块 进程池 管道

    一.生产者消费者 主要是为解耦(借助队列来实现生产者消费者模型) import queue  # 不能进行多进程之间的数据传输 (1)from multiprocessing import Queue ...

  3. 兼容多浏览器的网页复制插件(ZeroClipboard)

    前言: 常规利用JS编写的网页复制功能是最简单的方法,但是只对IE有效,无法做到兼容其它浏览器,对其他浏览器也就只能弹窗提示用户手动复制了. <script type="text/ja ...

  4. 重哈希 · rehashing

    [抄题]: [思维问题]: [一句话思路]: [输入量]:空: 正常情况:特大:特小:程序里处理到的特殊情况:异常情况(不合法不合理的输入): [画图]: newindex = (hashTable[ ...

  5. Python学习day5作业

    目录 Python学习day5作业 ATM和购物商城 1. 程序说明 2. 基本流程图 3. 程序测试帐号 4. 程序结构: 5. 程序测试 title: Python学习day5作业 tags: p ...

  6. fragment 事务回滚 ---动态创建fragment

    import java.util.Date; import java.util.LinkedList; import com.qianfeng.gp08_day23_fragment5.fragmen ...

  7. linux系统挂载ISO文件

    1 上传iso文件使用xftp上传系统oracleLinux7.3.iso光盘镜像到/toolsPackage 为方便使用,重命名光盘镜像文件[root@rhel64 software]# mv rh ...

  8. 表单提交的两种请求方式:post与get。post与get两者的对比分析

    post与get两者的对比分析:

  9. 大神真会玩~这组C4D动图,我都看了一整天!

    来自法国的Guillaume Kurkdjian 擅长创作一些平面动态图像 每张都诉说了一个小笑话或者小故事 像个极其微型的小电影. 这些动图的灵感可能来自某个交通工具 或是某个悠闲的时光 也可能是生 ...

  10. 使用 springmvc请求 返回 字符串时 ,中文出现乱码

    @RequestMapping(value="/askQuestion" ,method = RequestMethod.GET , produces = {"appli ...