• Stars
    star
    262
  • Rank 156,136 (Top 4 %)
  • Language
    JavaScript
  • Created about 7 years ago
  • Updated about 5 years ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

react仿饿了么app(高度还原,动态获取数据)

react-ele

react仿饿了么app
技术:react+react-router+redux+create-react-app+fetch

git clone [email protected]:YMBo/react-ele.git  
npm install
npm start

虽然用的create-react-app但是我觉得还是有必要记录一下webpack的热更新(HMR)
webpack热更新(HMR)


一、准备阶段:

因为用的是create-react-app创建的项目,在项目中用到了less、rem,所以添加在webpack中添加这两个功能

1.初始化并添加less、px2rem功能

点我查看详情

二、记录    

1.header

header区域没有什么特别得。用到的布局是flex

2.banner

banner区域:

  • 轮播图用的是react-swipe插件
  • 因为数据是从饿了么取来的,所以需要对整个数组拆分为几个小数组,这就是循环的页数,然后小数组里有一些元素,为每一页的展示项目
  • 比如图片的hash值为'asdfghh',需要的图片地址需要进行格式上的转变为'a/sd/fghh',不明白为啥饿了么要这么做,直接用不可以么,我实现的方法是字符串转换为数组,进行插入,转换为字符串,详情看src/components/banner/banner.js文件,数据格式请看 src/data/data.js
  • 轮播图下面的控制按钮,我是用操作dom对象来实现的,因为用这几个小按钮是我循环出来的,this.state 用不了,希望能找到更好的办法 。
     (这个今天找到了解决办法,上面说到按钮是循环出来的,是在componentDidMount生命周期操作的,然后我将循环后的数组保存在this.state中,然后render的时候就不行了,我把循环的过程放到render中,this.state控制按钮行为的操作是成功的,所以如果需要循环数据并展现在页面中时,要在render中操作

3.首页预览    

首页预览
其中深红色部分为随机打乱数据并展现,红色部分为模仿请求来的数据进行操作并展现,现在还没有下拉刷新和无限滚动

4.搜索框采用position:fixed与position:sticky结合的方式,达到顶部吸附功能

搜索框吸附

5.回到顶部    

回到顶部按钮是判断滚动高度来计算的,采用了函数节流的模式,提高效率    

6.下拉加载更多功能    

由于数据都是本地的,所以利用setTimeout模拟网络请求延迟,如果所示:     加载更多    

7.底部导航(路由)    

用的是react-router 4,效果:
footer
使用路由带来的问题及解决办法:

  1. 注意因为首页的路由是/,所以匹配任何一个路由都会匹配到它,因此给它加一个精确匹配即可解决
<NavLink  to="/" exact activeClassName='active'>
	<svg className='index_footer_icon first' viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" >....</svg>
	<span className='index_footer_word'>外卖</span>
</NavLink >

其中activeClassName表示如果在当前路由的话就添加上active的class,或者用activeStyle是添加style。

  1. 路由的改变会触发组件的销毁、渲染等,所以要注意,如果绑定了事件,那么要在componentWillUnmount阶段解除绑定
  2. 因为首页的回到顶部、模拟数据延迟加载都用到了setTimeout,所以在开始setTimeout事件到真正执行setTimeout事件阶段触发了路由,那么将会报错,因为此时的state销毁了,我的解决办法为,定义一个变量,在componentWillUnmount这个阶段改变变量的状态,执行setTimeout时进行判断,即可解决:    
setTimeout(()=>{
		/*如果已经销毁*/
		if(this.isUnmount){return;}
		if(body[this.state.page+1]){
		this.setState({
			listData:[...body[this.state.page+1],...this.state.listData],
			page:this.state.page+1
		})
		}else{
		this.setState({
			noMore:true
		})
	}
	this.flag=false;
},1000)

8.发现页  

footer
其中几个活动是用的一个组件,遇到的问题是活动标题前的图标该怎么处理
footer    

render(){
	let dayLogo=<svg xmlns="http://www.w3.org/2000/svg" viewBox="-2 3 37 35" version="1.1" fill="#ff7e30"></svg>,
	foodsLogo=<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 34 33" version="1.1"></svg>,
	giftLogo=<svg xmlns="http://www.w3.org/2000/svg" viewBox="-4 3 30 30" version="1.1" fill="#ff7e30"></svg>;
	return(
		<div>
			<EntrySmart/>
			<Activity logo={foodsLogo} title={'美食热推'} sub={'你的口味,我都懂得'} data={this.state.foodsData}/>
			<Activity logo={dayLogo} title={'天天特价'}  sub={'特价商品,一网打尽'} data={this.state.data}/>
			<Activity logo={giftLogo} title={'限时好礼'}  sub={'小积分换豪礼'} data={this.state.giftData}/>
		</div>
	)
}

可是感觉这种办法不太好,但暂时又想不出别的办法

9.四个主页面完成

footer

10.登录页    

  1. 这块的重点是如果当前为登录页,那怎么让底部导航消失?我的解决办法为用了Switch
    footer
  2. 这一部分为表单验证以及存储登录状态,用到了redux
    footer
    3.最后登录页的两种表现形式,分别是从订单页登录后的状态和从我的页登录后的状态,看图(gif时间相对长点,中间有一会儿停顿,这是切换两种状态,耐心看完找区别)
    第一种:从我的页进行登录
    第二种:从订单页进行登录
    footer    

11.添加退出功能

footer        

12.获取地址页面    

这块的难点是:url不变化,但是却可以通过浏览器的前进返回按钮控制动画
涉及到的知识点请移步:点我查看

效果

13.最后一个页面商铺详情页

从首页的商铺列表进入每个商铺页的时候,会通过 两个参数请求商铺的详情数据,参数分别是,用户所在地理位置的geohash值,和 用户id值来请求数据,所以我用了fetch做请求
效果

14.上商铺详情页的第一个tab商品页

用了better scroll 插件,要注意的是,这里的数据全是真实的饿了么数据(实时取过来的)所以要依靠网络,那么就会有DOM高度变化的情况, 初始化 better-scroll 后,一定要 componentDidUpdate这个生命周期里进行更新    

 /*注意,要更新一下,因为dom的高度发生了变化*/
componentDidUpdate(){
	this.state.scroll.refresh();
}
componentDidMount() {
	/*初始化*/
	this.body.style.height=window.screen.height-this.body.offsetTop+'px';
	let scroll = new BScroll(document.querySelector('.commodity_main'),{//初始化BScroll对象
		scrollY:true,
		probeType:3,
		bounce: false,
		momentum:true,
		HWCompositing: true ,
		click: true
	});
	this.setState({
		scroll
	});
}

目前小加号的抛物线动画还没有做
 效果

15.修改商品页的滚动的实现方式

上面14说到,我用better-scroll实现滚动,但是本着能不用插件就不用插件,能用css就用css的原则(其实是看了ele官网的实现方式,觉得很巧妙),所以这一次修改了滚动的实现方式,注意看header部分和商品列表之间滚动条的联动~(这种方式的体验感觉非常不错)
效果

16.商家详情页左右联动添加动画    

这一块会有些稍微的复杂,不过也就是添加一个动画函数,和在动画发生的时候避免scroll事件的触发
 效果

17.购物车功能(还没有动画)    

这块主要是对数据的处理,注意选热销优惠部分的商品时,别的分类的同样食物也会被选中,而且这两类不会被红色圈圈标记,也就是说优惠热销其实与下面分类是联动的关系,注意看图
效果

18.添加抛物线动画、数据的处理、列表、主内容、购物车之间的联动。评价和店铺页    

动画部分原理:点击添加时,新建一个div和一个子div,然后父级元素运动轨迹从上到下,子div轨迹从做到右,这样就形成了一个抛物线
联动:数据处理,利用数据驱动
效果 效果