Vue项目的适配

Vue中使用vw实现移动端适配👍


  1. 我们在vue移动端项目中的适配一般都采用rem,但是rem也不是能兼容所有的终端。随着viewport单位越来越受到众多浏览器的支持,下面简单介绍怎么实现vw的兼容问题,用vw代替rem.
  • 当我们采用vue-cli脚手架搭建完项目,安装所有依赖包之后,用npm run dev启动后,在根目录有一个 .postcssrc.js 文件,文件结构如下:
    1
    2
    3
    4
    5
    module.exports = {
    "plugins": {
    "autoprefixer": {}
    }
    }
  1. 然后我们安装:
    1
    npm i postcss-aspect-ratio-mini postcss-px-to-viewport postcss-write-svg postcss-cssnext postcss-viewport-units cssnano --save
  • 安装成功之后,在项目根目录下的package.json文件中,可以看到新安装的依赖包.
  1. 接下来在.postcssrc.js文件对新安装的PostCSS插件进行配置:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    module.exports = {
    "plugins": {
    "postcss-import": {},
    "postcss-url": {},
    "postcss-aspect-ratio-mini": {},
    "postcss-write-svg": {
    utf8: false
    },
    "postcss-cssnext": {},
    "postcss-px-to-viewport": {
    viewportWidth: 750, // 视窗的宽度,对应的是我们设计稿的宽度,一般是750
    viewportHeight: 1334, // 视窗的高度,根据750设备的宽度来指定,一般指定1334,也可以不配置
    unitPrecision: 3, // 指定`px`转换为视窗单位值的小数位数
    viewportUnit: "vw", //指定需要转换成的视窗单位,建议使用vw
    selectorBlackList: ['.ignore','.hairlines'], // 指定不转换为视窗单位类,可以自定义,可以无限添加,建议定义一至两个通用的类名
    minPixelValue: 1, // 小于或等于'1px'不转换为视窗单位,你也可以设置为你想要的值
    mediaQuery: false // 允许在媒体中转换'px'
    },
    "postcss-viewport-units": {},
    "cssnano": {
    preset: "advanced",
    autoprefixer: false,
    "postcss-zindex": false
    }
    }
    }
  • cssnano:主要用来压缩和清理CSS代码。在Webpack中,cssnano和css-loader捆绑在一起,所以不需要自己加载它。在cssnano的配置中,使用了preset: “advanced”,所以我们需要另外安装:

    1
    npm i cssnano-preset-advanced --save-dev
    1
    2
    3
    4
    "cssnano": {
    "autoprefixer": false,
    "postcss-zindex": false
    }
  • 注意: 上面的代码把autoprefixer和postcss-zindex禁掉了。前者是有重复调用,只要启用了这个插件,z-index的值就会重置为1。千万记得将postcss-zindex设置为false。

Flex

CSS伸缩布局📕


Flex布局是什么❓

  • Flex是Flexible Box的缩写,意为”弹性布局”,用来为盒状模型提供最大的灵活性。
  • 任何一个容器都可以指定为Flex布局。

    1
    2
    3
    .box{
    display: flex;
    }
  • 行内元素也可以使用Flex布局。

    1
    2
    3
    .box{
    display: inline-flex;
    }
  • Webkit内核的浏览器,必须加上-webkit前缀。

    1
    2
    3
    4
    .box{
    display: -webkit-flex; /* Safari */
    display: flex;
    }
  • 注意,设为Flex布局以后,子元素的float、clear和vertical-align属性将失效。

基本概念

  • 采用Flex布局的元素,称为Flex容器(flex container),简称”容器”。它的所有子元素自动成为容器成员,称为Flex项目(flex item),简称”项目”。
  • 容器默认存在两根轴:水平的主轴(main axis)和垂直的交叉轴(cross axis)。主轴的开始位置(与边框的交叉点)叫做main start,结束位置叫做main end;交叉轴的开始位置叫做cross start,结束位置叫做cross end。
  • 项目默认沿主轴排列。单个项目占据的主轴空间叫做main size,占据的交叉轴空间叫做cross size。

容器的属性

  • 以下6个属性设置在容器上
    • flex-direction
    • flex-wrap
    • flex-flow
    • justify-content
    • align-items
    • align-content
  1. flex-direction属性
  • flex-direction属性决定主轴的方向(即项目的排列方向)。

    1
    2
    3
    .box {
    flex-direction: row | row-reverse | column | column-reverse;
    }
  • 它可能有4个值

    • row(默认值):主轴为水平方向,起点在左端。
    • row-reverse:主轴为水平方向,起点在右端。
    • column:主轴为垂直方向,起点在上沿。
    • column-reverse:主轴为垂直方向,起点在下沿。
  1. flex-wrap属性
  • 默认情况下,项目都排在一条线(又称”轴线”)上。flex-wrap属性定义,如果一条轴线排不下,如何换行。

    1
    2
    3
    .box{
    flex-wrap: nowrap | wrap | wrap-reverse;
    }
  • 它可能取三个值。

    • nowrap(默认):不换行。
    • wrap:换行,第一行在上方。
    • wrap-reverse:换行,第一行在下方。
  1. flex-flow
  • flex-flow属性是flex-direction属性和flex-wrap属性的简写形式,默认值为row nowrap。
    1
    2
    3
    .box {
    flex-flow: <flex-direction> || <flex-wrap>;
    }
  1. justify-content属性
  • justify-content属性定义了项目在主轴上的对齐方式。

    1
    2
    3
    .box {
    justify-content: flex-start | flex-end | center | space-between | space-around;
    }
  • 它可能取5个值,具体对齐方式与轴的方向有关。下面假设主轴为从左到右。

    • flex-start(默认值):左对齐
    • flex-end:右对齐
    • center: 居中
    • space-between:两端对齐,项目之间的间隔都相等。
    • space-around:每个项目两侧的间隔相等。所以,项目之间的间隔比项目与边框的间隔大一倍。
  1. align-items属性
  • align-items属性定义项目在交叉轴上如何对齐。

    1
    2
    3
    .box {
    align-items: flex-start | flex-end | center | baseline | stretch;
    }
  • 它可能取5个值。具体的对齐方式与交叉轴的方向有关,下面假设交叉轴从上到下。

    • flex-start:交叉轴的起点对齐。
    • flex-end:交叉轴的终点对齐。
    • center:交叉轴的中点对齐。
    • baseline: 项目的第一行文字的基线对齐。
    • stretch(默认值):如果项目未设置高度或设为auto,将占满整个容器的高度。
  1. align-content属性
  • align-content属性定义了多根轴线的对齐方式。如果项目只有一根轴线,该属性不起作用。

    1
    2
    3
    .box {
    align-content: flex-start | flex-end | center | space-between | space-around | stretch;
    }
  • 该属性可能取6个值。

    • flex-start:与交叉轴的起点对齐。
    • flex-end:与交叉轴的终点对齐。
    • center:与交叉轴的中点对齐。
    • space-between:与交叉轴两端对齐,轴线之间的间隔平均分布。
    • space-around:每根轴线两侧的间隔都相等。所以,轴线之间 的间隔比轴线与边框的间隔大一倍。
    • stretch(默认值):轴线占满整个交叉轴。

      项目的属性

  • 以下6个属性设置在项目上。
    • order
    • flex-grow
    • flex-shrink
    • flex-basis
    • flex
    • align-self
  1. order属性
  • order属性定义项目的排列顺序。数值越小,排列越靠前,默认为0。
    1
    2
    3
    .item {
    order: <integer>;
    }
  1. flex-grow属性
  • flex-grow属性定义项目的放大比例,默认为0,即如果存在剩余空间,也不放大。

    1
    2
    3
    .item {
    flex-grow: <number>; /* default 0 */
    }
  • 如果所有项目的flex-grow属性都为1,则它们将等分剩余空间(如果有的话)。如果一个项目的flex-grow属性为2,其他项目都为1,则前者占据的剩余空间将比其他项多一倍。

  1. flex-shrink属性
  • flex-shrink属性定义了项目的缩小比例,默认为1,即如果空间不足,该项目将缩小。

    1
    2
    3
    .item {
    flex-shrink: <number>; /* default 1 */
    }
  • 如果所有项目的flex-shrink属性都为1,当空间不足时,都将等比例缩小。如果一个项目的flex-shrink属性为0,其他项目都为1,则空间不足时,前者不缩小。

  • 负值对该属性无效。
  1. flex-basis属性
  • flex-basis属性定义了在分配多余空间之前,项目占据的主轴空间(main size)。浏览器根据这个属性,计算主轴是否有多余空间。它的默认值为auto,即项目的本来大小。

    1
    2
    3
    .item {
    flex-basis: <length> | auto; /* default auto */
    }
  • 它可以设为跟width或height属性一样的值(比如350px),则项目将占据固定空间。

  1. flex属性
  • flex属性是flex-grow, flex-shrink 和 flex-basis的简写,默认值为0 1 auto。后两个属性可选。

    1
    2
    3
    .item {
    flex: none | [ <'flex-grow'> <'flex-shrink'>? || <'flex-basis'> ]
    }
  • 该属性有两个快捷值:auto (1 1 auto) 和 none (0 0 auto)。

  • 建议优先使用这个属性,而不是单独写三个分离的属性,因为浏览器会推算相关值。
  1. align-self属性
  • align-self属性允许单个项目有与其他项目不一样的对齐方式,可覆盖align-items属性。默认值为auto,表示继承父元素的align-items属性,如果没有父元素,则等同于stretch。

    1
    2
    3
    .item {
    align-self: auto | flex-start | flex-end | center | baseline | stretch;
    }
  • 该属性可能取6个值,除了auto,其他都与align-items属性完全一致。


👏👏👏 小编有话讲:
以上只是小编的浅见,如果有误,欢迎提意见@小编😊❤️

GitHub

GitHub的相关内容✍️

相关博客: 🙆🕮

WordPress-Cecilia


GitHub 是一个面向开源及私有软件项目的托管平台,是使用 git 分布式版本控制系统.下面是我的一些学习总结:

常用辅助命令

1
2
3
4
5
// 查看提交日志
$ git log -3 --------查看最近三次提交的记录

// 查看文件提交状态
$ git status

常用的分支命令

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
// 查看当前所有分支
$ git branch

# * dev ---- 当前分支
# master ---- 主分支


// 创建分支
$ git branch dev

// 切换分支
$ git checkout dev

// 创建并切换分支(相当于前两步操作)
$ git checkout -b dev

// 合并分支
$ git merge dev ------ ⚠️ (此命令为:合并某分支到当前分支,例:将dev合并到master),则当前所处于master分支。

// 删除指定分支
$ git branch -D dev ------ ⚠️(保证当前分支为非删除分支

设置静态资源的预览

1
2
3
4
5
6
7
8
// 创建gh-pages分支(此分支的名字只能是gh-pages)
$ git branch gh-pages

// 切换到此分支
$ git checkout gh-pages

// 提交远程(完成)
$ git push origin gh-pages

🖊️补充: 怎么找回不小心删除的文件(在本地仓库中):

1
2
3
4
5
6
7
8
// 查看当前状态
$ git status

// 重置
$ git reset head index.html

// 切回
$ git checkout index.html

👏👏👏 小编有话讲:
更多相关内容请关注我的博客呦,有什么不懂和有问题的也可以@小编😊❤️

node.js

node.js阶段总结


什么是前端和后端

后端的主要工作

  1. 后端为前端程序员暴露API接口;
  2. 后端也要操作数据库;
  3. 优化后端业务的性能;

    前端的主要工作

  4. 绘制网页的页面(HTML)
  5. 写CSS样式美化页面、写JS做网页交互(更多的是网页的特效)
  6. 借助于 XHR($.ajax $.get $.post)请求后端的接口;实现前后端分离开发
  7. 使用前端的(框架)去完成界面的开发
  8. 总结:前端的主要工作:用户能看到的东西,基本上都是前端做出来;

    前后端协作流程

  • 将来进入工作,大家会接触到【前后端分离开发】;
  • 协作开发的流程:后端为我们暴露数据接口,前端单纯的调用后端接口;
  • 在当前Node阶段中,我们学习的是 后端开发;
  • 在Node阶段,我们主要教大家如何写后端的接口;

环境安装

LTS 和 Current 版本区别

  1. LTS 是长期稳定版的意思(这个安装包用起来比较稳定)【推荐在企业中使用】
  2. Current 是最新特征版,这个安装包中有最新的Node特性,但是,可能有一些潜藏的Bug未解决;【推荐学习或尝鲜去使用】

    下载安装

    查看 Node 版本号

    打开终端,在命令行输入命令node -v即可
    如何进入终端呢?
  3. 使用快捷键windows徽标 + R打开运行面板,输入 cmd 后直接回车;
  4. 在任意目录的空白位置,先按住shift键不松开,然后,在空白位置,鼠标右键单击,会出来一个右键菜单,选择在此处打开 powershell/cmd 窗口【将来第二种方式用的会多一些】

    环境变量

    什么是环境变量

    Path环境变量的作用:能够让我们通过命令行的形式,快速启动一些应用程序;

    系统环境变量和用户环境变量的区别

  5. 用户环境变量,是每个用户私有的,用户之间不会共享;
  6. 全局环境变量,是共享的,只要你能登录这台计算机,就能访问到全局的环境变量;【今后在配置环境变量的时候,推荐直接配置到系统环境变量】

    通过命令行快速启动应用程序时,路径的查找规则

  7. 先在当前 cmd 终端的目录中查找,如果有则直接运行;
  8. 如果当前目录中没有,则去全局的path环境变量中查找;

浏览器中的 JavaScript

Javascript的诞生

  1. JS 诞生 和 网景公司 有关;form
  2. JS 诞生的需求,就是为了做客户端表单验证的;
  3. JS作者刚把JS创建出来之后,它叫 LiveScript -> Javascript

    浏览器一战

    主角是 IE 和 网景浏览器;
  4. 一战的果实:ECMAScript 规范的确立!
  5. 短暂的和平期:在和平期阶段,JS都在做什么事情呢(进行表单的验证、做简单的网页动效、狗皮膏药),一战之后,JS能力有限,当时被称作是“脚本语言”

    浏览器二战

  • 在 2008 年,二战开始了;
  • 谷歌chrome、IE、火狐(浴火重生)
  • 在 2008 年,谷歌 利用 XHR 这个对象,实现了网页的局部刷新;
  • 2010 - 2013年左右,公司中,不管是Java,还是.NET, 还是 PHP(会不会Ajax)
  1. 二战的果实:XHR 对象的诞生; chrome 浏览器的 JS V8 解析引擎;

    注意

  • 在 一战 和 二战期间,JS 只能运行在 浏览器中;
    浏览器中的JS组成部分:ECMAScript核心 + DOM + BOM
    浏览器属于前端环境,所以,之前的JS只运行在前端浏览器中;也就是,无法使用Javascript实现后端编程;

Node中的Javascript

  • Node.js 的诞生,解放了Javascript,从此之后,Javascript 就可以在 服务器端运行了;

    ECMAScript

  • Node中的Javascript也有一个ECMAScript核心

    没有 BOM 和 DOM

  • Node中并没有浏览器的概念,所以,BOM和 DOM ,Node中不需要,因此,就把它们给剔除了;

    全局成员(网页和Node中都可以用)

  1. console
  2. setInterval
  3. setTimeout
  4. …其它全局成员

    模块系统

  5. Node中自己扩展出来的一套API规范

    Node中的JS组成部分

  • ECMAScript核心 + 全局成员 + 模块系统成员(这是Node平台所独有的)
  1. 全局成员(console.log, setTimeout setInterval)
  2. 模块系统成员(就是Node中的一些核心模块,提供了一些后端编程的能力)

ECMAScript 规范 和 浏览器中的JS 以及 Node 中的 JS 之间的关系

  1. ECMAScript 规范(标准):就是一本书,这本书中记录了基本的语法定义;
  2. 浏览器中的 JS:浏览器中的JS是一门具体的编程语言,实现了 ECMAScript 规范;
    • 浏览器中的JS组成部分: ECMAScript 核心 + DOM + BOM
  3. Node中的JS:也是一门具体的编程语言,也实现了 ECMAScript 规范;
    • Node中的JS组成部分: ECMAScript 核心 + 全局成员 + 模块系统成员

总结-什么是 Node.js

  • 基于 Chrome 的V8 JS 解析引擎之上,解放了Javascript的编程能力,为 Javascript 提供了 后端编程的能力;
  • 所以说,Node.js 是 一个后端编程的平台,用到的语言是Javascript;

Node.js 环境中执行JS代码的两种方式

REPL 环境

  1. 如何进入 REPL 环境: 打开任意终端,直接输入 node 并回车,就会进入到 REPL 环境中;
  2. 如何离开 REPL 环境:按两次ctrl + c 就能退出 REPL 环境;
  3. REPL中,每个字母代表什么意思呢:
    • R: Read 的意思,每当我们输入完毕代码之后,只要敲击回车,Node环境就会读取用户输入的代码
    • E:Evaluate 的意思,表示把 Read 进来的用户代码,调用 类似于 Eval 的函数,去解析执行
    • P:Print 输出的意思;把第二步中解析执行的结果,输出给用户;
    • L:Loop 循环的意思,表示当输出完毕之后,进入下一次的 REP循环

      node 命令【推荐形式】

  • (Node为JS提供了一个脱离浏览器平台也能被解析的执行环境)
  • 直接使用node 要执行的js文件的路径 来执行指定的JS文件
  1. 使用 ↑ 快速定位到上一次执行的命令
  2. 使用 tab 键能够快速补全路径
  3. 使用 cls 可以清屏

ECMAScript 6常用语法

let 与 const

  • 之前定义变量,用 var 关键字,用var有没有缺点:
  1. 变量提升问题
  2. 没有块级作用域
  • let特性:
    1. 使用let关键字定义变量,不存在变量提升的问题
    2. let定义的变量受到{ } 作用域的影响(有{}的作用域)
    3. let有块级作用域
  • const特性:
    1. 没有变量提升的问题
    2. const 定义的量叫常量,只要被定义了,无法被重新赋值
    3. 当定义常量的时候,必须定义且初始化,否则报语法错误

      变量的解构赋值

  1. 所谓的解构赋值,就是把 某个对象中的属性,当作变量,给解放出来,这样,今后就能够当作变量直接使用了
  2. 可以使用 :为解构出来的变量重命名
    1
    2
    3
    // 变量的解构赋值
    const { name : name123, age, gender } = person
    console.log(name123)

字符串扩展

  1. 模板字符串
  • 模板字符串的特点: 支持换行,可以嵌入变量的值
    1
    2
    3
    4
    5
    str +=`<tr>
    <td>${arr[i].id}</td>
    <td>${arr[i].name}</td>
    <td>${arr[i].age}</td>
    </tr>`
  1. startsWith() 和 endsWith()
    • startsWith() 用来判断字符串,是否以指定的字符开头,如果是,返回值是 true,否则返回 false
    • endsWith() 用来判断字符串,是否以指定的字符结尾;如果是,返回值是 true,否则返回 false
  2. padStart() 和 padEnd()
  • padStart()第一个参数是填充完毕之后总长度是多少;第二个参数是填充的内容

    函数扩展

  1. 形参默认值

    1
    2
    3
    function add(x, y = 0) {
    return x + y;
    }
  2. 解构赋值和形参默认值结合使用

  3. rest参数(定义函数的时候使用…来定义的参数叫做rest参数,定义一个接受所有参数的数组)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    // ------------------rest参数-------------------
    function add(...args) {
    console.log(args instanceof Array)

    let total = 0
    args.forEach(item => {
    total += item
    })
    console.log(total)
    }

    add(1, 2, 3, 4)
  4. 扩展运算符(在调用函数的时候,使用的…的运算符来扩展数组,…运算符称为扩展运算符)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    // ----------------------扩展运算符--------------
    function add(...values) {
    let total = 0
    values.forEach(item => {
    total += item
    })

    console.log(total)
    }

    const arr = [1, 2, 3]
    add(...arr)

箭头函数(是ES6中新增的函数形式)【今后我们会每天写箭头函数的】

  1. 如何把 function 改成 箭头函数呢: 先把 function 删掉,然后,在 () 和 { } 之间,添加一个 => 就好了
  2. 箭头函数的特性: 箭头函数内部的 this, 永远和 箭头函数外部的 this 保持一致;
  3. 箭头函数,本质上就是一个匿名函数 (不能直接调用)
  4. 最标准的箭头函数格式是 ( 参数列表 ) => { 函数体 }
  5. 变体1: 如果 箭头函数左侧的 形参列表中,只有一个 形参,那么,( ) 可以省略 ( x ) => { console.log(x) } 可以改造成 x => { console.log(x) }
  6. 变体2:如果 箭头函数右侧的 函数体中,只有一行代码,那么, { } 可以省略 (x, y) => {console.log(x + y)} 可以改造成 (x, y) => console.log(x + y)
  7. 变体3:如果箭头函数 左侧 只有一个形参,右侧只有一行代码,那么, 左侧的 () 和 右侧的 {} 都可以省略 ( x ) => { console.log(x) } 可以改造成 x => console.log(x)
  8. 注意: 如果我们省略了 右侧的 { }, 那么,默认就会把 右侧函数体中的代码执行结果,返回出去 (x, y) => { return x + y } 可以简写成 (x, y) => x + y

    对象中定义方法和属性的便捷方式

在Node中使用fs模块进行文件操作

文件读取

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
  // 1. 使用require 来导入需要的模块
const fs = require('fs')
// 参数一: 要读取文件的路径
// 参数二: 可选参数,表示字符编码, 默认为空null
// 参数三: callback回调函数
// fs.readFile('./files/1.txt', function (err,buf){
// console.log(err)//null
// console.log(buf.toString())//Buffer是一种类型,表示二进制的意思
// 如果读取文件没有出错,则err默认为null,buf是读取到的二进制
// 可以调用buffer.toString转换为正常的字符串

// Buffer 实例和字符串拼接,得到的结果,是一个字符串
// console.log(buf + '')
// })

// fs.readFile('./files/1.txt',(err,buf) => {
// Error 实例对象中,有个message属性,表示错误信息
// if(err)return console.log(err.message)
// console.log(buf.toString())
// })
// 第二个参数可以用'utf-8'的编码格式,这样buf就不用转换为字符串
fs.readFile('./files/1.txt','utf-8',(err,dataStr) => {
// Error 实例对象中,有个message属性,表示错误信息
if(err)return console.log(err.message)
console.log(dataStr)
})

文件写入

  • 参数一: 文件路径
  • 参数二: 要写入的数据
  • 参数三: 可选的编码格式, 默认utf-8
  • 参数四: 文件写入后的回调函数
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
      const fs = require('fs')
    // 写入文件到指定文件中去(会覆盖原来的内容)
    fs.write('文件路径','内容',(err) => {
    // 内容的改变会覆盖上一次的上传
    if(err) return console.log('写入失败了:' + err.message)
    console.log('写入成功了!')
    })
    // fs.copyFile 也可以,但它只支持8.5.0以上的版本
    fs.copyFile('./files/1.txt''./files/1-copy.txt'(err) => {
    if(err) return console.log('写入文件失败:' + err.message)
    console.log('恭喜,写入成功')
    })

文件追加

  • fs.appendFile(file,data[,option],callback)
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    // 1. 导入 fs 文件系统模块
    const fs = require('fs')
    // 参数一: 要追加的文件的路径
    // 参数二: 要追加的数据内容
    // 第三个参数:追加时候的编码格式 默认为utf-8
    // 参数三: 追加完毕之后的回调函数
    fs.appendFile('./files/2.txt','\n降龙十八掌',(err) => {
    if(err) return console.log('写入文件失败:' + err.message)
    console.log('恭喜,写入成功')
    })

fs模块中路径操作问题【难点】

  • 在Node中,使用fs模块来操作文件的时候,如果我们给定的路径是一个以’./‘开头的相对路径,找文件指的是Node命令所在的目录来查找 ,所以最好使用绝对路径(拼接成绝对路径 __dirname + ‘文件名’)
  1. __dirname 表示当前文件所在的目录
  2. __filename 表示当前文件的完整路径
  • const path = require(‘path’) const abspath = path.join(__dirname,’文件名’)来解决/的问题
  • 注意: 今后在使用fs模块中任意方法时只要涉及路径的操作都是用_dirname做拼接

读取文件信息 fs.stat

  • fs.stat(path,callback)

    读取指定目录中所有文件的名称 fs.readdir

  • fs.readir(path[,option],callback)

在ES6中用path来进行路径操作

  1. path.join([…paths])
  • path.join 来解决路径分隔符的问题
  • 今后只要涉及到路径的拼接,推荐大家使用 path.join 方法
  1. path.sep
  2. path.basename(path[, ext])
  3. path.dirname(path)
  4. path.extname(path)

    Javascript 是单线程的一门语言

  5. 什么是单线程:用户无法主动开启子线程,对于JS的运行来说,永远是主线程在执行关键代码;
  6. 什么是多线程:用户可以主动开启子线程; Thread td = new Thread()
  7. 在Node中,操作文件和网络都是比较耗时的操作;

Node中为什么大量使用异步方法

  1. 为什么要使用 异步方法呢: 因为 异步方法,不会阻塞CPU去执行其它任务;
  2. 为什么在Node中不推荐使用同步呢: 因为 同步,需要一个一个执行,耗时的操作会阻碍CPU执行后续任务,因此,效率慢;

CommonJS 模块规范和模块的使用

Node.js 实现了 CommonJS 模块化规范;

  1. 什么是 CommonJS 规范?
    • CommonJS 是为了实现 Javascript 的模块化,而制定的一套规范;
  2. 为什么 Javascript 需要模块化?(require,exports,module)
    • 所谓的模块化,就是在一个js文件中,能够引入其他的js文件
    • 浏览器中的Javascript有没有实现模块化?(在一个JS文件中,能不能引用另外JS文件中的方法)
    • 因为有了模块,我们就可以更方便地使用别人的代码,想要什么功能,就加载什么模块。
  3. 如何实现 Javascript 的模块化?
    • 为了统一大家编写模块时候的规则,方便各模块之间的依赖和调用,于是 CommonJS 规范就应运而生了。
  4. 那么,CommonJS 模块化规范,到底是个什么东西??
    • 定义了什么是模块
    • 在NodeJs中,可以认为一个js文件就是一个模块,一个模块可以是一个js文件,也可以是由多个js文件组成的
    • 一个JS模块中,如何引入其它的JS模块
    • 用require引入: require(‘路径’)
    • 一个JS模块中,如何向外暴露一些成员,供其它模块调用;
    • exports.xxx = xxxx
    • 使用module对象去访问当前模块, module.exports.xxx=xxx
    • 如果没有类似于 CommonJS 的规范,行不行?
    • 只有大家遵守同样的规范,才能够协作开发,方便别人,同时也方便自己;

全局作用域和模块作用域

  1. 每个JS文件,就是一个独立的模块,在这个JS文件中,所定义的任何方法、属性、变量、常量、对象,默认都属于模块作用域,并不会属于 全局作用域;
  2. 如果在某个模块内部,想为 全局的 global 作用域挂载一些属性,需要显示的调用global.***来挂载;

    global(全局作用域)

  • 使用global这个全局对象,会造成全局变量的污染(推荐使用CommonJS规范中定义模块化机制来向外暴露成员)

    require(模块引用)

    每一个实现了 CommonJS 规范的模块,必须定义一个 require() 函数,使用这个 require 函数,就能够 很方便的导入其它 模块中的成员,供自己使用;

    exports(模块定义)

    每一个模块中,如果想要把自己的一些私有成员,暴露给别人使用,那么,必须实现一个 exports 对象,这个对象,将来,如果你想把自己的成员,暴露给别人使用,只需要把自己的成员,挂载到 exports 上就行了(exports默认是空对象)

    module(模块标识)

    这个 module 也是Common JS 规定的,它表示一个具体的模块,也是一个对象;

module.exports 和 exports 的关系

  • 在一个模块中,默认情况下module.exports和exports是指向同一个空对象的
  • 在一个模块中,在向外暴露成员的时候,永远以module.exports指向的对象为准

Node 中的 Javascript 由几部分组成

  1. ECMAScript 核心
  2. 全局成员
  3. 模块系统成员
    • 模块系统成员,根据一些区别,又可以分为三大类: 核心模块、第三方模块、用户自定义模块

模块分类

核心模块

  1. 什么是核心模块:由Node官方提供的好用的模块,叫做核心模块;只要大家在计算机中,安装了Node这个应用程序,那么,我们的计算机中就已经安装了所有的 核心模块;
  2. 如何使用核心模块:require('核心模块标识符')

    第三方模块

  3. 什么是第三方模块:一些非官方提供的模块,叫做第三方模块;注意,第三方模块,并不在我们的计算机上,如果大家需要使用某些第三方模块,必须去一个叫做 NPM 的网站上搜索并下载才能使用;
  4. 如何使用第三方模块:
    • 先从 npm 官网上下载指定的第三方模块
    • 使用 require('第三方模块的名称标识符')来导入这个模块
    • 根据 第三方模块的 官方文档,尝试使用

      用户自定义模块

  5. 什么是用户模块:程序员自己写的JS文件,就叫做 用户自定义模块;
  6. 如何使用用户模块:require('路径标识符')

什么是包

  1. 英文名叫做 Packages,包是在模块基础上更深一步的抽象,目的是:方便分发推广基于 CommonJS 规范实现的 应用程序 或 类库;
  2. 包可以看作是 模块、代码 和 其它资源 组合起来形成的 独立作用域;

定义一个包

  1. 首先包应该是一个独立的文件夹(名字应该是英文)
  2. 包的文件夹里面应该有一个package.json文件
  3. package.json是一个json文件,在文件里编写的代码必须符合json规范(编写一个对象,对象有三个属性: name,version, main)
  4. 自定义的包目录(图片)

规范的包结构

  1. 包都要以一个单独的目录而存在
  2. package.json 必须在包的顶层目录下
  3. package.json 文件必须符合 JSON 格式,并且必须包含如下三个属性:name, version, main
    • name: 包的名字(名字不能为中文)
    • version: 包的版本号
    • main: 表示包的入口文件
  4. 二进制文件应该在bin目录下;
  5. javaScript代码应该在lib目录下;
  6. 文档应该在doc目录下;
  7. 单元测试应该在test目录下;
  8. Node.js对包要求并没有那么严格,只要顶层目录下有package.json,并符合基本规范即可;

    包描述文件 package.json

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    name:包的名称,必须是唯一
    description:包的简要说明
    version:符合语义化版本识别规范的版本字符串
    keywords:关键字数据,通常用于搜索
    maintainers:维护者数组,每个元素要包含name、email、web可选字段
    contributors:贡献者数组,格式与maintainers相同。包的坐着应该是贡献者数据的第一个元素
    bugs:提交bug的地址,可以是网址或者电子邮件地址
    licenses:许可证数组,每个元素要包含type和url字段
    repositories:仓库托管地址数组,每个元素要包含type、url和path字段
    dependencies:包的依赖,一个关联数组,由包名称和版本号组成。
    devDependencies:开发依赖项,表示一个包在开发期间用到的依赖项

npm

npm 的两层含义

  1. NPM 是一个 第三方模块的托管网站,指的就是https://www.npmjs.com/
  2. NPM 是Node的包管理工具(全名叫做 Node package manager),在我们安装Node时候,就已经顺便也安装了 NPM 这个管理工具;

    安装和卸载全局包

  3. 什么是全局的包:通过 npm install 包名 -g 方式安装的包,都安装到了全局;一般全局的安装目录是C:\Users\自己的用户文件夹\AppData\Roaming\npm
  4. 带大家演示如何安装一个全局的包:npm install i5ting_toc -g, 注意:这里的-g表示全局安装包的意思;
  5. 注意:一般,只有一些工具,才有全局安装的必要性;
  6. 如果要全局卸载某个包,比如要卸载 i5ting_toc了,直接运行npm uninstall i5ting_toc -g就可以全局卸载包了!

    安装和卸载本地包

  7. 什么是本地的包:跟着项目安装的包,叫做本地包;
  8. 如果拿到一个空项目,必须先初始化一个package.json的配置文件,npm init或者npm init -y(方便些)
  9. 运行npm i 包名@版本号 --save去安装指定的包,本地安装的包,都安装到了node_modules的目录下
  10. 如果大家用的是npm 5.x的版本,可以不指定--save命令,如果用的是 npm 3.x 的版本,则需要手动指定 --save, 同时,--save有缩写形式,是:-S
  11. package-lock.json文件中记录了曾经装过的包的下载地址,方便下次直接下载包;
  12. 卸载本地包: npm uninstall 包名 --save

    其它常用命令

  13. --save-dev它的缩写是-D
  14. 注意:dependencies节点,表示项目上线部署时候需要的依赖项;devDependencies节点,表示项目在开发阶段需要的依赖项,但是当项目要部署上线了,devDependencies节点中的包,就不再需要了!
  15. 注意:当使用npm i快速装包的时候,npm会检查package.json文件中,所有的依赖项,然后都为我们安装到项目中
  16. --production 表示只安装 dependencies 节点下,记录的包,不安装devDependencies节点下的包;当项目要上线了,才会使用--production命令

    解决 npm 下载慢问题

  17. 默认,NPM在下载包的时候,连接的是国外的服务器,所以,有时候如果网速不是特别好,可能下载不下来包;此时,大家可以安装一个工具,叫做nrm,里面记录了好多下载NPM包的服务器地址,可以让我们方便的切换下载包时候请求的服务器;
  18. 运行npm i nrm -g(注意:只要是工具,一般都是全局 -g 安装)
  19. 当装完 nrm 之后,可以运行nrm ls 查看所有可用的服务器列表
  20. 可使用nrm use 服务器名称来切换下载包时候的服务器地址

构建web应用

Apache 是一个PHP的服务器,当我们把做好的网站,丢到 WWW 目录下,就能够使用 IP地址 + 端口号 访问我们的网站了;

  • IP地址的作用,是为了表示当前网络中这台计算机唯一身份的;
  • 端口号:端口号和应用程序有关联,每一个应用程序,只能独占一个端口号,不能说多个应用程序公用一个端口;
    疑问:Node中,有没有类似于 Apache 这样的服务器软件,来提供对应的网站服务呢?注意:Node中,并没有现成的 类似于 Apache 的服务器软件,如果我们想通过Node,来对外托管一个网站的话,需要自己手写一个 类似于 Apache 的服务器;

    BS 交互模型

  1. HTTP 协议是基于 请求 - 处理 - 响应 通信模型的

    实现静态资源服务器

  2. 后端路由的本质
  • 重点理解URL(统一资源定位符)的本质

    在 Node 中使用模板引擎

    使用 http 核心模块 - 构建自己的 web server(web服务器)

    理解 BS 交互模型

    B/S:表示 Browser / Server C/S Client / Server
  1. 什么是服务器:在网络节点中,专门对外提供资源服务的一台电脑;
  2. 什么是客户端:在网络节点中,专门用来消耗或呈现服务器中返回的数据的电脑;
  3. 什么是静态资源:像 .js , .css, .jpg, .html ;所谓的静态资源,就是无需数据交互,服务器直接把资源读取,并响应给客户端就完事儿;
  4. 什么是动态资源:当一些资源,服务器上并没有现成的,需要现在服务器端,做一层处理,最后把处理的结果返回给客户端,这样的资源,叫做动态资源;
  5. HTTP 协议的通信模型:请求 - 处理 - 响应的过程;

    创建基本http服务器

  • 1.先导入Node中提供分核心模块 http : const http = require(‘http’)
    1. 创建服务器 : const server = http.createServer()
    1. 为这个server服务器,通过on方法,绑定一个事件: server.on(‘request’,function(){
      console.log(‘ok)
      })
    1. 启动服务器: server.listen(3000,function(){
      console.log(‘通知大家,服务器已经启动’)
      })

      解决返回内容的编码格式

  • 200 是状态码
    1
    2
    3
    res.writeHeader(200,{
    "Content-Type":'text/html;chartset=utf-8'
    })

实现静态资源服务器

  1. 后端路由的本质
  • 重点理解URL(统一资源定位符)的本质
  • 注意: res.end()方法只接受字符串或Buffer二进制,在网络传输中内容都是以二进制进行传输的

    结合模板引擎实现动态资源服务器

静态资源请求路径问题

  1. 在浏览器的眼中,只要是地址栏中的地址,浏览器永远把 最后一个 / 后面的符号,认为是文件名
  2. 对于服务器来说,客户端请求的 URL 资源路径只是一个 标识符 而已,URL 不一定非要对应实际的物理磁盘路径!
  3. 一定要区分html中书写的路径标识符 ../ .// 在浏览器中代表含义!
  • / 表示,直接从端口号后面,开始资源请求
  • ./ 表示,在发起资源请求之前,浏览器需要先 把 URL 地址 ,和 资源路径做一层拼接
  • ../ 表示,在发起资源请求之前,浏览器需要先 把 URL 地址 ,和 资源路径做一层拼接

    使用 nodemon 工具来自动重启web服务器

  • 这个工具的作用:能够实时监听 web 服务器中,代码的改变,只要代码被修改并保存了,则 nodemon 工具,会自动重新启动 web 服务器;
  • 运行 npm i nodemon -g 就能够在全局环境中,安装这个工具了
  • 当安装完毕 nodemon 之后,就可以 使用 nodemon 要执行的js文件路径 来运行JS文件了
  • 今后在开发Web项目的时候,推荐使用 nodemon 来执行 web 服务器

Node 中的 Web 快速开发框架 - Express

定义什么是Express:

  1. 基于 Node.js 后端Javascript平台之上,开发出来的一套Web开发框架;
  2. Express中,基于 原生Node的特性,做了进一步的封装,提供了一些更加好用的方法,来提高Web开发的体验;
  3. Express中,并没有覆盖或者删除原生的http模块方法;

    express 框架的安装和基本使用

  4. 直接运行 npm install express --save 就可以安装Express框架了

    使用 express 快速托管静态资源

  5. 如果我们网站中,有很多静态资源需要被外界访问,此时,使用 res.sendFile 就有点力不从心了,这时候,express 框架,为我们提供了一个 内置的(中间件) express.static('静态资源目录') , 来快速托管指定目录下的所有静态资源文件;
  6. 用法: app.use(express.static('public'));
  • 其中, express.static 是一个express的内置中间件;
  • app.use()方法,是专门用来注册 中间件;
  1. 当使用 第二步中的方法,把指定目录托管为静态资源目录之后,那么,这一层被托管的目录,不应该出现在 资源访问的 URL地址中;

  2. 在一个Web项目中,我们可以多次调用app.use(express.static())

  3. 在多次调用 express.static 的时候,如果文件名称有重复的,则以先注册的中间件为主!

  4. 如果项目要部署了,推荐大家配置一个叫做compression的中间件,它能够开启服务器的GZip压缩功能;

  5. 1
    var compression = require('compression') app.use(compression())

为 express 框架配置模板引擎渲染动态页面

  1. 安装 ejs 模板引擎npm i ejs -S
  2. 使用 app.set() 配置默认的模板引擎 app.set('view engine', 'ejs')
  3. 使用 app.set() 配置默认模板页面的存放路径 app.set('views', './views')
  4. 使用 res.render() 来渲染模板页面res.render('index.ejs', { 要渲染的数据对象 }),注意,模板页面的 后缀名,可以省略不写!
  5. 使用res.send()来解决中文乱码问题

    使用 express 框架中提供的路由来分发请求

  6. 什么叫做路由:前端请求的URL地址,都要对应一个后端的处理函数,那么 这种URL地址到 处理函数之间的对应关系,就叫做后端路由;
  7. 在Express中,路由主要负责 分发请求处理的;
  8. 在Express中,如何 定义并使用路由呢?

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    // 1. 封装单独的 router.js 路由模块文件
    const express = require('express')
    // 创建路由对象
    const router = express.Router()

    router.get('/', (req, res)=>{})
    router.get('/movie', (req, res)=>{})
    router.get('/about', (req, res)=>{})

    // 导出路由对象
    module.exports = router
  9. express创建的 app 服务器,如何使用 路由模块呢?

    1
    2
    3
    4
    // 导入自己的路由模块
    const router = require('./router.js')
    // 使用 app.use() 来注册路由
    app.use(router)

Express 框架里 中间件的概念

  1. 什么是中间件
  • 中间件是一个函数
  • 中间价这个函数是一个路由的处理函数
  • 中间件这个函数,不但是一个路由处理函数,而且在参数列表中,还有一个很重要的形参,叫做next
  • 这个next是一个函数, 因此,我们在中间件中,调用这个next()函数
  • 中间件的表现形式: 只要这个函数的形参列表中,有一个next函数,它就是中间件
  1. 中间件的作用是
  • 中间件表示每一个处理环节,这些处理环节,只负责单独的处理,每当上一个中间件处理完毕后,必须把处理的原材料交给下一个中间件来继续处理
  • 中间件之间,共享的是 req和res这两个对象
  1. 如何注册中间件
  • app.use(中间件的函数)
  1. 中间件里next函数的作用
  • 从上一个中间件处理函数中,进入下一个中间件处理函数

    自己模拟一个解析表单数据的中间件

  1. 自己模拟中间件的时候,需要使用 req.on('data', (chunk)=>{})req.on('end', ()=>{}) 来获取表单,并使用 querystring模块的parse方法来解析成对象;
  2. 我们在开发中,推荐大家直接使用第三方的body-parser中间件来解析表单;

    Express 框架中对中间件的5种分类

  3. 应用级别中间件:挂载到 app 对象身上的 中间件(函数 )
  4. 路由级中间件: 挂载到 router 对象上的中间件
  5. 错误处理中间件:参数列表中要有四个形参,从前到后分别是 err, req, res, next
  6. 内置中间件: Express 中唯一的内置中间件 express.static(root, [options])
  7. 第三方中间件: 通过 npm安装的中间件,叫做 第三方中间件!

Express 中进行数据库操作

  1. 用的数据库是MySql
  2. 大家是直接安装的MySql
  3. 安装了一个叫做 Navicat 的软件,来方便我们操作数据库

    配置 MySql 数据库环境

    mysql 第三方模块的介绍和基本配置

    使用 mysql 第三方模块实现 CRUD

  • C: Create
  • R: Read
  • U: Update
  • D: Delete

模块加载机制

  1. 只要使用 require 来加载指定的模块了,那么,必然会执行被加载模块中的代码!

    优先从缓存中加载

  2. Node中,默认会把曾经加载过的模块,缓存到内存中,这样,当下次再使用相同的模块,就直接从缓存中加载就行了,能够提高模块的运行效率;

    核心模块的加载机制

  3. 先从缓存中查找,如果有,则直接使用;
  4. 如果缓存中没有,则加载本地的核心模块并缓存起来,供下次使用;

    用户模块的加载机制

  5. 先从缓存中查找,如果有,则直接使用;
  6. 如果缓存中没有,则根据路径标识符,加载本地的用户模块并缓存起来,供下次使用;
  7. 用户模块的查找规则:index -> index.js -> index.json -> index.node

    第三方模块的加载机制

  8. 先从缓存中查找,如果有,则直接使用;
  9. 如果缓存中没有,则根据第三方模块的标识符,加载第三方模块并缓存起来,供下次使用;

    通过学习moment这个第三方模块来了解第三方模块的加载规则

  10. 会根据包的名称,直接在当前项目的根目录中,去查找一个叫做 node_modules 的文件夹;
  11. 如果有,则在 node_modules 中,继续查找,一个叫做 模块引用名称的文件夹;
  12. 如果有,则 在 模块对应的文件夹中,查找一个叫做 package.json 的文件;
  13. 如果有 package.json, 则查找 其中的 main 属性,并尝试加载 main 指定的文件作为入口;
  14. 如果能正常加载 main 属性中指定的文件,则模块/包加载成功!
  15. 如果 在 package.json 文件中,没有 main 属性,则会依次尝试加载 包根目录中的 index.js, index.json, index.node
  16. 如果在 包的根目录中,根本没有 package.json 文件,或者 在 node_modules 目录中没有 index 相关的文件,或者,根本没有对应的包文件夹,或者在项目根目录中根本没有node_modules, 则会向上层目录中,去查找node_modules, 查找规则同上;
  17. 如果在上一层目录中还是没有找到对应的模块,则继续向上翻,直到翻到项目所在的磁盘根目录位置;
  18. 如果翻到了磁盘的根目录中,还没有找到,此时,会报错!cannot find module ***

    express中获取参数的几种形式

    从URL地址中获取查询参数

    通过 URL 地址栏中,? 形式传递的参数,可以直接通过 req.query 来获取;

    从URL地址中获取路径参数

    直接通过路径标识符来传递参数,/userinfo/10/zs, 可以通过 req.params来获取参数

    从post表单中获取提交的数据

  • 借助于body-parser来解析表单数据
  • npm i body-parser -S
  • const bodyParser = require('body-parser')
  • app.use(bodyParser.urlencoded({ extended: false }))

Web 开发模式

混合模式(传统开发模式)

  • 以后端程序员为主,基本上不需要前端程序员,或者,前端程序员只负责画页面、美化样式、写JS特效,前端程序员不需要进行数据的交互;
  • 这种开发模式,在前几年比较常见;
  • 他们用的最多的是 Jquery + 模板引擎
  • 后端页面 .php .jsp .aspx .cshtml

    前后端分离(趋势)

  • 后端负责操作数据库、给前端暴露接口
  • 前端负责调用接口,渲染页面、前端就可以使用一些流行的前端框架 Vue, React, Angular

需求分析

  1. 后端项目运行地址:http://127.0.0.1:5000
  2. 前端项目运行地址:http://127.0.0.1:4000
  3. 前后端分离开发模式的注意点:
    • 跨域问题
    • 如果不考虑 表单的 Post 提交,则 可以使用 JSONP的形式来请求接口
    • 但是,我们的项目中,涉及到了 英雄表单的 提交,表单提交一般都是Post
    • 经过分析,由于JSONP,不支持Post,所以,我们的后端接口,无法设计成JSONP的接口;

JSONP 和 CORS 的区别

  1. JSONP的原理:动态创建script标签;
    • JSONP发送的不是Ajax请求
    • 不支持 Post 请求;
  2. CORS中文意思是跨域资源共享 , 本质,就是使用 XHR 对象,发送Ajax请求,来进行跨域的资源共享;
    • CORS 发送的是真正的Ajax请求
    • CORS 支持Ajax的跨域
    • 如果要启用 CORS 跨域资源共享,关键在于 服务器端,只要 服务器支持CORS跨域资源共享,则 浏览器肯定能够正常访问 这种 CORS 接口;而且,客户端在 发送 Ajax的时候,就像发送普通AJax一样,没有任何代码上的变化;
  3. 对于Node来说,如果想要开启 CORS 跨域通信,只需要安装cors的模块即可;

    HTTP协议的无状态性

  4. HTTP协议的通信模型:基于请求 - 处理 - 响应的!
  5. 由于这个通信协议的关系,导致了HTTP每个请求之间都是没有关联的,每当一个请求完成之后,服务器就忘记之前谁曾经请求过!
  6. 如果纯粹基于HTTP通信模型,是无法完成登录状态保持的!每次请求服务器,服务器都会把这个请求当作新请求来处理!
  7. 我们可以通过 cookie 技术,实现状态保持,但是由于cookie是存储在客户端的一门技术,所以安全性几乎没有,因此不要使用cookie存储敏感的数据!

cookie介绍

什么是cookie,作用是什么

  • 由于Http协议是无状态的,且传统服务器只能被动的响应请求,所以,当服务器获取到请求的时候,并不知道当前请求属于哪个客户端!
  • 服务器为了能够明确区分每个客户端,需要使用一些小技术,来根据不同的请求区分不同的客户端;
  • 只要有请求发生,那么必然对应一个客户端,那么,我们可以在每次客户端发起请求的时候,向服务器自动发送一个标识符,告诉服务器当前是哪个客户端正在请求服务器的数据;
  • 如何提供这个标识符呢?我们可以在请求头(Request Headers)中添加一个标签,叫做cookie,这样,每次发送请求,都会把这个cookie随同其他报文一起发送给服务器,服务器可以根据报文中的cookie,区分不同的客户端浏览器。
  • 如何在客户端请求头中添加标识符?
    • 在Node中可以在writeHeader的时候,通过Set-Cookie来将cookie标识通过响应报文发送给客户端!
    • 客户端也可以通过一些方式来操作自己的cookie,比如通过jquery.cookie这个插件!

cookie的基本使用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
var http = require('http');

var server = http.createServer();

server.on('request', function (req, res) {
// 解析cookie
var cookies = {};
var cookieStr = req.headers.cookie; // 从请求的headers中获取cookie信息
cookieStr && cookieStr.split(';').forEach(function (item) {
var parts = item.split('=');
cookies[parts[0].trim()] = parts[1].trim(); // 将cookie解析出来,保存到对象中
});

res.writeHeader(200, {
'Content-Type': 'text/plain; charset=utf-8',
"Set-Cookie": ['issend=ok', 'age=20']
});

if(cookies.issend ==='ok'){
res.end('不要太贪心哦!');
}else{
res.end('呐,赏你一朵小红花~~');
}
});

server.listen(4000, function () {
console.log('服务器已启动!');
});

通过expires设置Cookie的过期时间

1
2
3
4
5
6
7
8
// 设置 过期时间 为60秒之后
// 注意:在设置过期时间的时候,需要将时间转换为 UTC 格式
var expiresTime = new Date(Date.now() + 1000 * 60).toUTCString();
res.writeHeader(200, {
'Content-Type': 'text/html; charset=utf-8',
'Set-Cookie': ['isvisit=true;expires=' + expiresTime, 'test=OK']
});
res.end('<h3>你好,欢迎光临,送给你一个苹果!</h3>');

GMT和UTC有什么区别?格林尼治标准时(GMT)与世界时(UTC)是怎么回事

cookie可以被伪造,不安全

使用谷歌插件edit this cookie,就能伪造cookie数据!所以不要使用cookie存储敏感的数据!比如登录状态和登录信息;
一些敏感的数据,应该存储都服务器端!

什么是Cookie的应用场景

  1. 对安全性要求不高
  2. 不需要存储大量的数据
  3. 主要应用场景,是用来做 客户端 与 服务器之间的 状态保持技术;

使用express-session来保存登录状态

什么是session

由于HTTP是无状态的,所以服务器在每次连接中持续保存客户端的私有数据,此时需要结合cookie技术,通过session会话机制,在服务器端保存每个HTTP请求的私有数据;

session原理

在服务器内存中开辟一块地址空间,专门存放每个客户端私有的数据,每个客户端根据cookie中保存的私有sessionId,可以获取到独属于自己的session数据。

在express中使用session

  1. 安装session模块

    1
    npm install express-session -S
  2. 导入session模块

    1
    var session = require('express-session')
  3. 在express中使用session中间件:

    1
    2
    3
    4
    5
    6
    // 启用 session 中间件
    app.use(session({
    secret: 'keyboard cat', // 相当于是一个加密密钥,值可以是任意字符串
    resave: false, // 强制session保存到session store中
    saveUninitialized: false // 强制没有“初始化”的session保存到storage中
    }))
  4. 将私有数据保存到当前请求的session会话中:

    1
    2
    3
    4
    // 将登录的用户保存到session中
    req.session.user = result.dataValues;
    // 设置是否登录为true
    req.session.islogin = true;
  5. 通过destroy()方法清空session数据:

    1
    2
    3
    4
    5
    6
    req.session.destroy(function(err){
    if(err) throw err;
    console.log('用户退出成功!');
    // 实现服务器端的跳转,这个对比于 客户端跳转
    res.redirect('/');
    });

相关文章

  1. node.js中express-session配置项详解
  2. MD5在线生成器1
  3. MD5在线生成器2
  4. JavaScript-MD5

JavaScript-summarize

JavaScript学习总结【2】、JS基础


JS命名规范

命名规范是很有必要的,可增强代码的可读性,一眼就能看懂要表达的意思,规范就是符合规则,使代码有利于后期维护,也能很大程度的提高开发效率。一个正常的网站有很多 JS 代码,如果在编写的过程中,不遵循某种规则,那么写到后面自己都看不懂自己写的什么,这是很麻烦的一件事,所以要在平时的练习过程中,养成良好的编写代码的习惯。

  • 一般都采用匈牙利命名法或者驼峰命名法。
  • 匈牙利命名法的原则:变量名=属性+类型+对象描述。他的关键是:以一个或多个小写字母作为前缀,前缀之后是一个或多个首字母大写的单词组合,该单词指明变量的用途。
  • 驼峰命名法的原则:第一个单词以小写字母开始,之后每一个单词的首字母大写。例如:myFirstName、myLastName,这样的变量名看上去就像驼峰一样此起彼伏,因此得名。驼峰法的关键是:除第一个单词外,其他单词首字母大小,混合使用大小写字母来构成变量名和函数名,还可以使用下划线来形成逻辑断点,这样更能增强代码的可读性。

注释很重要

  • JS中单行注释用“ // 注释内容” 标识,多行注释使用“ / 注释内容 / “标识。注释的作用是提高代码的可读性,不仅自己以后用着方便,也有助于别人阅读和理解你所编写的JS代码,注释中的内容不会在网页中显示。为了方便阅读,注释一般放在需要解释的语句结尾处或者周围。在学习的过程中,我们更要养成书写注释的良好习惯,有利于我们对于代码的理解,或者标记出当时比较模糊的概念,回头再做深入的定向学习,更牢固的掌握该知识点。

JS语句和符号

  • JS 语句是发送给浏览器的命令。这些命令的作用是告诉浏览器要做的事情。JS 的执行规则是自上往下以行为单位的,一般情况下,每一行就是一个语句。比如:var a = 1+2; 这条语句先用 var 关键词,声明了变量 a,再将 1+2 的运算结果赋值给变量 a。这里需要注意 = 符号,在 JS 中并不是等号的意思,而是赋值。再比如:alert(‘hello’); 这是一条 JS 语句,一行的结束被认定为语句的结束,通常在结尾加上一个 ; 来表示语句的结束,如果有多行 JS 语句,每句结束都有 ;,则按顺序执行语句。注意:JS 中的代码和符号都必须在英文状态下输入,虽然 ; 也可以不写,但难免会遇到一些错误,浏览器会判定前一句和后一句是可以连在一起解释的,这样就导致了一些意想不到的错误。我们要养成良好的编程习惯,记得在必须加分号的地方一定不要忘记加上。

  • JS 对大小敏感,在编写JS代码时,需要留意是否关闭了大小写切换键.

JS判断语句和for循环

  • if 判断语句和 for 循环在 JS 中使用非常频繁。
  • 通常在写代码时,总是需要为不同的决定来执行不同的动作,在代码中就可以使用 if 条件语句来完成该任务。
  • 在 JS 中,可以使用以下条件语句:
  1. if 语句:只有当指定条件为 true 时,也就是条件成立时执行的代码。
  2. if… else 语句:当条件成立时执行 if 后代码,条件不成立(为 false )时执行 else 后的代码。
  3. if… else if…. else 语句:使用该语句根据判断条件来选择多个代码块之一来执行。
  4. 实例:根据不同的时间,提示不同的问候,当时间小于12点,问候早上好,当时间大于或等于12点小于18点,问候下午好,否则都问候晚上好。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    <script>
    var d = new Date();
    var time = d.getHours();
    if (time < 12){
    alert('早上好');
    }
    else if (time >= 12 && time < 18){
    alert('下午好');
    }
    else{
    alert('晚上好');
    }
    </script>
  • 如果希望一遍又一遍的运行相同的代码,并且每次的值都不同,那么使用循环是很方便的,当有一组元素的时候,就可以使用 for 循环为这一组元素添加事件。for循环的语法:

    1
    2
    3
    4
    5
    6
    for (语句 1; 语句 2; 语句 3){
    被执行的代码块
    }
    语句1用于初始化循环中所有的变量。通常为:var i=0;
    语句2用于设置初始变量的条件。通常为:i<object.length;
    语句3用于增加初始变量的值。通常为:i++ 也可以为:i--
  • 实例:循环遍历数组中的数据,依次输出:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    //在不使用循环时,我们可以这样输出数组中的值:
    var cars=["路虎","宝马","奔驰","奥迪","别克","大众"];
    document.write(cars[0] + "<br>");
    document.write(cars[1] + "<br>");
    document.write(cars[2] + "<br>");
    document.write(cars[3] + "<br>");
    document.write(cars[4] + "<br>");
    document.write(cars[5] + "<br>");
    //使用for循环可以很简洁的完成输出:
    for (var i=0, i<cars.length; i++){
    document.write(cars[i] + "<br>");
    }
  • document.write() 可用于直接向 HTML 输出流写内容,可以在平时做练习时用于向页面输出内容测试代码,这里需要注意 document.write() 一定要向文档输出写内容,如果文档已经加载完成后,再来执行该语句,则整个页面将会被覆盖。如果 document.write() 放在事件中,则会先清空页面上所有的内容,然后再写入内容。

JS一些基本概念

  1. 标识符:标识符是 JS 中定义的符号,可以由任意顺序的大小写字母、数字、下划线、和美元符号( $ )组成。标识符就是识别一个具体对象的名称,最常见的标识符就是变量名和函数名,JS对大小写敏感,所以 a 和 A 是两个不同的标识符。标识符不能以数字开头,也不能是JS中的保留关键字,具体可百度参考资料。另外还有三个虽然不是保留字,但是因为他们具有特别的含义,也不能用作标识符:Infinity、NaN、undefined。
  2. 代码块:代码块其实不难理解,先来解释以下 JS 代码,JS 代码就是 JS 语句的序列,浏览器依据编写 JS 语句的顺序依次逐行的执行每个语句,而代码块则是 JS 语句的组合,并且包含在花括号内,代码块的作用是告诉浏览器这些代码一起执行语句序列。JS 函数就是将语句组合在块中的典型例子。
  3. 变量:从字面上来理解,变量就是可以改变的量,但是从编程角度讲,变量是用于存储某种/某些数值信息的“容器”,简单说就是对“值”的引用,使用变量等同于引用一个值,每一个变量都有一个变量名。比如:var x = 1; 先声明一个变量 x,x 就是变量名,然后用 = 赋值,也就是将 1 赋值给 x,以后,在引用 x 的时候,就会得到值 1。在 JS 中创建一个变量通常被称为“声明”一个变量,var 就是用来声明变量的。变量在声明之后是空的,他的值为undefined(未定义),需要给他赋值后使用,= 就是建立这种引用关系。上面的代码可以看作为:var x;x=1;这样写是先声明一个变量,再给其赋值,上面的代码则在声明的同时就进行了赋值。在一条语句中,可以声明多个变量,并使用逗号隔开。注意:在给变量命名的时候不能使用 JS 关键词和 JS 保留词。
  4. 常量:有变量就会有常量,变量可以理解为变化的量,而常量就是不变的量。其实在 JS 中并没有常量这个概念,所谓的常量,只不过是提前赋值的变量而已。常量和变量都属于变量,只不过常量是赋过值后就不能再改变的变量,而普通的变量可以再次进行赋值操作。为了与变量有所区分,增强代码的可读性,所以在声明一个常量时,一般采用常量名全部大写,若有多个单词,可用下划线隔开。
  5. 字面量:所谓的字面量,其实是对象的表示形式,或者说是创建方式,他不是一种值,而是一种表示值的记法,简单说字面量就是如何表达一个对象的值,在给变量赋值时,赋值运算符后面的都可以认为是字面量。字面量也叫直接量,一个字面量,也可以被认为是一个常量,如 100。这里需要注意:变量是一个名称,而字面量是一个值。字面量可分为:数字字面量、字符串字面量和表达式字面量。数字字面量,可以是整数或者是小数,比如:var a=10; var b=3.14; 10 和 3.14 就是数字字面量。字符串字面量,使用引号包含起来的一系列字符,比如:var str=’小明’; ‘小明’就是字符串字面量。表达式字面量又可分为:数组字面量、对象字面量、函数字面量。数组字面量,每个值用逗号隔开,比如:var arr = [1,2,3,4,5,6]; [1,2,3,4,5,6] 就是数组字面量。对象字面量是一个键值对的组合,每个键值对之间用逗号分割,并包含在花括号内,比如:var obj = {a:12, b:5, c:’21’}, {a:12, b:5, c:’21’} 就是对象字面量。函数字面量,function myFunction(a, b) { return a b;} 函数字面量是用关键字 function 后加可选的函数名、用圆括号括起来的参数和用花括号括起来的执行语句构成。函数字面量是一个表达式,而不是语句。上面的例子可写为:var myFunction = function (a, b) { return a b;} ,这样就有便于理解了,也可以说函数的字面量就是一个匿名函数,他的指向是归谁使用。
  6. 变量的作用域:变量分为:全局变量和局部变量。全局变量简单说就是在函数外声明的变量,任何地方都可以使用,而局部变量就是在函数内部声明的变量,只能在声明他的函数内部使用。这就是变量的作用域,通俗理解就是他的作用范围。JS 变量的生命期从他们被声明的时候开始,全局变量会在页面被关闭之后删除,局部变量则在函数被运行以后删除。
  7. 表达式:表达式与数学中的定义相似,是指具有一定的值、用运算符把常量和变量连接起来的代数计算式,一个表达式可以包含常量或变量。比如:var a=a+1; a 是变量名称,a+1 就是表达式。在生活中”再见“表达方式有很多种,比如:英语(goodbey),网络语(886),肢体语言(摆摆手)等。JS 中的表达式无处不在,可以表达以下几种内容:字符串的连接,被称为串表达式,var str = “I” + “love” + “you”; 还有这种形式:var str = “hello”; var str1 = str + “World”; 串表达式值为字符串。数值表达式,var num = 10 + 2.5; 也有如下形式:var num = 10 + 2.5; var num1 = num + 10 * 2.5; 数值表达式值为数值。还是有一种是布尔表达式,var num = 2; alert(num == 2); 返回 ture,alert(num > 10); 返回 false。布尔表达式值为 true 或 false。
  8. 函数:一看到函数,很多人可能就头疼,但是编程中函数还是很好理解的,是由事件驱动的或者当它被调用时执行的可重复使用的代码块。简单说就是完成某个特定功能的一组语句,使用function关键字定义包裹在花括号中的代码块,便于反复调用。其基本形式为:function moveStart(){代码} 。声明一个函数只是在告诉浏览器这有一个函数,不会被实际执行,而在函数调用的时候,才真正执行函数内的代码。moveStart 就是函数名,遵循 JS 命名规范,在函数调用的时候使用:moveStart()。若将函数定义在变量后,变量则可作为函数使用。函数存储在变量中,不需要函数名,可以通过变量名调用。我们把没有名称的函数称为匿名函数。函数返回值,函数执行的结果就是函数返回值,return 可以将函数内的结果返回到函数外调用,在使用 return 语句时,函数会停止执行,并返回指定的值,再从调用的地方开始执行,函数调用会被返回值取代,同样一个函数应该只返回一种类型的值,在仅仅是希望退出函数时,也可以使用 return,返回值是可选的,比如下面的代码:如果 a 大于 b,则退出函数,并不会计算 a 和 b 的和。

    1
    2
    3
    4
    5
    6
    function myFunction(a, b){
    if (a > b){
    return;
    }
    x = a+b;
    }
  9. 函数传参:在调用函数时,可以向其传递值,这些值被称为参数,这些参数可以在函数中使用,可以传递任意多的参数,并由逗号分割,比如:function myFunction(x, y){return x * y;} ,在调用的时候传入值:myFunction(3 ,4),则返回 x乘y 的运算结果。简单理解,参数就是一个占位符,即先把位置占住,后面再用。传递的值必须与参数以一致的顺序出现,第一个值就是第一个被传递的参数给定的值,依次类推。函数很灵活,可以传递不同的值,来调用该函数。函数参数可分为:显式参数和隐藏参数( arguments )。函数的显式传参,也叫固定参,就是在函数被声明定义的时候列出的参数。隐藏参数也叫可变参,或者不定参,arguments 对象是 JS 内置的对象,对象包含了函数调用的参数数组,通过这一点可以很方便的找到最后一个参数的值,或者计算所有参数的和。当函数里有一部分定不下来的时候可以用函数传参,举一个简单的例子:点击按钮改变 DIV 的样式:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    <style>
    #div1{
    width:200px;
    height:200px;
    background:red;
    }
    </style>
    <body>
    <div id="div1"></div>
    <input type="button" value="变宽" onclick="setWid('width','400px')" />
    <input type="button" value="变高" onclick="setWid('height','400px')" />
    <input type="button" value="变绿" onclick="setWid('background','green')" />
    <script>
    function setWid(name, value){ //函数传参
    var x = document.getElementById('div1');
    x.style[name] = value;
    }
    </script>
    </body>
1
2
3
4
5
6
7
8
9
10
11
//参数求和:
<script>
function sumArr() {
var result = 0;
for(var i = 0; i < arguments.length; i++) {
result += arguments[i];
}
return result;
}
alert(sumArr(3,5,2,12,8,51,99)); //和为:180
</script>
  1. 对象:在现实生活中,一个人可以被视为一个对象,对象有他的属性,比如性别、身高、年龄,籍贯等,方法有:走、跑、跳等。所有的人都有这些属性,但是每个人的属性又不尽相同,所有的人都有这些方法,但是他们执行的时间都不尽相同。在 JS 中,对象就是拥有属性和方法的数据,JS 中的所有事物都是对象:字符串、日期、数组、数字等等。可以说在 JS 中一切皆对象,属性是与对象相关的值,方法是能够在对象上执行的动作。简单说对象只是带有属性和方法的特殊数据类型。在 JS 中对象是数据(变量),拥有属性和方法,当在声明一个变量时,var txt = “你好”; 实际上已经创建了一个字符串对象,该对象拥有 length 属性,字符串对象同时拥有很多个内置的方法,比如:charAt() 可获取某个字符,返回字符串的某一位的字符。可以说 JS 对象是变量的容器,但是,通常认为 JS对象是键值对的容器,键值对的写法为:name:value,键与值以冒号分隔,键值对又常被称为对象属性,所以 JS 对象就是属性变量的容器。JS支持自定义对象,可以通过 new 关键字创建。

JS数据类型

  • JS 数据类型可分为基本数据类型和复合数据类型两种,其中基本数据类型有五种:字符串(String)、数字(Number)、布尔(Boolean)、空(Null)、未定义(Undefined)。复合数据类型即 Object,Object 本质是一组无序的名值对组成的,严格来说,又被分为三类:对象(Object)、数组(Array)、函数(function)。
  1. 字符串:字符串是存储字符的变量。比如:var a=’小明’;,字符串可以是引号中的任意文本,可以使用单引号或者双引号。
  2. 数字:数字就是用来存储数字的变量。可以为整数也可以是小数。比如:var a1=314; var a2=3.14;。
  3. 布尔:布尔值是 “ture” 真和 “false” 假两个特定值,布尔常用在条件测试中。
  • 什么是真 ture:非零数字、非空字符串、非空对象
  • 什么是假 false:数字零、空字符串、空对象(null)、undefined
  1. Null:null 是一个只有一个值的特殊类型,表示一个空对象引用,可以用来清空变量。
  2. Undefined:表示为定义,有两种情况:1:真的没有定义。2、虽然定义了,但是没有赋值。
  3. Object:对象由大括号包含。在括号内部,对象的属性以名称和值对的形式{name : value}来定义。属性由逗号分隔,包括了除数字、字符串和布尔值以外的所有类型。比如:var person = {name:”小明”, sex:”男”, id:5566};,此例子中的对象(person)有三个属性:name, sex,id。
  4. Array:使用单独的变量名来存储一系列的值。创建一个数组的方法:var arr = new Array();,之后可以给数组添加值:arr[0] = 1; arr[1] = 2; arr[2] = 3;,数组的下标是基于零的,所以从 0 开始算起。在 JS 中,很多时候,要避免使用 new 关键字,所以将数组创建为:var arr = [1,2,3] 的形式。
  5. function:函数其实是处理数据的方法,JS 将函数视为一种数据类型,可以像其他数据类型一样,进行赋值和传递,这就为编程带来了很大的灵活性。
  • 变量的类型:变量本身是没有类型的,取决于他里边存储的什么数据类型,存的什么类型就是什么类型的变量。当声明新变量时,可以使用 new 来声明其类型,比如:var userName = new String; var x = new Number; var y = new Boolean; var cars = new Array; var person = new Object; 。JS 变量均为对象,当声明一个变量时,就创建了一个新的对象。
  • typeof运算符:typeof 操作符用来检测变量的数据类型,返回一个字符串。字符串、数字、布尔值分别返回 string、number、boolean。用 typeof 检测 null 返回 object,在 JS 中 null 表示什么都没有,但是他是一个对象。undefined 是没有赋值的变量,所以 typeof 一个没有值的变量会返回 undefined。typeof 一个对象则返回 object。JS 中数组是一种特殊类型的对象,所以也返回 object。函数则返回 function。
  • undefined 和 null 的区别:typeof undefined,返回 undefined。typeof null,返回 object。(null === undefined),返回 false,(null == undefined),返回true。

JS运算符

算数运算符:

  • 除了平时常见的加减乘数之外,JS 中还有一些其他的运算符:
  1. 取模运算符:%,取模通俗理解就是取余数,比如:5%2,值为1,5除2,商2余1。
  2. 自增运算符:++,自增运算分为两种情况,一种是先赋值再运算,一种是先运算再赋值。实例:假设 a = 2
  3. 先赋值再运算:var b = a++; 运算结果为:b=2,a=3 解析:b = a,a = a+1。
  4. 先运算再赋值:var b = ++a;运算结果为:b=3,a=3 解析:a = a+1,b = a。
  • 通过上面的例子,可以看到,先赋值再运算,实质是先把 a 赋值给 b,然后自己再加 1。先运算再赋值,实质是先自己加 1,再把值赋给 b。
  • 他们的相同点都是自增1,a = a+1,都被作为一个整体表达式运算,即 (a++)(++a),虽然他们的值都自增 1,但是 (a++) 取 a 自增前的值,而 (++a) 取 a 自增后的值。
  1. 自减运算符:–,自减运算符和自增运算符一样,即每次自减1。也分为两种情况:实例:假设a=2
  2. 先赋值再运算:var b=a–; 运算结果为:b=2,a=1 解析:b=a,a=a-1。
  3. 先运算再赋值:var b=–a;运算结果为:a=1,b=1 解析:a=a-1,b=a。
  • 运算符可用于字符串变量的连接,若需要把多个字符串连接起来,就可以使用 + 运算符。
  • 如果把字符串和数字相加,则得到一个字符串。比如:var str=’hello’+2; 返回:hello2

赋值运算符:

  • 赋值运算符用于给变量赋值。有以下几种:= += -= *= /= %=
    1
    2
    3
    4
    5
    6
    7
    实例:假设 a=10 b=5
    =:a = b 结果:5
    +=:a += b,相当于:a = a+b 结果:15
    -=:a -= b,相当于:a = a-b 结果:5
    *=:a *= b,相当于:a = a*b 结果:50
    /=:a /= b,相当于:a = a/b 结果:2
    %=:a % b,相当于:a = a/b 结果:0 (取模运算是取余数)

比较运算符:

  • 比较运算符在条件语句中使用,用于判断变量或值的关系,返回 ture 或 false。
  • 比较运算符有以下几种:== === != !== > < >= <=
    实例:假设 a=2
  1. ==:等于。注意双等号在JS中才表示等于,一个等号为赋值。比较:a == 2,返回 ture。a == 1,返回false。
  2. ===:绝对等于,值和类型均相等。比较:a === ‘2’,返回 false。a === 2,返回 true。
  3. !=:不等于。和等于相反。比较:a != 2,返回 false,a != 1,返回 ture。
  4. !==:绝对不等于,和绝对等于相反,值和类型均不相等。比较:a !== ‘2’,返回 ture,a !== 2,返回 false。
  5. :大于。比较:a>5,返回false。

  6. <:小于。比较:a<5,返回ture。
  7. =:大于等于。比较:a>=5,返回false。

  8. <=:小于等于。比较:a<=5,返回ture。

###逻辑运算符:

  • 逻辑运算符用于描述变量或值之间的逻辑关系。
  • 逻辑运算符有以下几种:&& || !
  1. &&:并且。在数学中我们将 b 大于 a、b 又小于 c 表示为:a<b<c,但是在 JS 中要用 && 表示:b>a && b<c。两个条件必须同时满足,则返回 ture,有一个条件不满足,则返回 false。实例:判断一个数字是否为两位数:a>9 && a<100,假设 a=50,则返回:ture。
  2. ||:或。当两个条件中,有任一个条件满足,逻辑或的运算结果就为真。实例:a=5,b=10,判断c=a<b || a == b ,c的值为:ture。
  3. !:否。也叫逻辑非操作符,是非颠倒,好比小明买了一本 JS 书籍,小白说:是乌龟书;小红说:是犀牛书。小明说:小白说的不是真话,小红说的不是假话。那么是小红说对了,小明买的书是犀牛书。实例:a=10 b=5,判断c =! (a>b),c 的值为:false。

三元运算符:

  • 三元运算符也叫条件运算符,其基本形式可用 if 判断语句表示,用三元运算符表示为: ? :。
  • 所谓三元运算符,顾名思义就是需要进行三次操作,语法为:条件?结果1:结果2 。条件写在问号之前,后面跟着用冒号分隔的结果1和结果2,当满足条件时为结果1,否则就是结果2。好比你去看演唱会,条件就是需要入场券,若你带了就可以直接进去,如果没带那就请回吧,用三元运算符可表示为:带没带入场券 ? 带了直接进去 : 没带那就请回吧。
  • 所有使用 if 判断语句的地方,都可以使用三元运算符,使用 if 判断语句代码比较繁琐,使用三元运算符,代码则十分简洁,但是对于初学者来说,三元运算符不是那么直观,使用 if 判断语句更容易理解,随着学习的不断深入,以及理解的加深,就可以使用三元运算符代替 if 了。
  • 实例:判断一个数为偶数还是奇数。假设:a=12
  • 先用 if 判断语句表示:

    1
    2
    3
    4
    5
    6
    7
    var a = 12;
    if(a%2 == 0){
    alert('a为偶数');
    }
    else{
    alert('a为奇数');
    }
  • 用三元运算符可表示为:

    1
    2
    var a = 12;
    a%2===0 ? alert('偶数') : alert('奇数');

运算符之间的优先级:

  • 从高到低依次为:算术操作符 → 比较操作符 → 逻辑操作符 → “=”赋值符号
  • 同级的运算是按从左到右依次进行运算,若有括号,从多层括号由里向外进行运算。
  • 实例:
    1
    2
    3
    4
    5
    6
    var numA = 2;
    var numB = 5;
    var numC = numA + 40 > 10 $$ numB * 2 < 20;
    var numD =( ( numA + 40 ) / ( 12 - numB ) ) * 10;
    alert(numC); //返回:ture
    alert(numD); //返回:60

JS事件

  • HTML 事件是发生在 HTML 元素上的事情。当在 HTML 页面中使用 JS 时,JS 可以触发这些事件。事件可以是浏览器行为,也可以是用户操作行为,用户操作行为可分为鼠标操作和键盘操作。比如:在页面加载完成时触发事件,这属于浏览器行为,用户的操作行为如点击按钮触发事件,鼠标的移入移出,按键提交信息等。
  • 下面是一些常用的事件列表:
事件 描述
onload 页面已完成加载时触发事件
onresize 调整浏览器大小时触发事件
onchange 当元素改变时触发事件
onfocus 当元素获得焦点时触发事件
onselect 当选取元素时触发事件
onsubmit 用户提交表单时触发事件
onclick 点击鼠标时触发事件
onmouseover 鼠标移入时触发事件
onmouseout 鼠标移出时触发事件
onmousedown 按下鼠标时触发事件
onmouseup 松开鼠标时触发事件
onmousemove 移动鼠标时触发事件
onmousewheel 用户滚动鼠标滚轮时触发事件
onscroll 当滑动滚动条时触发事件
onkeydown 用户按下键盘按键时触发事件
onkeyup 用户松开按键时触发事件

JS常用的互动方法

  • 在 JS 中可以创建三种类型的消息框:警告框、确认框、提示框。
  1. 警告框
  • 警告框常用于确保用户可以得到某些信息,平时我们在访问网页的时候,有时突然弹出一个小窗口,上面写这一些提示文字,这就是警告框,在警告框出现之后,用户必须点击确定按钮后才能继续操作,否则就不能对网页做出任何操作。这样的弹出窗口是用”alert“实现的。
  • 语法:alert(str或var);
  1. 确认框
  • 确认框常用于验证用户是否接受操作,允许用户做出选择,当确认框弹出时,用户可以点击”确定“或者”取消“来确定用户操作,当用户点击确定时,返回值为 ture,如果点击取消,则返回值为 false。用户在点击对话框之前不能进行任何操作。这样的弹出窗口是用”confirm“实现的。
  • 语法:confirm(str);
  1. 提示框
  • 提示框也叫提问框,用于提示用户在进入页面前输入某个值,主要是询问一些需要与用户交互的信息,提示框包含一个确定、取消按钮,和一个文本框,当提示框弹出后,用户需要输入某个值,然后点击确定或者取消才能继续操作,当用户点击确认时,返回值为文本框输入的值,如果用户点击取消,则返回值为null。提示框可以和确认框相互配合使用。这样的弹出窗口是用”prompt“实现的。
  • 语法:prompt(str1, str2);
  • str1 为要显示在对话框的值,也就是与用户交互的内容描述,不可修改。str2 为文本框中提示用户输入的默认内容,可以修改。
  • 一般情况下,在实际的网站中,这些对话框都很少或者说几乎不使用,尤其是警告框,因为用户会反感这种突然弹出来的东西,在弹出对话框后用户不点击按钮之前,浏览器就跟死了一样,不能做任何操作,确认框和提示框相对来说还有一些使用,也是比较有意义的,比如页面中一个跳转按钮,如果不使用确认对话框,则直接跳转到新页面,使用确认对话框之后,用户可以点击确认或者取消来执行对应操作,确认则跳转新页面,取消则继续浏览,有时候这个跳转按钮或者链接是用户不小心点到的,并不希望跳转。大部分网站中,都使用的是一套自定义的对话框,更友好的显示。

JS转义字符

  • 在 JS 中字符串通常用单引号或双引号包含起来,比如:var txt = “谁看到”小明”今天来上课了吗?”; 所以这个例子会解析错误,从 “谁看到” 被截断,浏览器报错提示:语法错误,而且这是很严重的错误,错误到代码将被终止,后面的代码无法执行。其实这个例子还是很好解决的,我们可以将其用单引号括起来,再给小明加上双引号,OK,跟原来要表达的一样,但是如果我们需要换行呢?这时候就需要用到转义字符,转义字符在 JS 中应用十分广泛,尤其是在正则表达式 (RegExp) 中,因此上面的代码应该写为: var txt = “谁看到 \”小明 \”今天来上课了吗?”; 需要换行则写为:var txt = “谁看到 \”小明 \” \n 今天来上课了吗?”; 。
  • **反斜杠()是一个转义字符,转义字符可用于将特殊字符转换为字符串字符,可以用于转义撇号、引号、换行等其他特殊字符,在编写代码时需要注意特殊字符问题,很多运行时出现的问题都是因为特殊字符而引起的,由于反斜杠本身被用作转义符,因此不能在代码中只键入一个 \ ,如果需要显示一个反斜杠,必须一次键入两个 \

👏👏👏小编有话讲:
以上小编的总结如有异议,欢迎指导!!!😃💖

Cmd-Markdown

欢迎使用 Cmd Markdown 编辑阅读器


我们理解您需要更便捷更高效的工具记录思想,整理笔记、知识,并将其中承载的价值传播给他人,Cmd Markdown 是我们给出的答案 —— 我们为记录思想和分享知识提供更专业的工具。 您可以使用 Cmd Markdown:

  • 整理知识,学习笔记
  • 发布日记,杂文,所见所想
  • 撰写发布技术文稿(代码支持)
  • 撰写发布学术论文(LaTeX 公式支持)

cmd-markdown-logo

除了您现在看到的这个 Cmd Markdown 在线版本,您还可以前往以下网址下载:

Windows/Mac/Linux 全平台客户端

请保留此份 Cmd Markdown 的欢迎稿兼使用说明,如需撰写新稿件,点击顶部工具栏右侧的 新文稿 或者使用快捷键 Ctrl+Alt+N


什么是 Markdown

Markdown 是一种方便记忆、书写的纯文本标记语言,用户可以使用这些标记符号以最小的输入代价生成极富表现力的文档:譬如您正在阅读的这份文档。它使用简单的符号标记不同的标题,分割不同的段落,粗体 或者 斜体 某些文字,更棒的是,它还可以

1. 制作一份待办事宜 Todo 列表

  • 支持以 PDF 格式导出文稿
  • 改进 Cmd 渲染算法,使用局部渲染技术提高渲染效率
  • 新增 Todo 列表功能
  • 修复 LaTex 公式渲染问题
  • 新增 LaTex 公式编号功能

2. 书写一个质能守恒公式[^LaTeX]

$$E=mc^2$$

3. 高亮一段代码[^code]

1
2
3
4
5
6
7
@requires_authorization
class SomeClass:
pass

if __name__ == '__main__':
# A comment
print 'hello world'

4. 高效绘制 流程图

1
2
3
4
5
6
7
8
st=>start: Start
op=>operation: Your Operation
cond=>condition: Yes or No?
e=>end

st->op->cond
cond(yes)->e
cond(no)->op

5. 高效绘制 序列图

1
2
3
Alice->Bob: Hello Bob, how are you?
Note right of Bob: Bob thinks
Bob-->Alice: I am good thanks!

6. 高效绘制 甘特图

1
2
3
4
5
6
7
8
9
10
11
12
13
title 项目开发流程
section 项目确定
需求分析 :a1, 2016-06-22, 3d
可行性报告 :after a1, 5d
概念验证 : 5d
section 项目实施
概要设计 :2016-07-05 , 5d
详细设计 :2016-07-08, 10d
编码 :2016-07-15, 10d
测试 :2016-07-22, 5d
section 发布验收
发布: 2d
验收: 3d

7. 绘制表格

项目 价格 数量
计算机 \$1600 5
手机 \$12 12
管线 \$1 234

8. 更详细语法说明

想要查看更详细的语法说明,可以参考我们准备的 Cmd Markdown 简明语法手册,进阶用户可以参考 Cmd Markdown 高阶语法手册 了解更多高级功能。

总而言之,不同于其它 所见即所得 的编辑器:你只需使用键盘专注于书写文本内容,就可以生成印刷级的排版格式,省却在键盘和工具栏之间来回切换,调整内容和格式的麻烦。Markdown 在流畅的书写和印刷级的阅读体验之间找到了平衡。 目前它已经成为世界上最大的技术分享网站 GitHub 和 技术问答网站 StackOverFlow 的御用书写格式。


什么是 Cmd Markdown

您可以使用很多工具书写 Markdown,但是 Cmd Markdown 是这个星球上我们已知的、最好的 Markdown 工具——没有之一 :)因为深信文字的力量,所以我们和你一样,对流畅书写,分享思想和知识,以及阅读体验有极致的追求,我们把对于这些诉求的回应整合在 Cmd Markdown,并且一次,两次,三次,乃至无数次地提升这个工具的体验,最终将它演化成一个 编辑/发布/阅读 Markdown 的在线平台——您可以在任何地方,任何系统/设备上管理这里的文字。

1. 实时同步预览

我们将 Cmd Markdown 的主界面一分为二,左边为编辑区,右边为预览区,在编辑区的操作会实时地渲染到预览区方便查看最终的版面效果,并且如果你在其中一个区拖动滚动条,我们有一个巧妙的算法把另一个区的滚动条同步到等价的位置,超酷!

2. 编辑工具栏

也许您还是一个 Markdown 语法的新手,在您完全熟悉它之前,我们在 编辑区 的顶部放置了一个如下图所示的工具栏,您可以使用鼠标在工具栏上调整格式,不过我们仍旧鼓励你使用键盘标记格式,提高书写的流畅度。

tool-editor

3. 编辑模式

完全心无旁骛的方式编辑文字:点击 编辑工具栏 最右侧的拉伸按钮或者按下 Ctrl + M,将 Cmd Markdown 切换到独立的编辑模式,这是一个极度简洁的写作环境,所有可能会引起分心的元素都已经被挪除,超清爽!

4. 实时的云端文稿

为了保障数据安全,Cmd Markdown 会将您每一次击键的内容保存至云端,同时在 编辑工具栏 的最右侧提示 已保存 的字样。无需担心浏览器崩溃,机器掉电或者地震,海啸——在编辑的过程中随时关闭浏览器或者机器,下一次回到 Cmd Markdown 的时候继续写作。

5. 离线模式

在网络环境不稳定的情况下记录文字一样很安全!在您写作的时候,如果电脑突然失去网络连接,Cmd Markdown 会智能切换至离线模式,将您后续键入的文字保存在本地,直到网络恢复再将他们传送至云端,即使在网络恢复前关闭浏览器或者电脑,一样没有问题,等到下次开启 Cmd Markdown 的时候,她会提醒您将离线保存的文字传送至云端。简而言之,我们尽最大的努力保障您文字的安全。

6. 管理工具栏

为了便于管理您的文稿,在 预览区 的顶部放置了如下所示的 管理工具栏

tool-manager

通过管理工具栏可以:

发布:将当前的文稿生成固定链接,在网络上发布,分享
新建:开始撰写一篇新的文稿
删除:删除当前的文稿
导出:将当前的文稿转化为 Markdown 文本或者 Html 格式,并导出到本地
列表:所有新增和过往的文稿都可以在这里查看、操作
模式:切换 普通/Vim/Emacs 编辑模式

7. 阅读工具栏

tool-manager

通过 预览区 右上角的 阅读工具栏,可以查看当前文稿的目录并增强阅读体验。

工具栏上的五个图标依次为:

目录:快速导航当前文稿的目录结构以跳转到感兴趣的段落
视图:互换左边编辑区和右边预览区的位置
主题:内置了黑白两种模式的主题,试试 黑色主题,超炫!
阅读:心无旁骛的阅读模式提供超一流的阅读体验
全屏:简洁,简洁,再简洁,一个完全沉浸式的写作和阅读环境

8. 阅读模式

阅读工具栏 点击 或者按下 Ctrl+Alt+M 随即进入独立的阅读模式界面,我们在版面渲染上的每一个细节:字体,字号,行间距,前背景色都倾注了大量的时间,努力提升阅读的体验和品质。

9. 标签、分类和搜索

在编辑区任意行首位置输入以下格式的文字可以标签当前文档:

标签: 未分类

标签以后的文稿在【文件列表】(Ctrl+Alt+F)里会按照标签分类,用户可以同时使用键盘或者鼠标浏览查看,或者在【文件列表】的搜索文本框内搜索标题关键字过滤文稿,如下图所示:

file-list

10. 文稿发布和分享

在您使用 Cmd Markdown 记录,创作,整理,阅读文稿的同时,我们不仅希望它是一个有力的工具,更希望您的思想和知识通过这个平台,连同优质的阅读体验,将他们分享给有相同志趣的人,进而鼓励更多的人来到这里记录分享他们的思想和知识,尝试点击 (Ctrl+Alt+P) 发布这份文档给好友吧!


再一次感谢您花费时间阅读这份欢迎稿,点击 (Ctrl+Alt+N) 开始撰写新的文稿吧!祝您在这里记录、阅读、分享愉快!

作者 @ghosert
2016 年 07月 07日

[^LaTeX]: 支持 LaTeX 编辑显示支持,例如:$\sum_{i=1}^n a_i=0$, 访问 MathJax 参考更多使用方法。

[^code]: 代码高亮功能支持包括 Java, Python, JavaScript 在内的,四十一种主流编程语言。