作者:freewind
比原项目仓库:
Github地址:https://github.com/Bytom/bytom
Gitee地址:https://gitee.com/BytomBlockchain/bytom
在前面一篇文章,我们粗略的研究了一下比原的dashboard是如何做出来的,但是对里面提到的各种细节功能,并没有深入的去研究。那么从本文开始,我们将在这一段时间,分别研究里面提到的每一项功能。
在前一篇文章中,当我们第一次在浏览器中打开dashboard时,因为还没有创建过密钥,所以比原会提示我们输入一些别名和密码,为我们创建一个密钥和相应的帐户。就是下面这张图所对应的:
那么本文就将研究一下,当我们点击了"Register"按钮以后,我们在前端页面上填写的参数,到底是如何一步步的传到比原的后端的。
跟之前一样,我们将对这个问题进行细分,然后各个击破:
- 前端:当我们填完表单,点了提交以后,比原在前端是如何发送数据的?
- 后端:比原的后端是如何接收到数据的?
前端:当我们填完表单,点了提交以后,数据会发送到后端的哪个接口?
当我们点击了"Register"按钮,在前端页面中,一定会在某个地方触发一个向比原节点webapi接口发出请求的操作。究竟是访问的哪个web api?提交的数据又是什么样的呢?让我们先从前端代码中寻找一下。
注意,比原的前端代码位于另一个项目仓库bytom/dashboard中。为了能与我们在本系列文章中使用的比原v1.0.1的代码相匹配,我找到了dashboard中的v1.0.0的代码,并且提交到了一个单独的项目中:freewind/bytom-dashboard-v1.0.0。注意该项目代码未做任何修改,其master
分支对应于官方代码仓库的v1.0.0
分支。之所以要弄一个单独的出来,这是因为我们在文章中,每次引用一段代码的时候,都会给出相应的github上的链接,方便读者跳过去查看全貌,使用一个独立项目,会让这个过程更简便一些。
由于比原的前端页面是使用React
为主的,所以我猜想在代码中,也该会有一个名为Register的组件,或者某个表单中有一个名为Register的按钮。经过搜索,我们幸运的发现了Register.jsx 这个组件文件,它正好是我们需要的。
经过高度简化后的代码如下:
src/features/app/components/Register/Register.jsx#L9-L148
class Register extends React.Component { // ... // 4. submitWithErrors(data) { return new Promise((resolve, reject) => { // 5. this.props.registerKey(data) .catch((err) => reject({_error: err.message})) }) } // ... render() { // ... return ( // ... // 3. <form className={styles.form} onSubmit={handleSubmit(this.submitWithErrors)}> // 1. <TextField title={lang === 'zh' ? '账户别名' : 'Account Alias'} placeholder={lang === 'zh' ? '请输入账户别名...' : 'Please enter the account alias...'} fieldProps={accountAlias} /> <TextField title={lang === 'zh' ? '密钥别名' : 'Key Alias'} placeholder={lang === 'zh' ? '请输入密钥别名...' : 'Please enter the key alias...'} fieldProps={keyAlias}/> <TextField title={lang === 'zh' ? '密钥密码' : 'Key Password'} placeholder={lang === 'zh' ? '请输入密钥密码...' : 'Please enter the key password...'} fieldProps={password} type='password'/> <TextField title={lang === 'zh' ? '重复输入密钥密码' : 'Repeat your key password'} placeholder={lang === 'zh' ? '请重复输入密钥密码...' : 'Please repeat the key password...'} fieldProps={repeatPassword} type='password'/> // 2. <button type='submit' className='btn btn-primary' disabled={submitting}> {lang === 'zh' ? '注册' : 'Register'} </button> // .... </form> // ... ) } }
上面的代码,共有5个地方需要注意,被我用数字标示出来了。注意这5个数字并不是从上到下标注,而是按照我们关注的顺序来的:
- 表单上的各个输入框,就是我们填写别名和密码的地方。这里需要关注的是每个
TextField
的fieldProps
属性,它对应我们提交到后台的数据的name
- 就是那个“Register”按钮了。需要注意的是,它的
type
是submit
,也就是说,点击它以后,将会触发所在form
的onSubmit
方法 - 回到了
form
的开头。注意它的onSubmit
里面,调用的是handleSubmit(this.submitWithErrors)
。其中的handleSubmit
是从该表单所使用的第三方redux-form中传入的,用来处理表单提交,我们在这里不关注它,只需要知道我们需要把自己的处理函数this.submitWithErrors
传给它。而在后者中,我们将会调用比原节点提供的web api - 第3步中的
this.submitWithErrors
最终将走到这里定义的submitWithErrors
函数 submitWithErrors
将会发起一个异步请求,最终调用由外部传进来的registerKey
函数
从这里我们还看不到调用的是哪个api,所以我们必须继续去寻找registerKey
。很快就在同文件中找到了registerKey
:
src/features/app/components/Register/Register.jsx#L176-L180
(dispatch) => ({ registerKey: (token) => dispatch(actions.core.registerKey(token)), // ... })
它又将会调用actions.core.registerKey
这个函数: