Redux-form嵌套到实际项目开发案例八

11 篇文章 0 订阅
10 篇文章 1 订阅

初始化数据

|demo
|----webpack.config.js
|----package.json
|----index.html //引入了bootstrap.css
|----node_modules  //存放工具包
|----src  
|--------index.js //入口文件
|--------action
|------------index.js
|--------components
|------------InitializeFromStateForm.js
|------------style.css
|--------containers
|------------InitializeFromStateFormConnect.js
|--------reducers
|------------test1.js
|------------index.js

一、src/action/index.js文件代码

'use strict';
export const LOAD = 'LOAD';
export const SHOW = 'SHOW';

export function load(data) {
    return {type: LOAD,data}
}
export function foo(arg) {
    console.log('arg',arg);
    alert(JSON.stringify(arg));
    return{type: SHOW, arg}
}

二、src/components/InitializeFromStateForm.js文件代码

'use strict';
import React, {Component} from 'react'
import {Field, reduxForm} from 'redux-form'
//引入样式
import style from './style.css';
//定义一个同步校验的方法
const validate = value => {
    const errors = {};
    if (!value.firstName) {
        errors.firstName = '必填字段';
    } else if (value.firstName.length < 2 || value.firstName.length > 10) {
        errors.firstName = '长度在2-10个字符之间';
    }
    //最后一个名字校验
    if(!value.lastName){
        errors.lastName = '必填字段';
    }else if(value.lastName.length < 2 || value.lastName.length > 10){
        errors.lastName = '长度在2-10个字符之间';
    }
    //年龄校验
    if(!value.age){
        errors.age = '必填字段';
    }else if(isNaN(Number(value.age))){
        errors.age = '年龄必须是数字';
    }else if(value.age < 18){
        errors.age = '你还没成年';
    }
    //校验文本框
    if(!value.describe){
        errors.describe = '必填字段';
    }else if(value.describe.length > 50){
        errors.describe ='长度不能超过50个字符'
    }
    //下拉框校验
    if(!value.favoriteColor){
        errors.favoriteColor = '请选择颜色';
    }
    return errors;
}
//定义一个输入框的组件
class renderField extends Component {
    render() {
        let {input, label, name, type, placeholder, meta: {touched, error, warning}} = this.props;
        return (
            <div className="form-group">
                <label>{label}</label>
                <div className={style.inputGroup}>
                    <input {...input} name={name} type={type}
                           className={"form-control" + (touched ? (error || warning ? ' borderred' : '') : '')}
                           placeholder={placeholder}/>
                    {
                        touched && ((error && <span className="text-danger">{error}</span>) || (warning &&
                        <span className="text-danger">{warning}</span>))
                    }
                </div>
            </div>
        )
    }
}
// //定义一个单选框的组件
// class radioField extends Component{
//     render(){
//         //注意如果是单选按钮写name取值不到
//         let {input, label, name1,val,meta: {touched, error, warning}} = this.props;
//         return(
//             <label className="checkbox-inline">
//                 <input {...input} name={name1} type="radio" value={val}/>&nbsp;&nbsp;{label}
//             </label>
//         )
//     }
// }
//定义一个多行文本框
class renderTextarea extends Component{
    render(){
        let {input, label, name1,placeholder, meta: {touched, error, warning}} = this.props;
        return(
            <div className="form-group">
                <label>{label}</label>
                <div>
                    <textarea {...input} name={name1} placeholder={placeholder} className="form-control" style={{resize: 'none'}}></textarea>
                    {touched && ((error && <span className="text-danger">{error}</span>) || (warning &&
                    <span className="text-danger">{warning}</span>))}
                </div>
            </div>
        )
    }
}
//定义一个下拉框组件
class renderSlect extends Component{
    render(){
        let {input,name, label, dataSet, meta: {touched, error, warning}} = this.props;
        return(
            <div className="form-group">
                <label>{label}</label>
                <div>
                    <select className="form-control" name={name} {...input}>
                        <option value="">--请选择颜色--</option>
                        {dataSet.map(colorOption =>
                            <option value={colorOption} key={colorOption}>{colorOption}</option>)}
                    </select>
                    {touched && ((error && <span className="text-danger">{error}</span>) || (warning &&
                    <span className="text-danger">{warning}</span>))}
                </div>
            </div>
        )
    }
}
class InitializeFromStateForm extends Component {
    constructor(props){
        super(props);
        this.state = {}
    }
    componentWillMount(){
        const data = {
            firstName: '李四',
            lastName: '王五',
            age: '42',
            sex: '男',
            employed: true,
            favoriteColor: 'Blue',
            describe: '就一句话简单介绍完毕'
        };
        const colors = ['Red', 'Orange', 'Yellow', 'Green', 'Blue', 'Indigo', 'Violet'];
        this.setState({'data':data,'colors':colors});
    }
    render() {
        const {handleSubmit, foo, load, pristine, reset, submitting} = this.props;
        let {data,colors} = this.state;
        return (
            <div className="container">
                <div className="col-md-6">
                    <form onSubmit={handleSubmit(val => foo(val))} role="form">
                        <div className="form-group">
                            <button type="button" onClick={() => load(data)} className="btn btn-success">填充数据</button>
                        </div>
                        <Field label="第一名称" name="firstName" component={renderField} type="text"
                               placeholder="输入第一名称"/>
                        <Field label="最后名称" name="lastName" component={renderField} type="text" placeholder="输入最后名称"/>
                        <Field label="年龄" name="age" component={renderField} type="number" placeholder="请输入年龄"/>
                        <div className="form-group">
                            <label>性别</label>
                            <div className="checkbox">
                                <label className="checkbox-inline">
                                    <Field name="sex" component="input" type="radio" value="男"/> 男
                                </label>
                                <label className="checkbox-inline">
                                    <Field name="sex" component="input" type="radio" value="女"/> 女
                                </label>
                            </div>
                        </div>

                        {/*下拉框*/}
                        <Field name="favoriteColor" component={renderSlect} label="请选择颜色" dataSet={colors}/>
                        <div className="form-group">
                            <label htmlFor="employed">是否聘用</label>
                            <div>
                                <Field name="employed" id="employed" component="input" type="checkbox"/>
                            </div>
                        </div>
                        {/*多行文本框*/}
                        <Field name="describe" name1="describe" label="描述" component={renderTextarea}/>
                        <div className="form-group">
                            <button type="submit" disabled={pristine || submitting} className="btn btn-success"
                                    style={{marginRight: '20px'}}>提交
                            </button>
                            <button type="button" disabled={pristine || submitting} onClick={reset}
                                    className="btn btn-success">重置
                            </button>
                        </div>
                    </form>
                </div>
            </div>
        )
    }
}
InitializeFromStateForm.propTypes = {
    foo: React.PropTypes.func,
    load: React.PropTypes.func
}
export default InitializeFromStateForm = reduxForm({
    form: 'initializeFromState',
    validate
})(InitializeFromStateForm)

三、src/containers/InitializeFromStateFormConnect.js代码

use strict';
import { connect } from 'react-redux';
import InitializeFromStateForm from './../components/InitializeFromStateForm';

import * as ActionCreators from '../action';
export default connect(
    function (state) {
        console.info('state',state);
        return {
            initialValues: state.test1.data,
        }
    },
    ActionCreators
)(InitializeFromStateForm);

四、src/reducers/test1.js代码

'use strict';
import {LOAD} from './../action/index';
export default function test1(state = {}, action){
    switch (action.type) {
        case LOAD:
            return {
                data: Object.assign({},state,action.data)
            }
        default:
            return state
    }
}

五、src/reducers/index.js代码

'use strict';
import {combineReducers} from 'redux';
import { reducer as formReducer } from 'redux-form';
import test1 from './test1';

const rootReducer = combineReducers({
    test1,
    form: formReducer
});
export default rootReducer;

六、src/index.js代码

'use strict';
// 导入react的相关模块
import React from 'react';
import ReactDOM from 'react-dom';
// 导入redux的相关模块
import {createStore,applyMiddleware} from 'redux';
import thunk from 'redux-thunk';
import {Provider} from 'react-redux';
import InitializeFromStateFormConnect from './containers/InitializeFromStateFormConnect';
import counter from './reducers';

const store = createStore(counter, applyMiddleware(thunk));
ReactDOM.render(
    <Provider store={store}>
        <InitializeFromStateFormConnect />
    </Provider>,
    document.getElementById('app')
);

七、demo/package.json代码

{
  "name": "react-demo05",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "start": "webpack-dev-server --inline --host localhost --port 3000"
  },
  "author": "",
  "license": "ISC",
  "dependencies": {},
  "devDependencies": {
    "babel-core": "^6.23.1",
    "babel-loader": "^6.3.2",
    "babel-preset-es2015": "^6.22.0",
    "babel-preset-react": "^6.23.0",
    "css-loader": "^0.28.0",
    "react": "^15.4.2",
    "react-dom": "^15.4.2",
    "react-redux": "^5.0.3",
    "redux": "^3.6.0",
    "redux-form": "^6.6.1",
    "redux-thunk": "^2.2.0",
    "style-loader": "^0.16.1",
    "webpack": "^2.2.1",
    "webpack-dev-server": "^2.4.1"
  }
}

八、demo/index.html代码

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <link href="https://cdn.bootcss.com/bootstrap/4.0.0-alpha.6/css/bootstrap.css" rel="stylesheet">
    <style>
        .borderred{
            border:1px solid #ff0000;
        }
        .text-danger{
            position: absolute;
            left:0;
            top:35px;
            color: #ff0000!important;
        }
    </style>
</head>
<body>
<div id="app"></div>
</body>
<script src="./index.build.js"></script>
</html>

九、demo/webpack.config.js代码

'use strict';
module.exports = {
    entry:{
        index:'./src/index.js',
    },
    output:{
        path:__dirname,
        filename:'[name].build.js',
    },
    module:{
        loaders:[
            {
                test:/\.(js|jsx)$/,
                exclude:'/node_modules/',
                loader:'babel-loader',
                query:{
                    presets:['es2015','react']
                }
            },
            {
                test: /\.css$/,
                loaders: ['style-loader','css-loader?modules']
            }
        ]
    },
    resolve:{
        extensions:['.js',".css",".jsx"]
    }
}

十、src/components/style.css代码

@charset "utf-8";
/*仅仅是使用cssModule,也可以不这样使用*/
.inputGroup{
    position: relative;
}

十一、运行效果

运行效果

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

水痕01

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值