import React, { Component } from 'react'
import { Link } from 'react-router-dom'
import { API, BASE_URL } from '../../utils'
import NavHeader from '../../components/NavHeader'
import HouseItem from '../../components/HouseItem'
import NoHouse from '../../components/NoHouse'
import styles from './index.module.css'
export default class Rent extends Component {
state = {
// 出租房屋列表
list: []
}
// 获取已发布房源的列表数据
async getHouseList() {
const res = await API.get('/user/houses')
const { status, body } = res.data
if (status === 200) {
this.setState({
list: body
})
} else {
const { history, location } = this.props
history.replace('/login', {
from: location
})
}
}
componentDidMount() {
this.getHouseList()
}
renderHouseItem() {
const { list } = this.state
const { history } = this.props
return list.map(item => {
return (
history.push(`/detail/${item.houseCode}`)}
src={BASE_URL + item.houseImg}
title={item.title}
desc={item.desc}
tags={item.tags}
price={item.price}
/>
)
})
}
renderRentList() {
const { list } = this.state
const hasHouses = list.length > 0
if (!hasHouses) {
return (
您还没有房源,
去发布房源
吧~
)
}
return {this.renderHouseItem()}
}
render() {
const { history } = this.props
return (
history.go(-1)}>房屋管理
{this.renderRentList()}
)
}
}
{/* 配置登录后,才能访问的页面 */}
{/* 搜索框 */}
history.go(-1)}
/>
{/* 搜索提示列表 */}
{this.renderTips()}
handleSearchTxt = value => {
this.setState({ searchTxt: value })
if (!value) {
// 文本框的值为空
return this.setState({
tipsList: []
})
}
}
handleSearchTxt = value => {
this.setState({ searchTxt: value })
if (!value) {
// 文本框的值为空
return this.setState({
tipsList: []
})
}
// 清除上一次的定时器
clearTimeout(this.timerId)
this.timerId = setTimeout(async () => {
// 获取小区数据
const res = await API.get('/area/community', {
params: {
name: value,
id: this.cityId
}
})
this.setState({
tipsList: res.data.body
})
}, 500)
}
// 渲染搜索结果列表
renderTips = () => {
const { tipsList } = this.state
return tipsList.map(item => (
this.onTipsClick(item)}
>
{item.communityName}
))
}
onTipsClick = item => {
this.props.history.replace('/rent/add', {
name: item.communityName,
id: item.community
})
}
constructor(props) {
super(props)
// console.log(props)
const { state } = props.location
const community = {
name: '',
id: ''
}
if (state) {
// 有小区信息数据,存储到状态中
community.name = state.name
community.id = state.id
}
}
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-OZjtHyBI-1575112741233)(images/发布房源 -布局结构.png)]
import React, { Component } from 'react'
import {
Flex,
List,
InputItem,
Picker,
ImagePicker,
TextareaItem,
Modal
} from 'antd-mobile'
import NavHeader from '../../../components/NavHeader'
import HousePackge from '../../../components/HousePackage'
import styles from './index.module.css'
const alert = Modal.alert
// 房屋类型
const roomTypeData = [
{ label: '一室', value: 'ROOM|d4a692e4-a177-37fd' },
{ label: '二室', value: 'ROOM|d1a00384-5801-d5cd' },
{ label: '三室', value: 'ROOM|20903ae0-c7bc-f2e2' },
{ label: '四室', value: 'ROOM|ce2a5daa-811d-2f49' },
{ label: '四室+', value: 'ROOM|2731c38c-5b19-ff7f' }
]
// 朝向:
const orientedData = [
{ label: '东', value: 'ORIEN|141b98bf-1ad0-11e3' },
{ label: '西', value: 'ORIEN|103fb3aa-e8b4-de0e' },
{ label: '南', value: 'ORIEN|61e99445-e95e-7f37' },
{ label: '北', value: 'ORIEN|caa6f80b-b764-c2df' },
{ label: '东南', value: 'ORIEN|dfb1b36b-e0d1-0977' },
{ label: '东北', value: 'ORIEN|67ac2205-7e0f-c057' },
{ label: '西南', value: 'ORIEN|2354e89e-3918-9cef' },
{ label: '西北', value: 'ORIEN|80795f1a-e32f-feb9' }
]
// 楼层
const floorData = [
{ label: '高楼层', value: 'FLOOR|1' },
{ label: '中楼层', value: 'FLOOR|2' },
{ label: '低楼层', value: 'FLOOR|3' }
]
export default class RentAdd extends Component {
constructor(props) {
super(props)
// console.log(props)
const { state } = props.location
const community = {
name: '',
id: ''
}
if (state) {
// 有小区信息数据,存储到状态中
community.name = state.name
community.id = state.id
}
this.state = {
// 临时图片地址
tempSlides: [],
// 小区的名称和id
community,
// 价格
price: '',
// 面积
size: '',
// 房屋类型
roomType: '',
// 楼层
floor: '',
// 朝向:
oriented: '',
// 房屋标题
title: '',
// 房屋图片
houseImg: '',
// 房屋配套:
supporting: '',
// 房屋描述
description: ''
}
}
render() {
const Item = List.Item
const { history } = this.props
const {
community,
price,
roomType,
floor,
oriented,
description,
tempSlides,
title,
size
} = this.state
return (
发布房源
{/* 房源信息 */}
'房源信息'}
data-role="rent-list"
>
{/* 选择所在小区 */}
- history.replace('/rent/search')}
>
小区名称
{/* 相当于 form 表单的 input 元素 */}
租 金
this.getValue('size', val)}
>
建筑面积
-
户 型
- 所在楼层
-
朝 向
{/* 房屋标题 */}
'房屋标题'}
data-role="rent-list"
>
{/* 房屋图像 */}
'房屋图像'}
data-role="rent-list"
>
{/* 房屋配置 */}
'房屋配置'}
data-role="rent-list"
>
{/* 房屋描述 */}
'房屋描述'}
data-role="rent-list"
>
取消
提交
)
}
}
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ICGMW4Z9-1575112741237)(images/getValue.png)]
示例代码:
/*
获取表单数据:
*/
getValue = (name, value) => {
this.setState({
[name]: value
})
}
// 给相应组件添加 onChange 事件,传递 name 和value
/*
获取房屋配置数据
*/
handleSupporting = selected => {
this.setState({
supporting: selected.join('|')
})
}
...
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-clwi2iUG-1575112741238)(images/图片上传接口.png)]
要上传图片,首先需要先获取到房屋图片
handleHouseImg = (files, type, index) => {
// files 图片文件的数组; type 操作类型:添加,移除(如果是移除,那么第三个参数代表就是移除的图片的索引)
console.log(files, type, index)
this.setState({
tempSlides: files
})
}
...
图片已经可以通过 ImagePicker 的 onChange 事件来获取到了,接下来就需要把图片进行上传,然后获取到服务器返回的成功上传图片的路径
// 上传图片
addHouse = async() => {
const { tempSlides } = this.state
let houseImg = ''
if (tempSlides.length > 0) {
// 已经有上传的图片了
const form = new FormData()
tempSlides.forEach(item => form.append('file', item.file))
const res = await API.post('/houses/image', form, {
headers: {
'Content-Type': 'multipart/form-data'
}
})
// console.log(res)
houseImg = res.data.body.join('|')
}
}
...
提交
到现在,我们已经可以获取到发布房源的所有信息了,接下来就需要把数据传递给服务器
addHouse = async () => {
const {
tempSlides,
title,
description,
oriented,
supporting,
price,
roomType,
size,
floor,
community
} = this.state
let houseImg = ''
// 上传房屋图片:
if (tempSlides.length > 0) {
// 已经有上传的图片了
const form = new FormData()
tempSlides.forEach(item => form.append('file', item.file))
const res = await API.post('/houses/image', form, {
headers: {
'Content-Type': 'multipart/form-data'
}
})
houseImg = res.data.body.join('|')
}
// 发布房源
const res = await API.post('/user/houses', {
title,
description,
oriented,
supporting,
price,
roomType,
size,
floor,
community: community.id,
houseImg
})
if (res.data.status === 200) {
// 发布成功
Toast.info('发布成功', 1, null, false)
this.props.history.push('/rent')
} else {
Toast.info('服务器偷懒了,请稍后再试~', 2, null, false)
}
}
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-dCBhVvUr-1575112741243)(images/生产环境.jpg)]
如果出现以下提示,就代表打包成功,在根目录中就会生成一个build文件夹
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-8arTTF5q-1575112741247)(images/build命令.png)]
create-react-app 中隐藏了 webpack的配置,隐藏在react-scripts包中
两种方式来修改
运行命令 npm run eject 释放 webpack配置(注意:不可逆)
如果您对构建工具和配置选择不满意,您可以eject
随时进行。此命令将从项目中删除单个构建依赖项。
相反,它会将所有配置文件和传递依赖项(Webpack,Babel,ESLint等)作为依赖项复制到项目中package.json
。从技术上讲,依赖关系和开发依赖关系之间的区别对于生成静态包的前端应用程序来说是非常随意的。此外,它曾经导致某些托管平台出现问题,这些托管平台没有安装开发依赖项(因此无法在服务器上构建项目或在部署之前对其进行测试)。您可以根据需要自由重新排列依赖项package.json
。
除了eject
仍然可以使用所有命令,但它们将指向复制的脚本,以便您可以调整它们。在这一点上,你是独立的。
你不必使用eject
。策划的功能集适用于中小型部署,您不应觉得有义务使用此功能。但是,我们知道如果您准备好它时无法自定义此工具将无用
通过第三方包重写 webpack配置(比如:react-app-rewired 等)
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-8WNqUAqi-1575112741249)(images/scripts配置.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-NfRi4YbM-1575112741254)(images/overrides.png)]
const { override, fixBabelImports } = require('customize-cra');
module.exports = override(
fixBabelImports('import', {
libraryName: 'antd-mobile',
style: 'css',
}),
);
打完包后,你会发现,两次打包的体积会有变化,这样达到了一个代码体积优化的层面
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-U21VZObR-1575112741257)(images/两次打包对比.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-nR1oGuPt-1575112741259)(images/路由分割.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-3qAur6qu-1575112741264)(images/suspense.png)]
项目中代码修改:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-DtzZ8ATO-1575112741269)(images/项目代码.png)]
React.js 优化性能文档
react-virtualized只加载用到的组件 文档
脚手架配置 解决跨域问题
安装 http-proxy-middleware
$ npm install http-proxy-middleware --save
$ # or
$ yarn add http-proxy-middleware
创建src/setupProxy.js
并放置以下内容
const proxy = require('http-proxy-middleware');
module.exports = function(app) {
app.use(proxy('/api', { target: 'http://localhost:5000/' }));
};
**注意:**无需在任何位置导入此文件。它在启动开发服务器时自动注册,此文件仅支持Node的JavaScript语法。请务必仅使用支持的语言功能(即不支持Flow,ES模块等)。将路径传递给代理功能允许您在路径上使用通配和/或模式匹配,这比快速路由匹配更灵活
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-zqucj2vu-1575112741271)(images/长列表优化.png)]