Dva: [讨论] - 关于页面初始数据依赖的声明问题

Created on 17 Dec 2017  ·  3Comments  ·  Source: dvajs/dva

官方文档 和 hackernews示例中,都使用了在model的subscription中监听匹配history url的方式为页面加载初始数据,如下。

//摘自api文档
app.model({
  namespace: 'todo',
  // ... 
  subscriptions: {
    setup({ history, dispatch }) {
      // Subscribe history(url) change, trigger `load` action if pathname is `/`
      return history.listen(({ pathname }) => {
        if (pathname === '/') {
          dispatch({ type: 'load' });
        }
      });
    },
  },
});

传送门:类似写法的 dva-hackernews的item model

这与通常见到的在页面组件的生命周期加载数据有所不同,比如同样是hakernews的例子,我们可以选择在ListPage 的componentWillMount或componentDidMount去dispatch 相应的effects action做请求,甚至从server render的角度思考,可以添加额外的生命周期(比如next.js的getInitProps)来负责声明这种页面的初始数据依赖。

目前把页面的初始数据依赖放到model的subcription中的方式,个人存在以下疑问:

  1. url match逻辑重复: 解析url参数并转发到业务逻辑是router的职责,从hackernews的例子能看出来 已经 有一部分重复了,甚至会用到pathToRegex这样相对“底层”的库(react-router/express背后也是用的它做url匹配和解析)
  2. 职责分离:不同的做法对应不同的语义,是由页面声明该页依赖哪些数据,还是由model声明在什么url下执行数据加载?
  3. 页面失去了对请求的控制权,如果某个页面想在请求成功或失败后执行特定的逻辑,会比较难实现 ,因为页面本身对加载数据这个动作是没有感知的
  4. 如何应对server render/isomorphic场景,其实是3的延续,在server render下,需要“先加载页面依赖的数据,再执行页面渲染”,而如果对请求的声明根本不在页面级,要做到这事就比较麻烦了
  5. subscription的设计似乎是受elm的影响,但是在elm中subscription的使用其实也并不多,只是用来对付websocket等场景,初始请求还是通过页面声明init做的。

当然,dva并没有限制采用哪种方式,在dva中使用页面组件生命周期的做法是完全可行的,只是我觉得具有示范作用的官方文档和示例都用了另一种做法,很可能还有我不知道的考量,之前也加了微信群提问,但没能得到答案(有朋友说是因为dva希望页面组件也是functional component,确实是一个点,但似乎没有那么强的说服力),因此开issue叨扰,见谅。
@sorrycc

discussion wontfix

All 3 comments

model 的inithook

              邮箱:[email protected]

签名由 网易邮箱大师 定制
在2017年12月17日 16:30,Qin Junwen 写道: 在官方文档 和 hackernews示例中,都使用了在model的subscription中监听匹配history url的方式为页面加载初始数据,如下。
//摘自api文档
app.model({
namespace: 'todo',
// ...
subscriptions: {
setup({ history, dispatch }) {
// Subscribe history(url) change, trigger load action if pathname is /
return history.listen(({ pathname }) => {
if (pathname === '/') {
dispatch({ type: 'load' });
}
});
},
},
});
传送门:类似写法的 dva-hackernews的item model
这与通常见到的在页面组件的生命周期加载数据有所不同,比如同样是hakernews的例子,我们可以选择在ListPage 的componentWillMount或componentDidMount去dispatch 相应的effects action做请求,甚至从server render的角度思考,可以添加额外的生命周期(比如next.js的getInitProps)来负责声明这种页面的初始数据依赖。
目前把页面的初始数据依赖放到model的subcription中的方式,个人存在以下疑问:

url match逻辑重复: 解析url参数并转发到业务逻辑是router的职责,从hackernews的例子能看出来 已经 有一部分重复了,甚至会用到pathToRegex这样相对“底层”的库(react-router/express背后也是用的它做url匹配和解析)
职责分离:不同的做法对应不同的语义,是由页面声明该页依赖哪些数据,还是由model声明在什么url下执行数据加载?
页面失去了对请求的控制权,如果某个页面想在请求成功或失败后执行特定的逻辑,会比较难实现 ,因为页面本身对加载数据这个动作是没有感知的
如何应对server render/isomorphic场景,其实是3的延续,在server render下,需要“先加载页面依赖的数据,再执行页面渲染”,而如果对请求的声明根本不在页面级,要做到这事就比较麻烦了
subscription的设计似乎是受elm的影响,但是在elm中subscription的使用其实也并不多,只是用来对付websocket等场景,初始请求还是通过页面声明init做的。

当然,dva并没有限制采用哪种方式,在dva中使用页面组件生命周期的做法是完全可行的,只是我觉得具有示范作用的官方文档和示例都用了另一种做法,很可能还有我不知道的考量,之前也加了微信群提问,但没能得到答案(有朋友说是因为dva希望页面组件也是functional component,确实是一个点,但似乎没有那么强的说服力),因此开issue叨扰,见谅。
@sorrycc

—You are receiving this because you are subscribed to this thread.Reply to this email directly, view it on GitHub, or mute the thread.

{"api_version":"1.0","publisher":{"api_key":"05dde50f1d1a384dd78767c55493e4bb","name":"GitHub"},"entity":{"external_key":"github/dvajs/dva","title":"dvajs/dva","subtitle":"GitHub repository","main_image_url":"https://cloud.githubusercontent.com/assets/143418/17495839/a5054eac-5d88-11e6-95fc-7290892c7bb5.png","avatar_image_url":"https://cloud.githubusercontent.com/assets/143418/15842166/7c72db34-2c0b-11e6-9aed-b52498112777.png","action":{"name":"Open in GitHub","url":"https://github.com/dvajs/dva"}},"updates":{"snippets":[{"icon":"DESCRIPTION","message":"[讨论] - 关于页面数据依赖的问题 (#1402)"}],"action":{"name":"View Issue","url":"https://github.com/dvajs/dva/issues/1402"}}}

@yangbin1994

model的inithook指的是?
我在model文档里没看到呢。

假设有这个Hook,其实和在subscription中做似乎也没有本质上的不同,上述1-4点疑问仍然存在

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

Was this page helpful?
0 / 5 - 0 ratings