Nodejs express动态视图助手换locals快疯了,求指导

Nodejs express动态视图助手换locals快疯了,求指导

官方的文档和社区的帖子都看过了,就是不好使啊。 这是我的代码:

app.configure(function(){
	app.use(express.bodyParser());
	app.use(express.cookieParser());
	app.use(express.cookieSession({ key:"lgyCookie", secret: "mySecret" }));
	// 使用flash插件
	app.use(flash());
	// 动态全局变量
	app.use(function(req, res, next){
			app.locals({
			  inspect: function(obj) {
			    return util.inspect(obj, true);
			  }
			});
			next();
		}
	);
	app.use(app.router);
	routers(app);
	// 静态资源访问
	app.use(express.static(__dirname + '/html'));
	app.use(express.static(__dirname + '/html/js'));
	app.use(express.static(__dirname + '/html/css'));
	app.use(express.static(__dirname + '/html/img'));
});

ejs页面:

<div class=“navbar-inner”> <div class=“container”> <%=inspect(headers) %> <ul class=“nav pull-right”> <li><a href="/logout">退出</a></li> </ul> </div> 控制台报错:

inspect is not defined

10 回复

当然,可以帮你解决这个问题。问题出在你试图通过 app.locals 来动态添加局部变量,但 app.locals 应该是一个对象,而不是一个函数。我们可以使用中间件来将动态变量注入到视图中。

示例代码

首先,修改你的中间件部分,确保 app.locals 是一个对象,并且可以在所有路由中访问:

const express = require('express');
const app = express();
const bodyParser = require('body-parser');
const cookieParser = require('cookie-parser');
const session = require('express-session');
const flash = require('connect-flash');

// 中间件配置
app.use(bodyParser.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(session({ key: "lgyCookie", secret: "mySecret" }));
app.use(flash());

// 动态全局变量
app.use((req, res, next) => {
    res.locals.inspect = function(obj) {
        return require('util').inspect(obj, { showHidden: false, depth: null });
    };
    next();
});

// 路由配置
app.get('/', (req, res) => {
    res.render('index', { headers: req.headers });
});

// 静态资源
app.use(express.static(__dirname + '/html'));
app.use(express.static(__dirname + '/html/js'));
app.use(express.static(__dirname + '/html/css'));
app.use(express.static(__dirname + '/html/img'));

// 启动应用
app.listen(3000, () => {
    console.log('Server is running on port 3000');
});

解释

  1. 中间件:

    • res.locals 是一个特殊的对象,它在每次请求时都会被重置。你可以在这个对象上定义一些属性,这些属性将会传递给模板引擎。
    • 在中间件中,我们定义了一个 inspect 函数,并将其赋值给 res.locals.inspect。这样,每个请求都可以访问到这个函数。
  2. 视图模板:

    • 在 EJS 模板中,你可以直接使用 res.locals.inspect 定义的函数。例如,<%= inspect(headers) %> 会调用 inspect 函数并输出 headers 对象的字符串表示形式。

控制台错误

之前的错误 inspect is not defined 是因为 app.locals 是一个对象,而不是一个函数。通过将 inspect 添加到 res.locals 中,你可以确保它在每个请求中都能被正确访问。

希望这能帮助你解决问题!如果还有其他问题,请随时告诉我。


routers(app);
// 静态资源访问
app.use(express.static(__dirname + '/html'));
app.use(express.static(__dirname + '/html/js'));
app.use(express.static(__dirname + '/html/css'));
app.use(express.static(__dirname + '/html/img'));

放在路由器之前

// 静态资源访问
app.use(express.static(__dirname + '/html'));
app.use(express.static(__dirname + '/html/js'));
app.use(express.static(__dirname + '/html/css'));
app.use(express.static(__dirname + '/html/img'));

routers(app);

感谢回复,但是无济于事啊…

app.js

var myUtil = require(’./myUtil’); app.use(function(req, res, next){ res.locals.myUtil=myUtil; next(); }

myUtil.js

var MyUtil = function () { }; MyUtil.prototype.hello=function (name) { console.log('hello '+name); return 'hello '+name; } module.exports = new MyUtil();

index.ejs

<%=myUtil.hello(‘aaa’)%>

再次感谢你的回复~ 我按照你的建议把代码单独精简出来一个测试项目 试了一下还是不行啊,还是说user undefined这是我的所有代码,您运行一下试试 server.js

var express = require("express");
var ejs = require('ejs');
var fs = require("fs");
var user = require("./User");
var app = express();
var server = require('http').createServer(app);

function start(){ app.configure(function(){ app.use(express.bodyParser()); app.use(express.cookieParser()); app.use(express.cookieSession({ key:“lgyCookie”, secret: “mySecret” })); // 动态全局变量 app.use(function(req, res, next){ res.locals.user = user; next(); } ); });

app.get('/test', function(req, res){
	res.set({'Content-Type': 'text/html'});
	var tmp = fs.readFileSync('home.ejs', 'utf8');
	var html = ejs.render(tmp, {message:'lgyhitler'});
	res.send(html);
});

server.listen(8888);
console.log("服务器启动...");

}

exports.start = start;

User.js

/**
 * 用户实体
 */
function User(){
	
}
module.exports = new User();
/**
 * 根据用户名、密码获得用户
 * [@user](/user/user) 用户参数
 */
User.prototype.get = function (){
	console.log('lgyhitler !!!!!!!!');
	return 'lgyhitler!!!!!!!!';
}

index.js

var server = require("./server");
server.start();

视图用的ejs

home.ejs

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="content-type" content="text/html; charset=UTF-8" />
<link type="text/css" rel="stylesheet" href="bootstrap.css" />
<script type="text/javascript" src="jquery-1.7.min.js"></script>
</head>
<body>
	<%=user.get() %>
</body>
</html>

如果这是你的全部的代码,肯定是有问题的。

  1. ejs引擎,你并没有加载到app中。
  2. 路由也没有加载,app.use(app.router);

你先参考我放到 github的工程,让程序先运行起来。

问一下 一定要加载路由吗?我之前也没引用ejs引擎 就是直接render 也可以实现数据绑定。这2者对 我的问题缺一不可?

最近刚加入nodejs 发现和楼主一样的问题,本人已经解决,猜测这个问题的原因是:路由的顺序放在了app.use(fn)之前,这样请求就会直接走路由,而不调用req.locals.xxx

…中间件加载顺序呀 哥们 你被其他中间件return掉了

在你的代码中,app.locals 应该使用一个对象来定义局部变量,而不是直接调用 app.locals() 方法。你可以修改中间件函数中的 app.locals 定义方式,并确保该中间件在路由之前运行。

以下是修正后的代码:

var express = require('express');
var app = express();

app.configure(function(){
    app.use(express.bodyParser());
    app.use(express.cookieParser());
    app.use(express.cookieSession({ key: "lgyCookie", secret: "mySecret" }));
    
    // 使用flash插件
    app.use(flash());

    // 动态全局变量
    app.use(function(req, res, next) {
        app.locals.inspect = function(obj) {
            return require('util').inspect(obj, true);
        };
        next();
    });

    app.use(app.router);
    routers(app);

    // 静态资源访问
    app.use(express.static(__dirname + '/html'));
    app.use(express.static(__dirname + '/html/js'));
    app.use(express.static(__dirname + '/html/css'));
    app.use(express.static(__dirname + '/html/img'));
});

function routers(app) {
    app.get('/', function(req, res) {
        res.render('index', { headers: req.headers });
    });
}

app.listen(3000);

解释

  1. 定义中间件:中间件 app.use(function(req, res, next) {...}) 在每次请求时都会执行。你需要在这里设置 app.locals.inspect 属性,而不是调用 app.locals({...}) 方法。
  2. 设置 app.locals.inspect:这样可以在所有视图中直接使用 inspect 函数。
  3. 路由处理:在路由中,你可以将需要的数据传递给视图。例如,在根路径上渲染 index.ejs 视图,并传递 headers 数据。

EJS 页面

在 EJS 页面中,你可以直接使用 inspect 函数:

<div class="navbar-inner">
    <div class="container">
        <%= inspect(headers) %>
        <ul class="nav pull-right">
            <li><a href="/logout">退出</a></li>
        </ul>
    </div>
</div>

通过这种方式,你可以在任何视图中使用 inspect 函数,而不会出现 inspect is not defined 的错误。

回到顶部