DataBinder 数据交互方案

如果项目中使用的是 1.x 版本的基础组件(@alifd/next),请在左侧导航顶部切换组件版本。

安装方法

  1. 在命令行中执行以下命令npm install @icedesign/data-binder@0.1.11 -S

ICE 前后端数据绑定、交互方案。

介绍和使用方法

目标

灵感来源于 Webx,基于一定的约定帮你在组件上绑定一些数据和用来更新数据的 API,让你专注于 render 方法中界面显示逻辑,从而屏蔽掉 AJAX、state 管理等开发成本。

如果你希望你的接口更自由,或者你希望自行把数据维护在组件 state 内,则都不推荐使用本方案。

15 分钟快速上手教程

15 分钟视频演示快速对比 Data-Binder 与 AJAX 方案对比,详细文档在下面。

点击这里查看视频

使用方法

1. 在某个 Class 上面配置当前需要的 DataSource

DataBinder 采用 decorator(类似 Java 注解)的方式使用,即在 class 上面调用并配置相关信息即可生效。

DataSource 是 ICE DataBinder 解决方案中最重要的概念,组件、页面中某一块依赖数据的功能会被作为一个 DataSource 模块,用一个模块 Key 来区分,每一个数据模块可以配置多种数据获取方式以及默认数据等,然后注入到组件中被使用(详细的说明在下面)。比如我们最常见的通过 AJAX 获取、操作数据:

  1. @DataBinder({
  2. '模块名 key': {
  3. url: 'xxxx.json',
  4. method: 'post',
  5. // 请求附带的 request 参数,method post 下是 data 参数
  6. data: {
  7. page: 1
  8. },
  9. // AJAX 部分的参数完全继承自 axios ,参数请详见:https://github.com/axios/axios
  10. // 下面是请求会返回的默认数据
  11. defaultBindingData: {
  12. // ...字段需要与 xxxx.json 接口返回的字段一一对应
  13. }
  14. }
  15. })
  16. class ListView extends Component {
  17. ...
  18. }

例如:

  1. @DataBinder({
  2. account: {
  3. url: '/getAccountInfo.json',
  4. type: 'post',
  5. data: {
  6. uid: '123123'
  7. },
  8. defaultBindingData: {
  9. // 配置接口返回数据的字段的初次默认值
  10. userName: '',
  11. userAge: 0
  12. }
  13. }
  14. })
  15. class ListView extends Component {
  16. ...
  17. }

详细的解释下:

  • 模块名 key 必填 用来将数据和接口约束在某一个范围下,通常按照接口数据划分或者按照功能区块。

  • url, type, data, etc. 选填 配置当前模块接口相关信息,基于 axios 支持其文档所有参数。该参数可选,部分模块可能无需 AJAX 交互,或者无法写死配置需要通过其他接口来获取。

  • defaultBindingData 选填 该字段配置当前模块数据初始化默认值,如果当前模块有异步接口配置,则模块的字段需要与接口返回的数据字段一一对应。该参数可选,因为有些接口只需要提交成功即可,无需 UI 变化。

2. 通过 this.props.bindingData.模块key 来获取绑定的数据

对某个 React class 添加 DataBinder 绑定配置之后,DataBinder 会在组件上添加一个 props bindingData 用来存放配置的所有数据,模块 key 为你对应的 DataSource key 的前部分,比如:配置 account 可以通过 this.props.bindingData.account 获取到被绑定的数据,第一次为 defaultBindingData 里面配置的数据。

因此你可以在你 render 部分的代码编写如下代码调用:

  1. @DataBinder({...})
  2. class ListView extends Component {
  3. render() {
  4. const { account } = this.props.bindingData;
  5. return (
  6. <div>
  7. <p>用户名:{account.userName}</p>
  8. <p>年龄:{account.userAge}</p>
  9. </div>
  10. );
  11. }
  12. }

3. 通过 this.props.updateBindingData 来更新模块数据

DataBinder 除了为组件添加一个 props 之外,还向组件内部注入一个 API 用来更新模块数据:

this.props.updateBindingData(key, params, callback); 第一个参数是模块 key ,字符串类型,用来标记更新哪一个 DataSource,需要保留全名(例如:account)。第二个参数是 DataSource 的配置,对象类型,调用时它会和默认定义的数据进行一个 merge 操作,并发起 AJAX 请求。通常你只需要传递 {data: {…}} 数据即可,data 用来描述对接口发请求时附加的参数。第三个参数是 callback,是一个函数,当请求结束之后调用,方便你处理额外逻辑。

注意:updateBindingData 里面传递的参数,跟顶部配置的初始化参数是一个 deepmerge 的合并操作。

比如一个翻页组件,当页码变化时获取新数据可以这样做:

  1. @DataBinder({
  2. accountTable: {
  3. url: '/getAccountTableList.json',
  4. type: 'post',
  5. data: {
  6. page: 1,
  7. pageSize: 10,
  8. },
  9. defaultBindingData: {
  10. page: 1,
  11. pageSize: 10,
  12. total: 0,
  13. lists: [],
  14. },
  15. },
  16. })
  17. class ListView extends Component {
  18. changePage = (pageNo) => {
  19. this.props.updateBindingData('accountTable', {
  20. data: {
  21. page: pageNo,
  22. },
  23. });
  24. };
  25. render() {
  26. const { accountTable } = this.props.bindingData;
  27. return (
  28. <div>
  29. 当前 Table 数据:{accountTable.lists}
  30. <Pagination
  31. current={accountTable.page}
  32. pageSize={accountTable.pageSize}
  33. total={accountTable.total}
  34. onChange={this.changePage}
  35. />
  36. </div>
  37. );
  38. }
  39. }

DataBinder 不会在组件初始化的时候帮你自动请求一次,因为有些 DataSource 不需要默认就请求一次。如果你需要在初始化的异步请求数据,就需要在合适的生命周期中主动调用该方法,比如组件即将渲染的时候拉取数据:

  1. @DataBinder({...})
  2. class ListView extends Component {
  3. componentDidMount() {
  4. // 拉取第一页的数据
  5. this.props.updateBindingData('accountTable', {
  6. data: {
  7. page: 1
  8. }
  9. });
  10. }
  11. }

4. 处理 Loading 逻辑和效果

AJAX 是异步的,为了更好的用户体验,推荐添加一个 Loading 效果组件来给用户请求中的反馈。

每一个 DataSource 模块的数据附带了一个私有属性 __loading 来标记当前模块是否正在请求过程中,这样你可以在组件 render 中读取这个数据来判断是否正在加载数据。比如 Table 组件内部封装了一个 Loading 的效果,需要使用 isLoading props 进行配置,那么就可以写:

  1. const { accountTable } = this.props.bindingData;
  2. <Table dataSource={accountTable.lists} isLoading={accountTable.__loading}>
  3. ...
  4. </Table>;

你也可以使用 Loading 组件进行 loading 效果的模拟,参照文档可以写出如下代码:

  1. import DataBinder from '@icedesign/data-binder';
  2. import { Loading } from '@icedesign/base';
  3. @DataBinder({
  4. account: {
  5. // 接口返回数据:{status: 'SUCCESS', data: {foo: 'bar'}}
  6. url: '/getdefaultBindingData.json',
  7. defaultBindingData: {
  8. foo: null,
  9. },
  10. },
  11. })
  12. class ListView extends Component {
  13. componentDidMount() {
  14. this.props.updateBindingData('account');
  15. }
  16. refresh = () => {
  17. this.props.updateBindingData('account');
  18. };
  19. render() {
  20. const { account } = this.props.bindingData;
  21. return (
  22. <div>
  23. <Loading
  24. state={account.__loading ? 'on' : 'off'}
  25. shape="fusion-reactor"
  26. >
  27. <div>当前 foo 的值为:{account.foo}</div>
  28. </Loading>
  29. <div style={{ marginTop: 20 }}>
  30. <Button onClick={this.refresh}>点击重新请求</Button>
  31. </div>
  32. </div>
  33. );
  34. }
  35. }

效果如图示:

DataBinder 数据交互方案 - 图1

此外,根模块也有一个 loading 属性(即:this.props.bindingData.loading),用来标记当前注册的所有模块中是否有某个模块在发送 AJAX 请求。这样可以便于进行全局的提示,比如一个 AJAX 请求全局提示标记等。

参数配置

DataBinder decorator 用法

调用方法:

  1. @DataBinder({
  2. 模块key: {
  3. url: 'xxx.json',
  4. //... AJAX axios 配置
  5. responseFormatter: (responseHandler, res, originResponse) => {
  6. // 做一些数据转换
  7. const newRes = {
  8. status: res.code !== 0 ? 'SUCCESS' : 'ERROR',
  9. message: res.successMsg,
  10. };
  11. // 回传给处理函数
  12. // 不做回传处理会导致数据更新逻辑中断
  13. responseHandler(newRes, originResponse);
  14. },
  15. defaultBindingData: {
  16. foo: 'bar',
  17. },
  18. },
  19. })
  20. class ListView extends React.Component {
  21. render() {
  22. const key = this.props.bindingData.key;
  23. return <div>{key.foo}</div>;
  24. }
  25. }
  • dataSouce 内容为符合 axios 的请求参数。

  • responseFormatter 用来做老接口数据转换用,老接口如果不按照现有模式需要进行一层数据转换处理。

  • defaultBindingData 内容为接口对应字段的默认数据,在 render 中使用 this.props.bindingData 获取。

接口 API

以下 API 会注入到 Class 中,通过 this.props.xxxx 的方式调用。

API 名说明是否有参数参数类型参数值备注
this.props.updateBindingData获取更新 DataSource 的数据truekey: string, params: object, callback: functionthis.props.updateBindingData('account', {data: {page: 5}})
this.props.getDataSource获取某个 DataSource 的默认配置truekey: string

后端接口协议

配置的 AJAX 接口需要按照一定的协议规则实现:

request:

业务接口自定。

response:

  1. {
  2. "status": "SUCCESS",
  3. "message":
  4. "接口请求完成的提示,可有可无,status 为非 SUCCESS 时会显示报错的 UI",
  5. "data": {
  6. "foo":
  7. "data 是具体的数据,需要与该接口定义的 defaultBindingData 字段结构保持一致"
  8. }
  9. }

自定义 requestClient

如果你的项目 ajax 模块进行了统一配置和通用处理的封装,或者使用 ws 或者其它的 RPC 手段进行网络通信,DataBinder 允许对请求客户端进行自定义。在 DataBinder 传递第二个参数对象,并指定 requestClient 为一个返回 promise 的请求函数。该 Promise resolve 的值为 response 对象,该 response 对象必须包含一个 data 字段,值为返回的数据。

DEMO

  1. import jsonp from 'jsonp';
  2. /**
  3. * 自定义的 json request client
  4. */
  5. function request(opts) {
  6. return new Promise((resolve, reject) => {
  7. jsonp(opts.url, { name: 'callback' }, (err, data) => {
  8. if (err) {
  9. reject(err);
  10. } else {
  11. resolve({ data });
  12. }
  13. })
  14. });
  15. }
  16. @DataBinder({
  17. account: {
  18. // 这里的所有字段会作为参数传递给 requestClient
  19. url: 'https://ice.alicdn.com/assets/mock/53141.jsonp.js',
  20. }
  21. }, { requestClient: request })
  22. export default class extends React.Component {
  23. // ...
  24. }

常见需求

发送数组类型数据,key 自动加了

当你传输的 data 中有个 key 数据(例如:items)为数组格式时,提交给后端 key 会自动添加 [](例如:items[]=xxx、items[]=yyy)。如果你不需要这种功能,希望使用原本的 key 进行提交,可以添加下面配置解决:

  1. {
  2. serializeArray: false;
  3. }

接口是老版本接口,不符合 DataBinder 接口协议如何处理?

配置 DataSource 时,添加 responseFormatter 配置进行数据处理,然后返回符合规范的数据。

自定义请求成功、失败的提示和逻辑

在 DataSource 配置部分自定义 success、error callback 实现,以 success 为例:

  1. @DataBinder({
  2. key: {
  3. url: 'xxx.json',
  4. success: (res, defaultCallback, originResponse) => {
  5. console.log('请求成功了,返回的数据为', res)
  6. // 执行默认的逻辑请求成功逻辑
  7. // 通常为弹出反馈 Toast
  8. defaultCallback();
  9. // originResponse 内容请参见:https://github.com/axios/axios#response-schema
  10. },
  11. defaultBindingData: {
  12. foo: 'bar'
  13. }
  14. }
  15. })
  16. class ...

error callback 的参数和逻辑同 success。

代码示例

简单的用法

本 Demo 演示最基础的用法。

DataBinder 数据交互方案 - 图2

查看源码在线预览

  1. import React, {Component} from 'react';
  2. import ReactDOM from 'react-dom';
  3. import DataBinder from '@icedesign/data-binder';
  4. import {
  5. Button
  6. } from '@icedesign/base';
  7. @DataBinder({
  8. fooData: {
  9. url: 'https://ice.alicdn.com/assets/mock/53138.json',
  10. // ajax 参数参见:https://github.com/axios/axios
  11. defaultBindingData: {
  12. foo: 'bar'
  13. }
  14. }
  15. })
  16. class App extends Component {
  17. refreshFoo = () => {
  18. this.props.updateBindingData('fooData', {
  19. // ajax 参数参见:https://github.com/axios/axios
  20. // 当前接口不需要参数,在这里只是演示,可以打开 Devtool 的 network 面板查看做了什么
  21. params: {
  22. bar: 'foo'
  23. }
  24. });
  25. };
  26. render() {
  27. const {fooData} = this.props.bindingData;
  28. return (
  29. <div>
  30. <div>
  31. foo 的值: {fooData.foo}
  32. </div>
  33. <div style={{marginTop: 10}}>
  34. <Button onClick={this.refreshFoo}>请求获取新数据</Button>
  35. </div>
  36. </div>
  37. );
  38. }
  39. }
  40. ReactDOM.render((
  41. <App />
  42. ), mountNode);

实际场景 Demo

演示一个实际场景。

DataBinder 数据交互方案 - 图3

查看源码在线预览

  1. import React, { Component } from 'react';
  2. import ReactDOM from 'react-dom';
  3. import DataBinder from '@icedesign/data-binder';
  4. import { Pagination, Table } from '@icedesign/base';
  5. @DataBinder({
  6. account: {
  7. url: 'https://ice.alicdn.com/assets/mock/53141.json',
  8. // ajax 参数参见:https://github.com/axios/axios
  9. defaultBindingData: {
  10. pagination: {
  11. page: 1,
  12. total: 0,
  13. pageSize: 10
  14. },
  15. table: []
  16. }
  17. }
  18. })
  19. class App extends Component {
  20. componentDidMount() {
  21. const {account} = this.props.bindingData;
  22. // 第一次渲染,初始化第一页的数据
  23. this.props.updateBindingData('account', {
  24. params: {
  25. ...account.pagination,
  26. page: 1
  27. }
  28. });
  29. }
  30. changePage = (pageNo) => {
  31. // 有些参数可能需要从数据中获取
  32. const {account} = this.props.bindingData;
  33. this.props.updateBindingData('account', {
  34. params: {
  35. ...account.pagination,
  36. page: pageNo
  37. },
  38. // 通过设置这个数据,可以快速将页码切换,避免等接口返回才会切换页面
  39. // 这里的变更是同步生效的
  40. // 需要注意多层级数据更新的处理,避免丢掉某些数据
  41. defaultBindingData: {
  42. ...account,
  43. pagination: {
  44. ...account.pagination,
  45. page: pageNo
  46. }
  47. }
  48. });
  49. };
  50. render() {
  51. const {account} = this.props.bindingData;
  52. return (
  53. <div>
  54. <Table dataSource={account.table} isLoading={account.__loading}>
  55. <Table.Column dataIndex="name" title="name" />
  56. <Table.Column dataIndex="age" title="age" />
  57. </Table>
  58. <Pagination
  59. current={account.pagination.page}
  60. pageSize={account.pagination.pageSize}
  61. total={account.pagination.total}
  62. onChange={this.changePage}
  63. style={{marginTop: 20}}
  64. />
  65. </div>
  66. );
  67. }
  68. }
  69. ReactDOM.render((
  70. <App />
  71. ), mountNode);

格式化接口返回

格式化接口返回的 Demo 适配老接口。

由于 DataBinder 方案对于接口有一定的规范,因此在接入老接口或者其他人的接口时,可能会有一些数据不兼容的问题,此时可以使用 resposeFormatter 配置来做数据格式兼容。

打开 Network 面板可以看到当前 Mock 接口的数据格式不符合 DataBinder 的数据要求。

DataBinder 数据交互方案 - 图4

查看源码在线预览

  1. import React, {Component} from 'react';
  2. import ReactDOM from 'react-dom';
  3. import DataBinder from '@icedesign/data-binder';
  4. import { Button } from '@icedesign/base';
  5. @DataBinder({
  6. fooData: {
  7. url: 'https://ice.alicdn.com/assets/mock/53146.json',
  8. // ajax 参数参见:https://github.com/axios/axios
  9. responseFormatter: (responseHandler, res, originResponse) => {
  10. // 拿到接口返回的 res 数据,做一些格式转换处理,使其符合 DataBinder 的要求
  11. // 最后再按照顺序丢到 responseHandler 方法里继续执行
  12. res = {
  13. success: res.code === "0" ? false : true,
  14. message: res.msg,
  15. params: {
  16. ...res.content
  17. }
  18. };
  19. responseHandler(res, originResponse);
  20. },
  21. defaultBindingData: {
  22. foo: 'bar'
  23. }
  24. }
  25. })
  26. class App extends Component {
  27. refreshFoo = () => {
  28. this.props.updateBindingData('fooData', {
  29. // ajax 参数参见:https://github.com/axios/axios
  30. // 当前接口不需要参数,在这里只是演示,可以打开 Devtool 的 network 面板查看做了什么
  31. params: {
  32. bar: 'foo'
  33. }
  34. });
  35. };
  36. render() {
  37. const {fooData} = this.props.bindingData;
  38. return (
  39. <div>
  40. <div>
  41. foo 的值: {fooData.foo}
  42. </div>
  43. <div style={{marginTop: 10}}>
  44. <Button onClick={this.refreshFoo}>请求获取新数据</Button>
  45. </div>
  46. </div>
  47. );
  48. }
  49. }
  50. ReactDOM.render((
  51. <App />
  52. ), mountNode);

自定义加载效果

自定义加载效果的 Demo。

在 AJAX 加载过程中,给用户一个加载反馈是非常重要的,DataBinder 针对每个 DataSource 附加了一个私有属性 __loading 用来标记当前模块是否在请求中。因此你可以判断这个属性来看是否显示加载效果。

为了方便,我们还提供了一个全局的 __loading 属性在 this.props.bindingData 上面,当前 Class 注册的任意 DataSource 在请求中,全局都会随之改变。

DataBinder 数据交互方案 - 图5

查看源码在线预览

  1. import React, {Component} from 'react';
  2. import ReactDOM from 'react-dom';
  3. import DataBinder from '@icedesign/data-binder';
  4. import {
  5. Button,
  6. Loading
  7. } from '@icedesign/base';
  8. @DataBinder({
  9. foo1Data: {
  10. url: 'https://ice.alicdn.com/assets/mock/53138.json',
  11. // ajax 参数参见:https://github.com/axios/axios
  12. defaultBindingData: {
  13. foo: 'bar'
  14. }
  15. },
  16. foo2Data: {
  17. url: 'http://dip.alibaba-inc.com/api/v2/services/schema/mock/53138',
  18. // ajax 参数参见:https://github.com/axios/axios
  19. defaultBindingData: {
  20. foo: 'bar'
  21. }
  22. }
  23. })
  24. class App extends Component {
  25. refreshFoo1 = () => {
  26. this.props.updateBindingData('foo1Data', {
  27. params: {
  28. bar: 'foo'
  29. }
  30. });
  31. };
  32. refreshFoo2 = () => {
  33. this.props.updateBindingData('foo2Data', {
  34. params: {
  35. bar: 'foo'
  36. }
  37. });
  38. };
  39. render() {
  40. const {foo1Data, foo2Data} = this.props.bindingData;
  41. return (
  42. <div>
  43. <div>
  44. <Loading visible={foo1Data.__loading} shape="fusion-reactor">
  45. <div>
  46. foo1 的值: {foo1Data.foo}
  47. </div>
  48. </Loading>
  49. <div style={{marginTop: 10}}>
  50. <Button onClick={this.refreshFoo1}>请求获取 foo1 新数据</Button>
  51. </div>
  52. </div>
  53. <div style={{marginTop: 30}}>
  54. <Loading visible={foo2Data.__loading} shape="fusion-reactor">
  55. <div>
  56. foo2 的值: {foo2Data.foo}
  57. </div>
  58. </Loading>
  59. <div style={{marginTop: 10}}>
  60. <Button onClick={this.refreshFoo2}>请求获取 foo2 新数据</Button>
  61. </div>
  62. </div>
  63. <h3>当前页面是否有模块正在加载:{this.props.bindingData.__loading ? '是' : '否'}</h3>
  64. </div>
  65. );
  66. }
  67. }
  68. ReactDOM.render((
  69. <App />
  70. ), mountNode);

自定义请求客户端

本 Demo 演示自定义 requestClient,使用 jsonp 的方法发送请求

DataBinder 数据交互方案 - 图6

查看源码在线预览

  1. import React, {Component} from 'react';
  2. import ReactDOM from 'react-dom';
  3. import DataBinder from '@icedesign/data-binder';
  4. import jsonp from 'jsonp';
  5. import { Pagination, Table } from '@icedesign/base';
  6. /**
  7. * 自定义的 json request client
  8. */
  9. function request(opts) {
  10. return new Promise((resolve, reject) => {
  11. jsonp(opts.url, { name: 'callback' }, (err, data) => {
  12. if (err) {
  13. reject(err);
  14. } else {
  15. resolve({ data });
  16. }
  17. })
  18. });
  19. }
  20. @DataBinder({
  21. account: {
  22. url: 'https://ice.alicdn.com/assets/mock/53141.jsonp.js',
  23. defaultBindingData: {
  24. pagination: {
  25. page: 1,
  26. total: 0,
  27. pageSize: 10
  28. },
  29. table: []
  30. }
  31. }
  32. }, { requestClient: request })
  33. class App extends Component {
  34. componentDidMount() {
  35. const {account} = this.props.bindingData;
  36. // 第一次渲染,初始化第一页的数据
  37. this.props.updateBindingData('account', {
  38. params: {
  39. ...account.pagination,
  40. page: 1
  41. }
  42. });
  43. }
  44. changePage = (pageNo) => {
  45. // 有些参数可能需要从数据中获取
  46. const {account} = this.props.bindingData;
  47. this.props.updateBindingData('account', {
  48. params: {
  49. ...account.pagination,
  50. page: pageNo
  51. },
  52. // 通过设置这个数据,可以快速将页码切换,避免等接口返回才会切换页面
  53. // 这里的变更是同步生效的
  54. // 需要注意多层级数据更新的处理,避免丢掉某些数据
  55. defaultBindingData: {
  56. ...account,
  57. pagination: {
  58. ...account.pagination,
  59. page: pageNo
  60. }
  61. }
  62. });
  63. };
  64. render() {
  65. const {account} = this.props.bindingData;
  66. return (
  67. <div>
  68. <Table dataSource={account.table} isLoading={account.__loading}>
  69. <Table.Column dataIndex="name" title="name" />
  70. <Table.Column dataIndex="age" title="age" />
  71. </Table>
  72. <Pagination
  73. current={account.pagination.page}
  74. pageSize={account.pagination.pageSize}
  75. total={account.pagination.total}
  76. onChange={this.changePage}
  77. style={{marginTop: 20}}
  78. />
  79. </div>
  80. );
  81. }
  82. }
  83. ReactDOM.render((
  84. <App />
  85. ), mountNode);

自定义请求 callback

自定义请求成功或者失败的处理逻辑。

DataBinder 默认的请求成功和失败的行为是弹一个 Toast 将接口的 message 字段信息展示一下。如果你需要自定义一些成功失败的行为可以在 DataSource 中配置 success 和 error 来接入。其中第二个参数是 DataBinder 默认的回调处理逻辑(弹 Toast)如果不需要可以不调用。

error 有两类错位,一类是网络中断,请求都没有到后端服务器;另一类是服务器接口报错(即接口返回 success 字段为 false)。两者应该给用户不同的提示和处理逻辑,可以通过其他参数来判断。

此外为了方便在 render 中处理,与 loading 类似,我们针对每个 DataSource 附加了一个 error 属性用来标记当前模块是否有报错,默认值为 null,出错时会变为 {message: '报错信息'} 数据。

DataBinder 数据交互方案 - 图7

查看源码在线预览

  1. import React, {Component} from 'react';
  2. import ReactDOM from 'react-dom';
  3. import DataBinder from '@icedesign/data-binder';
  4. import { Button, Loading, Feedback } from '@icedesign/base';
  5. @DataBinder({
  6. foo1Data: {
  7. url: 'https://ice.alicdn.com/assets/mock/53138.json',
  8. // ajax 参数参见:https://github.com/axios/axios
  9. success: (res, defaultCallback, originResponse) => {
  10. console.log('res', res, originResponse);
  11. defaultCallback();
  12. },
  13. error: (res, defaultCallback, originResponse) => {
  14. console.log('res', res, originResponse);
  15. defaultCallback();
  16. },
  17. defaultBindingData: {
  18. foo: 'bar'
  19. }
  20. },
  21. foo2Data: {
  22. url: 'http://dip.alibab2a-inc.com/api/v2/services/schema/mock/53138',
  23. // ajax 参数参见:https://github.com/axios/axios
  24. error: (res, defaultCallback, originResponse) => {
  25. console.log('res', res, originResponse);
  26. console.log('详细网络问题可以通过 originResponse 参数拿到:', originResponse.status);
  27. defaultCallback();
  28. },
  29. defaultBindingData: {
  30. foo: 'bar'
  31. }
  32. }
  33. })
  34. class App extends Component {
  35. refreshFoo1 = () => {
  36. this.props.updateBindingData('foo1Data', {
  37. params: {
  38. bar: 'foo'
  39. }
  40. });
  41. };
  42. refreshFoo2 = () => {
  43. this.props.updateBindingData('foo2Data', {
  44. params: {
  45. bar: 'foo'
  46. }
  47. });
  48. };
  49. render() {
  50. const {foo1Data, foo2Data} = this.props.bindingData;
  51. return (
  52. <div>
  53. <div>
  54. <h3>foo1 演示自定义回调</h3>
  55. <Loading visible={foo1Data.__loading} shape="fusion-reactor">
  56. <div>
  57. foo1 的值: {foo1Data.foo}
  58. </div>
  59. </Loading>
  60. {foo1Data.__error
  61. ?
  62. <Feedback type="error">
  63. foo1 数据获取失败,失败 message {foo1Data.__error.message}
  64. </Feedback>
  65. :
  66. <Feedback>
  67. foo1 数据获取成功
  68. </Feedback>
  69. }
  70. <div style={{marginTop: 10}}>
  71. <Button onClick={this.refreshFoo1}>请求获取 foo1 新数据</Button>
  72. </div>
  73. </div>
  74. <div style={{marginTop: 30}}>
  75. <h3>foo2 接口有问题,会模拟网络请求 error</h3>
  76. <Loading visible={foo2Data.__loading} shape="fusion-reactor">
  77. <div>
  78. foo3 的值: {foo2Data.foo}
  79. </div>
  80. </Loading>
  81. {foo2Data.__error &&
  82. <Feedback type="error">
  83. foo1 数据获取失败,失败 message {foo2Data.__error.message}
  84. </Feedback>
  85. }
  86. <div style={{marginTop: 10}}>
  87. <Button onClick={this.refreshFoo2}>请求获取 foo2 新数据</Button>
  88. </div>
  89. </div>
  90. <h3>当前页面是否有模块请求报错:{this.props.bindingData.__error ? '是' : '否'},报错信息:{this.props.bindingData.__error && this.props.bindingData.__error.message}</h3>
  91. </div>
  92. );
  93. }
  94. }
  95. ReactDOM.render((
  96. <App />
  97. ), mountNode);

相关区块

DataBinder 数据交互方案 - 图8

暂无相关区块