一、需求

1.分析:用react开发一个类似bootstrap4中的card组件http://v4-alpha.getbootstrap.com/components/card/,界面类似如下:

2.确定发目标:

3.确定开发顺序

4.开发流程介绍

测试采用TDD

二、代码

1.Card.js

  1. var React = require('react/addons');
  2.  
  3. var Card = React.createClass({
  4. getInitialState: function() {
  5. return this.props.content;
  6. },
  7. handleClick: function() {
  8. this.setState({
  9. blocks : [{
  10. title: "Allen Iverson(已关注)",
  11. subtitle: "PG",
  12. text: "Cool player",
  13. links: [{
  14. url:"http://www.163.com",
  15. name:"链接1"
  16. }, {
  17. url:"http://www.g.cn",
  18. name:"链接2"
  19. }
  20. ]
  21. }]
  22. })
  23. },
  24. render: function(){
  25. var content = this.state;
  26.  
  27. var blocks = [];
  28. for(var i = 0; i < content.blocks.length; i++){
  29. var block = content.blocks[i];
  30. var links = [];
  31. for(var i = 0; i < block.links.length; i++){
  32. links.push(<a onClick={this.handleClick} className="card-link" href={block.links[i].url}>{block.links[i].name}</a>);
  33. }
  34. blocks.push(<div className="card-block">
  35. <h4 className="card-title">{block.title}</h4>
  36. <h6 className="card-subtitle">{block.subtitle}</h6>
  37. <p className="card-text">{block.text}</p>
  38. <p>
  39. {links}
  40. </p>
  41. </div>
  42. );
  43. }
  44.  
  45. var listGroup = [];
  46. for(var i = 0; i < content.listGroup.length; i++){
  47. listGroup.push(<li className="list-group-item">{content.listGroup[i]}</li>);
  48. }
  49.  
  50. var option = this.props.option ? "card text-xs-" + this.props.option : "card";
  51. return <div className="container-fluid">
  52. <div className="row">
  53. <div className="col-sm-4">
  54. <div className={option}>
  55. <div className="card-header">{content.header}</div>
  56. <img className="card-img-top" src={content.imgTop.url} alt={content.imgTop.alt}></img>
  57. {blocks}
  58. <ul className="list-group list-group-flush">
  59. {listGroup}
  60. </ul>
  61. <img className="card-img-bottom" src={content.imgBottom.url} alt={content.imgBottom.alt}></img>
  62. <div className="card-footer">{content.footer}</div>
  63. </div>
  64. </div>
  65. </div>
  66. </div>
  67. }
  68. })
  69.  
  70. module.exports = Card

2.test.jsx

  1. var React = require('react/addons');
  2. var jasmineReact = require('jasmine-react-helpers');
  3. var TestUtils = React.addons.TestUtils;
  4. var Card = require('./Card.jsx');
  5.  
  6. describe('Card component', function(){
  7.  
  8. var card;
  9. var content;
  10.  
  11. beforeEach(function(){
  12. //渲染
  13. var blocks = [
  14. {
  15. title: "Allen Iverson",
  16. subtitle: "PG",
  17. text: "Cool player",
  18. links: [{
  19. url:"http://www.163.com",
  20. name:"链接1"
  21. }, {
  22. url:"http://www.g.cn",
  23. name:"链接2"
  24. }
  25. ]
  26. }
  27. ];
  28. var header = "76ers";
  29. var footer = "mvp";
  30. var listGroup = ["艾弗森1996年6月26日被费城76人队选中,成为NBA状元秀,绰号答案(The Answer)","场均出战41.1分钟,获得26.7分、6.2次助攻和2.2次抢断"];
  31. var imgTop = {
  32. url: "http://a1.hoopchina.com.cn/attachment/Day_100424/43_3842044_665ae051136b4b8.jpg",
  33. alt: "dribble"
  34. };
  35. var imgBottom = {
  36. url: "http://www.onlinedown.net/bigsoftimg/androidimg/260000/255860_0.jpg",
  37. alt: "crossover"
  38. }
  39. var content = {
  40. blocks: blocks,
  41. header: header,
  42. footer: footer,
  43. listGroup: listGroup,
  44. imgBottom: imgBottom,
  45. imgTop: imgTop
  46. }
  47. card = TestUtils.renderIntoDocument(<Card content={content} option="center"></Card>);
  48. })
  49.  
  50. afterEach(function(){
  51. React.unmountComponentAtNode(React.findDOMNode(card))
  52. })
  53.  
  54. it('should exist', function(){
  55. expect(!!React.findDOMNode(card)).toBe(true)
  56. //card = TestUtils.renderIntoDocument(<Card content={content}></Card>);
  57. //expect(React.findDOMNode(card).textContent).toContain('Hello world')
  58. });
  59.  
  60. it('should have correct structure', function(){
  61. //测试
  62. //card = TestUtils.renderIntoDocument(<Card content={content}></Card>);
  63. var content = React.findDOMNode(card).textContent;
  64. expect(content).toContain("Allen");
  65. expect(content).toContain("76ers");
  66. expect(content).toContain("mvp");
  67. expect(content).toContain("艾弗森");
  68. expect(React.findDOMNode(card).getElementsByTagName("img")[0].alt).toContain("dribble");
  69. expect(React.findDOMNode(card).getElementsByTagName("img")[1].alt).toContain("crossover");
  70.  
  71. });
  72.  
  73. it('should have correct style', function() {
  74. var cardBox = React.findDOMNode(card).getElementsByClassName("card");
  75. expect(!!cardBox.length).toBe(true);
  76. });
  77.  
  78. it('should correctly use options', function() {
  79. var cardBox = React.findDOMNode(card).getElementsByClassName("text-xs-center");
  80. expect(!!cardBox.length).toBe(true);
  81. });
  82.  
  83. it('should be response', function() {
  84. TestUtils.Simulate.click(React.findDOMNode(card).getElementsByTagName("a")[0]);
  85. var content = React.findDOMNode(card).textContent;
  86. expect(content).toContain("已关注");
  87. });
  88. })

3.show.jsx

  1. var React = require('react/addons');
  2. var Card = require('./Card.jsx');
  3.  
  4. var blocks = [
  5. {
  6. title: "Allen Iverson",
  7. subtitle: "PG",
  8. text: "Cool player",
  9. links: [{
  10. url:"http://www.163.com",
  11. name:"链接1"
  12. }, {
  13. url:"http://www.g.cn",
  14. name:"链接2"
  15. }
  16. ]
  17. }
  18. ];
  19. var header = "76ers";
  20. var footer = "mvp";
  21. var listGroup = ["艾弗森1996年6月26日被费城76人队选中,成为NBA状元秀,绰号答案(The Answer)","场均出战41.1分钟,获得26.7分、6.2次助攻和2.2次抢断"];
  22. var imgTop = {
  23. url: "http://a1.hoopchina.com.cn/attachment/Day_100424/43_3842044_665ae051136b4b8.jpg",
  24. alt: "dribble"
  25. };
  26. var imgBottom = {
  27. url: "http://www.onlinedown.net/bigsoftimg/androidimg/260000/255860_0.jpg",
  28. alt: "crossover"
  29. }
  30. var content = {
  31. blocks: blocks,
  32. header: header,
  33. footer: footer,
  34. listGroup: listGroup,
  35. imgBottom: imgBottom,
  36. imgTop: imgTop
  37. }
  38. React.render(<Card content={content} option="right"></Card>, document.body);

四、运行结果(bootstrap的css无效果)

源码:http://files.cnblogs.com/files/shamgod/BootstrapCard.zip

React开发项目例子的更多相关文章

  1. react实战项目开发(2) react几个重要概念以及JSX语法

    前言 前面我们已经学习了利用官方脚手架搭建一套可以应用在生产环境下的React开发环境.那么今天这篇文章主要先了解几个react重要的概念,以及讲解本文的重要知识JSX语法 React重要概念 [思想 ...

  2. Expo大作战(三)--针对已经开发过react native项目开发人员有针对性的介绍了expo,expo的局限性,开发时项目选型注意点等

    简要:本系列文章讲会对expo进行全面的介绍,本人从2017年6月份接触expo以来,对expo的研究断断续续,一路走来将近10个月,废话不多说,接下来你看到内容,讲全部来与官网 我猜去全部机翻+个人 ...

  3. react 开发 PC 端项目(一)项目环境搭建 及 处理 IE8 兼容问题

    步骤一:项目环境搭建 首先,你不应该使用 React v15 或更高版本.使用仍然支持 IE8 的 React v0.14 即可. 技术选型: 1.react@0.14 2.bootstrap3 3. ...

  4. react 前端项目技术选型、开发工具、周边生态

    react 前端项目技术选型.开发工具.周边生态 声明:这不是一篇介绍 React 基础知识的文章,需要熟悉 React 相关知识 主架构:react, react-router, redux, re ...

  5. 【腾讯Bugly干货分享】React Native项目实战总结

    本文来自于腾讯bugly开发者社区,非经作者同意,请勿转载,原文地址:http://dev.qq.com/topic/577e16a7640ad7b4682c64a7 “8小时内拼工作,8小时外拼成长 ...

  6. React Native 项目运行在 Web 浏览器上面

    React Native 的出现,让前端工程师拥有了使用 JavaScript 编写原生 APP 的能力.相比之前的 Web app 来说,对于性能和用户体验提升了非常多. 但是 React Nati ...

  7. 用Inferno代替React开发高性能响应式WEB应用

    什么是Inferno Inferno可以看做是React的另一个精简.高性能实现.它的使用方式跟React基本相同,无论是JSX语法.组件的建立.组件的生命周期,还是与Redux或Mobx的配合.路由 ...

  8. Immutable.js 以及在 react+redux 项目中的实践

    来自一位美团大牛的分享,相信可以帮助到你. 原文链接:https://juejin.im/post/5948985ea0bb9f006bed7472?utm_source=tuicool&ut ...

  9. React开发实时聊天招聘工具 -第一章

    第一章 课程道学 6个页面 弱化css Antd-mobile作为组件库 Redux 状态管理 React-Router 路由 Axios异步请求 后端Express框架 Socket.io 数据库: ...

随机推荐

  1. [大牛翻译系列]Hadoop(9)MapReduce 性能调优:理解性能瓶颈,诊断map性能瓶颈

    6.2 诊断性能瓶颈 有的时候作业的执行时间会长得惊人.想靠猜也是很难猜对问题在哪.这一章中将介绍如何界定问题,找到根源.涉及的工具中有的是Hadoop自带的,有的是本书提供的. 系统监控和Hadoo ...

  2. jquery的$(document).ready()和onload的加载顺序

    最近在改一个嵌入在frame中的页面的时候,使用了jquery做效果,而页面本身也绑定了onload事件.改完后,Firefox下测试正常流畅,IE下就要等个十几秒jquery的效果才出现,黄花菜都凉 ...

  3. linux下文件的复制、移动与删除

    linux下文件的复制.移动与删除命令为:cp,mv,rm 一.文件复制命令cp     命令格式:cp [-adfilprsu] 源文件(source) 目标文件(destination)      ...

  4. vmware虚拟机上网:host-only

    host-only配置 首先主机:vmware1要能共享本地连接这个网络,共享后vmware的ip会自动设置为如图 其次,vmware网络设置如图 最后,虚拟机设置如图 这样,主机与虚拟机之间就能pi ...

  5. Firebird数据库相关备忘录

    Firebird数据库中有一些很特别的东西,很好用,但由于平时用的不多,记在这里,以备以后用到时查询. 1.以ADO 的OLE ODBC驱动方式访问 Firebird,可以使用如下连接串: FBCon ...

  6. Asp.net MVC知识积累

    一.知识积累 http://yuangang.cnblogs.com/ 跟蓝狐学mvc教程专题目录:http://www.lanhusoft.com/Article/169.html 依赖注入:htt ...

  7. R简易入门(一)

    本文内容来源:https://www.dataquest.io/mission/126/introduction-to-r 本文数据来源:https://www.whitehouse.gov/21st ...

  8. Error LNK2005 从敌人到朋友

    本人在写学生信息管理系统时遇到一个很头疼的错误——error LNK2005重复定义错误,苦思冥想百度谷歌bing之后都没能解决问题,于一清早刹那间觉得知道问题出在哪儿了,于是乎起床.开机.修改代码一 ...

  9. linux 文件在磁盘上的表示

    基本构成 分区就是把磁盘像比萨饼一样切成大小一样的扇形, 当然分区大小不一样扇形的大小也就不一样 上下一串盘片中,相同半径的磁道所组成的一个圆柱型的环壁,就称为柱面 在柱面组中, 比较重要的两个结构是 ...

  10. 再也不要说,jquery动画呆板了

    1 show()方法和hide()方法 $("selector").show()  从display:none还原元素默认或已设置的display属性$("selecto ...