Ant-Design-Pro 基础问题[第四天]

2018/05/30 yield

其中是我在QQ群 362329545遇到的 问题,整理成问答录,希望能解决入门的烦恼,个人见解,如果有那里有错误请指出了我会积极改进,方便他人。

问答录[3问]

在Form如何进行编辑以及新增数据。

  • 开始这个演示,注意注释描述,代码不一定能运行,只是整体做个介绍

        const CreateForm = Form.create()(props => {
        const {modalVisible, form, handleAdd, handleEdit, handleModalVisible, formData, formType} = props;  /** 传入的可变变量 **/
        const okHandle = () => {
            form.validateFields((err, fieldsValue) => {
            if (err) return;
            form.resetFields();
            if (formType === 0) handleAdd(fieldsValue); /**判断类型进行展示数据,以及新增*/
            if (formType === 1) handleEdit(fieldsValue);
            });
        };
        return (
            <Modal
            title="微信配置"
            visible={modalVisible}
    
            onOk={okHandle} //修改和新增主要看这里  
    
            onCancel={() => handleModalVisible()}
            >
            //初始化数据 formData
    
            <FormItem labelCol= wrapperCol= label="公钥">
                {form.getFieldDecorator('public_key', {
                initialValue: Object.keys(formData || {}).length ? formData.public_key : '',
                rules: [{required: true, message: 'Please input  public_key...'}],
                })(<Input placeholder="请输入"/>)}
            </FormItem>
    
            /**这里定义的是 select 的数据以及修改的时候数据的加载 可以保证数据正常显示。**/
            /**目前存在一些疑惑,为什么通过formData 直接绑定,在修改的时候展示的是key 不是 value 通过外部传递就可以。**/
            <FormItem labelCol= wrapperCol= label="应用类型">
                {form.getFieldDecorator('channel_way', {
                initialValue: Object.keys(formData || {}).length ? formData.channel_way : '',
                })(
                <Select placeholder="不限" style=>
                    {channelWayData.map(item => (
                    <Option key={item.id} value={item.id}>
                        {item.desc}
                    </Option>
                    ))}
                </Select>
                )}
            </FormItem>
            </Modal>
        );
        });
    
          handleEdit = fields => {
                message.success(JSON.stringify(fields))
                const {paymentConfigId} = this.state;
                const {dispatch} = this.props;
                fields.channel_id = paymentConfigId;
                dispatch({
                type: 'parkingPayManager/modifyChannel',
                payload: JSON.stringify(fields),
                callback: () => {
                    dispatch({
                    type: 'parkingPayManager/queryChannelList',
                    callback: (e) => {
                        message.success("修改成功,列表已经刷新!")
                    },
                    })
                    this.setState({
                    modalVisible: false, // 清除
                    });
                },
                })
            }
    
            handleAdd = fields => {
                const {dispatch} = this.props;
                /**switchPress true = 0, fasle = 1 方便数据存储*/ 
                fields.channel_status = this.switchPress(fields.channel_status);
                /**触发action触发model层的state的初始化*/
                dispatch({
                type: 'parkingPayManager/insertChannel',
                payload: JSON.stringify(fields),
                callback: () => {
                    dispatch({
                    type: 'parkingPayManager/queryChannelList',
                    callback: (e) => {
                        message.success('successfully ');
                    },
                    })
                        this.setState({
                            modalVisible: false,
                        });
                    },
                });
            };
        /**传递数据*/
        state = {
            paymentTypeData: [
            {
                id: 1,
                desc: "支付宝",
            }
            ,
            {
                id: 0,
                desc: "微信",
            }
            ,
            ],
            channelWayData: [
            {
                id: 0,
                desc: "小程序,公众号",
            }, {
                id: 1,
                desc: "APP",
            },
            ],
            selectedRows: [],
            formType: 0, /** 0 add  1 edit 定义Form的弹出的模式  **/
            formData: {},
        }
        /**
        * @param  {state:Object} ... 里面多个参数 
        *
        */
        const {isLoading,...[省略]} = this.state;
    
        const parentMethods = {
            handleAdd: this.handleAdd,
            handleModalVisible: this.handleModalVisible,
            optionChildrenDataTemp: optionChildrenData,
            formData: formData,
            formType: formType,
    
            handleEdit: this.handleEdit,
            channelWayData: channelWayData,
            paymentTypeData: paymentTypeData,
        };
    
    
         /**
         * 组件参数配置(render => (这里面定义的组件))
         * @param {array}  parentMethods 是我们传递的参数组[多个]
         *
         * @param {boolean}  modalVisible 模态框 弹出还暗示隐藏的状态
         */
         <CreateForm {...parentMethods} modalVisible={modalVisible}/>
    
         /** models 里面的方法 */
         /**
         *@param {Object} payload 是我们提交的参数,或者是用来修改数据等。
         *@param {function} callback 执行成功的回调可以将参数 call回去。
         **/
         effects: {
            * insertChannelCfg({payload, callback}, {call, put}) {
                const response = yield call(insertParkManagerChannelCfg, payload);
                console.log("result Data  successfully");
                console.log(response);
                yield put({
                    type: 'updateStateInsertChannelCfg',
                    payload: response.data,
                    /**
                    *  (response.success) ? response.data : [], 也可以这样去写
                    */
                });
                if (response.success) {
                    callback();
                    /*
                    * callback(response);
                    * 可以将参数携带回去,也可以不携带,具体看下需求
                    **/
                    }
                },
         }
        /**
        *@param {reducers} 通过reducers -> updateStateInsertChannelCfg 将数据传递回去
        **/
        reducers:{
            updateStateInsertChannelCfg(state, action) {
            return {
                ...state,
                InsertChannelCfgNum: action.payload,
                /** InsertChannelCfgNum 记得在 state 里面注册 否则会出现undef */
            }
            },
         }
    
         /***
         * 解答一下 `namespace: 'parkingPayManager'`
         *  我们在dispatch 里面通过type 调用的 是先通过 namespace 再去找到具体的(effects)内的执行器。
         *
         **/
    
        /** services [用来发送请求,并且将数据携带回去] **/
    
        /**
        *@param {JSON} params 我们传递的参数,
        *@func  request 是自己封装的一个请求的方法。
        **/
        export async function insertParkManagerChannelCfg(params) {
            return request('/proxy-post/insertChannelCfg', {
                method: 'POST', data: params || {},
            })
        }
    

Ant StandardTable 数据格式

  • 开始演示

    
         /**
         * 我们通过 model获得的数据将如何渲染出去是个问题,StandardTable是一个 ant封装的组件,如果你要用他的组件就要满足他的数据格式
         **/
             const {parkingPayManager: {channelData}} = this.props;
                 const newdata = {
                 list: channelData,
                 pagination: {
                     total: channelData.length,
                     pageSize: 10,
                     current: 1,
                 },
             };
    
             ...
    
                 <StandardTable
                 selectedRows={selectedRows}
                 loading={isLoading}
                 data={newdata}
                 columns={columns}
                 />
    

按钮onClick,渲染触发。

  • 按钮定义

          /**
          * ()=>this.ModifyHandleModalVisible(row,true) 用匿名函数的方式定义不会再加载的时候被触发
          *
          * this.ModifyHandleModalVisible(row,true)  这样会直接被触发(渲染周期开始)。
          **/
          <Button type="edit" onClick={()=>this.ModifyHandleModalVisible(row,true)}>
                  修改
          </Button>
    

    dispatch type payload 获得数据的流程(Redux)

  • 第一个问题什么是 Store , Store主要功能

    1. Store需要负责接收Views传来的Action 然后,根据Action.type和Action.payload对Store里的数据进行修改 最后,

    2. Store还需要通知Views,数据有改变,Views便去获取最新的Store数据,通过setState进行重新渲染组件(re-render

  • Store如何接收来自Views的Action?
    1. 每一个Store实例都拥有dispatch方法,Views只需要通过调用该方法,并传入action对象作为形参,Store自然就就可以收到Action,就像这样:
            store.dispatch({
        type: 'modal(namespace)/function Name'
      });
      
  • Store在接收到Action之后,需要根据Action.type和Action.payload修改存储数据,那么,这部分逻辑写在哪里,且怎么将这部分逻辑传递给Store知道呢?
    1. 数据修改逻辑写在Reducer(一个纯函数)里,Store实例在创建的时候,就会被传递这样一个reducer作为形参,这样Store就可以通过Reducer的返回值更新内部数据了,先看一个简单的例子(具体的关于reducer我们后面再讲):
       // 一个reducer
       function counterReducer(state = 0, action) {
       switch (action.type) {
           case 'INCREASE':
           return state + 1;
           case 'DECREASE':
           return state - 1;
           default:
           return state;
       }
       }
      
       // 传递reducer作为形参
       let store = Redux.createStore(counterReducer);
      
  • Store通过Reducer修改好了内部数据之后,又是如何通知Views需要获取最新的Store数据来更新的呢?
    1. 每一个Store实例都提供一个subscribe方法,Views只需要调用该方法注册一个回调(内含setState操作),之后在每次dispatch(action)时,该回调都会被触发,从而实现重新渲染;对于最新的Store数据,可以通过Store实例提供的另一个方法getState来获取,就像下面这样:
      let unsubscribe = store.subscribe(() =>
          console.log(store.getState())
      );
      //如下
    
      function createStore(reducer, initialState, enhancer) {
          var currentReducer = reducer
          var currentState = initialState
          var listeners = []
    
          // 省略若干代码
          //...
    
          // 通过reducer初始化数据
          dispatch({ type: ActionTypes.INIT })
    
          return {
              dispatch,
              subscribe,
              getState,
              replaceReducer
          }
      }
    
  • 归纳总结

    1. Store的数据修改,本质上是通过Reducer来完成的。
    2. Store只提供get方法(即getState),不提供set方法,所以数据的修改一定是通过dispatch(action)来完成,即:action -> reducers -> store
    3. Store除了存储数据之外,还有着消息发布/订阅(pub/sub)的功能,也正是因为这个功能,它才能够同时连接着Actions和Views。

      3.1 dispatch方法 对应着 pub

      3.1 subscribe方法 对应着 sub

Ant Redux 页面传递参数,多种方式

  • path 携带参数 props.params

      /**传递*/
      import { Router,Route,hashHistory} from 'react-router';
      class App extends React.Component {
          render() {
          ...
          /**使用方式*/
          var data = {id:1,name:1,age:1};
          data = JSON.stringify(data);
          var path = `/user/${data}`;
          ...
          return (
              <Router history={hashHistory}>
                  <Route path='/user/:name' component={UserPage}></Route>
              </Router>
          )
          }
      }
      /**接收**/
    
      export default class UserPage extends React.Component{
          constructor(props){
              super(props);
          }
          render(){
              return(<div>this.props.params.name</div>)
          }
      }
    
  • query 类似requestget

        <Route path='/user' component={UserPage}></Route>
    
       ...
       /**使用方式**/
       var data = {id:1,name:1,age:1};
        var path = {
        pathname:'/user',
        query:data,
        }
       ...
        /**获取数据**/
        var data = this.props.location.query;
        var {id,name,age} = data;
    
  • state方式类似于post方式,使用方式和query类似,首先定义路由:

         <Route path='/user' component={UserPage}></Route>
         ...
         /**使用*/
         var data = {id:3,name:sam,age:36};
         var path = {
             pathname:'/user',
             state:data,
         }
         ...
         /**获取数据*/
         var data = this.props.location.state;
         var {id,name,age} = data;
    
  • state方式依然可以传递任意类型的数据,而且可以不以明文方式传输.

转载请注明出处,本文采用 CC4.0 协议授权

Affiliate

Search

    Post Directory