飞道的博客

VUE+Express+MongoDB前后端分离,实现一个便签墙(一)

302人阅读  评论(0)

计划来实现一个便签墙系列,这个东西做简单也简单,往复杂了做功能也很多,记录一下从零到有的开发过程吧,希望最后能把这个项目做得很完善。

首先是前后端分离架构,前端用vue,后台我们就用express,数据库用mongodb吧。

在脑袋里过一下,最最开始,要完成一个怎样的雏形呢?先把用户登录管理放在一边,当然是便签的增删改查+显示啊!

那么,我们就来实现“初号机”,一张张便签的显示,增加,修改,删除。

目录

1、怎么说也得先把样式画出来

2、对于便签的内容,该怎么编辑

3、下面不就是调接口的时候了


1、怎么说也得先把样式画出来

先别管接口,先把纯前端的问题解决先,我们先来一个像模像样的“黑板”,对了,这里推荐一个网站https://www.transparenttextures.com/,可以生成你喜欢的壁纸素材,于是就有了:

好了,我们要在这块黑板上“贴上”我们的便签了,这一块就是css的东西了,这个就看大家的美术设计功底了,我随意了:

那么重要的一点是,在这块背景板上,便签就应该是可以随意贴在你想要的位置,所以对于便签,用户应该可以拖拽并记录位置。

所以将便签div采取position: absolute,然后用top: y px和left: x px来实现定位。

于是我们考虑单个便签对象包含的属性有:

x: 便签距容器左侧距离, left的值

y: 便签距容器上边界距离, top得值

txt: 便签的内容

title: 标题

color: {

  bg: "", // 背景色

 pin: "" // 回形针颜色

 }

接下来我们就来实现便签的拖动:

(1) 在便签的div上绑定鼠标点击函数:

 @mousedown="mousedown($event)"

(2) 实现拖动:


  
  1. mousedown: function(event) {
  2. let _this = this;
  3. if (! this.isEdit) {
  4. this.startX = event.x;
  5. this.startY = event.y;
  6. this.note.moving = true;
  7. document.onmousemove = event => {
  8. if (!_this.note.moving) return false;
  9. let dx = event.x - _this.startX;
  10. let dy = event.y - _this.startY;
  11. if (
  12. _this.note.x + dx <= 0 ||
  13. _this.note.x + dx >= _this.width - 250 ||
  14. _this.note.y + dy <= 60
  15. ) {
  16. return false;
  17. }
  18. _this.note.x1 = _this.note.x + dx;
  19. _this.note.y1 = _this.note.y + dy;
  20. };
  21. document.onmouseup = () => {
  22. if (! this.isEdit) {
  23. this.note.moving = false;
  24. this.note.x = this.note.x1;
  25. this.note.y = this.note.y1;
  26. this.saveNote();
  27. document.onmousemove = null;
  28. document.onmouseup = null;
  29. }
  30. };
  31. }
  32. }

初始记录x和y的副本为x1,y1。用startX和startY记录下最开始鼠标按下的位置,然后在拖动过程中和原始值计算偏移量,赋值给x1和y1进行定位,在鼠标抬起时更新x,y为最终值。

这里有个关键点就是,如果用@mousemove,会导致在鼠标拖动过快的情况下,便签不能及时跟随鼠标,鼠标就会移出div,造成拖动失效。

所以这里只把mousedown绑定在目标上,而把mousemove和mouseup绑定在document上,这样就不会担心鼠标移快后出了便签导致便签卡住了。


2、对于便签的内容,该怎么编辑

这里设计一个按钮,鼠标hover上去后,显示按钮;点击编辑按钮,让便签内容变成可编辑的状态,当内容区域blur的时候自动保存。

由于div便签没有blur事件,所以在编辑状态下,将内容区域变为textarea:


  
  1. <div
  2. class= "note-content"
  3. v-if= "!isEdit"
  4. v-html= "content"
  5. :ref= "'note' + index"
  6. > </div>
  7. <el-input
  8. v-else
  9. class= "note-content my-textarea"
  10. type= "textarea"
  11. placeholder= "请输入内容"
  12. :autosize= "{ minRows: 10 }"
  13. v-model= "content"
  14. :ref= "'note' + index"
  15. @ blur= "handleChange"
  16. > </el-input>

很明显,这里的内容得用innerHTML结果保存,因为我们要保存换行回车空格这些样式,使显示保持一致,所以在获取编辑的字符串我们要用正则进行替换:

 this.content = this.content

        .replace(/\r\n/g, "<br/>")

        .replace(/\n/g, "<br/>")

        .replace(/\s/g, "&nbsp;");

变成编辑状态时,我们要把形式再转换一下给textarea:

 this.content = this.content

        .replace(/&nbsp;/g, " ")

        .replace(/<br\/>/g, "\r\n");


3、下面不就是调接口的时候了

express框架这里就不再赘述了,我们用mongoose连接mongodb数据库,创建controller文件夹,增加note.js来实现数据库操作:


  
  1. // controller/note.js
  2. const Notes = require( "../model/notes");
  3. var mongoose = require( 'mongoose');
  4. module.exports = {
  5. updateNote(obj) {
  6. if (!obj.params._id) {
  7. obj.params._id = new mongoose.mongo.ObjectID();
  8. }
  9. return Notes.findByIdAndUpdate(
  10. obj.params && obj.params._id,
  11. {
  12. $set: obj.body
  13. },
  14. {
  15. upsert: true,
  16. new: true,
  17. setDefaultsOnInsert: true
  18. }
  19. )
  20. .then( function (newobj) {
  21. return Promise.resolve({
  22. status: 200,
  23. messgae: "OK"
  24. });
  25. })
  26. .catch( (err) => {
  27. return Promise.reject(err);
  28. });
  29. },
  30. getNotes() {
  31. return new Promise( function (resolve, reject) {
  32. Notes.find()
  33. .then( function (newobj) {
  34. resolve(newobj);
  35. })
  36. .catch( (err) => {
  37. reject(err);
  38. });
  39. });
  40. },
  41. deleteNoteById(_id) {
  42. return Notes.findByIdAndDelete(_id)
  43. .then( function (newobj) {
  44. return Promise.resolve({
  45. status: 200,
  46. messgae: "OK"
  47. });
  48. })
  49. .catch( (err) => {
  50. return Promise.reject(err);
  51. });
  52. }
  53. };

这里先简单写写,还可以进一步封装好返回结果。

创建model文件夹,增加note.js存放Schema: 


  
  1. // model/note.js
  2. var mongoose = require( "mongoose");
  3. var Schema = mongoose.Schema;
  4. // 声明一个数据集 对象
  5. var noteSchema = new Schema({
  6. txt: {
  7. type: String,
  8. required: false
  9. },
  10. x: {
  11. type: Number
  12. },
  13. y: {
  14. type: Number
  15. },
  16. color: {
  17. type: Object
  18. },
  19. title:{
  20. type: String,
  21. default: "未命名"
  22. },
  23. createTime: {
  24. type: Date,
  25. default: Date.now
  26. }
  27. });
  28. mongoose.set( "useCreateIndex", true);
  29. mongoose.set( 'useFindAndModify', false);
  30. // 将数据模型暴露出去
  31. module.exports = mongoose.model( "Notes", noteSchema, "notes");

所以,在拖动结束时、便签blur时都要自动保存。

于是数据库里就会保存我们的便签了:

于是一个初步的雏形完成了,我们创建便签,拖动,编辑,删除,这些都是实时保存的,刷新页面后便签的位置都是能保留的。

下面看看效果:


接下来,还有好多任务清单没做呢,随便一想,功能上能完善的就很多,例如:用户管理、时间分类、多条件查询、便签内容支持富文本、便签支持自定义样式、备忘提醒功能等等。

再接再厉,任重道远~~~~


大家也可关注一下Cavans小游戏系列:

《VUE实现一个Flappy Bird~~~》

《VUE+Canvas实现上吊火柴人猜单词游戏》

《VUE+Canvas 实现桌面弹球消砖块小游戏》

《VUE+Canvas实现雷霆战机打字类小游戏》


转载:https://blog.csdn.net/denglouhen/article/details/115764533
查看评论
* 以上用户言论只代表其个人观点,不代表本网站的观点或立场