Node.js①

相应视频地址-Node.JS-黑马程序员

1. 认识Node.js

1.1 Node.js是什么

  • Node.js是JavaScript 运行时
  • 通俗易懂的讲,Node.js是JavaScript的运行平台
  • Node.js既不是语言,也不是框架,它是一个平台
  • 浏览器中的JavaScript
    • EcmaScript
    • BOM
    • DOM
  • Node.js中javaScript
    • 没有BOM,DOM
    • EcmaScript
    • 在Node中这个JavaScript执行环境为JavaScript提供了一些服务器级别的API
      • 文件的读写
      • 网络服务的构建
      • 网络通信
      • http服务器
  • 构建与Chrome的V8引擎之上
    • 代码只是具有特定格式的字符串
    • 引擎可以认识它,帮你解析和执行
    • Google Chrome的V8引擎是目前公认的解析执行JavaScript代码最快的
    • Node.js的作者把Google Chrome中的V8引擎移植出来,开发了一个独立的JavaScript运行时环境
  • Node.js uses an envent-driven,non-blocking I/O mode that makes it lightweight and efficent.
    • envent-driven 事件驱动
    • non-blocking I/O mode 非阻塞I/O模型(异步)
    • ightweight and efficent. 轻量和高效
  • Node.js package ecosystem,npm,is the larget scosystem of open sourcr libraries in the world
    • npm 是世界上最大的开源生态系统
    • 绝大多数JavaScript相关的包都存放在npm上,这样做的目的是为了让开发人员更方便的去下载使用
    • 例如:npm install jquery

1.2 Node.js能做什么

  • web服务器后台
  • 命令行工具
    • npm(node)
    • git(C语言)
    • hexo(node)
  • 对于前端工程师来讲,接触最多的是它的命令行工具
    • webpack
    • gulp
    • npm

1.3 安装Node环境

  • 查看Node环境的版本号
  • 下载:https://nodejs.org/en/
  • 安装:
    • 傻瓜式安装,一路next
    • 安装过再次安装会升级
  • 确认Node环境是否安装成功
    • 查看node的版本号:node --version
    • 或者node -v
  • 配置环境变量

1.4 解析执行JavaScript

  1. 创建编写javaScript脚本文件
  2. 打开终端,定位脚本文件所在目录
  3. 输入node 文件名执行对应文件

注意:文件名不要用node.js来命名,也就是说除了node这个名字随便起,最好不要用中文。


2. 文件的读写(fs文件操作模块)

2.1 读取文件readFile

//浏览器中的JavaScript是没有文件操作能力的
//但是Node中的JavaScript具有文件操作能力
//fs是file-system的简写,就是文件系统的意思
//在Node中如果想要进行文件的操作就必须引用fs这个核心模块
//在fs这个和兴模块中,就提供了人所有文件操作相关的API
//例如 fs.readFile就是用来读取文件的

//  1.使用fs核心模块
const fs = require('fs')

// 2.读取文件
fs.readFile('./data/a.txt', (err,data) => {
    if (err) {
        console.log('文件读取失败')
    }
    else {
         console.log(data.toString())
    }
})

2.2 写入文件writeFile

//  1.使用fs核心模块
const fs = require('fs')

// 2.将数据写入文件
fs.writeFile('./data/a.txt', '我是文件写入的信息', (err,data) => {
    if (err) {
        console.log('文件写入失败')
    }
    else {
        console.log(data.toString())
    }
})

2.3 读取目录 readdir

// readdir(‘读取文件的文件目录路径’,function(err,files){})读取目录

const fs = require('fs')

fs.readdir('D:/Movie/www', function (err, files) {
  if (err) {
    return console.log('目录不存在')
  }
  console.log(files)
})
//得到一个数组例如  ['a.txt','apple','img']

3. HTTP服务(http网络服务构建模块)

3.1 最简单的http服务

  • 你可以使用 Node 非常轻松的构建一个 Web 服务器
  • 在 Node 中专门提供了一个核心模块:http
  • http 这个模块的职责就是帮你创建编写服务器的
// 1. 加载 http 核心模块
const http = require('http')

// 2. 使用 http.createServer() 方法创建一个 Web 服务器
//    返回一个 Server 实例
const server = http.createServer()

// 3. 服务器要干嘛?
//    提供服务:对 数据的服务
//    发请求
//    接收请求
//    处理请求
//    给个反馈(发送响应)
//    注册 request 请求事件
//    当客户端请求过来,就会自动触发服务器的 request 请求事件,然后执行第二个参数:回调处理函数
server.on('request', (request,response) => {
  console.log('收到客户端的请求了')
})

// 4. 绑定端口号,启动服务器
server.listen(3000, () => {
  console.log('服务器启动成功了,可以通过 http://127.0.0.1:3000/ 来进行访问')
})

// ##################简写
const http = require('http')
http
  .createServer((req, res) => { // 创建Web服务
  })
  .listen('3000', () => { // 绑定端口,启动服务
    console.log('Server is Running…');
  })

3.2 发送响应

const http = require('http')

const server = http.createServer()

// request 请求事件处理函数,需要接收两个参数:
//    Request 请求对象
//        请求对象可以用来获取客户端的一些请求信息,例如请求路径
//    Response 响应对象
//        响应对象可以用来给客户端发送响应消息
server.on('request', function (request, response) {
  // http://127.0.0.1:3000/ /
  // http://127.0.0.1:3000/a /a
  // http://127.0.0.1:3000/foo/b /foo/b
  console.log('收到客户端的请求了,请求路径是:' + request.url)

  // response 对象有一个方法:write 可以用来给客户端发送响应数据
  // write 可以使用多次,但是最后一定要使用 end 来结束响应,否则客户端会一直等待
  response.write('hello')
  response.write(' nodejs')

  // 告诉客户端,我的话说完了,你可以呈递给用户了
  response.end()
})

server.listen(3000, function () {
  console.log('服务器启动成功了,可以通过 http://127.0.0.1:3000/ 来进行访问')
})

3.3 根据不同请求路径,返回不同数据

const http = require('http')
// 1. 创建 Server
const server = http.createServer()

// 2. 监听 request 请求事件,设置请求处理函数
server.on('request', function (req, res) {
  console.log('收到请求了,请求路径是:' + req.url)
  console.log('请求我的客户端的地址是:', req.socket.remoteAddress, req.socket.remotePort)
  // res.write('hello')
  // res.write(' world')
  // res.end()

  // 上面的方式比较麻烦,推荐使用更简单的方式,直接 end 的同时发送响应数据
  // res.end('hello nodejs')

  // 根据不同的请求路径发送不同的响应结果
  // 1. 获取请求路径
  //    req.url 获取到的是端口号之后的那一部分路径
  //    也就是说所有的 url 都是以 / 开头的
  // 2. 判断路径处理响应

  let url = req.url

  if (url === '/') {
    res.end('index page')
  } else if (url === '/login') {
    res.end('login page')
  } else if (url === '/products') {
    let products = [{
        name: '苹果 X',
        price: 8888
      },
      {
        name: '菠萝 X',
        price: 5000
      },
      {
        name: '小辣椒 X',
        price: 1999
      }
    ]
    // 响应内容只能是二进制数据或者字符串           数字  对象  数组  布尔值
    res.end(JSON.stringify(products))
  } else {
    res.end('404 Not Found.')
  }
})

// 3. 绑定端口号,启动服务
server.listen(3000, function () {
  console.log('服务器启动成功,可以访问了。。。')
})

3.4 IP地址和端口号

  • ip地址用来定位计算机
  • 端口号用来定位具体的应用程序
  • 所有需要联网通信的应用程序都会占用一个端口号
const http = require('http')
const server = http.createServer()

// 2. 监听 request 请求事件,设置请求处理函数
server.on('request', function (req, res) {
  console.log('收到请求了,请求路径是:' + req.url)
  console.log('请求我的客户端的地址是:', req.socket.remoteAddress, req.socket.remotePort)

  res.end('hello nodejs')
})

server.listen(5000, function () {
  console.log('服务器启动成功,可以访问了。。。')
})

3.5 Content-Type (响应内容类型)

解决node中乱码问题 HTTP Content-type对照表

  • 在服务端默认发送的数据,其实是 utf8 编码的内容,但是浏览器不知道你是 utf8 编码的内容
  • 浏览器在不知道服务器响应内容的编码的情况下会按照当前操作系统的默认编码去解析, 中文操作系统默认是 gbk
  • 解决方法就是正确的告诉浏览器我给你发送的内容是什么编码的
  • 在 http 协议中,Content-Type 就是用来告知对方我给你发送的数据内容是什么类型
res.setHeader('Content-Type', 'text/plain; charset=utf-8')
res.end('hello 世界')
  • Content-Type
    • 服务器最好把每次响应的数据是什么内容类型都告诉客户端,而且要正确的告诉
    • 不同的资源对应的 Content-Type 是不一样,具体参照:http://tool.oschina.net/commons
    • 对于文本类型的数据,最好都加上编码,目的是为了防止中文解析乱码问题
    • 通过网络发送文件
      • 发送的并不是文件,本质上来讲发送是文件的内容
      • 当浏览器收到服务器响应内容之后,就会根据你的 Content-Type 进行对应的解析处理
// 1. 结合 fs 发送文件中的数据
// 2. Content-Type
//    http://tool.oschina.net/commons
//    不同的资源对应的 Content-Type 是不一样的
//    图片不需要指定编码
//    一般只为字符数据才指定编码

const http = require('http')
const fs = require('fs')

const server = http.createServer()

server.on('request', function (req, res) {
  // / index.html
  let url = req.url

  if (url === '/') {
    // 肯定不这么干
    // res.end('<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><title>Document</title></head><body><h1>首页</h1></body>/html>')

    // 我们要发送的还是在文件中的内容
    fs.readFile('./resource/index.html', function (err, data) {
      if (err) {
        res.setHeader('Content-Type', 'text/plain; charset=utf-8')
        res.end('文件读取失败,请稍后重试!')
      } else {
        // data 默认是二进制数据,可以通过 .toString 转为咱们能识别的字符串
        // res.end() 支持两种数据类型,一种是二进制,一种是字符串
        res.setHeader('Content-Type', 'text/html; charset=utf-8')
        res.end(data)
      }
    })
  } else if (url === '/xiaoming') {
    // url:统一资源定位符
    // 一个 url 最终其实是要对应到一个资源的
    fs.readFile('./resource/ab2.jpg', function (err, data) {
      if (err) {
        res.setHeader('Content-Type', 'text/plain; charset=utf-8')
        res.end('文件读取失败,请稍后重试!')
      } else {
        // data 默认是二进制数据,可以通过 .toString 转为咱们能识别的字符串
        // res.end() 支持两种数据类型,一种是二进制,一种是字符串
        // 图片就不需要指定编码了,因为我们常说的编码一般指的是:字符编码
        res.setHeader('Content-Type', 'image/jpeg')
        res.end(data)
      }
    })
  }
})

server.listen(3000, function () {
  console.log('Server is running...')
})


4. Node中的模块系统

  • 核心模块
    • fs 文件操作模块
    • http 网络服务构建模块
    • os 操作系统信息模块
    • path 路径处理模块
    • url 路径操作模块
// 用来获取机器信息的
const os = require('os')
// 用来操作路径的
const path = require('path')
// 获取当前机器的 CPU 信息
console.log(os.cpus())
// memory 内存
console.log(os.totalmem())
// 获取一个路径中的扩展名部分
// extname extension name
console.log(path.extname('c:/a/b/c/d/hello.txt'))
  • 第三方模块
    • 第三方模块(模板引擎)
    • 必须通过npm来下载才可以使用
  • 自己编写的模块
    • 自己创建的文件

4.1 什么是模块化

  • 文件作用域(模块是独立的,在不同的文件使用必须要重新引用)【在node中没有全局作用域,它是文件模块作用域】
  • 通信规则
    • 加载require
    • 导出exports

4.2 CommonJS模块规范

在Node中的JavaScript还有个重要的概念,模块系统

  • 模块作用域

  • 使用require方法来加载模块

  • 使用exports接口对象来导出模块中的成员

    加载require

    语法:

    let 自定义变量名 = require('模块')
    

    作用:

    • 执行被加载模块中的代码
    • 得到被加载模块中的exports导出接口对象
    导出exports
    • Node中是模块作用域,默认文件中所有的成员只在当前模块有效
    • 对于希望可以被其它模块访问到的成员,我们需要把这些公开的成员挂载到exports接口对象上就可以了

    导出多个成员(必须在exports接口对象中)

    exports.a = 123
    exports.b = function () {
        console.log('bbb')
    }
    exports.c = {
        foo: "bar"
    }
    exports.d = 'hello'
    

    导出单个成员

    module.exports = 'hello'
    

    以下情况会覆盖

    module.exports = 'hello'
    // 后者会覆盖前者
    module.exports = function add (x,y) {
        return x + y
    }
    

    也可以通过以下方法来导出多个成员:

    module.expots = {
        foo: 'hello',
        add: function (x,y) {
            return x + y
        }
      }
    

4.3 模块原理

exportsmodule.exports指向同一个引用

console.log(exports === module.exports) // true

exports.foo = 'bar'
// 等价于
module.exports.foo = 'bar'

exports = 'bar' 重新赋值之后,exports != module.exports
因最终return的是module.exports,无论exports中的成员是什么都没用

真正去使用的时候:
导出单个成员:exports.xxx = xxx
导出多个成员:module.exports = {}

  1. jQuery中的each 和 原生JavaScript方法forEach的区别:
    提供源头:
    原生js是es5提供的(不兼容IE8)
    jQuery的each是jQuery第三方库提供的(如果要使用需要用2以下的版本也就是1.版本),它的each方法主要用来遍历jQuery实例对象(伪数组),同时也可以做低版本forEach的替代品,jQuery的实例对象不能使用forEach方法,如果想要使用必须转为数组([].slice.call(jQuery实例对象))才能使用

  2. 模块中导出多个成员和导出单个成员

  3. 301和302的区别:
    301永久重定向,浏览器会记住
    302临时重定向

  4. exports和module.exports的区别:
    每个模块中都有一个module对象
    module对象中有一个exports对象
    我们可以把需要导出的成员都挂载到module.exports接口对象中
    也就是module.exports.xxx = xxx的方式
    但是每次写太多了就很麻烦,所以Node为了简化代码,就在每一个模块中都提供了一个成员叫exports
    exports === module.exports结果为true,所以完全可以exports.xxx = xxx
    当一个模块需要导出单个成员的时候必须使用module.exports = xxx的方式,=,使用exports = xxx不管用,因为每个模块最终return的是module.exports,而exports只是module.exports的一个引用,所以exports即使重新赋值,也不会影响module.exports
    有一种赋值方式比较特殊:exports = module.exports这个用来新建立引用关系的。

  5. 当你采用了无分号的代码风格的时候,只需要注意以下情况:

    //  当一行代码是以:
    //    (
    //    [
    //    `
    //    开头的时候,则在前面补上一个分号用以避免一些语法解析错误。
    //  所以你会发现在一些第三方的代码中能看到一上来就以一个 ; 开头。
    // 结论:
    //  无论你的代码是否有分号,都建议如果一行代码是以 (、[、` 开头的,则最好都在其前面补上一个分号。
    //  有些人也喜欢玩儿一些花哨的东西,例如可以使用 ! ~ 等。
    

4.4 require的加载规则

  • 核心模块
    • 模块名
  • 第三方模块
    • 模块名
  • 用户自己写的
    • 路径
加载规则
  • 优先从缓存加载
  • 判断模块标识符
    • 核心模块
    • 自己写的模块(路径形式的模块)
    • 第三方模块(node-modules)
      • 第三方模块的标识就是第三方模块的名称(不可能有第三方模块和核心模块的名字一致)
      • npm
        • 开发人员可以把写好的框架库发布到npm上
        • 使用者通过npm命令来下载
      • 使用方式:npm install 下载的包名 const 名称 = require('下载的包名')
        • node_modules/express/package.json main
        • 如果package.json或者main不成立,则查找被选择项:index.js
        • 如果以上条件都不满足,则继续进入上一级目录中的node_modules按照上面的规则依次查找,直到当前文件所属此盘根目录都找不到最后报错
// 如果非路径形式的标识
// 路径形式的标识:
    // ./  当前目录 不可省略
    // ../  上一级目录  不可省略
    //  /xxx也就是D:/xxx
    // 带有绝对路径几乎不用(D:/a/foo.js)
// 首位表示的是当前文件模块所属磁盘根目录
// require('./a'); 


// 核心模块
// 核心模块本质也是文件,核心模块文件已经被编译到了二进制文件中了,我们只需要按照名字来加载就可以了
require('fs'); 

// 第三方模块
// 凡是第三方模块都必须通过npm下载(npm i node_modules),使用的时候就可以通过require('包名')来加载才可以使用
// 第三方包的名字不可能和核心模块的名字是一样的
// 既不是核心模块,也不是路径形式的模块
//      先找到当前文所述目录的node_modules
//      然后找node_modules/art-template目录
//      node_modules/art-template/package.json
//      node_modules/art-template/package.json中的main属性
//      main属性记录了art-template的入口模块
//      然后加载使用这个第三方包
//      实际上最终加载的还是文件

//      如果package.json不存在或者mian指定的入口模块不存在
//      则node会自动找该目录下的index.js
//      也就是说index.js是一个备选项,如果main没有指定,则加载index.js文件
//      
        // 如果条件都不满足则会进入上一级目录进行查找
// 注意:一个项目只有一个node_modules,放在项目根目录中,子目录可以直接调用根目录的文件
const template = require('art-template');

4.5 在node中使用模板引擎art-template

在 Node 中使用art-template模板引擎
模板引起最早就是诞生于服务器领域,后来才发展到了前端。
art-template 不仅可以在浏览器使用,也可以在 node 中使用

  1. 安装:

    • npm install art-template
    • 该命令在哪执行就会把包下载到哪里。默认会下载到 node_modules 目录中
    • node_modules 不要改,也不支持改。
  2. 使用:

    • 在需要使用的文件模块中加载 art-template
    • 只需要使用 require 方法加载就可以了:require('art-template')
    • 参数中的 art-template 就是你下载的包的名字
    • 也就是说你 install 的名字是什么,则你 require 中的就是什么
  3. 查文档,使用模板引擎的 API

HTML

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>{{ title }}</title>
</head>
<body>
  <p>大家好,我叫:{{ name }}</p>
  <p>我今年 {{ age }} 岁了</p>
  <h1>我来自 {{ province }}</h1>
  <p>我喜欢:{{each hobbies}} {{ $value }} {{/each}}</p>
  <script>
    let foo = '{{ title }}'
  </script>
</body>
</html>

使用

const template = require('art-template')
const fs = require('fs')

// 这里不是浏览器
// template('script 标签 id', {对象})

// let tplStr = `
// <!DOCTYPE html>
// <html lang="en">
// <head>
//   <meta charset="UTF-8">
//   <title>Document</title>
// </head>
// <body>
//   <p>大家好,我叫:{{ name }}</p>
//   <p>我今年 {{ age }} 岁了</p>
//   <h1>我来自 {{ province }}</h1>
//   <p>我喜欢:{{each hobbies}} {{ $value }} {{/each}}</p>
// </body>
// </html>
// `

fs.readFile('./tpl.html', function (err, data) {
  if (err) {
    return console.log('读取文件失败了')
  }
  // 默认读取到的 data 是二进制数据
  // 而模板引擎的 render 方法需要接收的是字符串
  // 所以我们在这里需要把 data 二进制数据转为 字符串 才可以给模板引擎使用
  let ret = template.render(data.toString(), {
    name: 'Jack',
    age: 18,
    province: '北京市',
    hobbies: [
      '写代码',
      '唱歌',
      '打游戏'
    ],
    title: '个人信息'
  })

  console.log(ret)
})

http案例加入art-template

const http = require('http')
const fs = require('fs')
const template = require('art-template')

const server = http.createServer()

let wwwDir = 'D:/Movie/www'

server.on('request', function (req, res) {
  let url = req.url
  fs.readFile('./template-apache.html', function (err, data) {
    if (err) {
      return res.end('404 Not Found.')
    }
    // 1. 如何得到 wwwDir 目录列表中的文件名和目录名
    //    fs.readdir
    // 2. 如何将得到的文件名和目录名替换到 template.html 中
    //    2.1 在 template.html 中需要替换的位置预留一个特殊的标记(就像以前使用模板引擎的标记一样)
    //    2.2 根据 files 生成需要的 HTML 内容
    // 只要你做了这两件事儿,那这个问题就解决了
    fs.readdir(wwwDir, function (err, files) {
      if (err) {
        return res.end('Can not find www dir.')
      }

      // 这里只需要使用模板引擎解析替换 data 中的模板字符串就可以了
      // 数据就是 files
      // 然后去你的 template.html 文件中编写你的模板语法就可以了
      let htmlStr = template.render(data.toString(), {
        title: '哈哈',
        files: files
      })

      // 3. 发送解析替换过后的响应数据
      res.end(htmlStr)
    })
  })
})
server.listen(3000, function () {
  console.log('running...')
})

4.6 客户端渲染和移动端渲染

  • 服务端渲染
    • 在服务端使用模板引擎
    • 模板引擎最早诞生于服务端,后来才发展到了前端
  • 服务端渲染和客户端渲染的区别
    • 客户端渲染不利于 SEO 搜索引擎优化
    • 服务端渲染是可以被爬虫抓取到的,客户端异步渲染是很难被爬虫抓取到的
    • 所以你会发现真正的网站既不是纯异步也不是纯服务端渲染出来的
    • 而是两者结合来做的
    • 例如京东的商品列表就采用的是服务端渲染,目的了为了 SEO 搜索引擎优化
    • 而它的商品评论列表为了用户体验,而且也不需要 SEO 优化,所以采用是客户端渲染
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 217,826评论 6 506
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,968评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,234评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,562评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,611评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,482评论 1 302
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,271评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,166评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,608评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,814评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,926评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,644评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,249评论 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,866评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,991评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,063评论 3 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,871评论 2 354

推荐阅读更多精彩内容

  • 1. Node.js是什么 1.1 概述 官网:https://nodejs.org[https://nodejs...
    Daeeman阅读 450评论 6 2
  • 前言 创始人:Ryan Dahl 2004年,在纽约罗彻斯特大学数学系读博士,研究一些分形、分类以及p-adic分...
    JackChen1024阅读 2,151评论 0 6
  • 官方文档中文文档 Node.js是什么 Node.js® is a JavaScript runtime buil...
    刘昊2018阅读 408评论 0 1
  • Node.js是什么? Node.js是建立在谷歌Chrome的JavaScript引擎(V8引擎)的Web应用程...
    陈威24阅读 377评论 1 1
  • 一、node概要 对nodeJS早有耳闻,但是一直迟迟没有对它下手,哈哈哈,今儿咱就来初探一下它。 nodeJS是...
    司小璇阅读 403评论 0 3