2019-02-12 16 JavaScript进阶
    
    Node.Js
  - 基础模块
    
      - fs文件读写模块- 
          - 读文件require('fs').readFile('sample.txt', 'utf-8', function (err, data){});
- 写文件require('fs').writeFile('output.txt', data, function(err) {})
- 获取文件大小, 创建时间等信息require('fs').stat('sample.txt', function(err, stat) {})
 
- stream数据结构- 流
 
  var rs = require('fs').createReadStream('sample.txt', 'utf-8');
  // data事件表示流的数据可获取
  rs.on('data', function (chunk) {});
  // end事件表示流已到末尾
  rs.on('end', function() {});
  // error事件表示出错
  rs.on('error', function() {});
      var ws = require('fs').createWriteStream('sample.txt', 'utf-8');
      ws.write('xxxxxxx');
      ws.end();
var http = require('http');
// request对象封装HTTP请求, request对象可获取HTTP请求信息
// response对象封装HTTP响应
var server = http.createServer(function (request, response){});
server.listen(8080);
// app.js, 在package.json文件的{"main":"app.js"}配置
const Koa = require('koa');
// koa对象, 表示web app对象
var app = new Koa();
app.use(async (ctx, next) => {
  console.log('${ctx.request.method} ${ctx.request.url}');// 打印URL
  await next(); // 调用下一个middleware, 即下一个async函数
})
app.use(async (ctx, next) => {
  await next();
  ctx.response.type = 'text/html';
  ctx.response.body = '<h1>Hello, Koa</h1>';
});
// koa 路由
// require('koa-router')()返回函数调用
const router = require('koa-router')();
router.get('/hello:/:name', async (ctx, next) => {
  // hello页面逻辑
});
// add router middleware
app.use(router.routes());
const nunjucks = require('nunjucks');
function createEnv(path, opts) {
  ...
  return env;
}
var env = createEnv('views', {
  watch: true,
  filters: {
    hex: function(n) {
      return '0x' + n.toString(16);
    }
  }
});
var s = env.render('hello.html', {name: '小明'});
  - MVC
    
      - 当用户通过浏览器访问URL, koa接受请求并调用async (ctx, next) => {}处理该URL(也可以通过路由转发到对应的模块处理), 在异步函数内部生成HTML, 最后输出给浏览器,ctx.render('home.html', {name: 'Michael'})
- 此时Controller为异步函数, 负责业务逻辑, 检查用户名等
- View为HTML/HTML模板, 负责显示逻辑
- Model即{name: 'Michael'}
 
- mocha(单元测试框架)
    
      - 支持before,after,beforeEach,afterEach
 
- WebSocket(浏览器和服务器双向通信通道)
  // 创建WebSocket Server
  const WebSocket = require('ws');
  // 引用Server类
  const WebSocketServer = WebSocket.Server;
  // 实例化
  const wss = new WebSocketServer({port:3000});
  wss.on('connection', function(ws) {
    ws.on('message', function(message) {
      ws.send(`ECHO:${message}`, (err) => {
        ...
      });
    });
  });
  // 创建WebSocket Client链接...
  var ws = new WebSocket('ws://localhost:3000/test');
  ws.onmessage = function(msg) {console.log(msg);};
  ws.send('hello');
  - REST(处理HTTP请求的async函数, 特点: 1. 除GET外,POST等其它请求BODY均为JSON格式, 2. 响应返回结果均为JSON数据格式)
  const app = new Koa();
  const controller = require('./controller');
  // parse request body..
  app.use(bodyParser());
  // add controller
  app.use(controller());
  app.listen(3000);
  // 暴露访问接口...
  module.exports = {
    'GET /api/products':async (ctx, next) => {
      ctx.response.type = 'application/json';
      ctx.response.body = {...};
    }
  }
  - MVVM
    
      - Angular, Google出品, 很难用
- Backbone.js, 入门困难
- Ember, 大而全
- Vue.js, 简单支持扩展, 推荐, 看vuejs基础语法教程;
 
ejs
  // 方法一
  var template = ejs.compile(str, options);
  template(data);
  // 方法二
  ejs.render(str, data, options);
  // 方法三
  ejs.renderFile(filename, data, options, function(err, str) {
  });
  - 标签含义
    
      - <%, 脚本标签, 用于流程控制, 无输出
- <%_, 删除前面的空格符
- <%=输出数据到模板(输出转移HTML模板)
- <%-输出非转义的数据到模板
- <%#注释标签
- <%%输出字符串- <%
- %>结束标签
- -%>删除紧随的换行符
- _%>将结束标签后面的空格符删除
 
- 包含
    
  
  // 模板
  <ul>
    <% users.forEach(function(user) { %>
      <%- include('user/show', {user: user}) %>
    <% }); %>
  </ul>
// 单个模板文件
ejs.render('<?= users.join(" | "); ?>', {users: users},
    {delimiter: '?'});
// => 'geddy | neil | alex'
// 全局
ejs.delimiter = '$';
ejs.render('<$= users.join(" | "); $>', {users: users});
2.15.4 参考文档