{"action":"created","issue":{"url":"https://api.github.com/repos/dvajs/dva/issues/1840","repository_url":"https://api.github.com/repos/dvajs/dva","labels_url":"https://api.github.com/repos/dvajs/dva/issues/1840/labels{/name}","comments_url":"https://api.github.com/repos/dvajs/dva/issues/1840/comments","events_url":"https://api.github.com/repos/dvajs/dva/issues/1840/events","html_url":"https://github.com/dvajs/dva/issues/1840","id":346432035,"node_id":"MDU6SXNzdWUzNDY0MzIwMzU=","number":1840,"title":"dva 改进建议","user":{"login":"Hiufan","id":5506237,"node_id":"MDQ6VXNlcjU1MDYyMzc=","avatar_url":"https://avatars1.githubusercontent.com/u/5506237?v=4","gravatar_id":"","url":"https://api.github.com/users/Hiufan","html_url":"https://github.com/Hiufan","followers_url":"https://api.github.com/users/Hiufan/followers","following_url":"https://api.github.com/users/Hiufan/following{/other_user}","gists_url":"https://api.github.com/users/Hiufan/gists{/gist_id}","starred_url":"https://api.github.com/users/Hiufan/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Hiufan/subscriptions","organizations_url":"https://api.github.com/users/Hiufan/orgs","repos_url":"https://api.github.com/users/Hiufan/repos","events_url":"https://api.github.com/users/Hiufan/events{/privacy}","received_events_url":"https://api.github.com/users/Hiufan/received_events","type":"User","site_admin":false},"labels":[{"id":442288838,"node_id":"MDU6TGFiZWw0NDIyODg4Mzg=","url":"https://api.github.com/repos/dvajs/dva/labels/discussion","name":"discussion","color":"fbca04","default":false}],"state":"open","locked":false,"assignee":null,"assignees":[],"milestone":null,"comments":35,"created_at":"2018-08-01T03:12:04Z","updated_at":"2018-08-24T07:29:44Z","closed_at":null,"author_association":"NONE","body":"dva是对react全家桶的最佳实践整合，已经能够非常有效地提升开发效率了。在实践中，发现dva理论上可以有更好地开发模式。因此，这里我提出一个建议，对dva进行改进，也希望参与到dva的开发之中。\r\n\r\n## dva的model\r\ndva常规的model编写结构如下所示：\r\n```js\r\n{\r\n  namespace: '', \r\n  subscriptions:{},  \r\n  state: {},  \r\n  effects: {},  \r\n  reducers: {},  \r\n}\r\n```\r\n熟悉dva的人大概都知道上面的结构所对应的操作是什么，不展开。这里想谈一谈effects和reducers这两个对象。`effects`对应的是相关的异步action，`reducers`对应的是相关的同步action。当我们写一个简单的页面时，`effects`和`reducers`中的方法都不会太多。但是当我们写一个复杂页面时，异步的请求与同步的状态更新都会有很多，这样就会导致`model`中的异步与同步`action`对象中的方法列表过长，后期维护与代码迭代时，当我们要找到对应的方法时，就不那么地直观和方便。\r\n\r\n## 示例\r\n\r\n```js\r\n{\r\n  namespace: '', \r\n  subscriptions:{},  \r\n  state: {},  \r\n  effects: {\r\n     getUserList(){},\r\n     create(){},\r\n     update(){},\r\n     remove(){},\r\n     removeAll(){}\r\n  },\r\n  reducers: {\r\n     setLoading(){},\r\n     saveModal(){},\r\n     switchView(){},\r\n     createSuccess(){},\r\n     updateSuccess(){},\r\n     removeSuccess(){},\r\n     removeAllSuccess(){}\r\n  }\r\n}\r\n\r\n```\r\n以一个管理用户的页面为例，这里内部实现没有写，非常简单的管理，`effects`和`reducers`中已经有五六个函数了。如果这个页面的管理功能更多一些，例如这个列表会继续地增长。当模型变得复杂时，我们阅读代码和寻找一个方法时就需要经常在`effects`和`reducers`这两个非常长的函数对象中跳来跳去，写代码异常不便。\r\n\r\n我们可以分析一下一个dva单页面的运行情况：\r\n1. 请求数据未到达浏览器端时，设置loading状态为true,数据到达后设置loading为false。这可以视为一个页面的前置阶段。\r\n2. 页面中任何的事件操作都需要触发`effects`中的方法进行异步请求，当请求完成时，调用`reducers`中的同步方法进行状态更新。从交互上来说，请求失败与请求成功都应该让用户有相对应的感知。\r\n\r\n## 更内聚的设计\r\n程序设计上我们通常讲究『高内聚，低耦合』的设计原则。从dva的`model`来说，其实是可以实现功能内聚的。也就是说，可以按模块组织相关的功能方法，因此，模块的相关操作从编辑体感上不会四分五裂。\r\n\r\n仔细观察，其实`effects`和`reducers`分别对应了异步调用与同步调用，写法都是存在自己各自的特征的。`effects`中都是`generator`函数或者是`async`函数，而`reducer`中是普通的函数。那么，在JS中，我们其实有办法识别这两者的特征的。这是实现功能内聚的前置条件。\r\n\r\n我希望的model写法如下：\r\n```\r\n{\r\n  namespace: 'user',\r\n  state: { },\r\n  userList: {\r\n    before() { },  // 同步，函数显示loading\r\n    after(){}, // 同步，隐藏loading\r\n    *retrieve() {}, // 异步, 请求读取列表\r\n    *create() {}, // 异步，创建用户\r\n    *update(){}, // 异步，更新用户信息\r\n    saveModal(){}, // 同步，显示或者隐藏modal\r\n    successMessage(){}, // 模块内可复用的消息提示\r\n    failMessage() { }, \r\n  },\r\n}\r\n```\r\n\r\n由于`model`的默置对象是固定的。因此，只要尊重`namespace`、`state`、`subscriptions`、`effects`和`reducers`这些保留关键字，就可以对`model`进行扩展了。\r\n\r\n意思是，不破坏同时兼容原有的`model`结构。`model`可以实现一层`语法糖`的转换功能来实现上面的写法。实质上`userList`这个模块的方法最终都会转换成经典的`model`结构，只是从`coder`的角度来看，更为直观一些，而上线后的结构其实与经典结构无异。\r\n\r\n这是一个初步的想法，也请大家斧正和补充。\r\n"},"comment":{"url":"https://api.github.com/repos/dvajs/dva/issues/comments/415676614","html_url":"https://github.com/dvajs/dva/issues/1840#issuecomment-415676614","issue_url":"https://api.github.com/repos/dvajs/dva/issues/1840","id":415676614,"node_id":"MDEyOklzc3VlQ29tbWVudDQxNTY3NjYxNA==","user":{"login":"fangkyi03","id":30390014,"node_id":"MDQ6VXNlcjMwMzkwMDE0","avatar_url":"https://avatars1.githubusercontent.com/u/30390014?v=4","gravatar_id":"","url":"https://api.github.com/users/fangkyi03","html_url":"https://github.com/fangkyi03","followers_url":"https://api.github.com/users/fangkyi03/followers","following_url":"https://api.github.com/users/fangkyi03/following{/other_user}","gists_url":"https://api.github.com/users/fangkyi03/gists{/gist_id}","starred_url":"https://api.github.com/users/fangkyi03/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/fangkyi03/subscriptions","organizations_url":"https://api.github.com/users/fangkyi03/orgs","repos_url":"https://api.github.com/users/fangkyi03/repos","events_url":"https://api.github.com/users/fangkyi03/events{/privacy}","received_events_url":"https://api.github.com/users/fangkyi03/received_events","type":"User","site_admin":false},"created_at":"2018-08-24T07:29:44Z","updated_at":"2018-08-24T07:29:44Z","author_association":"NONE","body":"我觉得 还是优先解决刚需比较好点 扩展性太高 但是实际开发 并不需要这么多东西 因为一个未知的定义 导致性能下降感觉也是很浪费的"}}
{"actor":{"display_login":"fangkyi03"}}