入门node.js你必须知道的那些事
最基本的一些操作和概念
用node执行一段js代码
在命令行中用cd切换到桌面
创建一个文件夹和并用cd命令切换到这个文件夹
mkdir nodeTest && cd nodeTest-
创建一个js文件并写上简单的js代码
touch a.js
`var a = 10; console.log(a); console.log(a + 10);
`
在命令行中输入node a.js
命令行会输出 10 20
node引用文件的方式
Node.js采用了CommonJS规范,通过require来引入一个js文件
-
新建文件b.js 并在文件中引入a.js
touch b.js
require('./a.js')
-
执行b.js
node b.js 命令行会输出10 20
node中的模块概念
node中一个模块就是一个js文件,多个模块组成一个特定功能的一堆文件叫包
-
一个js文件可以定义它自己暴露给外部的变量(意思就是另一个文件通过require引用它后需要怎么使用它),node中提供共了exports和module.exports两个变量来实现它
a.js
function func1() { console.log('aaa') } function func2() { console.log('bbb') } exports.a = func1 exports.b = func2
b.js
var a = require('./a.js') a.a() //会打印出aaa a.b() //会打印出bbb
c.js
//es6 模式匹配写法 var {fun1,fun2} = require('./a.js')//fun1和fun2必须跟a.js中的变量名相同,这里是固定的 fun1() //会打印出aaa fun2() //会打印出bbb
a.js
//类的写法 function Test() { this.func1 = function() { console.log('aaa') } this.func2 = function() { console.log('bbb') } } module.exports = Hello
b.js
var Test = require('./a.js') var test = new Test() test.func1() test.func2()
exports 和 module.exports 的关系
exports 是module.exports的一个引用,意思就是指向同一块内存地址,node中真正生效的是module.exports,修改exports本质上也是修改module.exports的值,
比如exports.a = 3,实际上module.exports.a也是等于3的
又比如exports = {},这样exports就和module.exports的指向的对象就不一样了,后面再怎么修改exports也不会影响到module.exports的值,也不会影响到文件输出的变量
再比如module.exports={},这样造成的效果和上面exports={}的效果是一样的这里表达有问题,虽然module.exports={}和exports={}都是让exports与module.exports的引用指向不同了,但是最后的效果实际上是不一样的,具体用法参考评论区。感谢@琪琪好笨笨 指出的错误
建议:如果你还傻傻分不清楚它们的区别,以后在不是必须用到module.exports的时候只用exports,如果导出一个类这样的必须用到module.exports就不要使用exports了,不要混在一起用就不会出错了
node中的npm
node中默认自带了npm,npm是一个包管理器,上面说到包就是一个个模块(js文件)组成的一个具有特定功能的一堆js文件,通过npm我们可以引入这些包(如果不理解,把包理解成一个个插件也没有错)来轻松实现一些功能
安装一个模块你只需要npm install xxx 就可以安装了,然后在你自己的js中用var xxx = require('./xxx')就可以使用了
通过npm install xxx 安装完xxx模块后,你会发现当前目录下多了一个node_modules文件夹,打开node_modules文件夹你会发现里面有一个xxx文件夹。你在执行npm install xxx的时候,实际上npm也只是帮你把xxx这个包下载下来了而已,仅此而已
当你通过npm安装了十来个或者更多的包的时候你可能自己早就不知道自己安装了哪些包了,因为很多包依赖了其它的包(一个包用到另一个包提供的功能是非常正常的行为,就像我们在用别人包里的功能一样),所以npm提供了package.json这个文件来管理包
package.json 是一个文件,里面可以定义很多键值对,其中有几个字段非常重要,dependencies表示上线运行时依赖的包,devDependencies表示开发时依赖的包,scripts可以定义自己的脚本,main表示所有的包你都会通过这个文件引入
当你在dependencies和devDependencies定义好依赖,然后在命令行中输入npm install,npm就会帮你自动安装好这些包;反过来你在命令行中输入npm install xxx --save后npm就会在package.json中的dependencies自动加上xxx,如果执行的是npm install xxx --save-dev 就会在devDependencies中自动加上xxx。
而在scripts中定义的脚本就直接可以在命令行中运行了,如果还弄不懂,可以看一下我的另一篇文章,如何制作自己的npm包
node.js中自带的那些模块
http模块
使用别人的模块,其实就是使用别人写好的方法(函数),只需要搞清楚别人提供的方法是怎么用的就可以了,可以查node.js官网查api或者看看网上写的教程就好。
下面演示了一个最简单的http模块的使用方法,在当前目录下在命令行中输入node test.js,http会挂起一个监听,只需要在浏览器中输入http://localhost:8000,test.js就会跟浏览器返回
显示在页面上:
hello world
test.js
var http = require('http')
var callBack = function(req, res) {
res.write('hello world')
res.end()
}
http.createServer(callBack).listen(8000)
url模块
在http模块的例子中传入了一个回调函数,两个参数分别是request和response,前者是浏览器传给我们的对象,后者是我们传给浏览器的对象。
其中req中包含了url这个属性,可以在回调函数中把它打印出来
console.log(req.url)
,加入你在浏览器中输入的是:http://localhost:8000/aaa/bbb?abc=3,那么打印出来的值是:/aaa/bbb?abc=3在这里我们需要使用到的是/aaa/bbb和abc=3分开来的结果,node给我们提供了一个处理url的模块,就叫做url模块.当然如果你自己想处理这个url也是完全可以的,用正则表达式就可以,但是已经有现成的为啥不用呢
下面简单演示一下用法,在浏览器输入:http://localhost:8000/aaa/bbb?abc=3
test.js
var http = require('http')
var url = require('url')
var callBack = function(req, res) {
var urlString = url.parse(req.url)
var path = urlString.pathname
var query = urlString.query
console.log(path,query)//打印出/aaa/bbb abc=3
res.write('hello world')
res.end()
}
http.createServer(callBack).listen(8000)
fs模块
fs是一个提供文件操作功能的模块,可以对文件进行读写存删等操作,下面演示向浏览器返回本js的内容:
test.js
var http = require('http')
var fs = require('fs')
var callBack = function(req, res) {
fs.readFile('./test.js', 'utf-8', function(err, data) {
res.write(data)
res.end()
})
}
http.createServer(callBack).listen(8000)
用http模块、url模块、http模块搭建一个静态服务器
var http = require('http')
var url = require('url')
var fs = require('fs')
var callBack = function(req, res) {
var pathname = url.parse(req.url).pathname
if (pathname == '/') {
pathname = '/index.html'
}
fs.readFile('.' + pathname, 'utf-8', function(err, data) {
if (err) {
res.write('Error 404')
} else {
res.write(data)
}
res.end()
}
)}
http.createServer(callBack).listen(8000)
使用外部模块
简单说明
外部模块都是第三方提供的模块,node.js默认是不提供的,所以需要用npm安装,这里提供package.json文件,只需要执行npm install 安装就行了,另外是管理MongoDB数据库的一个包,所以本地需要把MongoDB单独安装一下。
package.json
{
"dependencies": {
"cheerio": "^1.0.0-rc.2",
"eventproxy": "^1.0.0",
"express": "^4.16.2",
"koa": "^2.4.1",
"superagent": "^3.8.1"
}
}
express
express提供了基本的路由和静态文件访问的功能,当然还有其它的功能,这里主要演示它的基本使用
下面1,2,3都是设置public和files目录下为静态文件,可以直接通过文件路径访问,1、2可以同时存在,即可以指定几个目录均为静态文件目录,在指定目录为静态文件后,访问静态文件需要省略这个目录,比如访问public目录下的css/index.css:localhost:8000/css/index.css,直接省略了public,
可以通过3来指定替换目录名称的路径,通过3设置后,要访问public下的css/index.css:localhost:8000/public/css/index.css
var express = require('express')
var app = express()
1. app.use(express.static('public'))
2. app.use(express.static('files'))
3. app.use('/static',express.static(public))
app.get('/', function (req, res) {
res.send('Hello World');//一个回调方法对应一个路径
})
app.get('/user', function (req, res) {
res.send('user');
})
app.listen(8000, function () {
console.log('app is listening at port 3000');
})
superagent、cheerio模块
superagent是一个可以发http请求的模块,回调函数中的res就是请求到的内容
cheerio是在服务器端类式jquery的框架,看代码应该能看出来
下面演示的是抓取糯米网的餐品列表链接
var superagent = require('superagent')
var cheerio = require('cheerio')
var spideUrl = 'https://t10.nuomi.com/pc/t10/index'
superagent.get(spideUrl)
.end(function(err, res) {
if (err) {
return console.error(err);
}
var foodUrls = [];
var $ = cheerio.load(res.text)
// 获取首页所有的链接
$('.j-item a').each(function(idx, element) {
var $element = $(element)
foodUrls.push($element.attr('href'))
})
console.log(topicUrls)
})
eventproxy
在爬取一堆类式的链接的时候,一个个链接写挺麻烦的,eventproxy提供了监听,然后触发回调的方式来处理这类问题,下面是我拷贝的一段代码,应该挺容易看懂的
//得到一个 eventproxy 的实例
var ep = new eventproxy()
// 命令 ep 重复监听 urls.length 次(在这里也就是 10 次)
ep.after('topic_html', urls.length, function (topics) {
topics = topics.map(function(page) {
var $ = cheerio.load(page)
var userId = $('.runUserName a font').eq(0).text()
return userId
});
console.log(topics);
})
urls.forEach(function(item) {
superagent.get(item)
.end(function (err, res) {
ep.emit('topic_html', res.text)
})
})
总结
大部分学习前端其实是没必要深入学习node.js的,一方面没那个精力,然后也没那么必要,但是一些基本的东西还是有必要好好学学的
大多数前端同学之所以觉得应该学前端,其实是平时接触到的npm、require模块、es6的语法等问题觉得比较棘手,以为是自己不懂node.js,其实这些和node.js并无太大关系,这些已经影响到学习前端其它内容的地方还是需要好好学习的
学习node.js基本的东西还是有必要的,比如搭建个简单的服务器,做点基本的逻辑处理和数据处理,做个爬虫啥的。而这些都很简单,看两篇博客做几个练习就够了,再深入就根据实际情况学习就好了。