// 添加 className 和 rightContent(导航栏右侧内容) 属性
function NavHeader({
children,
history,
onLeftClick,
className,
rightContent
}) {
// 默认点击行为
const defaultHandler = () => history.go(-1)
return (
}
onLeftClick={onLeftClick || defaultHandler}
rightContent={rightContent}
>
{children}
)
}
// 添加props校验
NavHeader.propTypes = {
...
rightContent: PropTypes.array
}
// withRouter(NavHeader) 函数的返回值也是一个组件
export default withRouter(NavHeader)
this.props.history.push(`/detail/${house.houseCode}`)}
// 注意:该组件中应该接收 style,然后给组件元素设置样式!!!
style={style}
src={BASE_URL + house.houseImg}
title={house.title}
desc={house.desc}
tags={house.tags}
price={house.price}
/>
componentDidMount() {
// 获取房屋数据
this.getHouseDetail()
}
async getHouseDetail() {
const { id } = this.props.match.params
// 开启loading
this.setState({
isLoading: true
})
const res = await API.get(`/houses/${id}`)
this.setState({
houseInfo: res.data.body,
isLoading: false
})
const { community, coord } = res.data.body
// 渲染地图
this.renderMap(community, coord)
}
使用房屋数据,渲染页面
解构出需要的数据
const {
isLoading,
houseInfo: {
community,
title,
price,
roomType,
size,
floor,
oriented,
supporting,
description
}
} = this.state
渲染小区名称
{/* 导航栏 */}
]}
>
{community}
渲染轮播图
// 渲染轮播图结构
renderSwipers() {
const {
houseInfo: { houseImg }
} = this.state
return houseImg.map(item => (
))
}
渲染标签
// 渲染标签
renderTags() {
const {
houseInfo: { tags }
} = this.state
return tags.map((item, index) => {
// 如果标签数量超过3个,后面的标签就都展示位第三个标签的样式
let tagClass = ''
if (index > 2) {
tagClass = 'tag3'
} else {
tagClass = 'tag' + (index + 1)
}
return (
{item}
)
})
}
渲染价格,房型,面积等
{price}
/月
租金
{roomType}
房型
{size}平米
面积
渲染装修,楼层,朝向等
装修:
精装
楼层:
{floor}
朝向:
{oriented.join('、')}
类型:普通住宅
渲染地图
// 渲染地图
renderMap(community, coord) {
const { latitude, longitude } = coord
const map = new BMap.Map('map')
const point = new BMap.Point(longitude, latitude)
map.centerAndZoom(point, 17)
const label = new BMap.Label('', {
position: point,
offset: new BMap.Size(0, -36)
})
label.setStyle(labelStyle)
label.setContent(`
${community}
`)
map.addOverlay(label)
}
渲染房屋配套
{/* 房屋配套 */}
房屋配套
{/* 判断是否有数据 */}
{supporting.length === 0 ? (
暂无数据
) : (
)}
渲染房屋概况
房源概况
王女士
已认证房主
发消息
{description || '暂无房屋描述'}
渲染推荐,可以复用 HouseItem组件
猜你喜欢
{recommendHouses.map(item => (
))}
对应结构:
{/* 顶部导航 */}
账号登录
{/* 登录表单 */}
还没有账号,去注册~
功能实现:
state = {
username: '',
password: ''
}
getUserName = e => {
this.setState({
username: e.target.value
})
}
getPassword = e => {
this.setState({
password: e.target.value
})
}
render() {
const { username, password } = this.state
return (
...
{/* 登录表单 */}
)
}
}
// 表单提交事件的事件处理程序
handleSubmit = async e => {
// 阻止表单提交时的默认行为
e.preventDefault()
...
}
// 表单提交事件的事件处理程序
handleSubmit = async e => {
// 阻止表单提交时的默认行为
e.preventDefault()
// 获取账号和密码
const { username, password } = this.state
// console.log('表单提交了', username, password)
// 发送请求
const res = await API.post('/user/login', {
username,
password
})
console.log('登录结果:', res)
const { status, body, description } = res.data
if (status === 200) {
// 登录成功
localStorage.setItem('hkzf_token', body.token)
this.props.history.go(-1)
} else {
// 登录失败
Toast.info(description, 2, null, false)
}
}
// Login组件中
render() {
// const { username, password } = this.state
// 通过 props 获取高阶组件传递进来的属性
const { values, handleSubmit, handleChange } = this.props
return (
{/* 顶部导航 */}
账号登录
{/* 登录表单 */}
还没有账号,去注册~
)
}
// 使用 withFormik 高阶组件包装 Login 组件,为 Login 组件提供属性和方法
Login = withFormik({
// 提供状态:
mapPropsToValues: () => ({ username: '', password: '' }),
// 表单的提交事件
handleSubmit: async (values, { props }) => {
// 获取账号和密码
const { username, password } = values
// 发送请求
const res = await API.post('/user/login', {
username,
password
})
console.log('登录结果:', res)
const { status, body, description } = res.data
if (status === 200) {
// 登录成功
localStorage.setItem('hkzf_token', body.token)
// 注意:无法在该方法中,通过 this 来获取到路由信息
// 所以,需要通过 第二个对象参数中获取到 props 来使用 props
props.history.go(-1)
} else {
// 登录失败
Toast.info(description, 2, null, false)
}
}
})(Login)
// 导入Yup
import * as Yup from 'yup'
示例代码:
// 使用 withFormik 高阶组件包装 Login 组件,为 Login 组件提供属性和方法
Login = withFormik({
...
// 添加表单校验规则
validationSchema: Yup.object().shape({
username: Yup.string()
.required('账号为必填项')
.matches(REG_UNAME, '长度为5到8位,只能出现数字、字母、下划线'),
password: Yup.string()
.required('密码为必填项')
.matches(REG_PWD, '长度为5到12位,只能出现数字、字母、下划线')
}),
...
})(Login)
在结构中需要渲染错误信息:
{/* 登录表单 */}
示例代码:
// 导入withFormik
import { withFormik, Form, Field, ErrorMessage } from 'formik'