文章目录

  • 前言
  • 一、页面组件构成
    • 1.navTop(页头导航栏)
    • 2.Swiper(轮播图+前后端分离)
    • 3.Footernav(底部导航栏+前后端分离)
    • 3.List组件(初级版本未与sort发生联系)
    • 4.Sort组件
    • 6.Goods组件

前言

经过一段时间的学习终于算是对React有了一定的了解,今天试着写了下一个项目,不得不感慨一句,学习的最好方式还得是实践。废话不多说,开始实现项目。
类似于之前实现的博客项目,我们依然采用mongodb存储相关数据,根据react进行组件式开发,并且利用express实现前后端分离,flex实现页面布局


整体设计

一、页面组件构成

1.navTop(页头导航栏)

功能:进行历史记录的跳转,并根据页面不同,所展示的文字也不同,在首页时没有返回按钮,在其它页面时有返回按钮,可退回至上次浏览的页面
实现思路:属于一个路由的高阶组件封装,因为跳转后的页面与该导航栏有关联,所以要在Route里利用children渲染出该组件。
文字内容:因为该导航栏所显示文字与当前所在页面有关系,所以利用location.pathname封装出一个判断函数,进行判断,从而渲染出对应的文字。
按钮:渲染此按钮要判断当前所处位置是否为首页,不是则渲染,否则不渲染。
代码

class NavTop extends Component{panduan(e){var pageName=''if(e=='/'){pageName='首页'}else if(e=='/sort'){pageName='商品列表'}else if(e=='/shoppingcar'){pageName='购物车'}else{pageName='商品详情'}return pageName}render(){return(// getProps为跳转路由参数的传递<Route path='/' children={(getProps)=>{// 判断是否为首页var {pathname}=getProps.locationvar isRenderButton=pathname==='/'?false:truereturn(<div className='navTop'>{/* 点击后退按钮,直接运用getProps.history.goBack函数 不带括号为立即执行 */}{isRenderButton?(<button className='changeButton' onClick={getProps.history.goBack}> {'<'} </button>):'' }<p className='pageTitle'> {this.panduan(pathname)}</p></div>)}}></Route>)}}

相关知识点:
①当页面跳转按钮与当前页面有关系时利用Route 的children渲染组件。
②location.pathname可以追踪当前页面所处位置(跳转位置)
③常利用三元运算符渲染组件
④onclick函数中调用的函数不带括号为立即执行函数

2.Swiper(轮播图+前后端分离)

功能:实现点击对应按钮跳转,并自动轮播。
实现思路:采用前后端分离:
后端:将数据存于mongodb中,调用4000接口,拉取数据,发送至前端。
前端:发起ajax请求,拉取响应接口数据,用数据渲染页面。
轮播部分:为组件设置state:{index,imgsArr}其中index标识当前展示图片索引,imgsArr存放拉取的数据,拉拉取到数据后对此进行更新。封装一个gonext方法对index值进行改变,并更新state中的index。设置定时器,调用此方法。渲染部分,就利用简单的map方法渲染即可,渲染时候检查index与我们的map中key是否相等,相等则将它类名设置加上active(提前写好该样式为 透明度为1 zindex为999)否则为普通(样式为透明度0 zindex为0),在渲染小圆点按钮时,为它添加一个onclick事件,点击就利用它的key值更新state中的index。

代码

class Swiper extends Component
{constructor(props){super(props)this.state={imgsArr:[],imgListArr:[]}}_goNext(){let index=this.state.indexif(index==this.state.imgsArr.length-1){index=0}else{index++}this.setState({index:index})}_goPre(){let index=this.state.indexif(index==0){index=this.state.imgsArr.length-1}else{index--}this.setState({index:index})}componentWillMount(){$.ajax({type:'GET',url:'http://localhost:4000/imgs',data:{},success:(res)=>{this.setState({imgsArr:res,index:0})}})setInterval(()=>{this._goNext()},3000)}render(){return(<div className='home'><div className='wrap'><ul className='pic-list'> {this.state.imgsArr.map((value,key)=>{return(<li key={key}   className={key==this.state.index?'pic-list active':'pic-list'} ><img src={value.swiperImgSrc} alt=""/></li>)})}</ul><ul className='point-list'>{this.state.imgsArr.map((value,key)=>{return(<li key={key} onClick={()=>{this.setState({index:key})}} className={key==this.state.index?'point-list-item active':'point-list-item'} ></li>)})}</ul></div></div>)}
}

相关知识点:
①巧妙利用key可以实现轮播图
②先设置好样式后添加类名使渲染更简洁
③ajax和setinterval都设置在componentWillMount()周期函数内

3.Footernav(底部导航栏+前后端分离)

功能:实现点击对应按钮跳转,对应页面图标为红色。
实现思路:采用前后端分离:
后端:将数据存于mongodb中,调用4000接口,拉取数据,发送至前端。
前端:发起ajax请求,拉取响应接口数据,用数据渲染页面。
跳转部分:为组件设置state:{data,}data存放拉取的数据,类似与顶部导航栏的实现,依旧是一个高阶组件封装——自定义路由,所以要在Route里利用children渲染出该组件。并且每一项又是一个Link点击可以跳转到相应页面,并且对于每一个Link渲染,利用match来进行判断它是否相匹配,匹配图标为红,否则为灰。

代码

class Footernav extends Component {constructor() {super();this.state = {data:[]};}componentDidMount(){$.ajax({type:'GET',url:'http://localhost:4000/footerNavImgs',success:(result)=>{console.log(result)this.setState({data:result})}})}render() {return (<ul className="footer-nav">{this.state.data.map((value, key) => {return (<li className='footer-nav-item' key={key}><Route path={value.path} exact children={(e)=>{return(<Link className="footer-nav-link" to={value.path}>{/* 高级封装组件 点击上就是match */}<img src={e.match?value.activerImgSrc:value.normalImgSrc} alt=""/></Link>)}}></Route></li>);})}</ul>);}
}

相关知识点
①match返回boolean值 匹配为true否则false

3.List组件(初级版本未与sort发生联系)

1.功能:在首页轮播图下方,点击对应图标。可跳转至分类一页的对应项:如点击京东服饰,便会跳转到分类中的京东服饰一页,并拉取商品数据。
2.实现思路:
后端:查找mongodb中的相应数据发回到前端。
前端:简单的发起ajax请求拉取数据。
具体实现:(初级版本不与sort组件发生关联,单纯展示)同上,拉取数据后利用map方法渲染。

4.Sort组件

1.功能:位于页脚导航栏,点击可跳转至分类列表,在分类页面中,点击对应的类别,该类别高亮,并拉取对应的商品类别。
2.实现思路
后端:存放数据的时候,为每件商品添加一个sort属性,拉取数据时根据此属性进行判断。
前端:设置初始state时有{leftlist[],showArr[]},其中leftlist为对应的类别描述,showArr存放后台拉取的数据。
具体实现:因为商品有不同的类别,在点击左侧列表时,不同类别,拉取的数据也不一样,所以需要封装一个filter方法:这个方法接受两个参数,一个是表明点击的列表项的索引是哪一个(index),一个是点击的列表项名(content),在函数里去发起ajax请求(post方法),把参数content作为data传至后端,后端根据这个content去数据库拉取对应类别的商品数据,将数据返回更新showArr数组;将参数index用来更新state中的index值,从而实现左侧列表对应类别高亮效果。
渲染
首先对leftlist数组调用map方法,渲染出一个li并且拥有onClick事件,在onClick事件中,利用箭头函数调用filter方法,将value.descText和key传入。
其次渲染展示列表,对showArr数组调用map方法,渲染出一个商品信息展示列表,并且为了后续的商品详情展示页面,每个商品项还需要渲染出link标签。
代码:

class Sort extends Component{constructor(){super()this.state={leftList:[{descText:'数码电器',index:0},{descText:'京东超市',index:1},{descText:'京东服饰',index:2}],showArr:[],}}// 定义接受的值static contextTypes={contentText:PropTypes.string,index:PropTypes.number}componentWillMount(){var {contentText,index}=this.contextif(contentText==''){     this.filterItems('数码电器',0)}else{ this.filterItems(contentText,index)}}filterItems(content,key)  //筛选 去对比传入的项 项相同就是true 就加入到数组  然后更新数组{$.ajax({type:'POST',url:'http://localhost:4000/sortImgs',data:{content:content},success:(result)=>{console.log(result)this.setState({showArr:result,})}})this.setState({index:key})          //每次点击就将key传过来 然后修改indexrender(){return(<div className='sort'><div className='search'><input type="text"/></div><ul className='list-left'>{// 每次点击 都将自己的序列号传到filter方法里 然后发起ajax请求,post 后台去数据库查找对应的信息 加到showarray中this.state.leftList.map((value,key)=>{return(<li onClick={()=>{this.filterItems(value.descText,key)}}  className={key==this.state.index?'list-left-item active':'list-left-item'}  key={key}  >{value.descText}</li>)})}</ul><ul className='list-right'>{this.state.showArr.map((value,key)=>{return(<li className='list-right-item' key={key}><Link to={'/goods/'+value._id}><img src={value.imgSrc} alt=""/><p className='desc'>{value.desc}</p><p>{value.price}</p></Link></li>)})}</ul><Footernav></Footernav></div>)}
}

5.sort list关联
功能:在list中点击对应的sort项可跳转至sort,并依旧满足对应项高亮。
实现思路:根据本文最开始的各组件关系,可以知道list所属App->Home ->List而sort所属App->Sort,这里无疑涉及到状态提升与下放,我们要将list的相关属性提升到App,并在App中定义一个函数可以改变这些相关属性,改变后下放至Sort。
在这里利用context进行属性的提升下放。
首先,我们在App组件中声明即将传递的state,在getChildContext 方法中返回一个对象(即将传递的context),定义一个函数getNameIndex(contentText,index)下放至List点击时调用,更新state值,声明static childContextTypes={}对象表明传递的类型。
其次,在List组件中,接收context中的函数getNameIndex,依旧定义static childContextTypes={},并在渲染页面时,li添加onClick,调用该函数,传入value.contentText和key。
最后,在Sort组件中,接收contextType和index。因为Sort页面有两种方式:1是直接点击分类按钮,2是通过List。在componentWillMount()中,若接收到的contentText为‘’证明是点击按钮进入的该页面,就为filter()默认传一组初始值,否则就传入contentText。
相关知识点:
这里主要涉及了老版的context:
getChildContext 根组件中声明,一个函数,返回一个对象,就是context
childContextTypes 根组件中声明,指定context的结构类型,如不指定,会产生错误
contextTypes 子孙组件中声明,指定要接收的context的结构类型,可以只是context的一部分结构。contextTypes 没有定义,context将是一个空对象。
this.context 在子孙组件中通过此来获取上下文
注意:在指定结构类型时,npm install prop-types并 import PropTypes from ‘prop-types’

6.Goods组件

1.功能:展示商品详情、并能将对应商品添加到购物车,点击添加到购物车后,跳转至购物车页面。
在sort中已经提到了,我们在渲染商品时为每个商品渲染Link标签,为的就是商品详情页的展示,注意在渲染Link时,跳转地址将商品id作为参数传入。
前端:将_id=this.props.match.params._id,传到后端,查找数据库中对应的数据。
后端:数据获取、渲染同上,不再赘述。
2.具体实现:值得一提的是添加购物车,我们在该组件中声明一个方法:AddToShoppingCar(_id),在该方法中发起ajax请求,将_id作为data传递给后端,后端利用_id查询数据库中对应的有关商品信息,并将这些信息插入到数据库中的购物车商品表中,在ajax的success函数当中利用this.props.history.push(’/shoppingcar’)实现页面跳转,这里你可能会有疑问,为什么不利用link因为,如果此处利用link就会发生点击直接跳转到购物车页面,而无法进行数据存储。
3.代码

class Goods extends Component
{constructor(){super()this.state={data:[]}}componentWillMount()  //即将加载的时候拉取数据{var _id=this.props.match.params._idconsole.log(_id)$.ajax({type:'GET',url:"http://localhost:4000/goods",data:{_id:_id},success:(result)=>{console.log(result)this.setState({data:result[0]})}})const id =this.props.match.params.id  //获取参数}AddToShoppingCar(_id){$.ajax({type:'POST',url:"http://localhost:4000/addshoppingcar",data:{_id:_id},success:(result)=>{console.log(result)this.props.history.push('/shoppingcar')}})}render(){const {data}=this.statereturn(<div className='detail-view'><img  className='detail-img' src={data.imgSrc} alt=""/><h4 className='detail-name'>{data.desc}</h4><p className='detail-price'>{data.price}</p><div className='bottom-button'><button className='bottom-buy'>立即购买</button><button className='bottom-shopping-car' onClick={()=>{this.AddToShoppingCar(data._id)}}>加入购物车</button> </div></div>)}}

7.Shoppingcar组件
1.功能:点击购物车按钮,可以查看购物车中的商品,并且点击对应商品,会跳转到该商品的详情展示。
2.前端后端数据拉取实现同上
3.实现思路:该组件没有什么难点,需要注意的是,渲染时依旧带上Link标签 跳转地址要携带id参数
4.代码

class ShoppingCar extends Component
{constructor(){super()this.state={data:[]}}componentWillMount(){$.ajax({type:'GET',url:'http://localhost:4000/shoppingcar',data:{},success:(result)=>{console.log(result)this.setState({data:result})}})
}
render()
{const {data}=this.statereturn(<div><ul className='shopping-car-view'>{data.map((value,key)=>(<Link key={value.id+key} to={`/detail/${value.id}`}><li  className='list-items' id={value.id}><img className='item-img' src={value.imgSrc} alt=""/><div className='item-wrap'><p className='item-name'>{value.desc}</p><p className='item-price'>{value.price}</p></div></li></Link>))
}</ul><Footernav></Footernav></div>)}
}

React全栈项目——京东商城相关推荐

  1. vue商城项目源码_CMS全栈项目之Vue和React篇(下)(含源码)

    今天给大家介绍的主要是我们全栈CMS系统的未讲解完的后台部分和前台部分,如果对项目背景和技术栈不太了解,可以查看我之前的文章 基于nodeJS从0到1实现一个CMS全栈项目(上) 基于nodeJS从0 ...

  2. 视频教程-React全栈:前后端分离的招聘Web App项目(含资料)-ReactJS

    React全栈:前后端分离的招聘Web App项目(含资料) 张长志技术全才.擅长领域:区块链.大数据.Java等.10余年软件研发及企业培训经验,曾为多家大型企业提供企业内训如中石化,中国联通,中国 ...

  3. React全栈之Instagram开源视频教程

    这个冬天特别的寒冷且慢长,终于可以静下心来,做一些开源工作.读了zhoushaw老师的 打造属于你自己的instagram! 全栈项目(react + egg.js)项目, 非常喜欢, 于是决定为此开 ...

  4. Vue、Node全栈项目~面向小白的博客系统~

    个人博客系统 前言 ❝ 代码质量问题轻点喷(去年才学的前端),有啥建议欢迎联系我,联系方式见最下方,感谢! 页面有啥bug也可以反馈给我,感谢! 这是一套包含前后端代码的个人博客系统,欢迎各位提出建议 ...

  5. 0217前端日报:2020前端实践|优雅的实现一个全栈项目

    给 「前端开发博客」 加星标,每天打卡学习 长按二维码即可识别"进入网页"查看哟~ 1.2020前端实践|优雅的实现一个全栈项目(一) vweb_visual是一个简单的后台管理项 ...

  6. 面试超尴尬瞬间:我从没参与过一个全栈项目

    写简历是找工作的第一步,第二步就是面试,那么简历就是一块敲开面试大门的敲门砖,所以写简历的根本目的就是要体现出你的专业水平和项目经验,那么什么样的简历能够快速的抓住HR的眼球呢?作为前端工程师的简历来 ...

  7. 王者荣耀全栈项目部署到阿里云服务器笔记

    王者荣耀全栈项目部署到阿里云服务器笔记 原创Charles_GX 最后发布于2020-03-27 01:27:00 阅读数 177  收藏 展开 王者荣耀全栈项目部署到阿里云服务器笔记 学习的项目来自 ...

  8. react 技术栈项目轻量化方案调研

    react 技术栈项目轻量化方案调研 团队的新项目,无论是pc端的还是移动端的,都已全面转移到了 react 的技术栈. 然而,对移动端来说,react 框架脚本的体量还是有些偏大. 在后续项目比较成 ...

  9. 一个nuxt(vue)+mongoose全栈项目聊聊我粗浅的项目架构

    这是一篇求职文章 年龄21 坐标成都 找一份vue.js移动端H5工作 一份没有任何包装纯真实的简历 简历戳这 求职文章一共有两篇 另外一篇请点击一个基于Vue+TypeScript的[移动端]Vue ...

  10. React全Hook项目实战在线聊天室历程(三):加个音乐直播?

    前情提要: React全Hook项目实战在线聊天室历程(一):基本功能 React全Hook项目实战在线聊天室历程(二):引用与话题功能 正文 聊天应该有什么?背景音乐,茶与酒,零食,后两个我是没法实 ...

最新文章

  1. python中nltk_python2.7和NLTK安装详细教程
  2. spring和hibernate整合的几种方式详细介绍
  3. 链接ftp命令行_windows下最轻便的FTP/SCP文件管理器
  4. Spring JSR-250 注释
  5. 关于gcc扩展中的宏定义中用 # 和 ##
  6. 多线程java 银行_Java 多线程 之 银行ATM实例
  7. P2550 [AHOI2001]彩票摇奖(python3实现)
  8. C#中设置webBrowser为可编辑模式
  9. 微课|玩转Python轻松过二级(2.1.3节):字符串与字节串简介
  10. 摩根大通分析:随着灰度资金流动缓慢,比特币能否重回4万美元仍存疑问
  11. docker命令易错点整理
  12. sql for循环_【赵强老师】什么是PL/SQL?
  13. VS2017编译配置和使用LOG4CPP
  14. 字节版 趣味测试小程序源码
  15. 最近火爆的美团饿了么外卖cps分销裂变小程序搭建及推广秘籍(附搭建源码)
  16. (转)python基础之迭代器协议和生成器(一)
  17. three.js 渲染调优,如何提升3d场景更逼真的渲染效果
  18. 2016 黑客必备的Android应用都有哪些?
  19. 虾皮物流怎么收费?收费标准是什么?
  20. 《用计算机画画》教学设计,第8课《简简单单画幅画》教学设计

热门文章

  1. java adminlte 使用_AdminLTE框架基础布局使用
  2. 手把手教你做个人 app
  3. 手机12306买卧铺下铺技巧_12306订下铺有什么技巧?
  4. 二哥杂货铺matlab安装步骤,Matlab2017a软件安装教程
  5. 测试小故事82:好好说话
  6. Tableau商业智能与可视化应用实战系列视频教程(史上最全)
  7. 线性代数辅导讲义(第三章 向量)
  8. MATLAB 转置与共轭转置、在legend中输入数字、求频偏的小收获
  9. Matlab之共轭转置与非共轭转置
  10. 如何清除项目 git 版本控制信息