4

Node は初めてで、ExpressJS ( http://expressjs.com/ ) を使用して MVC アプリを作成しようとしています。GitHubの MVC サンプル ( https://github.com/visionmedia/express/tree/master/examples/mvc )と同じフォルダー構造を使用しています。

controllers フォルダーには、main と system の 2 つのフォルダーがあります。私が望むのは、/controllers/system/index.js にベース コントローラーを定義し、/controllers/main/index.js にシステム コントローラーを継承させることです。他のすべてのモジュールはシステムを拡張し、いくつかの関数をオーバーライドしてページを生成します。

別のチュートリアルで、次のコードを見つけました。

Base.js

var _ = require("underscore");
module.exports = {
    name: "base",
    extend: function(child) {
        return _.extend({}, this, child);
    },
    run: function(req, res, next) {

    }
};

ホーム.js

var BaseController = require("./Base"),
    View = require("../views/Base"),
    model = new (require("../models/ContentModel"));

module.exports = BaseController.extend({ 
    name: "Home",
    content: null,
    run: function(req, res, next) {
        model.setDB(req.db);
        var self = this;
        this.getContent(function() {
            var v = new View(res, 'home');
            v.render(self.content);
        })
    },
    getContent: function(callback) {
        var self = this;
        this.content = {};
        model.getlist(function(err, records) {
            if(records.length > 0) {
                self.content.bannerTitle = records[0].title;
                self.content.bannerText = records[0].text;
            }
            model.getlist(function(err, records) {
                var blogArticles = '';
                if(records.length > 0) {
                    var to = records.length < 5 ? records.length : 4;
                    for(var i=0; i<to; i++) {
                        var record = records[i];
                        blogArticles += '\
                            <div class="item">\
                                <img src="' + record.picture + '" alt="" />\
                                <a href="/blog/' + record.ID + '">' + record.title + '</a>\
                            </div>\
                        ';
                    }
                }
                self.content.blogArticles = blogArticles;
                callback();
            }, { type: 'blog' });
        }, { type: 'home' });
    }
});

アンダースコアの拡張機能なしでこれを行うにはどうすればよいですか? Express には、モジュールを拡張するためのメソッドが組み込まれていますか? テンプレートに doT.js を使用しているため、1 つの関数に別の大きなライブラリを含めたくありません。

ありがとう!

編集: dc5 からベース コードを動作させるには、いくつかの変更を加える必要がありました。システムは機能しますが、メインの場合、継承呼び出しでこのエラーが発生します:

util.js:555
  ctor.prototype = Object.create(superCtor.prototype, {
                          ^
TypeError: Object prototype may only be an Object or null
    at Function.create (native)
    at Object.exports.inherits (util.js:555:27)

/controllers/system/index.js:

var util = require( 'util' ),
    system = { };

system.index = function( req, res, next ) {
    res.render( 'main' );
};

module.exports = system;

/controllers/main/index.js:

var util = require( 'util' ),
    system = require( './../system/index' ),
    main = { };

util.inherits( main, system );

module.exports = main;
4

2 に答える 2

9

説明したものにはutil.inheritsを使用できます。これは の代わりではありませんが、_.extend()上記の例に必要なのは単純な継承だけです。

使用法:util.inherits(constructor, superConstructor)

base.js:

var util = require('util');

function Base() {…}

Base.prototype.run = function(req,res,next) {…}
module.exports = Base;

ホーム.js:

var util = require('util');
var BaseController = require("./base");

function Home() {…}

util.inherits(home, BaseController);

Home.prototype.run = function(req,res,next) {…}

または、標準の JS 継承パターン:

base.js:

function Base() {…}

Base.prototype.run = function(req,res,next) {…}
module.exports = Base;

ホーム.js:

var BaseController = require("./base");

function Home() {
    BaseController.apply(this, arguments);
}

Home.prototype = Object.create(BaseController.prototype);
Home.prototype.run = function(req,res,next) {…}

質問の更新されたサンプルから、モジュールは次のようになります。

システム:

var util = require('util');

function System() {
    this.txt  = "hello from ";
    this.name = "System"; 
}

System.prototype.sayHello = function() {
    console.log(this.txt + this.name);
}

System.prototype.run = function(req,res,next) {
    this.sayHello();

    console.log('calling ==> overrideMe');
    this.overrideMe();

    console.log('calling ==> noOverride');
    this.noOverride();
    next ? next() : "";
}

System.prototype.overrideMe = function() {
    console.log('System.overrideMe');
}

System.prototype.noOverride = function() {
    console.log('System.noOverride');
}


module.exports = System;

主要:

var util = require('util');
var System = require("../system/");

function Main() {
    // Makes sure the System constructor is run
    System.apply(this, arguments);
    this.name = "Main"; 
}

util.inherits(Main, System);

Main.prototype.run = function(req,res,next) {
    this.sayHello();

    console.log('calling ==> overrideMe');
    this.overrideMe();

    console.log('calling ==> noOverride');
    this.noOverride();

    next ? next() : "";
}

Main.prototype.overrideMe = function() {
    console.log('Main.overrideMe');
}

module.exports = Main;

ルートの app.js - 簡素化された Express サーバー:

var System  = require('./controllers/system');
var Main    = require('./controllers/main');
var express = require('express');
var path    = require('path');
var http    = require('http');
var app     = express();
var server;

var system = new System();
var main   = new Main();

app.configure(function() {
    "use strict";
    app.set('port', process.env.PORT || 3000, '127.0.0.1');
    app.use(system.run.bind(system));
    app.use(main.run.bind(main));
    app.use(app.router);
    //app.use(express.compress());
    app.use(express.static(path.join(__dirname, '..', 'public'), {redirect: false}));
    app.use(express.static(path.join("/Users/dave/personal/playground/yo"), {redirect: false}));
});


server = http.createServer(app);
server.listen(app.get('port'), function() {
    "use strict";
    console.log("Express server listening on port " + app.get('port'));
});

ブラウザ アクセスから:http://localhost:3000/

コンソール出力:

Express server listening on port 3000
hello from System
calling ==> overrideMe
System.overrideMe
calling ==> noOverride
System.noOverride
hello from Main
calling ==> overrideMe
Main.overrideMe
calling ==> noOverride
System.noOverride

重要

この例ではSystemとのインスタンスを使用Mainしてルートを提供してrunいるため、express に渡すときにメソッドをインスタンスにバインドする必要があります。詳細については、 MDN .bind ドキュメントを参照してください。

于 2013-09-07T00:14:51.030 に答える