当前位置: 首页 > 后端技术 > Node.js

走全栈的第一步,vue+node+mysql独立完成前后端分离的增删改查查询过程

时间:2023-04-03 11:11:22 Node.js

写在前面这篇文章只是我学习的记录过程,不是很严谨的教程,希望能和大家一起进步。也希望您能指出我的问题。适合有一定基础,以全栈学习为目标的前端初学者。从点击按钮提交ajax,到获取服务器响应,再到更新页面,到底发生了什么?接下来我们来实现一个小demo,通过前后端分离的方式独立运行一个简单的增删改查流程,走全栈第一步。使用的一些技术栈数据库:mysqlmysqlfront(数据库gui工具)backend:nodeexpressmysqljs(node数据库模块)frontend:vue(mvvm框架)elment-ui(快速搭建前端页面)axios(ajax)webpack(buildtool)后端负责提供接口,操作数据库,提供前端所需的数据和状态。前端负责调用接口,向用户展示数据,并将用户的一些操作转发给后端处理。当然,数据库是负责存储数据的。关于数据库,网上很多教程都是用mongodb的。通过mongoose操作mongodb确实比mysql方便很多,但是在实际工作中,还是有很多人在使用mysql,技术还是要回归到实际应用中才能体现它的价值。本demo使用node创建本地服务器,整个过程可以在localhost上完成,不需要在线服务器。虽然功能很简单,但是用到的模块和工具还是蛮多的。建议大家关注从前到后的流程。一些工具和库的使用我就不详细介绍了。你可以自己谷歌。成为全栈还是要有学习能力的。项目结构首先进入github仓库地址。下面简单介绍一下项目结构。前后端在不同文件夹下,互不影响。前端使用webpack构建,使用webpack-dev-server开发。前端入口是localhost:8888/dist/index.html。后端使用express框架,使用nodemon自动重启,host为localhost:9999。使用webpack-dev-server和express分别创建两个服务器,使用同一个端口会冲突,所以这里会出现跨域问题,但是用devserver可以轻松解决,具体解决方法后面会说。如果是在线服务器,就放一个进去。从前端开始,先用vue-cli生成项目模板。使用webpack-simple就足够了。更改相关配置更方便。我们的页面非常简单。它主要有两个组件:list.vue(显示所有数据和相关操作)和一个form.vue(添加和修改产品)。这样的页面前端估计点几下就搞定了。用不用element-ui无所谓,用了会更快更漂亮。请忽略我项目中使用的pug(jade)模板、饿了么主题文件、登录组件等,这只是为了方便以后的扩展。前端index.html只用一个空壳。配置前端路由,/admin下有list和form两个子页面,默认是list(一般默认是后台概览页面)exportdefaultnewRouter({routes:[{path:'/admin',redirect:'/admin/list',name:'admin',component:Admin,children:[{path:'/admin/list',name:'list',component:List,},{path:'/admin/form',name:'form',component:Form,},]},]});静态部分基本完成了,下面开始在组件中编写数据流转逻辑。列表的数据来自于后端,所以在列表组件创建的钩子中应该有一个ajax来获取所有的数据。先别着急,ajax用到的地方很多,先把ajax的方法封装一下。//public/func.jsimportaxiosfrom"axios";exportdefault{ajaxGet(api,cb){axios.get(api).then(cb).catch(err=>{console.log(err);})},ajaxPost(api,post,cb){axios.post(api,post).then(cb).catch(err=>{console.log(err);})},}这里我们使用axios模块来做一个ajax请求,写法是一个promise的链式操作,封装一个get和一个post就可以了。//public/api.jslethost='/api';exportdefault{goodsList:host+'/goods-list',goodsDetail:host+'/goods-detail',goodsDelete:host+'/goods-delete',goodsAdd:host+'/goods-add',}同时创建public文件夹下的一个api.js,把所有接口信息写到一起,方便后续修改。路径要和后端接口一致。我们通过配置devserver.proxy来解决跨域问题。根据下面的配置,路径以/api开头的请求会被节点服务器转发到9999端口。关于webpack的一些东西,可以看我的另一篇Alittlenoteaboutwebpackinthisarticle//webpack.config.js//...devServer:{port:8888,historyApiFallback:true,stats:'minimal',//输入精简信息overlay:true,//将error显示在htmlproxy:{'/api':{target:'http://localhost:9999',secure:false,changeOrigin:true,}}},最后进入编写特定业务逻辑的组件,我们在创建时获取数据并将其呈现到表中。虽然后端还没有启动,但我们希望res.data是一个包含所有产品的数组(如果数据太大,会分页),稍后在后端处理数据。Mock可以用来模拟实际项目中的数据。删除操作将要删除的商品id发布到指定接口,然后在回调中判断返回的状态。状态应该是同意的,所以我设置成201表示成功。后台返回成功后,前端数据中相应的元素也应该被删除,视图更新。//list.vueimportfuncfrom'../../public/func';importapifrom'../../public/api';//...省略几行代码methods:{//deletehandleDelete(row){func.ajaxPost(api.goodsDelete,{id:row.Id},res=>{if(res.status===201){letindex=this.tableData.indexOf(row);this.tableData.splice(index,1);this.$message.success('删除成功');}});},//修改handleEdit(row){this.$router.push({name:'form',query:{id:row.Id}});},},created(){func.ajaxGet(api.goodsList,res=>{this.tableData=res.data;});},列表页的修改操作是路由跳转到表单页,以及同时以query的形式传递id。在表单的createdhook中判断,如果有query.id,说明正在修改product,如果没有,则添加,这样就可以复用表单组件了。不喜欢偷懒的程序员不是好程序员。这个修改操作也可以使用vuex传递商品数据,但是页面刷新会消失,使用ajax是安全的。//form.vue//...省略几行代码created(){letid=this.$route.query.id;控制台日志(id);if(id){func.ajaxPost(api.goodsDetail,{id},res=>{this.form=res.data;});}},还有一些操作就不具体了,挺简单的,让我们进入久违的后台。创建数据库后端的第一步是创建数据库。这里我用的是phpstudy自带的。当然你也可以自己安装。毕竟这个还是5.5的老版本。不会玩sql语句,就用phpstudy自带的gui工具mysqlfront。建一个库叫vue-admin,然后建一个goods表,只有id,name,price,create_time四个字段,简单明了。写完后端接口,终于可以玩node了。首先全局安装nodemon,帮助我们自动重启,然后安装express等包。新手不建议使用express-generator创建项目。看到这里,请先去预览mysqljs模块。我们把数据库的配置写在一个单独的文件中,提取配置文件是个好习惯。然后在控制器中使用mysql.createPool(db)创建连接池。//db.jsmodule.exports={host:'localhost',port:3306,user:'root',password:'root',database:'vue-admin'};//controls/goods.jsletpool=mysql.createPool(db);接下来编写增删改查等路由接口,与前端api.js中的路径保持一致。获取或发布视情况而定。回调函数这里就不写了,写到controllergoods.js里面了。在入口文件中使用路由器。这时候我们的接口路径是/api/goods-list//router.jsrouter.get('/goods-list',goods.getGoodsList);router.post('/goods-detail',goods.getOneGoods);router.post('/goods-add',goods.addGoods);router.post('/goods-delete',goods.deleteGoods);module.exports=router;//app.jsletrouter=require('./路由/路由器');app.use('/api',路由器);controller中的增删改查也有四种方法。首先,我们封装了一些可重用的SQL语句。这是mysqljs中的语法,?它是一个变量,double?是表名还是字段名,单?是价值。insert和update没有封装,涉及到具体字段的时候直接写。//sql.jsmodule.exports={queryAll:'SELECT*FROM??',queryById:'SELECT*FROM??WHEREid=?',del:'DELETEFROM??其中id=?',};Controller这里说一个方法,完整代码在github。使用pool.getConnection方法从连接池建立连接,SELECT*FROMgoods获取goods表中的所有数据,res.json将数据以json格式传递给前端。读操作完成后,调用release()释放连接。前端获取的rows和res的数据格式可以在控制台查看,都是数组类型。//获取商品列表getGoodsList(req,res){pool.getConnection((err,conn)=>{conn.query(sql.queryAll,'goods',(err,rows)=>{if(err)throwerr;rows=formatDate(rows);res.json(rows);conn.release();});});},//formatDate函数使用moment.js将数据库中的时间戳格式转换为年份,月日格式函数formatDate(rows){returnrows.map(row=>{letdate=moment(row.create_time).format('YYYY-MM-DD');returnObject.assign({},row,{create_time:date});});}写后端接口的时候,去前端提交请求还是挺痛苦的。这里推荐大家使用postman工具来测试接口,提高效率。Postman可以作为chrome插件安装,非常方便。后端接口跑通后,前端与前端协调修改。从前端调用接口,到后端从数据库读取数据,最后返回到前端,整个流程贯穿了。全栈之路任重而道远。我们只是完成了一个Web应用最基本的功能。新手可能一脸懵逼,高手一脸不屑。全栈的路还很远。接下来,我们需要加入登录等模块,更复杂的业务逻辑,以及安全方面的考虑,让程序更加强大。我们一起工作吧。