赵走x博客
网站访问量:151894
首页
书籍
软件
工具
古诗词
搜索
登录
49、Flux:理念、回顾Whinepad
48、lint、Flow、测试与复验:测试
47、lint、Flow、测试与复验:Flow
46、lint、Flow、测试与复验:ESLint
45、lint、Flow、测试与复验:package.json
44、构建实例应用:<Whinepad>
43、构建实例应用:应用配置
43、构建实例应用:<Excel>:改进的新版本
42、构建实例应用:组件:对话框
41、构建实例应用:组件:Actions
39、构建实例应用:表单:Form
38、构建实例应用:表单:<FormInput>“工厂组件”
37、构建实例应用:表单:Rating组件
36、构建实例应用:表单:Suggest
35、构建实例应用:Button组件
34、构建实例应用:组件
33、构建实例应用:Whinepad v.0.0.1
32、发布
31、开始构建
30、安装必备工具
29、为应用开发做准备:一个模板应用
28、JSX 和表单
27、JSX 和HTML 的区别
26、在JSX 中返回多个节点
25、展开属性
24、HTML 实体
23、JSX入门
22、Excel:一个出色的表格组件:下载表格数据
21、Excel:一个出色的表格组件:即时回放
20、Excel:一个出色的表格组件:搜索
19、Excel:一个出色的表格组件:编辑数据
18、Excel:一个出色的表格组件:排序
17、Excel:一个出色的表格组件
16、 PureRenderMixin
15、 性能优化:避免组件更新
14、 生命周期示例:使用子组件
13、组件生命周期示例:使用mixin
12、组件:生命周期方法
11、中途改变属性
10、从外部访问组件
9、在初始化state 时使用props:一种反模式
8、 props 与state
7、关于DOM 事件的说明
6、组件:带状态的文本框组件
5、组件的state
4、组件的propTypes
3、组件的属性
2、组件的基础
1、Hello World
50、Flux:Store
33、构建实例应用:Whinepad v.0.0.1
资源编号:76083
书籍
React快速上手开发
热度:110
到目前为止,你已经学会:创建React 自定义组件(以及使用内建组件)的所有相关基础知识,使用JSX 定义用户界面(可选)的方法,以及构建并发布应用的流程。是时候创建一个更完整的应用了。
到目前为止,你已经学会:创建React 自定义组件(以及使用内建组件)的所有相关基础知识,使用JSX 定义用户界面(可选)的方法,以及构建并发布应用的流程。是时候创建一个更完整的应用了。 我们把这个应用称为Whinepad,用户可以在这个应用中对品尝过的酒类写下笔记并进行评价。事实上,用户不仅可以评价酒类,还可以留下任何想要抱怨1 的内容。这个应用应该涵盖常见的添加、查询、修改、删除(CRUD)功能。此外,它还是一个把数据存储在客户端的纯客户端应用。由于本书以学习React 为目的,应用中所有与React 不相关的部分(比如数据存储、样式等)将不作详述。 在本章中,你将学习以下内容: * 从可重用的小组件开始,构建整个应用; * 进行组件间通信,让不同的组件共同发挥作用。 # Whinepad v.0.0.1 我们将在上一章建立的模板应用的基础上进行Whinepad 应用的开发。当你品尝了一些新的酒类之后,可以在这个应用中记录笔记并进行评价。不如就把欢迎界面设置为曾经评价过的内容列表吧?这只需简单地重用第3 章创建的
组件即可。 >注1:英文原文是whine,与酒类(wine)同音。这个单词在应用名中用作双关。——编者注 # 1、基本设置 首先复制一份reactbook-boiler 模板应用的源代码, 然后把项目重命名为whinepadv0.0.1,并在此基础上进行开发。(可以从https://github.com/stoyan/reactbook/ 下载代码。) 下一步,运行监听脚本,以便在文件内容发生改变时自动重新构建: ``` $ cd ~/reactbook/whinepad\ v0.0.1/ $ sh scripts/watch.sh ``` # 2、开始编写代码 修改index.html 文件中的标题,并把id 属性修改为`id="pad"`,以匹配我们的应用名称: ```
Whinepad v.0.0.1
``` 我们把JSX 版本Excel 组件的源代码(出现在第4 章末尾处)复制到js/source/components/Excel.js 中: ``` import React from 'react' // 从 React v15.5 开始 ,React.PropTypes 助手函数已被弃用,我们建议使用 prop-types 库 来定义contextTypes。 import PropTypes from 'prop-types' class Excel extends React.Component{ // propTypes:{ // headers:[], // initialData: [] // }, // propTypes:{ // headers:React.PropTypes.isRequired.arrayOf(React.PropTypes.string), // initialData: React.PropTypes.arrayOf( // React.PropTypes.arrayOf(React.PropTypes.string) // ).isRequired // }, getInitialState(){ return { data:this.props.initialData, sortby:null, descending:false, edit: null,// [行索引, 列索引], search:false } } _sort(e){ var column=e.target.cellIndex; var data=this.state.data.slice(); var descending=this.state.sortby===column && !this.state.descending; data.sort(function (a,b) { return descending?(a[column]
b[column]?1:-1) }); this.setState({ data:data, sortby:column, descending:descending }); } _showEditor(e){ this.setState({ edit:{ row:parseInt(e.target.dataset.row,10), cell:e.target.cellIndex } }); } _save(e){ e.preventDefault(); //进行保存 var input=e.target.firstChild; var data=this.state.data.slice(); data[this.state.edit.row][this.state.edit.cell]=input.value; this.setState({ edit:null, data:data }) } _renderToolBar(){ return React.DOM.div({className: 'toolbar'}, React.DOM.button( {onClick: this._toggleSearch,className:'toolbar'}, 'search' ), React.DOM.a({onClick:this._download.bind(this,'json'),href:'data.json'},'Export JSON'), React.DOM.a({onClick:this._download.bind(this,'csv'),href:'data.csv'},'Export CSV'), ) } _download(format,ev){ var contents=format==='json'?JSON.stringify(this.state.data): this.state.data.reduce(function (result, row) { return result+ row.reduce(function (rowresult,cell,idx) { return rowresult+'"'+cell.replace(/"/g,'""')+'"' +(idx
-1; }); this.setState({ data:searchData }); } _renderTable(){ return( React.DOM.table(null, React.DOM.thead({onClick:this._sort}, React.DOM.tr(null, this.props.headers.map(function (title,idx) { console.log(this) if(this.state.sortby===idx){ title+=this.state.descending?'\u2191':'\u2193' } return React.DOM.th({key:idx},title); },this) ) ), React.DOM.tbody({onDoubleClick:this._showEditor}, this._renderSearch(), this.state.data.map(function (row, rowidx) { return ( React.DOM.tr({key:rowidx}, row.map(function (cell, idx) { console.log("state",this); var content=cell; var edit=this.state.edit; if(edit && edit.row===rowidx && edit.cell===idx){ content=React.DOM.form( {onSubmit:this._save}, React.DOM.input({ type:'text', defaultValue:content }) ) } return React.DOM.td({ key:idx, 'data-row':rowidx },content) },this) ) ) },this) ) ) ) } render(){ return (
{this._renderToolbar()} {this._renderTable()}
) } } Excel.propTypes={ headers:PropTypes.arrayOf(PropTypes.string), initialData: PropTypes.arrayOf( PropTypes.arrayOf(PropTypes.string) ).isRequired }; export default Excel ``` 上述代码和之前的Excel 组件代码有一些不同,在于: * 使用了import/export 语句; * 使用了继承。 * 从 React v15.5 开始 ,React.PropTypes 助手函数已被弃用,我们建议使用 prop-types 库 来定义contextTypes。 相应地,所有CSS 样式需要添加前缀,就像这样: ``` .Excel input { font: 16px Arial; } .Excel td { border-top: 1px solid black; cursor: cell; padding: 5px; } .Excel th { cursor: pointer; padding: 5px; } .Excel table { border: 1px solid black; margin: 20px; } .Excel .toolbar { margin-left: 20px; } .Excel .toolbar a, .Excel .toolbar button { /* thanks css3buttongenerator.com! */ background: #3498db; background-image: linear-gradient(to bottom, #3498db, #2980b9); border-radius: 28px; box-shadow: 0px 1px 3px #666666; color: #ffffff; font-size: 14px; padding: 10px 20px 10px 20px; text-decoration: none; border: 0; margin-right: 5px; } .Excel .toolbar a:hover, .Excel .toolbar button:hover { background: #3cb0fd; background-image: linear-gradient(to bottom, #3cb0fd, #3498db); text-decoration: none; } ``` 目前还剩下一项工作,就是在主文件app.js 中引入
组件。前面已经提到,我们将在客户端存储数据(localStorage)。在起步阶段,为了避免页面空白,我们构造一些初始数据,并把数据传递到
组件中:: ``` 'use strict'; import Excel from './components/Excel'; import Logo from './components/Logo'; import React from 'react'; import ReactDOM from 'react-dom'; var headers = localStorage.getItem('headers'); var data = localStorage.getItem('data'); if (!headers) { headers = ['Title', 'Year', 'Rating', 'Comments']; data = [['Test', '2015', '3', 'meh']]; } ReactDOM.render(
Welcome to Whinepad!
, document.getElementById('pad') ); ``` 在Logo.css 文件中再增添一些样式,你就完成了这个0.0.1 版本(如图6-1 所示)!  图6-1:Whinepad v.0.0.1