美文网首页
正则表达式和Node.js

正则表达式和Node.js

作者: 玫瑰的lover | 来源:发表于2020-04-10 22:10 被阅读0次

    正则表达式:创建正则表达式的两种方式;正则表达式的常见用法;正则与数值和其它注意事项

    Node.js :什么是Node.jsNode.js基础NPM


    正则表达式


    创建正则表达式的两种方式

    1. 使用正则表达式字面量const reg=/[a-z]\d+[a-z]/i

    优点:简单方便,不需要考虑二次转义;

    缺点:子内容无法重复使用;过长的正则导致可读性差

    2. 使用RegExp构造函数

    const alphabet=`[a-z]`;

    const reg=new RegExp(`${alphabet}\\d+${alphabet}`,'i');

    优点:子内容可以重复使用,可以通过控制子内容的粒度提高可读性

    缺点:二次转义的问题非常容易导致bug

    const reg=new RegExp(`\d+`);

    reg.test('1');//false;reg.test('odd');//true

    正则表达式的常见用法

    1. RegExp.prototype.test()

    const reg=/[a-z]\d+[a-z]/i;

    reg.test('ala');//true

    reg.test('lal');//false

    reg.test(Symbol('ala'));//TypeError

    输入:要求是输入字符串,如果输入的不是字符串类型,会尝试进行类型转换,转换失败会抛出TypeError

    输出:true或者false,表示匹配成功或失败

    2. RegExp.prototype.source和 RegExp.prototype.flags

    const reg=/[a-z]\d+[a-z]/ig;

    reg.source;//[a-z]\d+[a-z]

    reg.flags;//gi

    前者返回当前正则表达式的模式文本的字符串

    es2015新增,返回当前正则表达式的修饰符的字符串,会随修饰符按照字母升序进行排序

    3. RegExp.prototype.exec()和 String.prototype.match()

    const reg=/[a-z]\d+[a-z]/i;

    reg.exec('ala');//["ala",index:0,input:"ala",groups:undefined]

    reg.exec('lal');//null

    'ala'.match(reg);//["ala",index:0,input:"ala",groups:undefined]

    'lal'.match(reg);//null

    输入:前者要求输入字符串,遇到非字符串

    类型会尝试转换,后者要求输入正则表达式,遇到其他类型会先尝试转成字符串,再以字符串为source创建正则表达式

    输出:匹配成功,返回匹配结果;匹配失败,返回null

    const reg=/(a)/g;

    reg.exec('ala');//["a","a",index:0,input:"ala",groups:undefined]

    'ala'.match(reg);//["a","a"]

    当反正则表达式含有g修饰符时,RegExp.prototype.exec每次只返回一个匹配结果,数据格式和不含g修饰符相同。String.prototype.match()会返回所有的匹配结果,数个是会变成字符串组。由于String.prototype.match()返回的数据格式不固定,因此大多数情况都建议使用RegExp.prototype.exec。

    4. RegExp.prototype.lastIndex

    const reg=/(a)/g;

    const str='ala';

    reg.lastIndex;//0

    reg.exec('ala');//["a","a",index:0,input:"ala",groups:undefined]

    reg.lastIndex;//1

    reg.exec('ala');//["a","a",index:2,input:"ala",groups:undefined]

    reg.lastIndex;//3

    reg.exec('ala');//null

    reg.lastIndex;//0

    当前正则表达式最后一次匹配成功的位置(也就是下一次匹配的开始位置)

    注意:lastIndex不会自己重置,只有当上一次匹配失败v瑷珲重置为0,因此,当你需要反复使用同一个正则表达式的时候,需要在每次匹配新的字符串之前重置lastIndex!

    5.String.prototype.replace(),String.prototype.search(),String.prototype.split()

    'ala'.replace(/a/,'b');//'bla'

    'ala'.replace(/a/g,'b');//'blb'

    'ala'.search(/a/);//0

    'ala'.search(/a/g);//0

    'ala'.split(/a/);//["","1",""]

    'ala'.split(/a/g);//["","1",""]

    正则与数值


    数值判断之一

    /[0-9]+/`[]`字符集,使用连字符 - 表示指定的字符范围,如果想要匹配连字符,需要挨着方括号放置,或进行转义

    `0-9` 表示匹配从 0 到 9 的数字字符,常用的还有 a-z 匹配小写字母,\u4e00-\u9fa5 匹配汉字等。如果只是匹配数字,还可以使用字符集缩写 \d

    `+`限定符,匹配一个或多个

    **不足之处**不是全字符匹配,存在误判,如 /[0-9]+/.test('a1') === true

    数值判断之二

    `/^\d+$/`

    `^`匹配字符串开始位置,当结合 m 修饰符时,匹配某一行开始位置

    `$`匹配字符串结束位置,当结合 m 修饰符时,匹配某一行结束位置

    **不足之处**- 不能匹配带符号的数值,如 +1,-2- 不能匹配小数,如 3.14159

    数值判断之三

    /^[+-]?\d+(\.\d+)?$/

    `()`圆括号内是一个子表达式,当圆括号不带任何修饰符时,表示同时创建一个捕获组

    `?` 在正则中有多种含义,作为限定符时,表示匹配零到一个

    `.`可以匹配除换行符之外的任意字符,当结合 s 修饰符时,可以匹配包括换行符在内的任意字符。当匹配小数点字符时需要转义。

    **不足之处**- 不能匹配无整数部分的小数,如.123- 捕获组会带来额外的开销

    数值判断之三

    /^[+-]?(?:\d*\.)?\d+$/

    `(?:)`创建一个非捕获组

    `*`限定符,匹配零个或多个

    **不足之处**不能匹配无小数部分的数值,如 2;不能匹配科学计数法,如 1e2、3e-1、-2.e+4

    完整的数值正则怎么写


    完整的数值 token

    https://drafts.csswg.org/css-syntax-3/#number-token-diagram

    ![img](https://p.ssl.qhimg.com/t01480d461b3c6ceb1f.webp)

    注意:这个 token 是 CSS 的 token,在 javascript 中,要多考虑一种情况

    +'2.'; // 2   +'2.e1'; // 20

    `|`用来创建分支,当位于圆括号内时,表示子表达式的分支条件,当位于圆括号外时,表示整个正则表达式的分支条件

    `i` 修饰符,表示匹配时忽略大小写,在这个例子中用于匹配科学计数法的 e,去掉 i 修饰符需要把 e 改为 [eE]

    **思考题:这个正则已经没有缺点了吗?**javascript 中,数值还可以如何表示?

     用正则处理数值

    **解析CSS**

    function execNumberList(str) {·········}

    const reg = /[+-]?(?:\d*\.)?\d+(?:e[+-]?\d+)?(?=px|\s|$)/gi;

    function execNumberList(str) {

        reg.lastIndex = 0;

        let exec = reg.exec(str);

        const result = [];

        while (exec) {

            result.push(parseFloat(exec[0]));

            exec = reg.exec(str);

        }

        return result;}

    `(?=\*expression\*)`

    正向肯定环视 / 顺序肯定环视 / 先行断言,用于匹配符合条件的**位置**

    类似的语法还有:

    **(?!*expression*)** 正向否定环视 / 顺序否定环视 / 先行否定断言

    **(?<=*expression*)** 反向肯定环视 / 逆序肯定环视 / 后行断言,es2018 新增

    **(?<!*expression*)** 反向否定环视 / 逆序否定环视 / 后行否定断言,es2018 新增

    `g`修饰符,表示全局匹配,用于取出目标字符串中所有符合条件的结果。

    **需要注意的点**- 按照 CSS 规范,只有数值为 0 才可以省略单位,这种情况没有必要靠正则来过滤- 这个例子中只验证了 px 单位,实际还存在 pt、em、vw 等单位,并且没有考虑百分比的情况

    - 实际工作中,要根据需求追加处理逻辑

    数值转货币格式

    不卖关子了,直接放结果:

    const reg = /(\d)(?=(\d{3})+(,|$))/g;

    function formatCurrency(str) {

       return str.replace(reg, '$1,');

    }

    console.log(formatCurrency('1')); // 1

    console.log(formatCurrency('123')); // 123

    console.log(formatCurrency('12345678')); // 12,345,678

    `{n}`限定符,表示重复 n 次,n 必须是非负整数

    类似的语法还有:

    {n, m} 表示重复 n 到 m 次,n 和 m 都必须是非负整数,且 n <= m

    {n,} 表示重复 n 次以上

    `$n`用于 replace 的字符串中,表示第 n 个捕获组,n 可以从 1 到 9

    $& 表示本次完整的匹配,所以这段代码还可以改写为:

    const reg = /\d(?=(?:\d{3})+(?:,|$))/g;

    function formatCurrency(str) {

       return str.replace(reg, '$&,');

    }

    在ES2018以上的环境,还可以使用反向环视

    const reg = /(?<=\d)(?=(?:\d{3})+(?:,|$))/g;

    function formatCurrency(str) {

       return str.replace(reg, ',');

    }

    其它注意事项

    环视中的圆括号也会生成捕获组,所以都要采用 (?:) 的非捕获组形式

    1.颜色有多少种表示方式

    16进制表示法


    color: #rrggbb;

    color: #rgb;

    color: #rrggbbaa;

    color: #rgba;


    **对应的正则写法**

    const hex = '[0-9a-fA-F]';

    const reg = new RegExp(`^(?:#${hex}{6}|#${hex}{8}|#${hex}{3,4})$`);

    - 也可以使用 i 修饰符来匹配大小写,i 修饰符和 a-fA-F 要根据实际需求来做取舍

     rgb/rgba 表示法


    color: rgb(r, g, b);

    color: rgb(r%, g%, b%);

    color: rgba(r, g, b, a);

    color: rgba(r%, g%, b%, a);

    color: rgba(r, g, b, a%);

    color: rgba(r%, g%, b%, a%);


    **对应正则写法**


    const num = '[+-]?(?:\\d*\\.)?\\d+(?:e[+-]?\\d+)?';

    const comma = '\\s*,\\s*';

    const reg = new RegExp(`rgba?\\(\\s*${num}(%?)(?:${comma}${num}\\1){2}(?:${comma}${num}%?)?\\s*\\)`);


    `\n`反向引用,表示引用第 n 个捕获组;由于 r/g/b 必须同时为数值或百分比,所以 %? 只需要捕获一次,用 \1 来引用

    `\s`字符集缩写,用于匹配空白

    **需要注意的点**

    - 按照规范,rgb(r,g,b,a) 和 rgba(r,g,b) 也是合法的

    - r/g/b 的值应该是 0~255 的整数,但是溢出或小数并不会报错

    - 当捕获组内的内容是可选的时候,一定要把问号写在捕获组内

      如果可选内容的圆括号不可省略,如(a|b|c)?,应该多嵌套一层:((?:a|b|c)?)

     其他


    /* hsl & hsla */

    color: hsl(h, s%, l%);

    color: hsla(h, s%, l%, a);

    color: hsla(h, s%, l%, a%);

    /* keywords */

    color: red;

    color: blue;

    /* …… */


    . 用正则处理颜色-----16进制颜色的优化


    function shortenColor(str) { // ……}

    console.log(shortenColor('#336600')); // '#360'

    console.log(shortenColor('#19b955')); // '#19b955'

    console.log(shortenColor('#33660000')); // '#3600'


    const hex = '[0-9a-z]';

    // ?<key>

    const hexReg = new RegExp(`^#(?<r>${hex})\\k<r>(?<g>${hex})\\k<g>(?<b>${hex})\\k<b>(?<a>${hex}?)\\k<a>$`, 'i');

    function shortenColor(str) {

        return str.replace(hexReg, '#$<r>$<g>$<b>$<a>');

    }

    console.log(shortenColor('#336600')); // '#360'

    console.log(shortenColor('#19b955')); // '#19b955'

    console.log(shortenColor('#33660000')); // '#3600


    **(?<key>)**

    - es2018 新增,具名捕获组

    - 反向引用时的语法为 \k<key>

    - 在 replace 中,使用 $<key> 来访问具名捕获组

    - 当应用 exec 时,具名捕获组可以通过 execResult.groups[key] 访问

    ```js

    const hex = '[0-9a-z]';

    const hexReg = new RegExp(`^#(?<r>${hex})\\k<r>(?<g>${hex})\\k<g>(?<b>${hex})\\k<b>(?<a>${hex}?)\\k<a>$`, 'i');

    hexReg.exec('#33660000');

    // ["#33660000", "3", "6", "0", "0", index: 0, input: "#33660000", groups: {r: "3", g: "6", b: "0", a: "0"}]

    正则与URL

     1. 用正则解析URL------完整的URL规范

    ![1586522101228](C:\Users\H\AppData\Roaming\Typora\typora-user-images\1586522101228.png)

    #### 解析URL

    ```js

    function execURL(url) {// …}

    console.log(execURL('https://www.360.cn'));

    {

      protocol: 'http:',

      host: 'www.360.cn',

      hostname: 'www.360.cn',

      port: '',

      pathname: '',

      search: '',

      hash: ''

    }

    console.log(execURL('http://localhost:8080/?#'));

    {

      protocol: 'http:',

      host: 'localhost:8080',

      hostname: 'localhost',

      port: '8080',

      pathname: '/',

      search: '?',

      hash: '#'

    }

    console.log(execURL('https://image.so.com/view?q=360&src=srp#id=9e17bd&sn=0'));

    {

      protocol: 'https:',

      host: 'image.so.com',

      hostname: 'image.so.com',

      port: '',

      pathname: '/view',

      search: '?q=360&src=srp',

      hash: '#id=9e17bd&sn=0'

    }

    console.log(execURL('this is not a url'));

    {

      protocol: '',

      host: '',

      hostname: '',

      port: '',

      pathname: '',

      search: '',

      hash: ''

    }

    ```js

    const protocol = '(?<protocol>https?:)';

    const host = '(?<host>(?<hostname>[^/#?:]+)(?::(?<port>\\d+))?)';

    const path = '(?<pathname>(?:\\/[^/#?]+)*\\/?)';

    const search = '(?<search>(?:\\?[^#]*)?)';

    const hash = '(?<hash>(?:#.*)?)';

    const reg = new RegExp(`^${protocol}\/\/${host}${path}${search}${hash}$`);

    function execURL(url) {

        const result = reg.exec(url);

        if (result) {

            result.groups.port = result.groups.port || '';

            return result.groups;

        }

        return {

            protocol: '', host: '', hostname: '', port: '',

            pathname: '', search: '', hash: '',

        };

    }

    console.log(execURL('https://www.360.cn'));

    console.log(execURL('http://localhost:8080/?#'));

    console.log(execURL('https://image.so.com/view?q=360&src=srp#id=9e17bd&sn=0'));

    console.log(execURL('this is not a url'));

    **注意事项**

    - port 捕获组可能为 undefined

    - 要考虑解析失败的情形

     2. 用正则解析search和hash----完整解析

    function execUrlParams(str) {

        // ……

    }

    console.log(execUrlParams('#')); // { }

    console.log(execUrlParams('##')); // { '#': '' }

    console.log(execUrlParams('?q=360&src=srp')); // { q: '360', src: 'srp' }

    console.log(execUrlParams('test=a=b=c&&==&a=')); // { test: 'a=b=c', '': '=', a: '' }

    function execUrlParams(str) {

        str = str.replace(/^[#?&]/, '');

        const result = {};

        if (!str) {

            return result;

        }

        const reg = /(?:^|&)([^&=]*)=?([^&]*?)(?=&|$)/y;

        let exec = reg.exec(str);

        while (exec) {

            result[exec[1]] = exec[2];

            exec = reg.exec(str);

        }

        return result;

    }

    console.log(execUrlParams('#')); // { }

    console.log(execUrlParams('##')); // { '#': '' }

    console.log(execUrlParams('?q=360&src=srp')); // { q: '360', src: 'srp' }

    console.log(execUrlParams('test=a=b=c&&==&a=')); // { test: 'a=b=c', '': '=', a: '' }

    其中:

    const reg = /(?:^|&)([^&=]*)=?([^&]*?)(?=&|$)/y;

    ? 可以跟在任何限定符之后,表示非贪婪模式(注意:这个例子其实不太恰当,使用贪婪模式效果是一样的)

    **y**es6 新增,粘连修饰符,和 g 修饰符类似,也是全局匹配。区别在于:

    1. y 修饰符每次匹配的结果必须是连续的

    2. y 修饰符在 match 时只会返回第一个匹配结果

    **其它注意事项**

    正则表达式如果可能匹配到空字符串,极有可能造成死循环,所以这段代码很重要:

    if (!str) {

        return result;

    }

    Node.js基础入门

    什么是Node.js

    1.Node.js是基于ChromeV8引擎中

    2.与JavaScript的区别:

    -基于I/O相关接口

    -基于node_modules和require的模块依赖

    -提供C++ addon API与底层系统的交互

    -语法与js很像

    3.Node.js可以干什么?

    Web服务端:Web Server、爬虫

    CLI命令行脚本:webpack

    GUI客户端软件:VSCode、网易云音乐

    IoT,图像处理,实时通讯

    利用node.js做一个对豆瓣上电影爬虫的例子:

    Node.js基础

    首先在官网下载Node.js

    使用node index.js去执行,可以看到

    模块:内置模块,编译在node中文件模块;原生模块之外的模块和文件(夹)一一对应模块类型:.js .json .node .mjs

    模块路径查找:绝对路径;相对路径:相对路径与当前路径处理为绝对路径模块名称/文件夹

    模块缓存:模块加载后会将返回值缓存起来;下次加载时直接读取缓存结果,避免文件I/O和解析时间导出对象缓存在Module._cache对象上

    NPM包管理:package.json文件应该存于包顶级目录下;二进制文件在bin目录下;Js代码放在lib目录下;文档放在doc目录下;单元测试放在test目录下

    Tip:可以使用 npm confirg set init.author.name等命令修改初始化时的默认值

    NPM的问题:速度问题;安全问题;npm audit检测npm安全问题

    基于Node.js的Web开发

    简单的web服务

    const http = require('http');

    const server = http.createServer((req, res) => {

      res.end('Hello World');

    });

    server.listen(3000);

    ##Koa

    const Koa = require('koa');

    const app = new Koa();

    // response

    app.use(ctx => {

      ctx.body = 'Hello Koa';

    });

    app.listen(3000);

    · 独有一个use方法,会对中间件去进行挂载

    · Koa是一个较简单的框架,对于Web服务中常用到的逻辑分层、路由处理、数据解析、校验、权限校验、Session、Cache、数据库、Redis、安全等,并没有涉及到

    · Koa 无规范约束,不利于团队开发

    · 中间件繁多,质量参差不齐,选择困难

    ##ThinkJS

    企业级目录规范

    ├─src

    │  ├─bootstrap

    │  ├─config

    │  │  ├─config.js

    │  │  └─adapter.js

    │  ├─controller

    │  │  ├─index.js

    │  ├─logic

    │  │  ├─index.js

    │  └─model

    ├─view

    │  ├─index_index.html

    └─www

    │  └─static

    │    ├─css

    │    ├─img

    │    └─js

    ├─development.js

    ├─production.js

    ├─package.json

    ThinkJS中的一些模块

    ##TODO List项目实践---项目效果

    功能列表

    · TODO List 的页面

    · API

    · 获取 TOO 列表

    · 增加 TODO

    · 删除 TODO

    · 更新 TODO 状态

    数据表设计

    CREATE TABLE `todo` (

      `id` int(11) unsigned NOT NULL AUTO_INCREMENT,

      `desc` varchar(255) NOT NULL DEFAULT '',

      `status` tinyint(11) NOT NULL DEFAULT '0' COMMENT '0 是未完成,1是已完成',

      `createdAt` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,

      `updatedAt` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,

      PRIMARY KEY (`id`)

    ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

    环境安装

    npm install -g think-cli

    $ thinkjs new todo    //会自动生成目录

    $ cd todo

    $ npm install

    启动项目:

    simple-todo npm start

    > simple-todo@1.0.0 start /Users/lizheming/Desktop/star-plan/simple-todo

    > node development.js

    [2019-04-21T21:58:16.197] [7077] [INFO] - Server running at http://127.0.0.1:8360

    [2019-04-21T21:58:16.201] [7077] [INFO] - ThinkJS version: 3.2.10

    [2019-04-21T21:58:16.201] [7077] [INFO] - Environment: development

    [2019-04-21T21:58:16.201] [7077] [INFO] - Workers: 1

    浏览器打开http://127.0.0.1:8360:

    可以把这个模版文件改成项目效果显示的样式

    API开发:使用RESTful开发

    RESTful 接口规范

    · 每个 API 都对应一种资源或资源集合

    · 使用 HTTP Method 来表示对资源的动作

    · 使用 HTTP Status Code 来表示资源操作结果

    RESTful API

    · GET /ticket 获取 ticket 列表

    · GET /ticket/:id 查看某个具体的 ticket

    · POST /ticket 新建一个 ticket

    · PUT /ticket/:id 更新 id 为 12 的 ticket

    · DELETE /ticket/:id 删除 id 为 12 的 ticekt

    创建API文件

    simple-todo thinkjs controller -r ticket

    think-cli · Create: src/controller/rest.js //所有RESTful接口的基类

    think-cli · Create: src/controller/ticket.js  //具体的tricket路由

    think-cli · Create: src/logic/api/ticket.js //tricket路由对应的逻辑校验层

    配置路由

    // src/config/router.js

    module.exports = [

      ['/ticket/:id?', 'rest'], // 配置 RESTful API 路由

    ]

    路由解析

    GET /api/todo 获取 TODO 列表,执行 getAction

    GET /api/todo/:id 获取某个TODO的详细信息,执行 getAction

    POST /api/todo 添加一个 TODO,执行 postAction

    PUT /api/todo/:id 更新一个 TODO,执行 putAction

    DELETE /api/todo/:id 删除一个 TODO,执行 deleteAction

    getAction

    // src/controller/rest.js

    async getAction() {

      let data;

      if (this.id) {

        const pk = this.modelInstance.pk;

        data = await this.modelInstance.where({ [pk]: this.id }).find();

        return this.success(data);

      }

      data = await this.modelInstance.select();

      return this.success(data);

    }

    postAction

      async postAction() {

        const pk = this.modelInstance.pk;

        const data = this.post();

        delete data[pk];

        if (think.isEmpty(data)) {

          return this.fail('data is empty');

        }

        const insertId = await this.modelInstance.add(data);

        return this.success({ id: insertId });

      }

    deleteAction

    async deleteAction() {

      if (!this.id) {

        return this.fail('params error');

      }

      const pk = this.modelInstance.pk;

      const rows = await this.modelInstance.where({ [pk]: this.id }).delete();

      return this.success({ affectedRows: rows });

    }

    putAction

    async putAction() {

      if (!this.id) {

        return this.fail('params error');

      }

      const pk = this.modelInstance.pk;

      const data = this.post();

      delete data[pk];

      if (think.isEmpty(data)) {

        return this.fail('data is empty');

      }

      const rows = await this.modelInstance.where({ [pk]: this.id }).update(data);

      return this.success({ affectedRows: rows });

    数据库配置

    // src/config/adapter.js

    exports.model = {

      type: 'mysql',

      common: {

        logConnect: isDev,

        logSql: isDev,

        logger: msg => think.logger.info(msg)

      },

      mysql: {

        handle: mysql,

        database: 'todo',

        prefix: '',

        encoding: 'utf8',

        host: '127.0.0.1',

        port: '',

        user: 'root',

        password: 'root',

        dateStrings: true

      }

    };

    http://127.0.0.1:8360/ticket

    {

      "errno": 0,

      "errmsg": "",

      "data": [{

        "id": 1,

        "desc": "八点打扫房间",

        "status": 0,

        "createdAt": "2018-07-08 17:12:59",

        "updatedAt": "2018-07-08 17:13:14"

      }]

    }

    数据校验;提供了 Logic 机制转门用来支持数据校验

    文件和 Action 与 Controller 一一对应

    // src/logic/ticket.js

    module.exports = class extends think.Logic {

      getAction() {

        this.rules = {

          id: {

            int: true

          }

        };

      }

      deleteAction() {

        this.rules = {

          id: {

            int: true,

            required: true,

            method: 'get'

          }

        };

      }

      putAction() {

        this.rules = {

          id: {

            int: true,

            required: true,

            method: 'get'

          },

          status: {

            int: true,

            required: true

          },

          desc: {

            required: true

          }

        };

      }

      postAction() {

        this.rules = {

          desc: {

            required: true

          }

        };

      }

    };

    数据库操作:封装了 think.Model 类;提供增删改查等操作;支持关联模型查询

    自动分析数据表字段类型;自动数据安全过滤;控制器中操作模型

    const model = this.model(modeName);

    根据模型名查找 src/model 下的模型文件

    文件存在,实例化对应的模型类

    文件不存在,实例化 think.Model 类

    定义模型类

    // src/model/todo.js

    module.exports = class TodoModel extends think.Model {

      getList () {

        // get list

      }

    }

    模型的好处:简化代码、提高效率;不用太懂 SQL 语句也能操作数据库

    避免手写 SQL 语句的安全风险;Node.js 的调试;日志调试;断点调试

    node --inspect

    vscode

    ndb

    Node 开发角色转换

    前端跟浏览器打交道,兼容性问题

    组件化加载速度、JS 执行性能、渲染性能;错误监控XSS、CSRF 等安全漏洞

    服务端:数据库、Redis 等周边服务;性能、内存泄露、CPU、机器管理;服务监控、错误监控、流量监控、报警;SQL注入、目录遍历等安全漏洞

    相关文章

      网友评论

          本文标题:正则表达式和Node.js

          本文链接:https://www.haomeiwen.com/subject/ldphmhtx.html