【问题标题】:Understanding TodoMVC Example了解 TodoMVC 示例
【发布时间】:2012-10-14 01:17:51
【问题描述】:

开始学习 node.js 和 backbone.js,并使用 TodoMVC 示例作为我的指南。有几个部分我很难理解。见下文。

这里是 app.js。

var express = require('express')
  , http = require('http')
  , mongoose = require('mongoose')
  , models = require('./models')
  , routes = require('./routes')
  , app = express();

app.configure(function () {
  app.set('views', __dirname + '/views');
  app.set('view engine', 'jade');
  app.use(express.favicon());
  app.use(express.logger('dev'));
  app.use(require('stylus').middleware({ src: __dirname + '/public' }));
  app.use(express.static(__dirname + '/public'));
  app.use(express.bodyParser());
  app.use(express.methodOverride());
  app.use(app.router);
});

app.configure('development', function () {
  app.use(express.errorHandler());
});

routes.init(app);


mongoose.connect("127.0.0.1", "todomvc", 27017);

http.createServer(app).listen(3000);

console.log("Express server listening on port 3000");

这里是 ./models:

var mongoose = require('mongoose'),

  TodoSchema = new mongoose.Schema({
    title: { 'type': String, 'default': 'empty todo...' },
    order: { 'type': Number },
    done: { 'type': Boolean, 'default': false }
  });

module.exports = mongoose.model('Todo', TodoSchema);

Andy 最后,这里是 ./routes:

(function (exports) {

  "use strict";

  var mongoose = require('mongoose')
    , crudUtils = require('../utils/crudUtils')
    , Todo = mongoose.model('Todo');

  function index(req, res) {
    res.render('index', { 'title': 'Backbone.js, Node.js, MongoDB Todos' });
  }

  exports.init = function (app) {
    app.get('/', index);
    crudUtils.initRoutesForModel({ 'app': app, 'model': Todo });
  };

}(exports));

所以我的问题是,路由模块中 mongoose.model('Todo') 中的 'Todo' 模型如何在此范围内可用?我看到模型模块正在导出 mongoose.model('Todo', TodoSchema);所以我必须相信这是路由模块访问它的方式,但我不知道为什么。我错过了什么?我有一种感觉,在这种情况下,它只是不完全理解范围。另外,我不确定路由功能匿名的原因。

非常感谢!

【问题讨论】:

    标签: javascript node.js backbone.js model-view-controller todomvc


    【解决方案1】:

    这是在开始使用 Node 和 Mongoose 时要处理的更令人困惑的事情之一。

    当您第一次require('mongoose') 时,它会创建一个 singleton 的 Mongoose 实例 - 以后每次需要它时都会返回相同的实例。

    这使得它非常容易使用,但有点“魔法”,一开始很难理解。

    这意味着当你在 app.js 中调用mongoose.connect("127.0.0.1", "todomvc", 27017); 时,它会创建一个与应用保持一致的连接。

    这也意味着mongoose.model('Todo', TodoSchema); 使 Todo 模型在通过mongoose.model('Todo') 调用require('mongoose') 的任何其他范围内可用。这可以在您require 的另一个文件的顶部(如上例所示)或您在回调中间需要它的那一刻进行 var'd。

    这是您将 Todo 模型放入您的 routes.js 的方式,并且有充分的理由确保告诉 Mongoose 您的模型是您在应用程序中首先要做的事情之一。

    回答您关于理解范围的问题;您require 的每个文件实际上都有自己的范围,并且除了进程之类的全局对象外,无法访问任何内容。您必须 require 处理您想要使用的所有内容,并且只能通过调用函数或创建通过 exports 对象公开的类来传递变量。

    因此,对于上面的实际示例,从 models.js 导出模型没有任何好处,因为它随后不会在需要 models.js 的应用程序中引用。正是 routes.js 中的这些行使 Todo 模型可用:

    var mongoose = require('mongoose')
    , Todo = mongoose.model('Todo'); // returns the Todo model that was registered by models.js
    

    这就是Todo在这一行的存在方式:

    crudUtils.initRoutesForModel({ 'app': app, 'model': Todo });
    

    将路由包装在匿名函数中也没有任何好处(据我所知),因为这基本上是由require 提供的。

    【讨论】:

    • 非常感谢!这清楚了很多。但是,如果我在 models.js 中注释掉 module.exports = mongoose.model('Todo', TodoSchema);,应用程序将无法显示“尚未为模型 'Todo' 注册架构”。是否需要该模式才能满足未来对 mongoose 的需求?
    • 抱歉,为了更清楚,您确实需要 mongoose.model('Todo', TodoSchema') 部分。这是向 mongoose 注册模型并使其随后可用的位。我的意思是你可以跳过module.exports = 部分,因为你没有使用你正在导出的内容。此外,如果您想向该 .js 文件添加更多模型并导出所有模型,您可能需要使用 exports.todoModel = ...,有关从模块导出的更多信息,请参阅 stackoverflow.com/questions/5311334/…
    【解决方案2】:

    您会想要查看 Express。

    Express 是一个最小且灵活的 node.js Web 应用程序框架,为构建单页和多页以及混合 Web 应用程序提供了一组强大的功能。

    您复制和粘贴的很多内容都使用了 Express Scaffold - 所以很多都是为您预先构建的,您可以在此处查看:http://expressjs.com/

    我希望这会为您指明正确的方向。

    【讨论】:

      猜你喜欢
      • 2017-03-28
      • 2012-06-01
      • 2017-06-24
      • 1970-01-01
      • 1970-01-01
      • 2016-09-13
      • 2020-04-24
      • 2012-01-28
      • 1970-01-01
      相关资源
      最近更新 更多