dvajs / dva Goto Github PK
View Code? Open in Web Editor NEW🌱 React and redux based, lightweight and elm-style framework. (Inspired by elm and choo)
Home Page: https://dvajs.com/
License: MIT License
🌱 React and redux based, lightweight and elm-style framework. (Inspired by elm and choo)
Home Page: https://dvajs.com/
License: MIT License
initialState参数,必须要将namespace里面的所有state全部写出来
类似这样的结构
{
namespace: {
...state
}
}
initialState能不能只写namespace中部分的state,因为state部分是在model中设置了初始化值的。
而动态创建dva的时候只希望部分initialSate有用。
Hi,
在使用dva的过程中,参照user-model的demo。遇到一个问题,
怎么替换mockjs,请求服务器数据?
在index.js里写
import { message } from 'antd';
// 1. Initialize
const app = dva({
onError(error) {
message.destroy();
message.error(error);
},
});
在models里
...
effects: { //params action,effect
* query({payload},{put, call, select}) {
//如何抛出一个error?
},
...
如题。
@nikogu @yiminghe @afc163 @ChrisFan
大家怎么选? 主要是 dva.router
拿来配 root component 是否合适。
方案 1:
import dva from 'dva/mobile';
const app = dva();
dva.model({});
dva.router(App);
dva.start('#root');
方案 2:
import dva from 'dva/mobile';
const app = dva();
dva.model({});
const Dva = dva.start();
ReactDOM.render(() => <Dva><App /></Dva>, document.getElementById('root'));
或者其他方案?
用老版本时,用chrome开发者工具时可以看到webpack://下面有src目录,用1.0时没有,就不知道如何进行断点调试了。
从0.0.16升级到了1.0.0-beta4,出现了这个问题。
import React, { PropTypes } from 'react';
import { Router, Route, IndexRedirect } from 'dva/router';
import IndexPage from './routes/IndexPage';
import Example from './routes/Example';
// import LoginPage from './routes/LoginPage';
export default ({ history }) => {
return (
<Router history={ history }>
<Route breadcrumbName="首页" path="/" >
<IndexRedirect to="example" />
<Route component={ IndexPage } >
<Route breadcrumbName="样例" path="example" component={ Example } />
</Route>
</Route>=
</Router>
);
};
是否可以开放个接口,在new dva()的时候,给effects 第二参数加入其他的属性
例如 history给传进去。
好吧,其实我只是想要effects可以调用history.push做跳转~
我在开发中,很多最下层的route,离开后它的一些state数据其实没有用了,我希望在对应的route离开的时候清除这些state的数据,减少内存中的数据。
我看subscription是适合写route leave的地方,现在官方的例子有history.listen,我要怎么写才是监听onLeave?再有就是我怎么清除store里面某个model.namespace的数据?在注销的时候,我怎么清除整个redux的state?
命名为
fuzzyQueryCourse
queryCollection
均无法调用,在后面加上数字就可以(eg:fuzzyQueryCourse1)...
还有,effects中可以调用当前model中的其他effects吗?
业务场景:
1.获取视频列表
2.修改查询条件,获取视频列表
我现在的做法,是先disptach 修改条件,再dispatch获取视频列表
第一次获取的时候可以拿到router,但是不知道为什么,router.replace后,router这个变量就消失了。
目前的项目无法通过dva
调用react-router-redux
的API。
建议在dva/router
下提供调用react-router-redux
的方式。
如题,期待可以支持!
const effects = {
// default: takeEvery
['setQuery']: function*() {},
// takeLatest
['setQuery']: [function*() {}, { type: 'takeLatest'}],
// you don't need to set type for takeEvery, it's by default.
['setQuery']: [function*() {}, { type: 'takeEvery'}],
}
when use browserHistory such as:
const app = dva({
history: browserHistory,
});
open browser to http://localhost:8989/about
and refresh got 404
open browser to http://localhost:8989 and click to http://localhost:8989/about works
state
验证来做路由跳转我想实现的是state
保存登陆状态,未登录跳转到/login
路由下
router.js
无法获取state
,无法通过onEnter
来实现;IndexPage.jsx
里做路由跳转必须使用有状态组建;还是说在 api 请求的时候验证登录状态而不是通过state
?
重新思考了下 api 的设计和功能,做了一些调整。欢迎讨论。
opts.onError:
默认 throw
出错信息,在 effect
和 subscription
出错时被调用。Takes the following arguments:
namespace:
model state 在全局 state 上所在的 key 值state:
model 的初始值reducers:
同步操作,用于更新数据,由 action
触发effects:
异步操作,不直接更新数据,由 action
触发,可以 dispatch action
subscriptions:
异步只读操作,不直接更新数据,可以 dispatch action
一个完整的例子:
app.model({
namespace: 'count',
state: 0,
reducers: {
['count/add' ](count) { return count + 1 },
['count/minus'](count) { return count - 1 },
},
effects: {
['count/add']: function*(action) {
yield call(delay, 1000);
yield put({
type: 'count/minus',
});
},
},
subscriptions: [
function(send) {
key('⌘+up' , () => { dispatch({type: 'count/add'}); });
key('⌘+down', () => { dispatch({type: 'count/minus'}); });
},
],
});
namespace
是 model 在全局 state 上所占的 key,格式为字符串。虽然叫 namespace,但像 a.b
并不会被扩展为 globalState.a.b
。
state
是 plain object 。
reducers
对应 redux 的 reducer,格式为 object/array。默认是 object,如果要支持 reducer enhancer,需要写成 array,第二个参数为 reducer enhancer 。例:
app.model({
reducers: [{}, reducerEnhander],
});
effects
对应 redux-saga。他有类型,takeEvery
或 takeLatest
。默认是 takeEvery
,如果想要 takeLatest
,可以这样:
app.model({
effects: {
['count/add']: [function*(){}, { type: 'takeLatest' }],
},
});
上面 reducers
和 effects
的扩展配置的方式都是通过数组第二项的方式进行配置,参考自 babel
。
subscriptions 用于订阅数据源,格式为数组,他们会在 domready 时被执行。详见:subscription 及其适用场景。
使用和 ReactRouter 相同的配置,不做封装,可用 jsx 格式,也可用 javascript object 的格式支持动态路由。
Opts can contain the following values:
opts.history:
default: hashHistory
opts.middlewares:
default: []
opts.reducers:
default: {}
opts.hmr:
default: null
opts.history
是给路由用的 history,支持 hashHistory 和 browserHistory 。默认是 hashHistory,如果要换成 browserHistory,可以这样:
import { browserHistory } from 'dva/router';
...
app.start(container, {
history: browserHistory,
});
opts.middlewares
是支持 redux 的 middleware,数组类型。
opts.reducers
是提供额外的 reducers,用于支持类似 redux-form 这种插件。
opts.hmr
作为用户通常不需要关心。顾名思义是拿来做 Hot Module Replacement 用的,格式为 (render, replaceReducer, restartSaga) => {}
,传入用于刷新 component, reducer, saga 的方法,给 HMR 用。(目前只支持 render)
HMR 的例子详见 user dashboard,代码有点多,之后会通过 babel 插件的方式让使用无感知。
dva/effects
的调用方式简化connect
的封装 (和 reselect 结合,默认高性能)fetch
的封装在react ui组件里面要监听全局的dom事件很麻烦。
比如一个组件需要监听document点击的事件来判断是否点击的是自身, 现在的方案是要在该ui组件里实现一遍document click监听并判断, 如果一个页面上有多个不同组件有这样的监听需求,显得代码非常冗余。
不知道有没有更优雅的方法实现上面的需求。
如果框架能统一监听这些事件,并通过类似react的componentDidMounted(documentClicked)这样的钩子方法暴露给组件就好了。
并不止是click事件。
将源码下载之后:
npm install
npm start
之后提示出错:
ERROR in ./src/index.js
Module build failed: ReferenceError: Unknown plugin "add-module-exports" specified in "/Users/hugo/Documents/workspace/react/dva-master/.babelrc" at 0, attempted to resolve relative to "/Users/hugo/Documents/workspace/react/dva-master"
at /Users/hugo/Documents/workspace/react/dva-master/examples/user-dashboard/node_modules/babel-core/lib/transformation/file/options/option-manager.js:172:17
at Array.map (native)
at Function.normalisePlugins (/Users/hugo/Documents/workspace/react/dva-master/examples/user-dashboard/node_modules/babel-core/lib/transformation/file/options/option-manager.js:150:20)
at OptionManager.mergeOptions (/Users/hugo/Documents/workspace/react/dva-master/examples/user-dashboard/node_modules/babel-core/lib/transformation/file/options/option-manager.js:224:36)
at OptionManager.init (/Users/hugo/Documents/workspace/react/dva-master/examples/user-dashboard/node_modules/babel-core/lib/transformation/file/options/option-manager.js:338:12)
at File.initOptions (/Users/hugo/Documents/workspace/react/dva-master/examples/user-dashboard/node_modules/babel-core/lib/transformation/file/index.js:216:65)
at new File (/Users/hugo/Documents/workspace/react/dva-master/examples/user-dashboard/node_modules/babel-core/lib/transformation/file/index.js:137:24)
at Pipeline.transform (/Users/hugo/Documents/workspace/react/dva-master/examples/user-dashboard/node_modules/babel-core/lib/transformation/pipeline.js:46:16)
at transpile (/Users/hugo/Documents/workspace/react/dva-master/examples/user-dashboard/node_modules/babel-loader/index.js:38:20)
at /Users/hugo/Documents/workspace/react/dva-master/examples/user-dashboard/node_modules/babel-loader/lib/fs-cache.js:145:18
@ multi index
如题
比如我在model A的一个effect方法中发起
yield put ({ type: 'B/update'})
没有调用到model B的reducer方法 update
目前做的应用网页版用的dva,感觉很赞,应用要求有app版,考虑用reactnative来开发,想用dva框架,因为rn不需要router,大部分都是导航,看到作者说dva支持reactnative,不知道是否有个简单的实例参考?
再为dva点赞!学习了很多!
现在我们需要显式的去声明,model router 自定义middleware的加载,这部分是否可以考虑使用约定大于配置的规则。比如设置工程默认指定的model router等目录,自动扫描下面的包文件,自动调用app.model等方法加载,这样初始化的地方可以省去不少代码
这个好像不难,在provider外面包下,然后做些polyfill的工作就好
想做登录拦截,打算放到路由中处理
但实际路由切换时,发现onEnter进入了多次
经验证:
router的function会进入两次,第一次没有传入app,第二次传入了app
route的onEnter 会进入多次(规则为2+订阅了history的model个数)
dva 版本 :1.0.0-beta1
什么时候支持TypeScript或者提供d.ts文件
import {connect} from "dva";
@connect(
state => (state.menu)
)
export default class extends React.Component {
.....
}
https://github.com/sorrycc/dva/blob/master/src/index.js#L148
有try catch
function* sagaWithErrorCatch(...arg) {
try {
yield _saga(...arg);
} catch (e) {
onError(e);
}
}
可以看到,报错不明显,并没有告诉错误在哪个代码的哪一行,支持报了catch的地方,提示不好
没有try catch
function* sagaWithErrorCatch(...arg) {
yield _saga(...arg);
}
报错信息更加明显
1、我的系统是左边是菜单,右边是操作区。官方例子用的是layout,我觉得麻烦,用了:
<Route path='main' component={MainPage}>
<Route path='person' component={PersonPage}/>
</Route>
MainPage负责获得菜单数据,PersonPage负责获取人员列表,打开PersonPage后,按f5刷新时,MainPage的菜单数据为空了...
另外,顺带问下2个问题:
2、我现在开发也是用proxy,我想问问,如果正式部署的时候,我也希望前端和后端分开部署,这个时候怎么办?用fetch-jsonp?
3、dva mobile的例子,比如说,我最开始打开的是个登录页面:
app.router(() => <LoginView />);
我想登录成功后,跳转到,这个MainView是个Tabbar的容器,这个时候我应该怎么跳转?
没有新概念,都是旧的。
经过一段时间的自学或培训,大家应该都能理解 redux 的概念,并认可这种数据流的控制可以让应用更可控,以及让逻辑更清晰。
但随之而来通常会有这样的疑问:概念太多,并且 reducer, saga, action 都是分离的(分文件)。
这带来的问题是:
还有一些其他的:
而 dva 正是用于解决这些问题。
dva 是基于现有应用架构 (redux + react-router + redux-saga 等)的一层轻量封装,没有引入任何新概念,全部代码不到 100 行。( Inspired by elm and choo. )
dva 是 framework,不是 library,类似 emberjs,会很明确地告诉你每个部件应该怎么写,这对于团队而言,会更可控。另外,除了 react 和 react-dom 是 peerDependencies 以外,dva 封装了所有其他依赖。
dva 实现上尽量不创建新语法,而是用依赖库本身的语法,比如 router 的定义还是用 react-router 的 JSX 语法的方式(dynamic config 是性能的考虑层面,之后会支持)。
他最核心的是提供了 app.model
方法,用于把 reducer, initialState, action, saga 封装到一起,比如:
app.model({
namespace: 'products',
state: {
list: [],
loading: false,
},
subscriptions: [
function(dispatch) {
dispatch({type: 'products/query'});
},
],
effects: {
['products/query']: function*() {
yield call(delay(800));
yield put({
type: 'products/query/success',
payload: ['ant-tool', 'roof'],
});
},
},
reducers: {
['products/query'](state) {
return { ...state, loading: true, };
},
['products/query/success'](state, { payload }) {
return { ...state, loading: false, list: payload };
},
},
});
在有 dva 之前,我们通常会创建 sagas/products.js
, reducers/products.js
和 actions/products.js
,然后在这些文件之间来回切换。
介绍下这些 model 的 key :(假设你已经熟悉了 redux, redux-saga 这一套应用架构)
参考 examples:
devtool
热替换支持开发工具层面的支持?
除了热替换还待适配,其他的比如 redux-devtool, css livereload 等都是兼容的。
是否已经可用于生成环境?
可以。
是否包含之前 redux + redux-saga 那套应用架构的所有功能?
是的。
浏览器兼容性?
IE8 不支持,因为使用了 redux-saga 。(后面会考虑以扩展的方式在 effects 层支持 thunk, promise, observable 等)
大家看下脚手架的目录应该如何组织? 以下是初始方案。
.
├── /mock/
├── /src/
│ ├── /components/ # React components
│ ├── /models/ # model 信息
│ ├── /routes/ # 路由 Component
│ ├── /services/ # 处理和服务器的交互
│ ├── index.html
│ ├── index.js # 应用入口
│ ├── index.less
│ └── router.js # 路由配置
├── package.json
├── proxy.config.js
└── webpack.config.js
详见:https://github.com/dvajs/dva-cli/tree/master/boilerplates/app
dva 提供各种 hooks,然后通过 .use()
来接入。使用方法:
const app = dva();
app.use(hmr());
app.use(log());
hooks 列表:
onError
,effects 和 subscriptions 出错时触发,比如可以有个 dva-plugin-antd-error
,用于整理处理应用的出错信息onStateChange
,可以让 state 和 localStorage 或者远程的 service 建立连接onAction
,等同于 redux middlewareonHmr
,热替换,目前支持 components 和 routesextraReducers
,这个比较纠结,唯一风格不同的,不知是否有更好的命名然后 app.start()
不再提供 middlewares
和 reducers
参数,这些配置本质上和 models
同级,而和 start
本身并无关系。
各位大神 为什么clone下来的dva项目中的examples 只有最后一个能够正常运行呢
Steps:
cd dva/examples/friend-list
npm install
npm start
Error:
Module not found: Error: Cannot resolve module 'babel'
in browser: index.js:7Uncaught Error: Cannot find module "./createDva"
目前仅支持 react-router-redux
希望可以提供选项支持 redux-router
我现在在做的类似于从列表视图跳转到详情视图。
history.push('/roles/xxxx-xxxx-xxxx/users')
用下来有很多奇怪的问题,当然也可能和我使用的方式不对有关。
想请问官方有推荐的方式吗?
有没有关于dva的OAuth2的样例,关于如何组织modal,如何进行权限校验?
1、dva用了redux,这样实际上所有的组件是不是都是stateless functions?容器组件也应该是stateless functions,只不过容器组件在redux的store里面的状态变化(简单判断是不是同一个实例)之后触发刷新?stateless functions无生命周期,无后台实例,这样是不是每次都重新生成,没有diff这个动作,是不是反而没有用到reactjs的vdom。
2、在dva里面展现树,编辑树节点,由于树节点要递归生成(我原来想采用parent.children.push(child)的方式,发现不可行),那么传入的数据就由很多层,对于state的数据一般不建议多层,因为更新困难,那么树这个数据应该怎么处理好一点呢?
3、我对redux还有点迷糊的就是,redux就一个store,整个应用一直运行,数据一直放在store里面,比如说,我的web有5个列表的功能,每个列表功能上拉加载了1000条,那么5000条数据一直存在store里面?这样对内存是不是占用较多?
谢谢@sorrycc的dva!
subscriptions会在domReady后全部都执行,而且没有任何约束。
对于需登录的系统,subscriptions是不应该执行的;
或者重刷当前页面,其他页面的subscriptions 也不应该执行;
该怎么控制比较好些?在每个subscriptions里面自己再做一次判断?
场景:app.start()渲染页面出来后,进行交互操作, 发送了一个addItem的dispatch到reducer, 改变state, 导致重新渲染视图,同时热加载app.model(a), 此时的app.model,执行的是redux的replaceReducer, 查看源码发现replaceReducer执行了dispatch({ type: ActionTypes.INIT });
而这个dispatch会将热加载之前调用过的所有dispatch-addItem(其他的dispatch也一样,只要是热加载前调用过的dispatch),全部都触发一次,为什么会是这样?
代码:
const OrganView = ({organ}) => { return ( <div> {organ.title} </div> ); };
错误:OrganView.jsx:6 Uncaught TypeError: Cannot read property 'title' of undefined
原因:因为我在初始状态时organ={},而这个数据是在subscription里面发一个effect action获取的,组件最开始渲染,organ={}。
我这个应该怎么写呢?
我们推荐传入dispatch还是让组件暴露接口,外部来调用?
https://github.com/dvajs/dva/blob/master/examples/user-dashboard/src/routes/Users.jsx#L32
// 1.
<UserSearch dispatch={dispatch} />
// 2.
<UserSearch onSearch={()=>{ dispatch(); }} />
第2种组件聚合性更好,但是方法多了要开很多接口。
大家觉得我们日常写的时候推荐哪种。
effects
怎么获取state
中的列表当前页,必须通过action
传过来吗?
例如在products/vote/success
的action成功后,触发一个和ProductList
不同的组件的action(即另一个model的变化),包括相应 state 的变化。
Hi @sorrycc you are making a really nice job here, but it is quite difficult to follow all your ideas. Is there some plan to release an English version for project's documentation?
Thanks!
想到和收集到的需求整理如下:
如有遗漏,请在下面评论添加。1.0 尽量把所有 api 都敲定,难免会有一些 break change 。
node v6.3.1
Steps:
cd dva/examples/user-dashboard
npm install
npm start
Error: Uncaught Error: Container must be DOMElement.
没有集成在 1.0 RoadMap 里的先放这里,可能 2.0 或者之后的版本再做。
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.