设为首页 收藏本站
查看: 1184|回复: 0

[经验分享] react+redux教程(八)连接数据库的redux程序

[复制链接]

尚未签到

发表于 2017-2-23 10:58:41 | 显示全部楼层 |阅读模式
  前面所有的教程都是解读官方的示例代码,是时候我们自己写个连接数据库的redux程序了!

例子
DSC0000.gif

  这个例子代码,是我自己写的程序,一个非常简单的todo,但是包含了redux插件的用法,中间件的用法,连接数据库的方法等多个知识点。
  源代码:
  https://github.com/lewis617/react-redux-tutorial/tree/master/redux-wilddog-todos
  运行方法:
  npm install
  npm run build
  手动打开index.html

wilddog数据库
  作为一名曾经的angular开发者,我非常喜欢用firebase来做自己的数据库,并结合angular实现酷炫的“三向数据绑定”。wilddog是中国的“firebase”,不仅语法兼容,而且国内速度更快。
  下面的程序都是基于wilddog和angular的程序,也用了我曾经的最爱requirejs,有兴趣的同学可以看看,顺便赏我点star哈哈!
  https://github.com/lewis617/wild-angular-seed
  https://github.com/lewis617/daily-task
  如今写react程序,仍然可以使用wilddog或者firebase,不仅不用配置数据库服务,也不用写数据库增删改查的api程序了,可以让我们前端工程师专注于写前端程序!
  https://www.wilddog.com/

redux的chrome插件
  本程序也用到了redux的chrome插件,可以帮助我们自动生成redux的devtool界面,非常好用啊!只需要在你的程序store注册中,加入一行代码:



export default (initialState) => {
const store = compose(
applyMiddleware(
thunk,
createLogger()
),
window.devToolsExtension ? window.devToolsExtension() : f => f
)(createStore)(reducers, initialState);
return store;
};
  就是这行代码:



window.devToolsExtension ? window.devToolsExtension() : f => f
  安装方法,就是去chrome的市场搜索redux关键字就可以了!

没有服务端渲染和热替换
  为什么要把这个单独提起来说呢?这是一个历史遗留问题。我们研究所用的web框架是flask,一个python框架,包括前端也是用flask的jinja模板。没有nodejs也就意味着无法使用服务端渲染和热替换这两个炫酷的功能。
  那么不是基于nodejs的前端程序,还能否使用redux和react呢?当然可以,我只通过webpack生成一个js文件,将js文件放进html里面。其他所有的功能都不要。这也是可以的。这也算是结合非node平台的一个实践经验吧!当然你的包管理还得用npm。
  从另一个方面来说,基于nodejs的前端时代已经来临,如果你拒绝它,将会失去很多,或者寸步难行!

获取所有的todos
  我们在action中进行http请求和服务端交互,即便是在中间件中执行http请求,其实质也是dispatch的封装。那么这个程序的关键就是action的编写。
  实例化wilddog,定义action类型:
  actions.js



import Wilddog from 'wilddog/lib/wilddog-node'
/*
* action 类型
*/
export const GET_TODO_ERROR = 'GET_TODO_ERROR';
export const GET_TODO_OK = 'GET_TODO_OK';
export const ADD_TODO_ERROR = 'ADD_TODO_ERROR';
export const ADD_TODO_OK = 'ADD_TODO_OK';
export const REMOVE_TODO_OK = 'REMOVE_TODO_OK';
export const REMOVE_TODO_ERROR = 'REMOVE_TODO_ERROR';
let wilddog=new Wilddog('https://redux-wilddog-todos.wilddogio.com')
  从wilddog数据库中获取所有的todos,因为wilddog数据库是树状结构,生成的列表,其实质也是个对象,所以我们需要将其转化为数组:



export function getTodo() {
return (dispatch,getState)=>{
wilddog.child('todos').once('value',(snapshot)=>{
let obj=snapshot.val();
let array=[];
for(let key in obj){
array.push({key:key,text:obj[key].text})
}
dispatch({
type: GET_TODO_OK,
payload: array
})
},(err)=>{
dispatch({
type: GET_TODO_ERROR,
payload: err
})
});

}
}
  wilddog.child('todos').once('value',function)是获取‘todos’节点数据的方法。获取到数据后,转化为数组。然后dispatch一个GET_TODO_OK,告诉reducer获取数据成功,可以更新state了。数据都装在payload中。如果失败,则dispatch一GET_TODO_ERROR。
  就是这么简单,不用写后台程序,在js中直接操作数据库!
  那么在哪里执行这个getTodo呢?你可以在组件渲染后dispatch它,也可以在初始化store后,立即执行它。我用的是后面一种:
  index.js



import { getTodo,registerListeners} from './actions'
let store = createStore();
store.dispatch(getTodo())


添加新的todo
  在action中定义添加todo的方法:
  actions.js



export function addTodo(text) {
return (dispatch,getState)=>{
wilddog.child('todos').push({
text
},(err)=>{
if(err){dispatch({type:ADD_TODO_ERROR,payload:err})}
});
}
}
  通过wilddog.child('todos').push()方法,直接往数据库中插入数据,第二参数是回调,失败的话,dispatch相应的action。
  那么成功后的action在哪执行?我们需要再写一个function,绑定数据变动的回调。其实正常情况下,我们在这个function中就直接写成功后的回调了,主要是因为wilddog数据库的成功回调不在push这个方法中。
  actions.js



export function registerListeners() {
return (dispatch, getState) => {
wilddog.child('todos').on('child_removed', snapshot => {
dispatch({
type: REMOVE_TODO_OK,
payload: snapshot.key()
})
});
wilddog.child('todos').on('child_added', snapshot => dispatch({
type: ADD_TODO_OK,
payload: Object.assign({},snapshot.val(),{key:snapshot.key()})
}));
};
}
  wilddog.child('todos').on('child_added')   这个方法定义了添加todo成功后的回调,我们执行了一个ADD_TODO_OK 的action,并把新的todo对象放在payload中返回给reducer。
  你也看到了,我们顺便把移除todo成功的回调也定义了。
  我们在哪执行这个绑定函数呢?就在获取所有todos的后面吧!其实放在组件渲染完也可以!
  index.js



store.dispatch(registerListeners())
移除指定todo
  在action中添加移除todo的方法:
  actions.js



export function removeTodo(key) {
return (dispatch,getState)=>{
wilddog.child(`todos/${key}`).remove((err)=>{
if(err)dispatch({type:REMOVE_TODO_ERROR,payload:err})
});
}
}
  通过wilddog的remove方法移除数据库的指定节点。就是这么简单!然后编写失败后的回调以及action!

数据库在action中完事,state还需要reducer
  数据库我们是操作完啦,不过组件的显示是基于state的,我们还要同步更新state,那么reducer就出场了!
  reducers.js



import { combineReducers } from 'redux'
import { ADD_TODO_OK, REMOVE_TODO_OK ,GET_TODO_OK} from './actions'
function todos(state=[], action) {
switch (action.type) {
case GET_TODO_OK:
return action.payload
case ADD_TODO_OK:
return [
...state,
action.payload
]
case REMOVE_TODO_OK:
return state.filter((todo)=>todo.key!==action.payload
)
default:
return state
}
}
const todoApp = combineReducers({
todos
})
export default todoApp
  很简单,如果你还不会,可以去前面几节教程补课。
  来个图吧:

  action操作数据库后,要在回调中返回信号,让reducer更新state,因为只有state变了,组件才会变。state变了,组件自动就变了,至少不用苦逼地操作dom了,还是挺开心的!

为什么不提react组件
  说了这么多我们的redux容器算是搞定了,为什么不提组件?不是不提,是要让大家知道,组件和redux容器的耦合度很低,我们可以完全将它们隔离开来编写,通过一些固定的套路将它们连接起来。什么套路?


  • 绑定state到props
  • 绑定action到props(可选)
  • 将store注入,并用provider在顶层包住组件
  redux是个状态容器,只能通过发起action改变state,这种集中管控的做法让状态管理和预测变的简单。组件只是state的展现形式而已!react只是一个界面库而已!




教程源代码及目录
  如果您觉得本博客教程帮到了您,就赏颗星吧!
  https://github.com/lewis617/react-redux-tutorial

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-346133-1-1.html 上篇帖子: Web开发学习之路是否有尽头 下篇帖子: [.net 面向对象程序设计深入](4)MVC 6 —— 谈谈MVC的版本变迁及新版本6.0发展方向
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表