You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于NodeJS实现AngularJS应用与MongoDB的连接及数据同步

好的,咱们一步步把你的AngularJS书籍管理应用和MongoDB打通,实现数据的实时同步增删改查。我会分成后端Node.js服务搭建和前端AngularJS代码修改两部分来讲解,确保每一步都清晰易懂。

第一步:搭建Node.js后端(连接MongoDB)

首先得搞个后端服务,负责和MongoDB交互,给前端提供API接口。

1. 初始化项目&安装依赖

先创建一个新文件夹(比如book-server),进入文件夹后执行命令:

npm init -y
npm install express mongoose cors body-parser

这些依赖的作用:

  • express:快速搭建Web服务
  • mongoose:MongoDB的ODM工具,简化数据库操作
  • cors:解决前后端跨域问题
  • body-parser:解析前端发送的JSON数据

2. 编写后端代码(server.js)

创建server.js文件,写入以下代码:

const express = require('express');
const mongoose = require('mongoose');
const cors = require('cors');
const bodyParser = require('body-parser');

const app = express();
const PORT = 3000;

// 连接MongoDB(本地地址替换成你的实际MongoDB地址)
mongoose.connect('mongodb://localhost:27017/bookDB', {
  useNewUrlParser: true,
  useUnifiedTopology: true
})
.then(() => console.log('MongoDB连接成功!'))
.catch(err => console.error('MongoDB连接失败:', err));

// 定义书籍Schema和Model,对应你前端的数据结构
const bookSchema = new mongoose.Schema({
  name: String,
  lName: String, // 作者名
  passw1: String, // 出版日期
  pages: String
});

const Book = mongoose.model('Book', bookSchema);

// 中间件配置
app.use(cors());
app.use(bodyParser.json());

// API路由:获取所有书籍
app.get('/api/books', async (req, res) => {
  try {
    const books = await Book.find();
    // 转换格式,把MongoDB的_id映射成前端用的id
    const formattedBooks = books.map(book => ({
      id: book._id,
      name: book.name,
      lName: book.lName,
      passw1: book.passw1,
      pages: book.pages
    }));
    res.json(formattedBooks);
  } catch (err) {
    res.status(500).json({ error: '获取数据失败' });
  }
});

// API路由:新增书籍
app.post('/api/books', async (req, res) => {
  try {
    const newBook = new Book(req.body);
    const savedBook = await newBook.save();
    res.json({
      id: savedBook._id,
      ...savedBook._doc
    });
  } catch (err) {
    res.status(500).json({ error: '新增书籍失败' });
  }
});

// API路由:更新书籍
app.put('/api/books/:id', async (req, res) => {
  try {
    const updatedBook = await Book.findByIdAndUpdate(
      req.params.id,
      req.body,
      { new: true } // 返回更新后的文档
    );
    if (!updatedBook) {
      return res.status(404).json({ error: '书籍不存在' });
    }
    res.json({
      id: updatedBook._id,
      ...updatedBook._doc
    });
  } catch (err) {
    res.status(500).json({ error: '更新书籍失败' });
  }
});

// API路由:删除书籍
app.delete('/api/books/:id', async (req, res) => {
  try {
    const deletedBook = await Book.findByIdAndDelete(req.params.id);
    if (!deletedBook) {
      return res.status(404).json({ error: '书籍不存在' });
    }
    res.json({ message: '删除成功' });
  } catch (err) {
    res.status(500).json({ error: '删除书籍失败' });
  }
});

// 启动服务
app.listen(PORT, () => {
  console.log(`后端服务运行在 http://localhost:${PORT}`);
});
第二步:修改AngularJS前端代码

现在把前端的本地数据换成从后端获取,同时修改增删改逻辑,让它们调用后端API。

1. 修改模块依赖

移除ngMockE2E(不需要模拟数据了),更新模块定义:

var app = angular.module("app", ["xeditable"]);

2. 更新控制器核心逻辑

给控制器注入$http服务,替换本地数组为后端请求,同时修改增删改方法:

app.controller('Ctrl', function($scope, $filter, filteredListService, $http) {
  // 页面初始化:从后端拉取数据
  $scope.init = function() {
    $http.get('/api/books')
      .then(function(response) {
        $scope.users = response.data;
        $scope.allItems = $scope.users;
        $scope.resetAll();
        $scope.pagination();
      })
      .catch(function(err) {
        console.error('获取数据失败:', err);
      });
  };

  // 保留原有名称校验逻辑
  $scope.checkName = function(data, id) {
    if (id === 2 && data !== 'narnia') {
      return "Username 2 should be `narnia(case sensitive)`";
    }
  };

  // 保存更新:调用后端PUT接口
  $scope.saveUser = function(data, id) {
    return $http.put(`/api/books/${id}`, data)
      .then(function(response) {
        // 更新本地数据
        const index = $scope.users.findIndex(user => user.id === id);
        if (index !== -1) {
          $scope.users[index] = response.data;
          $scope.allItems = $scope.users;
          $scope.resetAll();
        }
      })
      .catch(function(err) {
        console.error('更新失败:', err);
        return err.data.error; // 返回错误信息给前端提示
      });
  };

  // 删除书籍:调用后端DELETE接口
  $scope.removeUser = function(index) {
    const actualIndex = index + $scope.currentPage * $scope.pageSize;
    const bookId = $scope.users[actualIndex].id;

    $http.delete(`/api/books/${bookId}`)
      .then(function() {
        $scope.users.splice(actualIndex, 1);
        $scope.allItems = $scope.users;
        $scope.pagination();
      })
      .catch(function(err) {
        console.error('删除失败:', err);
      });
  };

  // 新增书籍:调用后端POST接口
  $scope.addUser = function($event) {
    const newBook = {
      name: 'Enter Book Name',
      lName: 'Author Name',
      passw1: 'Date of Publish',
      pages: 'Pages'
    };

    $http.post('/api/books', newBook)
      .then(function(response) {
        $scope.users.push(response.data);
        $scope.allItems = $scope.users;
        $scope.currentPage = Math.floor(($scope.users.length - 1) / $scope.pageSize);
        $scope.pagination();
        $scope.resetAll();
      })
      .catch(function(err) {
        console.error('新增失败:', err);
      });
  };

  // 原有搜索、分页逻辑保留,无需修改
  $scope.pageSize = 4;
  $scope.reverse = false;
  $scope.resetAll = function() {
    $scope.filteredList = $scope.allItems;
    $scope.newEmpId = '';
    $scope.newName = '';
    $scope.newEmail = '';
    $scope.searchText = '';
    $scope.currentPage = 0;
    $scope.Header = ['', '', ''];
  };

  $scope.pagination = function() {
    $scope.ItemsByPage = filteredListService.paged($scope.filteredList, $scope.pageSize);
  };

  $scope.setPage = function() {
    $scope.currentPage = this.n;
  };

  $scope.firstPage = function() {
    $scope.currentPage = 0;
  };

  $scope.lastPage = function() {
    $scope.currentPage = $scope.ItemsByPage.length - 1;
  };

  $scope.range = function(input, total) {
    var ret = [];
    if (!total) {
      total = input;
      input = 0;
    }
    for (var i = input; i < total; i++) {
      if (i != 0 && i != total - 1) {
        ret.push(i);
      }
    }
    return ret;
  };

  $scope.sort = function(sortBy) {
    $scope.resetAll();
    $scope.pagination();
  };

  $scope.search = function() {
    $scope.filteredList = filteredListService.searched($scope.allItems, $scope.searchText);
    if ($scope.searchText == '') {
      $scope.filteredList = $scope.allItems;
    }
    $scope.pagination();
  };

  // 页面加载时执行初始化
  $scope.init();
});

3. 其他小调整

  • 移除HTML中不必要的angular-mocks.js引用(如果不需要测试)
  • 确保页面结构和原有ng-repeat、编辑组件逻辑保持不变
第三步:运行测试
  1. 启动MongoDB服务(确保你的MongoDB已安装并正常运行)
  2. 启动后端:在book-server文件夹执行node server.js
  3. 启动前端:可以用http-server(先安装npm install -g http-server),在前端文件夹执行http-server后访问对应地址(比如http://localhost:8080)

现在你操作页面上的增删改查,所有变更都会实时同步到MongoDB里啦!

内容的提问来源于stack exchange,提问作者sahil

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 06:58:29