中国石凳联盟 登录注册

【原创】Node.JS各种FAQ汇总

rockage··1 回复·175 浏览

发表回复
本帖最后由 rockage 于 2017-12-26 02:52 编辑

名词解释:
NodeJS : 简单的说 就是运行在服务端的 JavaScript,
Express : 是基于NodeJS的一个WEB 框架,
Handlebars : 是一个将视图(View)和数据(Data)相分离的Web模板,
BootStrap :来自 Twitter,是目前最受欢迎的前端框架,可以大大简化UI设计与特效的实现;
JQuery :是一个 JavaScript 库, 它极大地简化了 JavaScript 编程。

1. app.render和res.render的区别? 【express】

app.render('email', { name: 'Tobi' }, function(err, html){
  // ...
});
res.render('email', {
name:'Tobi'
});
答:本质上没有区别,都是起最终页面渲染的作用。
区别是,res.render将渲染的结果直接传送到浏览器并刷新,很像我们打开一个新网址那意思。
而app.render不刷新浏览器,它产生一个回调函数,完成后,将被渲染后的html代码通过变量"html"回传回来。
有一些需要局部刷新的场合,比如说有动态内容的弹出式窗口,就需要用到app.render


2. popover弹出窗口太窄怎么办? 【bootstrap】
答:直接修改bootstrap.min.css源代码,先定位 【.popover】 , 然后在它附近找max-width,强设为2048px即可,
实践证明,此问题没有太多优雅的解决方案,建议强行修改完事。


3. 报错:express deprecated res.send(status): Use res.sendStatus(status) instead 是为何? 【express】
答:___________________________
首先,什么是路由(router)?
很多年前,网站的功能往往都是用一个存放在服务器上的文件来实现,比如用户管理模块,有user.asp或user.php ...等等,
我们一般通过【http://网站/文件名.php】这种形式的URL来访问,这种方法其实也没毛病,但是它有一个致命弊端就是很难做到程序与页面的分离,

如果对传统WEB编程还有印象的人,一定不会忘记,那时候的常规做法就是将程序内嵌到HTML中,但这种混杂着php或者asp的html页面比较凌乱,
难以维护,还有一个更严重的问题是前端和后端开发的往往不是同一个人,这种混杂型页面在单枪匹马的时候尚也问题不大,但是一旦进入团队协作,就会让人抓狂。
细心的人会发现,事实上,时至今日我们已经很难再看到以往那种以.asp或者.php为结尾的网址了,取而代之的是各种不带后缀的功能路径网址,
类似:http://www.myweb.com/user 这种。这就是本文所指的所谓“新办法”。
简单的说,路由的概念就是来了一个URL,找到一个控制器中的方法,然后实时将数据填充入html中相应的位置上,并将渲染之后的html代码推送到浏览器。
一句话攻略:
老办法:访问的是某个服务器上的某个物理文件,文件内部的程序控制数据,HTML代码是“生成”出来的。
新办法:访问的不是一个具体文件,而是一个程序接口,这个接口控制数据,将数据与预设好的HTML模板相结合,HTML代码是“渲染”出来的。


___________________________
nodejs不建议在同一个路由(router,)里使用两次res.send(),即使是在逻辑无误的判断里也不行,当然这只是个Warning(警告),
不建议,但也不碍事。比如这种:
if (x==y) {res.send 'ok'} else {res.send 'no'}
编译器会弹出一个警告。
正确的方法是针对每一种服务器状态提供不同的返回值,修改如下:
if (x==y) {res.status(200).send 'ok'} else {res.status(500).send 'no'} //状态500为服务器异常,200为服务器正常,类似的还有404:找不到页面等。
另外还需要注意的是,nodejs并不能直接返回数值,而只能是字符串、数组、JSON对象等,比如res.send(x),如果x是一个整数,那么就会报错,解决方法极其简单:res.send(String(x))即可。


4. 模态窗(modal)不垂直居中怎么办? 【bootstrap】

修改源文件bootstrape.js ,查找“Modal.prototype.adjustDialog”,修改文件如下:
--------------------
Modal.prototype.adjustDialog = function () {
var modalIsOverflowing = this.$element[0].scrollHeight > document.documentElement.clientHeight


this.$element.css({
paddingLeft: !this.bodyIsOverflowing && modalIsOverflowing ? this.scrollbarWidth : '',
paddingRight: this.bodyIsOverflowing && !modalIsOverflowing ? this.scrollbarWidth : ''
})
// 弹出框居中:
var $modal_dialog = $(this.$element[0]).find('.modal-dialog');
var m_top = ( $(window).height() - $modal_dialog.height() )/2;
$modal_dialog.css({'margin': m_top + 'px auto'});
}--------------------
绿色部分是新增上去的。


4. 使用res.render构建一个动态网页需要注意的内容是什么? 【express/handlebars】
a) res.render只有在首次加载的时候会主动将渲染结果传送到浏览器,
比如说你有两个路径:
1.router.get("/")
2.router.get("/test")
在执行第1个router时,res.render将渲染后的html代码立即传递到浏览器,然后生产页面。
在执行第2个router时,res.render只在回调函数里生成html代码,而并不会直接传递到浏览器,不刷新页面。
那么问题来了,如果确实需要整体刷新或者局部刷新页面该怎么办?
我们可以将需要刷新的内容放在一个div里,这个div可大可小,甚至可以将整个页面都包含在里面,
前端通过ajax向服务器提出post申请,然后在callback里获得渲染后的html代码,
最后将这些html代码(局部的或者时整体的)灌入div中,达到即时刷新的目的。

前端index文件名:index.hbs (.hbs是前端引擎handlebars的缩写,其他引擎也类似)
前端还有两个不同的页面,比如说一个页面管理用户(user),另一个管理产品(products)
现在要求在不刷新页面的情况下,对index.hbs进行动态渲染,需要显示user的时候渲染user模板,
需要显示products的时候渲染products模板,而index.hbs则像是一个容器,里面的内容不停在变,
但作为容器本身不变。

前端index html代码:<html>
<body>
<div id="test_div"></div>
</body>
</html>
前端html代码就这么简单,整个页面依靠一个id名为"test_div"的div层实现。

前端JS代码:
<script>
$.post("/test/",
{ id: 1 },
function (data, status) {
if (data != 'error') {
$("#test_div").html(data);
} else { alert('程序发生了一些错误,更新失败。') } //IF
});
});
</script>
前端负责将html代码灌入div层的JS代码也很简单。

服务器端index JS代码:
//第一种情况:直接访问根路径
router.get('/', function (req, res, next) {
res.render('index.hbs');
}); //访问根路径非常简单,即将index.hbs这个容器渲染到浏览器即可。


//但是,容器里面放什么内容,由以下代码实现:
router.post('/test/', function (req, res) {
var template;
if (req.body.id==1){template="user.hbs"
}else{template="products.hbs"};

app.render(template, {
layout: null,
datas: data
}, function (err, html) {
res.send(html);
}); //render
}); //router

根据前端post过来的id,决定装载哪个模板,达到实时渲染的目的(user.hbs或products.hbs)
请注意!对用户来说,此时浏览器尽管依然保持着index.hbs这个url不变,但页面的内容,
即<div id="test_div">这个层,却是在user和products之间不停刷新着的。

注意事项:如果模板里需要用到DOM,那么请将<script>标签本身也放进模板中去,因为若非如此,
则第一次装载页面OK,第二次<div>实时刷新后,原来的JS或者JQuery之类的操作DOM的命令将会失效,
因为都已经不是之前那颗DOM树了,各种ID失效乃是情理之中,鉴于此,我建议干脆把这些<script>
都放进模板,每次实时渲染后,这些script会随着页面动态刷新,也只能这样才能让我们在异步刷新
的前提下对动态DOM树进行操作。

4. 如何彻底关闭modal窗口,包括遮盖层? 【bootstrap】

当我们使用bootstrap的弹出式模式窗口时,按关闭按钮没问题,但是按下确定按钮后,页面背景会被套上一层
黑黑的遮盖层,即使我们手动添加$('#myModal').modal('hide')也没有用,窗口倒是关闭了,但是遮盖层还是会把页面挡住,
如何彻底关闭modal窗口,包括这层backdrop呢?很简单,用以下命令即可:
$("#myModal").removeClass('fade').modal('hide')


5.如何正确安装electron?
答:npm install electron -g --verbose
如果不带 --verbose,会卡在最后一步不动弹,加了这个参数一切ok

6. 如何正确设置node-http-proxy ?
var express = require('express');
var app = express();
var proxy;
var http = require('http');
var https = require('https');
var httpProxy = require('http-proxy');
var url = require('url');

proxy = httpProxy.createProxy({});

proxy.on('error', function(err) {
  console.log('ERROR');
  console.log(err);
});

app.use('/', function(req, res) {

  var finalUrl = 'http://stoneren.net';
  var finalAgent = null;
  var parsedUrl = url.parse(finalUrl);

  if (parsedUrl.protocol === 'https:') {
    finalAgent = https.globalAgent;
  } else {
    finalAgent = http.globalAgent;
  }

  proxy.on('proxyReq', function(proxyReq, req, res, options) { //Request 发出
  //console.log ('准备发送到服务器的Header:' +proxyReq)
  })

  proxy.on('proxyRes', function(proxyRes, req, res) {
  //  console.log('服务器Header回传:', JSON.stringify(proxyRes.headers, true, 2));
  });

  proxy.web(req, res, {
    target: 'http://stoneren.net',
    agent: finalAgent, //http
    headers: {
      host: 'localhost:3000', //host是关键!
      hostname: '', //好像不设也没影响
      href: '' //好像不设也没影响
    },
    prependPath: false,
    xfwd: true,
    //hostRewrite: finalUrl.host,
    protocolRewrite: parsedUrl.protocol
  });

})
module.exports = app;
以上是一个能够运行的例子!这段历程对我而言非常心酸,以后有空再专门写一篇长文回忆。




点赞0 收藏
这么大年纪了,还搞这个,不容易呀`~~~~~~~`
Being a devil is the same as being a human. We should be kind. If we are kind, we are not a devil, we are a hybrid.
点赞0 收藏
发表回复
发表回复