2016-10-10 65 views
0

我对Web应用程序有相当标准的要求,其中大多数页面将使用单个布局进行呈现(我使用的是把手,但同样适用于Jade或其他任何东西)。我应该如何在express.js页面布局中填充数据

布局使用数据库中相当多的数据,可能需要多次查找。我应该如何构造代码,以便不必在每个控制器中为每个页面/路径检索布局使用的数据?在许多Web框架中,有一种简单的方法可以通过模式拦截路由,并让拦截器进行所需的查找,装饰由控制器生成的模型并将其包装起来。

感觉应该有一些方法可以用中间件的正确定义来做到这一点,但我无法弄清楚。

寻找的东西做什么我下面的伪代码显示:

router.get('/', ctrlPublic.index); 
router.get('/index.html', ctrlPublic.index); 
router.get('/find-us.html', ctrlPublic.findUs); 

// apply same interceptor to all (/*) 
router.intercept('/*', ctrlDecorator.main); 

// ctrlPublic... 
index: function(req, res) { 
    // get data for index page, then render index.hbs 
}, 
findUs: function(req, res) { 
    // get data for find-us page, then render find-us.hbs 
} 

// ctrlDecorator... 
main: function(req, res) { 
    // lookup data needed by main layout - this gets automatically 
    // added to the model used by the page ctrlPublic handlers 
} 

我会非常喜欢的拦截目标的模式匹配,而不是申报的router.get()呼叫控制器,并为他们是添加剂等等多于一个可以适用于某一组控制器。

有没有一个模块可以帮助你做到这一点,或者只是一个通用的“最佳实践”方式来实现它?

回答

1

如果我理解您的问题,您需要一个全局中间件来获取数据并将其传递给相应的控制器,以便您不会在控制器上加载相同的布局数据?

在这种情况下,建立一个全球性的中间件

app.use(function(req, res, next){ 
    var excludeMiddleware = ['login', 'test', 'test2']; 
    //simple example for bypassing the middleware 
    for(var i = 0; i < excludeMiddleware.length; i++){ 
     if(excludeMiddleware[i] === req.path) { return next(); } 
    }     

    someAsyncFnFromDb.then(function(dataFromDb){ 
     //req.layoutData = dataFromDb;   
     res.locals.layoutData = dataFromDb; 
     return next(); 
    }).catch(function(err){ 
     return next(); // or throw new Error(err) 
    }); 
}); 

,并在控制器的数据分配给渲染功能,如果您使用req.layoutData,例如

res.render('myView', { layoutData: req.layoutData }); 

或者留下您的控制器是,如果你使用res.locals.layoutData,layoutData将在您的视图中可用。

+0

是的,您对数据使用的理解是正确的,像这样的解决方案也可以缓存我也需要的布局数据。但是,如何改变中间件的使用涉及到更改潜在的许多控制器和路由的声明,这似乎很不雅观。例如,这种中间件可以按照约定或模式匹配来应用,而不是在每个控制器中重复它? – darrend

+0

如果您在定义任何路由之前定义了该中间件,那么它将自动注入到每个路由中,并且如果将'req.layoutData = dataFromDb;'更改为'res.locals.layoutData = dataFromDb;',那么您不需要更改任何内容你的控制器layoutData将在每个模板上都可用。现在对于模式匹配,如果你不需要加载layoutData,你可以排除一些路由。我举了一个例子来看更新的答案。 –

+0

好的,是的,它更好,但拦截器(中间件)知道控制器以便排除它们有点落后。我起初有点惊讶,我以为我错过了一些express的一流功能,因为我用在其他语言中的每个web框架都具有这种性质。我想sailsjs.org是为快速应用程序提供这种更高级别的功能的集合..似乎更多的是我从扫视后看到的。 – darrend