五.首页
1./home/index
(去掉/index
)
- 把这个的path修改为
/home
,主要是为了图标的匹配
把/home/index改为/home,并且加上exact,不加上就会模糊匹配/home,那么每次切换路由 首页的内容都会被匹配上 1 2.默认地址重定向到home页 地址栏只输入域名,如:localhost://3000会自动跳到localhost://3000/home的页面,需要使用重定向redirect
redirect组件用于实现路由重定向,to属性指定要跳转到的路由地址 render属性:是一个函数prop,用于指定要渲染的内容
六.轮播图
1.安装aiox,yarn add axios
2.在index组件当中导入axios
3.在state当中添加轮播图数据:swipers
4.新建一个方法getSwipers用来获取轮播图数据,并且更新轮播图状态
5/在CommpontDidMount钩子函数当中调用该方法
6.使用获取到的数据渲染轮播图
1.把轮播图的样式拷贝进来,有的浏览器会有 未阻止默认事件的报错,修改下样式可以了
*{
box-sizing: border-box;
touch-action: pan-y;
}
但我这边还是不行,是通过注释了node_module的这一段注释
2.获取数据 安装axios :npm i axios --save
在package.json加上那个这么一段代码:
"proxy": "http://localhost:8080" 1 然后在页面引入axios就可以直接调用:
import axios from 'axios'
axios.get('/swiper')
.then(res => {
console.log(res)
})
.catch(err => console.log(err))
我这边出现了一个问题就是: 图片src的路径是我自己从其他网站上扒过来的,图片在浏览器地址展示没问题,但奇怪的是在轮播图展示图片的时候报错403.我是在html页面加了一行代码就解决了。
<meta name="referrer" content="no-referrer" />
import React from 'react'
import { Carousel } from 'antd-mobile';
import axios from 'axios'
export default class Index extends React.Component {
state = {
//轮播图状态数据
swipers: []
}
async getSwiper() {
const res = await axios.get('/swiper')
this.setState({
swipers:res.data.data
})
}
componentDidMount() {
this.getSwiper()
}
//渲染轮播图
renderSwipers(){
return this.state.swipers.map(item => (
<span
key={item.id}
style={{ display: 'inline-block', width: '100%', height: 188 }}
>
<img
src={item.imgScr}
alt=""
style={{ width: '100%', verticalAlign: 'top' }}
/>
</span>
))
}
render() {
return (
<div>
<Carousel
autoplay={false}
infinite
>
{this.renderSwipers()}
</Carousel>
</div>
);
}
}
3.导航菜单 出现的bug: 1)默认进入页面轮播图不会自动轮播 2)切换进入页面,轮播图的高度没有自动撑开
解决的办法: 第一种方法: 根据官网,给state一个默认数据,这样解决了问题,但页面会报错
//轮播图状态数据 swipers: [1,2,3],
第二种方法: 1.在state中添加状态数据
state = {
//轮播图状态数据
swipers: [],
//状态
isSwiperLoaded: false
}
2.数据加载按成,修改该数据状态值为true
async getSwiper() {
const res = await axios.get('/swiper')
this.setState({
swipers: res.data.data,
isSwiperLoaded: true
})
}
3.只有轮播图数据加载完成的情况下,才渲染轮播图组件
render() {
return (
<div>
{/* 轮播图 */}
{
this.state.isSwiperLoaded ? (
<Carousel
autoplay
infinite
>
{this.renderSwipers()}
</Carousel>
) : ''
}
{/* 导航菜单 */}
<Flex className="nav">
{this.renderNavs()}
</Flex>
</div>
);
}
第三种方法: 外元素宽度百分百,计算外元素高度 图片原型的高度 /图片原型的宽度 = 外元素的高度/100vw 那么:外元素的高度 = 图片原型的高度 * 100vw / 图片原型的宽度
.am-carousel,.slider-frame,.slider-list{
height: 50vw!important;
}
整体代码:
import React from 'react'
import { Carousel } from 'antd-mobile';
import { Flex } from 'antd-mobile';
import axios from 'axios'
import './index.css'
import nav1 from '../../assets/images/nav-1.png'
import nav2 from '../../assets/images/nav-2.png'
import nav3 from '../../assets/images/nav-3.png'
import nav4 from '../../assets/images/nav-4.png'
export default class Index extends React.Component {
state = {
//轮播图状态数据
swipers: [],
flexData: [
{
src: nav1,
text: '整租',
id: '1',
path: '/home/list'
},
{
src: nav2,
text: '合租',
id: '2',
path: '/home/news'
},
{
src: nav3,
text: '地图找房',
id: '3',
path: '/home'
},
{
src: nav4,
text: '整租',
id: '4',
path: '/home/profile'
}
],
isLoad: false,
isSwiperLoaded: false
}
async getSwiper() {
const res = await axios.get('/swiper')
this.setState({
swipers: res.data.data,
isSwiperLoaded: true
})
}
componentDidMount() {
this.getSwiper()
}
//渲染轮播图
renderSwipers() {
return this.state.swipers.map(item => (
<span
key={item.id}
className="swiperItem"
>
<img
src={item.imgScr}
alt=""
style={{ width: '100%', verticalAlign: 'top' }}
/>
</span>
))
}
renderNavs(){
return this.state.flexData.map(item => (
<Flex.Item key={item.id} onClick={() => {
this.props.history.push(item.path)
}}>
<img src={item.src} alt="" />
<h2>{item.text}</h2>
</Flex.Item>
)
)
}
render() {
return (
<div>
{/* 轮播图 */}
{
this.state.isSwiperLoaded ? (
<Carousel
autoplay
infinite
>
{this.renderSwipers()}
</Carousel>
) : ''
}
{/* 导航菜单 */}
<Flex className="nav">
{this.renderNavs()}
</Flex>
</div>
);
}
}
import React from 'react'
// 导入组件
import { Carousel, Flex } from 'antd-mobile'
// 导入axios
import axios from 'axios'
// 导入导航菜单图片
import Nav1 from '../../assets/images/nav-1.png'
import Nav2 from '../../assets/images/nav-2.png'
import Nav3 from '../../assets/images/nav-3.png'
import Nav4 from '../../assets/images/nav-4.png'
// 导入样式文件
import './index.css'
// 导航菜单数据
const navs = [
{
id: 1,
img: Nav1,
title: '整租',
path: '/home/list'
},
{
id: 2,
img: Nav2,
title: '合租',
path: '/home/list'
},
{
id: 3,
img: Nav3,
title: '地图找房',
path: '/map'
},
{
id: 4,
img: Nav4,
title: '去出租',
path: '/rent'
}
]
export default class Index extends React.Component {
state = {
// 轮播图状态数据
swipers: []
}
// 获取轮播图数据的方法
async getSwipers() {
const res = await axios.get('http://localhost:8080/home/swiper')
this.setState({
swipers: res.data.body
})
}
componentDidMount() {
this.getSwipers()
}
// 渲染轮播图结构
renderSwipers() {
return this.state.swipers.map(item => (
<a
key={item.id}
href="http://itcast.cn"
style={{
display: 'inline-block',
width: '100%',
height: 212
}}
>
<img
src={`http://localhost:8080${item.imgSrc}`}
alt=""
style={{ width: '100%', verticalAlign: 'top' }}
/>
</a>
))
}
// 渲染导航菜单
renderNavs() {
return navs.map(item => (
<Flex.Item
key={item.id}
onClick={() => this.props.history.push(item.path)}
>
<img src={item.img} alt="" />
<h2>{item.title}</h2>
</Flex.Item>
))
}
render() {
return (
<div className="index">
{/* 轮播图 */}
<Carousel autoplay infinite autoplayInterval={5000}>
{this.renderSwipers()}
</Carousel>
{/* 导航菜单 */}
<Flex className="nav">{this.renderNavs()}</Flex>
</div>
)
}
}
4.tabBar菜单高亮问题 问题:点击首页导航菜单,路由变了,渲染内容也变了,但下面图标高亮没变
原因:因为点击图标的时候,没有重新加载Home组件,只是组件路由的切换 解决:在路由切换的时候,也执行菜单高亮的逻辑代码 1.添加componentDidUpdate钩子函数 2.在钩子函数中判断路由地址是否切换(比较前后的两个props,因为路由的信息是通过props传递给组件的) 3.在路由地址切换时,让菜单高亮
componentDidUpdate(preProps){
console.log('上一次的路由信息',preProps)
console.log('当前路有信息',this.props)
if(preProps.location.pathname!==this.props.location.pathname){
this.setState({
selectedTab:this.props.location.pathname
})
}
}
七.node-sass
安装:npm i node-sass
然后就可以直接使用了,把之前的.css
结尾的文件改成.scss
的文件,然后.scss
的文件就可以直接使用语法。
有时候版本太高了会报错,建议手动安装5.0或者6.0的版本
八.租房小组
import React from 'react'
import { Carousel } from 'antd-mobile';
import { Flex } from 'antd-mobile';
import { Grid } from 'antd-mobile';
import { WingBlank } from 'antd-mobile';
import axios from 'axios'
import './index.scss'
export default class Index extends React.Component {
state = {
groups: [],
news: []
}
async getGroup() {
const res = await axios.get('/groups')
console.log(res)
this.setState({
groups: res.data.data
})
}
async getNews() {
const res = await axios.get('/news')
this.setState({
news:res.data.data
})
console.log(res)
}
componentDidMount() {
this.getSwiper()
this.getGroup()
this.getNews()
}
renderNavs() {
return this.state.flexData.map(item => (
<Flex.Item key={item.id} onClick={() => {
this.props.history.push(item.path)
}}>
<img src={item.src} alt="" />
<h2>{item.text}</h2>
</Flex.Item>
)
)
}
renderNews() {
return this.state.news.map(item => (
<div className="news-item" key={item.id}>
<div className="imgWrap">
<img className="img" src={item.imgSrc} alt="" />
</div>
<Flex className="content" direction="column" justify="between">
<h3 className="title">{item.title}</h3>
<div className="news-from">
<span>{item.from}</span>
<span>{item.data}</span>
</div>
</Flex>
</div>
))
}
render() {
return (
<div>
{/* 租房小组 */}
<div className="group">
<h3 className="title">租房小组
<span className="more">更多</span>
</h3>
{/* 宫格组件 */}
<Grid
data={this.state.groups}
columnNum={2}
square={false}
hasLine={false}
renderItem={(item) => (
<Flex className="group-item" justify="around" key={item.id}>
<div className="desc">
<p className="title">{item.title}</p>
<span className="info">{item.desc}</span>
</div>
{/* {item.imgScr} */}
<img src={item.imgScr} alt="" />
</Flex>
)
}
/>
</div>
{/* 最新资讯 */}
<div className="news">
<h3 className="group-title">最新资讯</h3>
<WingBlank size="md">
{this.renderNews()}
</WingBlank>
</div>
</div>
);
}
}
轮播图出现的问题: 不会自动播放,从其他路由返回的时候高度不够 轮播图的数据是动态加载的,加载完成前后,轮播图的数量不一致导致的我呢提 轮播图数据加载完成后渲染他就没有我呢提
如何解决:在state当中添加表示轮播图加载完成的数据, 在轮播图数据加载完成的时候,修改该数据的状态为tru 只有在轮播图数据加载完成的情况下,渲染数据的状态
第二个问题: 菜单没有出现高效的问题 点击菜跳转的时候出现高亮 点击首页导航菜单,导航到1找房列表页面的时候,找房菜单没有出现高亮
原因: 原来我们实现该功能的时候只考虑了点击以及第一次加载home组件的情况,但是我们没有考虑不重新加载组件的时候路由切换,因为这种情况下,我们的代码没有覆盖到 解决: 思路:在路由切换的时候也执行菜单高亮的代码 1.componmentDidUpdate钩子函数 2.在钩子函数当中判断路由地址是否切换,因为路由切换的信息是通过props传递给组件的,所以通过比较更新前后的两个props
3.在路由切换的时候让菜单高亮
componentDiduPDATE 21-在脚手架当中使用sass
yarn add nod-sasss
groups:[];
getGroups
// 渲染导航菜单
renderNavs() {
return navs.map(item => (
<Flex.Item
key={item.id}
onClick={() => this.props.history.push(item.path)}
>
<img src={item.img} alt="" />
<h2>{item.title}</h2>
</Flex.Item>
))
}
render() {
return (
<div className="index">
{/* 轮播图 */}
<div className="swiper">
{this.state.isSwiperLoaded ? (
<Carousel autoplay infinite autoplayInterval={5000}>
{this.renderSwipers()}
</Carousel>
) : (
''
)}
</div>
{/* 导航菜单 */}
<Flex className="nav">{this.renderNavs()}</Flex>
{/* 租房小组 */}
<div className="group">
<h3 className="group-title">
租房小组 <span className="more">更多</span>
</h3>
{/* 宫格组件 */}
<Grid
data={this.state.groups}
columnNum={2}
square={false}
hasLine={false}
renderItem={item => (
<Flex className="group-item" justify="around" key={item.id}>
<div className="desc">
<p className="title">{item.title}</p>
<span className="info">{item.desc}</span>
</div>
<img src={`http://localhost:8080${item.imgSrc}`} alt="" />
</Flex>
)}
/>
</div>
{/* <Flex className="group-item" justify="around">
<div className="desc">
<p className="title">家住回龙观</p>
<span className="info">归属的感觉</span>
</div>
<img
src="http://localhost:3000/static/media/group-1.263b84b0.png"
alt=""
/>
</Flex> */}
</div>
)
}
}
geolocation
getCurrentPosition
百度地图
怎么使用的呢
创建map组件,配置路由, oxtr default class mAp extends React,CIoibb {
import React from 'react'
// 导入样式
import './index.scss'
export default class Map extends React.Component {
componentDidMount() {
// 初始化地图实例
// 注意:在 react 脚手架中全局对象需要使用 window 来访问,否则,会造成 ESLint 校验错误
const map = new window.BMap.Map('container')
// 设置中心点坐标
const point = new window.BMap.Point(116.404, 39.915)
// 初始化地图
map.centerAndZoom(point, 15)
}
render() {
return (
<div className="map">
{/* 地图容器元素 */}
<div id="container" />
</div>
)
}
}
import React from 'react'
// 导入组件
import { Carousel, Flex, Grid, WingBlank } from 'antd-mobile'
// 导入axios
import axios from 'axios'
// 导入导航菜单图片
import Nav1 from '../../assets/images/nav-1.png'
import Nav2 from '../../assets/images/nav-2.png'
import Nav3 from '../../assets/images/nav-3.png'
import Nav4 from '../../assets/images/nav-4.png'
// 导入样式文件
import './index.scss'
// 导航菜单数据
const navs = [
{
id: 1,
img: Nav1,
title: '整租',
path: '/home/list'
},
{
id: 2,
img: Nav2,
title: '合租',
path: '/home/list'
},
{
id: 3,
img: Nav3,
title: '地图找房',
path: '/map'
},
{
id: 4,
img: Nav4,
title: '去出租',
path: '/rent'
}
]
// 获取地理位置信息
// navigator.geolocation.getCurrentPosition(position => {
// console.log('当前位置信息:', position)
// })
/*
1 打开百度地图JS API 定位文档 。
2 通过 IP 定位获取到当前城市名称。
3 调用我们服务器的接口,换取项目中的城市信息(有房源的城市的名称和id)。
4 将接口返回的城市信息展示在顶部导航栏中。
*/
export default class Index extends React.Component {
state = {
// 轮播图状态数据
swipers: [],
isSwiperLoaded: false,
// 租房小组数据
groups: [],
// 最新资讯
news: [],
// 当前城市名称
curCityName: '上海'
}
// 获取轮播图数据的方法
async getSwipers() {
const res = await axios.get('http://localhost:8080/home/swiper')
this.setState({
swipers: res.data.body,
isSwiperLoaded: true
})
}
// 获取租房小组数据的方法
async getGroups() {
const res = await axios.get('http://localhost:8080/home/groups', {
params: {
area: 'AREA%7C88cff55c-aaa4-e2e0'
}
})
// console.log(res)
this.setState({
groups: res.data.body
})
}
// 获取最新资讯
async getNews() {
const res = await axios.get(
'http://localhost:8080/home/news?area=AREA%7C88cff55c-aaa4-e2e0'
)
this.setState({
news: res.data.body
})
}
componentDidMount() {
this.getSwipers()
this.getGroups()
this.getNews()
// 2 通过 IP 定位获取到当前城市名称。
const curCity = new window.BMap.LocalCity()
curCity.get(async res => {
// console.log('当前城市信息:', res)
const result = await axios.get(
`http://localhost:8080/area/info?name=${res.name}`
)
// console.log(result)
this.setState({
curCityName: result.data.body.label
})
})
}
// 渲染轮播图结构
renderSwipers() {
return this.state.swipers.map(item => (
<a
key={item.id}
href="http://itcast.cn"
style={{
display: 'inline-block',
width: '100%',
height: 212
}}
>
<img
src={`http://localhost:8080${item.imgSrc}`}
alt=""
style={{ width: '100%', verticalAlign: 'top' }}
/>
</a>
))
}
// 渲染导航菜单
renderNavs() {
return navs.map(item => (
<Flex.Item
key={item.id}
onClick={() => this.props.history.push(item.path)}
>
<img src={item.img} alt="" />
<h2>{item.title}</h2>
</Flex.Item>
))
}
// 渲染最新资讯
renderNews() {
return this.state.news.map(item => (
<div className="news-item" key={item.id}>
<div className="imgwrap">
<img
className="img"
src={`http://localhost:8080${item.imgSrc}`}
alt=""
/>
</div>
<Flex className="content" direction="column" justify="between">
<h3 className="title">{item.title}</h3>
<Flex className="info" justify="between">
<span>{item.from}</span>
<span>{item.date}</span>
</Flex>
</Flex>
</div>
))
}
render() {
return (
<div className="index">
{/* 轮播图 */}
<div className="swiper">
{this.state.isSwiperLoaded ? (
<Carousel autoplay infinite autoplayInterval={5000}>
{this.renderSwipers()}
</Carousel>
) : (
''
)}
{/* 搜索框 */}
<Flex className="search-box">
{/* 左侧白色区域 */}
<Flex className="search">
{/* 位置 */}
<div
className="location"
onClick={() => this.props.history.push('/citylist')}
>
<span className="name">{this.state.curCityName}</span>
<i className="iconfont icon-arrow" />
</div>
{/* 搜索表单 */}
<div
className="form"
onClick={() => this.props.history.push('/search')}
>
<i className="iconfont icon-seach" />
<span className="text">请输入小区或地址</span>
</div>
</Flex>
{/* 右侧地图图标 */}
<i
className="iconfont icon-map"
onClick={() => this.props.history.push('/map')}
/>
</Flex>
</div>
{/* 导航菜单 */}
<Flex className="nav">{this.renderNavs()}</Flex>
{/* 租房小组 */}
<div className="group">
<h3 className="group-title">
租房小组 <span className="more">更多</span>
</h3>
{/* 宫格组件 */}
<Grid
data={this.state.groups}
columnNum={2}
square={false}
hasLine={false}
renderItem={item => (
<Flex className="group-item" justify="around" key={item.id}>
<div className="desc">
<p className="title">{item.title}</p>
<span className="info">{item.desc}</span>
</div>
<img src={`http://localhost:8080${item.imgSrc}`} alt="" />
</Flex>
)}
/>
</div>
{/* 最新资讯 */}
<div className="news">
<h3 className="group-title">最新资讯</h3>
<WingBlank size="md">{this.renderNews()}</WingBlank>
</div>
</div>
)
}
}
导入axios,发送请求,页面加载的时候拿到数据
componmentDidMount(){
}
gtCityList ({
axios.get();});
接口地址,p'p
P134 获取并且处理城市列表
// 数据格式化的方法
// list: [{}, {}]
const formatCityData = list => {
const cityList = {}
// const cityIndex = []
// 1 遍历list数组
list.forEach(item => {
// 2 获取每一个城市的首字母
const first = item.short.substr(0, 1)
// 3 判断 cityList 中是否有该分类
if (cityList[first]) {
// 4 如果有,直接往该分类中push数据
// cityList[first] => [{}, {}]
cityList[first].push(item)
} else {
// 5 如果没有,就先创建一个数组,然后,把当前城市信息添加到数组中
cityList[first] = [item]
}
})
// 获取索引数据
const cityIndex = Object.keys(cityList).sort()
return {
cityList,
/*
1 获取热门城市数据
2 将数据添加到 cityList 中
3 将索引添加到 cityIndex 中
*/
const hotRes = await axios.get('http://localhost:8080/area/hot')
// console.log('热门城市数据:', hotRes)
cityList['hot'] = hotRes.data.body
// 将索引添加到 cityIndex 中
cityIndex.unshift('hot')
console.log(cityList, cityIndex)
}