React前后端分离实战租房项目一

React前后端分离实战租房项目一

好客租房-20天

ES6新特性以及ReactJS入门

day01-ES6新特性以及ReactJS入门&

(02.ES6新特性之了解ES6以及其发展历史&)

02.ES6新特性之了解ES6以及其发展历史&

let声明变量

React前后端分离实战租房项目一_第1张图片

React前后端分离实战租房项目一_第2张图片

(04.ES6新特性之字符串扩展&)

04.ES6新特性之字符串扩展&

判断字符串是否包含

解构表达式

React前后端分离实战租房项目一_第3张图片

参数默认值

箭头函数

React前后端分离实战租房项目一_第4张图片

React前后端分离实战租房项目一_第5张图片

对象属性简写

函数参数解构

React前后端分离实战租房项目一_第6张图片

React前后端分离实战租房项目一_第7张图片

map和reduce

React前后端分离实战租房项目一_第8张图片

React前后端分离实战租房项目一_第9张图片

三点扩展运算符

React前后端分离实战租房项目一_第10张图片

Promise

React前后端分离实战租房项目一_第11张图片

React前后端分离实战租房项目一_第12张图片

set和Map集合

React前后端分离实战租房项目一_第13张图片

React前后端分离实战租房项目一_第14张图片

React前后端分离实战租房项目一_第15张图片

React前后端分离实战租房项目一_第16张图片

React前后端分离实战租房项目一_第17张图片

class类语法

React前后端分离实战租房项目一_第18张图片

React前后端分离实战租房项目一_第19张图片

React前后端分离实战租房项目一_第20张图片

generator函数

React前后端分离实战租房项目一_第21张图片 

for ...of循环

React前后端分离实战租房项目一_第22张图片

修饰器注解,

React前后端分离实战租房项目一_第23张图片

React前后端分离实战租房项目一_第24张图片

Babel

React前后端分离实战租房项目一_第25张图片

React前后端分离实战租房项目一_第26张图片

umi部署安装

React前后端分离实战租房项目一_第27张图片

模块化

React前后端分离实战租房项目一_第28张图片

(18.ReactJS入门之前端开发的演变&)

18.ReactJS入门之前端开发的演变&

(19.ReactJS入门之ReactJS简介&)

19.ReactJS入门之ReactJS简介&

(20.ReactJS入门之环境搭建以及编写HelloWorld程序&)

20.ReactJS入门之环境搭建以及编写HelloWorld程序&

创建项目工程

React前后端分离实战租房项目一_第29张图片

React前后端分离实战租房项目一_第30张图片

React前后端分离实战租房项目一_第31张图片

React前后端分离实战租房项目一_第32张图片

React前后端分离实战租房项目一_第33张图片

React前后端分离实战租房项目一_第34张图片

React前后端分离实战租房项目一_第35张图片

React前后端分离实战租房项目一_第36张图片

React前后端分离实战租房项目一_第37张图片

React前后端分离实战租房项目一_第38张图片

JSX语法

React前后端分离实战租房项目一_第39张图片

React前后端分离实战租房项目一_第40张图片

组件拆分

React前后端分离实战租房项目一_第41张图片

React前后端分离实战租房项目一_第42张图片

React前后端分离实战租房项目一_第43张图片

组件参数传递props.children

React前后端分离实战租房项目一_第44张图片

React前后端分离实战租房项目一_第45张图片

React前后端分离实战租房项目一_第46张图片

React前后端分离实战租房项目一_第47张图片

state组件状态

React前后端分离实战租房项目一_第48张图片

React前后端分离实战租房项目一_第49张图片

三点扩展运算符

React前后端分离实战租房项目一_第50张图片

React前后端分离实战租房项目一_第51张图片

组件生命周期函数

React前后端分离实战租房项目一_第52张图片

React前后端分离实战租房项目一_第53张图片

day02-Ant Design以及Ant Design Pro入门

(02.ReactJS入门之Model分层的概念&)

02.ReactJS入门之Model分层的概念&

React前后端分离实战租房项目一_第54张图片

(03.ReactJS入门之dva的使用&)

03.ReactJS入门之dva的使用&

DVA框架

React前后端分离实战租房项目一_第55张图片

React前后端分离实战租房项目一_第56张图片

ListData.js

import request from '../util/request';

export default {
    namespace: 'list',
    state: {
        data: [],
        maxNum: 1
    },
    reducers : { // 定义的一些函数
        addNewData : function (state, result) { // state:指的是更新之前的状态数据, result: 请求到的数据

            if(result.data){ //如果state中存在data数据,直接返回,在做初始化的操作
                return result.data;
            }

            let maxNum = state.maxNum + 1;
            let newArr = [...state.data, maxNum];


            return {
                data : newArr,
                maxNum : maxNum
            }
            //通过return 返回更新后的数据
        }
    },
    effects: { //新增effects配置,用于异步加载数据
        *initData(params, sagaEffects) { //定义异步方法
            const {call, put} = sagaEffects; //获取到call、put方法
            const url = "/ds/list"; // 定义请求的url
            let data = yield call(request, url); //执行请求
            yield put({ // 调用reducers中的方法
                type : "addNewData", //指定方法名
                data : data //传递ajax回来的数据
            });
        }
    }
}

List.js

import React from 'react';
import { connect } from 'dva';

const namespace = "list";

// 说明:第一个回调函数,作用:将page层和model层进行链接,返回modle中的数据
// 并且,将返回的数据,绑定到this.props

// 接收第二个函数,这个函数的作用:将定义的函数绑定到this.props中,调用model层中定义的函数
@connect((state) => {
    return {
        dataList : state[namespace].data,
        maxNum : state[namespace].maxNum
    }
}, (dispatch) => { // dispatch的作用:可以调用model层定义的函数
    return { // 将返回的函数,绑定到this.props中
        add : function () {
            dispatch({ //通过dispatch调用modle中定义的函数,通过type属性,指定函数命名,格式:namespace/函数名
                type : namespace + "/addNewData"
            });
        },
        init : () => {
            dispatch({ //通过dispatch调用modle中定义的函数,通过type属性,指定函数命名,格式:namespace/函数名
                type : namespace + "/initData"
            });
        }
    }
})
class  List extends React.Component{

    componentDidMount(){
        //初始化的操作
        this.props.init();
    }

    render(){
        return (
            
    { this.props.dataList.map((value,index)=>{ return
  • {value}
  • }) }
); } } export default List;

React前后端分离实战租房项目一_第57张图片

(04.ReactJS入门之dva的使用(实现点击事件)&)

04.ReactJS入门之dva的使用(实现点击事件)&

(05.ReactJS入门之Model中请求数据&)

05.ReactJS入门之Model中请求数据&

request.js

// import fetch from 'dva/fetch';

function checkStatus(response) {
    if (response.status >= 200 && response.status < 300) {
        return response;
    }

    const error = new Error(response.statusText);
    error.response = response;
    throw error;
}

/**
 * Requests a URL, returning a promise.
 *
 * @param  {string} url       The URL we want to request
 * @param  {object} [options] The options we want to pass to "fetch"
 * @return {object}           An object containing either "data" or "err"
 */
export default async function request(url, options) {
    const response = await fetch(url, options);
    checkStatus(response);
    return await response.json();
}

(06.ReactJS入门之mock数据&)

06.ReactJS入门之mock数据&

MockListData.js mock数据

React前后端分离实战租房项目一_第58张图片

export default {
    'get /ds/list': function (req, res) { //模拟请求返回数据
        res.json({
            data: [1, 2, 3, 4, 5],
            maxNum: 5
        });
    },
    'get /ds/user/list': function (req, res) {
        res.json([{
            key: '1',
            name: '张三1',
            age: 32,
            address: '上海市',
            tags: ['程序员', '帅气'],
        }, {
            key: '2',
            name: '李四2',
            age: 42,
            address: '北京市',
            tags: ['屌丝'],
        }, {
            key: '3',
            name: '王五3',
            age: 32,
            address: '杭州市',
            tags: ['高富帅', '富二代'],
        }]);
    }
}

(07.Ant Design入门之介绍&)

07.Ant Design入门之介绍&

(08.Ant Design入门之开始使用&)

08.Ant Design入门之开始使用&

MyTabs.js  tab组件

import React from 'react';
import { Tabs } from 'antd'; // 第一步,导入需要使用的组件

const TabPane = Tabs.TabPane;

function callback(key) {
    console.log(key);
}

class MyTabs extends React.Component{

    render(){
        return (
            
                hello antd wo de 第一个 tabs
                Content of Tab Pane 2
                Content of Tab Pane 3
            
        )
    }

}

export default MyTabs;

(09.Ant Design入门之布局&)

09.Ant Design入门之布局&

布局layout

React前后端分离实战租房项目一_第59张图片

src\layouts\index.js

React前后端分离实战租房项目一_第60张图片

React前后端分离实战租房项目一_第61张图片

导航栏 菜单链接

import React from 'react';
import { Layout, Menu, Icon } from 'antd';
import Link from 'umi/link';

const { Header, Footer, Sider, Content } = Layout;
const SubMenu = Menu.SubMenu;

class BasicLayout extends React.Component{

    constructor(props){
        super(props);
        this.state = {
            collapsed: false,
        }
    }

    render(){
        return (
            
                
                    
用户管理}> 新增用户 新增列表
Header
{this.props.children}
后台系统 ©2018 Created by 黑马程序员
) } } export default BasicLayout;

React前后端分离实战租房项目一_第62张图片

 

umi路由配置

React前后端分离实战租房项目一_第63张图片

React前后端分离实战租房项目一_第64张图片

props.children

React前后端分离实战租房项目一_第65张图片

React前后端分离实战租房项目一_第66张图片

(10.Ant Design入门之美化布局和引入导航条&)

10.Ant Design入门之美化布局和引入导航条&

(11.Ant Design入门之导航菜单添加链接&)

11.Ant Design入门之导航菜单添加链接&

src\pages\user\UserList.js

import React from 'react';
import { connect } from 'dva';

import {Table, Divider, Tag, Pagination } from 'antd';

const {Column} = Table;

const namespace = 'userList';

@connect((state)=>{
    return {
        data : state[namespace].list
    }
}, (dispatch) => {
    return {
        initData : () => {
            dispatch({
                type: namespace + "/initData"
            });
        }
    }
})
class UserList extends React.Component {

    componentDidMount(){
        this.props.initData();
    }

    render() {
        return (
            
( {tags.map(tag => {tag})} )} /> ( 编辑 删除 )} />
); } } export default UserList;

src\pages\user\UserAdd.js

import React from 'react'

class UserAdd extends React.Component{

    render(){
        return (
            
新增用户
); } } export default UserAdd;

 

 

(12.Ant Design入门之表格的基本使用&)

12.Ant Design入门之表格的基本使用&

(13.Ant Design入门之表格的数据分离&)

13.Ant Design入门之表格的数据分离&

 

 

day03-项目介绍以及开发后台系统

(07.后台系统开发之form表单组件以及表单提交的讲解&)

07.后台系统开发之form表单组件以及表单提交的讲解&

React前后端分离实战租房项目一_第67张图片

React前后端分离实战租房项目一_第68张图片

React前后端分离实战租房项目一_第69张图片

form方法

React前后端分离实战租房项目一_第70张图片

React前后端分离实战租房项目一_第71张图片

表单校验

React前后端分离实战租房项目一_第72张图片

AddResource.js getFieldDecorator双向数据绑定,提交表单,class内部this,提交表单多选项,input组件设置

import React, { PureComponent } from 'react';
import { connect } from 'dva';
import { formatMessage, FormattedMessage } from 'umi/locale';
import {
    Form,
    Input,
    DatePicker,
    Select,
    Button,
    Card,
    InputNumber,
    Radio,
    Icon,
    Tooltip,
    Checkbox,
    AutoComplete
} from 'antd';
import PageHeaderWrapper from '@/components/PageHeaderWrapper';
import PicturesWall from '../Utils/PicturesWall';

const FormItem = Form.Item;
const { Option } = Select;
const { RangePicker } = DatePicker;
const { TextArea } = Input;
const Search = Input.Search;
const InputGroup = Input.Group;
const CheckboxGroup = Checkbox.Group;

const estateMap = new Map([
  ['中远两湾城','1001|上海市,上海市,普陀区,远景路97弄'],
  ['上海康城','1002|上海市,上海市,闵行区,莘松路958弄'],
  ['保利西子湾','1003|上海市,上海市,松江区,广富林路1188弄'],
  ['万科城市花园','1004|上海市,上海市,闵行区,七莘路3333弄2区-15区'],
  ['上海阳城','1005|上海市,上海市,闵行区,罗锦路888弄']
]);


@connect(({ loading }) => ({
    submitting: loading.effects['form/submitRegularForm'],
}))
@Form.create()
class AddResource extends PureComponent {
    handleSubmit = e => {
        const { dispatch, form } = this.props;
        e.preventDefault();
      console.log(this.state.fileList);
        form.validateFieldsAndScroll((err, values) => {
            if (!err) {

              if(values.facilities){
                values.facilities = values.facilities.join(",");
              }
              if(values.floor_1 && values.floor_2){
                values.floor = values.floor_1 + "/" + values.floor_2;

              }

              values.houseType = values.houseType_1 + "室" + values.houseType_2 + "厅"
                                 + values.houseType_3 + "卫" + values.houseType_4 + "厨"
                                 + values.houseType_2 + "阳台";
              delete values.floor_1;
              delete values.floor_2;
              delete values.houseType_1;
              delete values.houseType_2;
              delete values.houseType_3;
              delete values.houseType_4;
              delete values.houseType_5;



              dispatch({
                    type: 'form/submitRegularForm',
                    payload: values,
                });
            }
        });
    };

    handleSearch = (value)=>{
      let arr = new Array();
      if(value.length > 0 ){
        estateMap.forEach((v, k) => {
          if(k.startsWith(value)){
            arr.push(k);
          }
        });
      }
      this.setState({
        estateDataSource: arr
      });
    } ;

  handleFileList = (obj)=>{
    console.log(obj, "图片列表");
  }


  constructor(props){
      super(props);
      this.state = {
        estateDataSource : [],
        estateAddress : '',
        estateId : ''
      }
    }

    render() {
        const { submitting } = this.props;
        const {
            form: { getFieldDecorator, getFieldValue },
        } = this.props;

        const formItemLayout = {
            labelCol: {
                xs: { span: 24 },
                sm: { span: 7 },
            },
            wrapperCol: {
                xs: { span: 24 },
                sm: { span: 12 },
                md: { span: 10 },
            },
        };

        const submitFormLayout = {
            wrapperCol: {
                xs: { span: 24, offset: 0 },
                sm: { span: 10, offset: 7 },
            },
        };



        return (
            
                
{ let v = estateMap.get(value); this.setState({ estateAddress: v.substring(v.indexOf('|')+1), estateId : v.substring(0,v.indexOf('|')) }); }} onSearch={this.handleSearch} filterOption={(inputValue, option) => option.props.children.toUpperCase().indexOf(inputValue.toUpperCase()) !== -1} /> } value={this.state.estateAddress} defaultValue={this.state.estateAddress} readOnly/> {getFieldDecorator('buildingNum',{rules:[{ required: true, message:"此项为必填项" }]})()} {getFieldDecorator('buildingUnit',{rules:[{ required: true, message:"此项为必填项" }]})()} {getFieldDecorator('buildingFloorNum',{rules:[{ required: true, message:"此项为必填项" }]})()} {getFieldDecorator('rent',{rules:[{ required: true, message:"此项为必填项" }]})()} {getFieldDecorator('paymentMethod',{initialValue:'1',rules:[{ required: true, message:"此项为必填项" }]}) ( )} {getFieldDecorator('rentMethod',{initialValue:'1',rules:[{ required: true, message:"此项为必填项" }]}) ( )} {getFieldDecorator('houseType_1',{rules:[{ required: true, message:"此项为必填项" }]})()} {getFieldDecorator('houseType_2',{rules:[{ required: true, message:"此项为必填项" }]})()} {getFieldDecorator('houseType_3',{rules:[{ required: true, message:"此项为必填项" }]})()} {getFieldDecorator('houseType_4',{rules:[{ required: true, message:"此项为必填项" }]})()} {getFieldDecorator('houseType_5',{rules:[{ required: true, message:"此项为必填项" }]})()} {getFieldDecorator('coveredArea',{rules:[{ required: true, message:"此项为必填项" }]})()} {getFieldDecorator('useArea',{rules:[{ required: true, message:"此项为必填项" }]})()} {getFieldDecorator('floor_1',{rules:[{ required: true, message:"此项为必填项" }]})()} {getFieldDecorator('floor_2',{rules:[{ required: true, message:"此项为必填项" }]})()} {getFieldDecorator('orientation',{initialValue:'南',rules:[{ required: true, message:"此项为必填项" }]}) ( )} {getFieldDecorator('decoration',{initialValue:'1',rules:[{ required: true, message:"此项为必填项" }]}) ( )} {getFieldDecorator('facilities',{initialValue:['1','2','3'],rules:[{ required: true, message:"此项为必填项" }]}) ( )} {getFieldDecorator('desc') (