前端开发基础知识汇总

一.HTML

1.前言与常用标签

浏览器 内核 备注
IE Trident IE、猎豹安全、360极速浏览器、百度浏览器
firefox Gecko 可惜这几年已经没落了,打开速度慢、升级频繁、猪一样的队友flash、神一样的对手chrome。
Safari webkit 现在很多人错误地把 webkit 叫做 chrome内核(即使 chrome内核已经是 blink 了)。苹果感觉像被别人抢了媳妇,都哭晕再厕所里面了。
chrome Chromium/Blink 在 Chromium 项目中研发 Blink 渲染引擎(即浏览器核心),内置于 Chrome 浏览器之中。Blink 其实是 WebKit 的分支。大部分国产浏览器最新版都采用Blink内核。二次开发
Opera blink 现在跟随chrome用blink内核。

Web标准构成:主要包括结构(Structure)、表现(Presentation)和行为(Behavior)三个方面。

web标准小结

  • web标准有三层结构,分别是结构(html)、表现(css)和行为(javascript)
  • 结构类似人的身体, 表现类似人的着装, 行为类似人的行为动作
  • 理想状态下,他们三层都是独立的, 放到不同的文件里面
声明位于文档中的最前面的位置,处于 标签之前。此标签可告知浏览器文档使用哪种 HTML 或 XHTML 规范。 指定html 语言种类

head 头部. 标题 title 文档标题

标签名 定义 说明
标题标签 作为标题使用,并且依据重要性递减

段落标签 可以把 HTML 文档分割为若干段落

水平线标签 没啥可说的,就是一条线

换行标签
div标签 用来布局的,但是现在一行只能放一个div
span标签 用来布局的,一行上可以放好多个span
标签 显示效果
b或strong 粗体
i或em 斜体
s或del 加删除线
u或ins 加下划线

b 只是加粗 strong 除了可以加粗还有 强调的意思, 语义更强烈。

属性 属性值 描述
src URL 图像的路径
alt 文本 图像不能显示时的替换文本
title 文本 鼠标悬停时显示的内容
width 像素 设置图像的宽度
height 像素 设置图像的宽度
border 数字 设置图像边框的宽度

**注意: **

  1. 标签可以拥有多个属性,必须写在开始标签中,位于标签名后面。

  2. 属性之间不分先后顺序,标签名与属性、属性与属性之间均以空格分开。

  3. 采取 键值对 的格式 key=“value” 的格式

链接标签

文字或图片
属性 作用
href 用于指定链接目标的url地址,(必须属性)当为标签应用href属性时,它就具有了超链接的功能
target 用于指定链接页面的打开方式,其取值有_self和_blank两种,其中_self为默认值,__blank为在新窗口中打开方式。
快捷键是: ctrl + / 或者 ctrl +shift + /

相对路径

路径分类 符号
同一级路径
下一级路径 “/”
上一级路径 “…/”

锚点定位

  1. 使用相应的id名标注跳转目标的位置。 (找目标)

第2集

2. 使用 链接文本创建链接文本(被点击的) (拉关系) 我也有一个姓毕的姥爷..

base标签

  1. base 可以设置整体链接的打开状态
  2. base 写到 之间
  3. 把所有的连接 都默认添加 target="_blank" 在新窗口中打开链接

预格式化文本pre

 标签可定义预格式化的文本。被包围在 
 标签 元素中的文本通常会保留空格和换行符。而文本也会呈现为等宽字体。

特殊字符

大于号 >

小于号 <

空格  

2.表格table

表格作用:

存在即是合理的。 表格的现在还是较为常用的一种标签,但不是用来布局,常见显示、展示表

格式数据

  1. table用于定义一个表格标签。
  2. tr标签 用于定义表格中的行,必须嵌套在 table标签中。
  3. td 用于定义表格中的单元格,必须嵌套在标签中。

**总结: **

  • 表格的主要目的是用来显示特殊数据的

  • 一个完整的表格有表格标签(table),行标签(tr),单元格标签(td)组成,没有列的标签

  • 中只能嵌套 类的单元格
  • 标签,他就像一个容器,可以容纳所有的元素

表格属性 重点记住 cellspacing 、 cellpadding

属性名 含义 常用属性值
border 设置表格的边框(border="0"为无边框) 像素值
cellspacing 设置单元格与单元格边框之间的空白间距 像素值(默认为2像素)
cellpadding 设置单元格内容与单元格边框之间的空白间距 像素值(默认为1像素)
width 设置表格宽度 像素值
height 设置表格高度 像素值
align 这是表格在网页中的水平对齐方式 left、center、right

表头单元格标签th

  • 作用:
    • 一般表头单元格位于表格的第一行或第一列,并且文本加粗居中
  • 语法:
    • 只需用表头标签替代相应的单元格标签即可

表格标题caption

  1. caption 元素定义表格标题,通常这个标题会被居中且显示于表格之上。
  2. caption 标签必须紧随 table 标签之后。
  3. 这个标签只存在 表格里面才有意义。

合并单元格

  • 跨行合并:rowspan=“合并单元格的个数”
  • 跨列合并:colspan=“合并单元格的个数”

合并的顺序我们按照 先上 后下 先左 后右 的顺序

  1. 先确定是跨行还是跨列合并
  2. 根据 先上 后下 先左 后右的原则找到目标单元格 然后写上 合并方式 还有 要合并的单元格数量 比如 :
  3. 删除多余的单元格 单元格

3.列表和表单

列表

无序列表ul

1. 
    中只能嵌套
  • ,直接在
      标签中输入其他标签或者文字的做法是不被允许的。 2.
    • 之间相当于一个容器,可以容纳所有元素。

      有序列表ol

      1. 列表项1
      2. 列表项2
      3. 列表项3
      4. ......

      自定义列表

      名词1
      名词1解释1
      名词1解释2
      ...
      名词2
      名词2解释1
      名词2解释2
      ...
      标签名 定义 说明
        无序标签 里面只能包含li 没有顺序,我们以后布局中最常用的列表
          有序标签 里面只能包含li 有顺序, 使用情况较少
          自定义列表 里面有2个兄弟, dt 和 dd

          表单

          input控件

          • input 输入的意思
          • 标签为单标签
          • type属性设置不同的属性值用来指定不同的控件类型
          • 除了type属性还有别的属性
          type的属性 描述
          text 文本框
          password 密码框
          radio 单选按钮
          checkbox 复选框
          button 普通按钮
          submit 提交按钮
          reset 重置按钮
          image 图像形式提交按钮
          file 文件域
          属性 属性值 描述
          name 由用户自定义 控件的名称
          value 由用户自定义 input控件中的默认文本值
          size 正整数 input控件在页面中的显示宽度
          checked checked 定义选择控件默认被选中的项
          maxlength 正整数 控件允许输入的最多字符数

          checked="checked"表示就默认选中了

          label标签

          作用: 用于绑定一个表单元素, 当点击label标签的时候, 被绑定的表单元素就会获得输入焦点。

          1.第一种用法就是用label直接包括input表单。

          用户名:

          2.第二种用法 for 属性规定 label 与哪个表单元素绑定


          textarea文本域

          • 语法:
          <textarea >
            文本内容
          textarea>
          
          • 作用:

            通过textarea控件可以轻松地创建多行文本输入框.

            cols=“每行中的字符数” rows=“显示的行数” 我们实际开发不用

          select下拉列表

          选项1 选项2 选项3 ...
          1. 一起使用
          2. form属性,可以将输入标签放在表单的外面,还受到表单的管理

          3. required:必填验证

          4. novalidate:关闭验证

            • 在表单上添加该属性,那么在提交的时候就不会再执行 required验证
          5. pattern:自定义验证-通过编写正则表达式自定义验证规则 一般和required同时使用

            • 表单事件
          6. audio 音频标签

            语法:

            <audio src="小猪佩奇.mp3" autoplay> audio>
            

            支持的格式

            格式 MIME-type
            MP3 audio/mpeg
            Ogg audio/ogg
            Wav audio/wav

            video 视频标签

            语法:

              <video src="小猪佩奇.mp4" autoplay controls >video>
            

            支持的格式

            格式 MIME-type
            MP4 video/mp4
            WebM video/webm
            Ogg video/ogg

            video常用属性、方法、事件

            属性 方法 事件
            duration 视频播放时长 play 播放 canplay 视频加载完毕 准备播放
            currentTime 当前播放进度 pause 暂停 timeupdate 播放时-持续触发
            volume 音量大小

            source标签

            可以通过在多媒体标签内加入source标签,用来指定多个播放路径,当第一个source标签的路径出错时,自动会切换到第二个source标签

                
                <video >
                  <source src="1.mp4">
                  <source src="2.mp4">
                  <source src="3.mp4">
                video>
            

            object-fit属性

            video标签视频内容宽度没有铺满video标签时,可以在css写上 该属性即可

                video {
                  /* 让视频内容铺满整个video标签 */
                  object-fit: fill;
                }
            

            公共属性

            以下属性 是要直接写在标签上的 如 autoplay controls

            <video src="小猪佩奇.mp4" autoplay controls >video>
            
            属性 描述
            autoplay autoplay 如果出现该属性,则音频在就绪后马上播放。
            controls controls 如果出现该属性,则向用户显示控件,比如播放按钮。
            loop loop 如果出现该属性,则每当音频结束时重新开始播放。
            muted muted 规定视频输出应该被静音。
            preload preload 如果出现该属性,则音频在页面加载时进行加载,并预备播放。如果使用 “autoplay”,则忽略该属性。
            src url 要播放的音频的 URL。

            伪类选择符

            结构伪类选择器

            E:first-child —— 匹配父元素的第一个子元素

            E:nth-child(n) E:nth-last-child(n)

            匹配到父元素的第n个元素 或者 是倒数第n个元素(n也可以为公式、数字、关键字)

            常见的关键词有even偶数、odd奇数

            E:nth-of-type(n)

            • E:nth-child(n) 匹配父元素的第n个子元素E。
            • E:nth-of-type(n) 匹配同类型中的第n个同级兄弟元素E。

            属性选择器

            1. E[att] 选择具有att属性的E元素。
            2. E[att=“val”] 选择具有att属性且属性值等于val的E元素。
            3. E[att^=“val”] 选择具有att属性且属性值为以val开头的字符串的E元素。
            4. E[att$=“val”] 选择具有att属性且属性值为包含val的字符串的E元素
            5. E[att*=“val”] 选择具有att属性且属性值为包含val的字符串的E元素。

            伪元素选择器

            1. E::before 在E元素前插入一个元素
            2. E::after 在E元素后插入一个元素
            3. E::first-letter 选择到了E容器内的第一个字母
            4. E::first-line 选择到了E容器内的第一行文本

            想要让伪元素有效,必须遵循以下注意事项

            1. 伪元素只能给双标签加 不能给单标签加
            2. 伪元素的冒号前不能有空格 如 E ::before 这个写法是错误的
            3. 伪元素里面必须写上属性 content:"";

            2.2D、3D转换、动画animation

            2d移动 translate

            语法:div{

            transform: translate(50px,50px);
            

            }

            1. translate中的百分比单位是相对于自身元素的 translate:(50%,50%);
            2. translate类似定位,不会影响到其他元素的位置
            3. 对行内标签没有效果

            2d旋转 rotate

            使用步骤:

            1. 给元素添加转换属性 transform
            2. 属性值为 rotate(角度)transform:rotate(30deg) 顺时针方向旋转30度
            div{
                  transform: rotate(0deg);
            }
            

            特点

            1. 角度为正时 顺时针 负时 为逆时针
            2. 默认旋转的中心点是元素的中心点

            转换中心 transform-origin

            该属性可以修改元素旋转的时候的中心点

            1. transform-origin:50% 50%; 默认值 元素的中心位置 百分比是相对于自身的宽度和高度
            2. transform-origin:top left; 左上角 和 transform-origin:0 0;相同
            3. transform-origin:50px 50px; 距离左上角 50px 50px 的位置
            4. transform-origin:0; 只写一个值的时候 第二个值默认为 50%;

            2d缩放 scale

            1. 给元素添加转换属性 transform
            2. 转换的属性值为 scale(宽的倍数,高的倍数) 如 宽变为两倍,高变为3倍 transform:scale(2,3)
            div{
                transform:scale(2,3);
            }
            

            小结

            1. transform:scale(1,1) 放大一倍 相对于没有放大
            2. transform:scale(2,2) 宽和高都放大了2倍
            3. transform:scale(2) 只写一个参数 第二个参数则和第一个参数一样 相当于 scale(2,2)
            4. transform:scale(0.5,0.5) 缩小
            5. transform:scale(-2,-2) 反向放大2倍 很少用负数 容易让人产生误解

            动画 animation

            用@keyframes定义动画,类似定义类选择器

               /* 1 声明动画函数 */
            
                @keyframes ani_div {
             0%{
                width: 100px;
                background-color: red;
              }
              50%{
                width: 150px;
                background-color: green;
              }
              100%{
                width: 300px;
                height: 300px;
                background-color: yellow;
              }
            }
             div {
                  width: 200px;
                  height: 200px;
                  background-color: aqua;
                  margin: 100px auto;
                  /* 2 调用动画 */
                  animation-name: ani_div;
                  /* 持续时间 */
                  animation-duration: 2s;
                }
            

            语法:

            1. 动画名

              设置要使用的动画名 animation-name:xxx;

            2. 持续时间

              设置动画播放的持续时间 animation-duration:3s

            3. 速度曲线

              和设置过渡的速度曲线一样 animation-timing-function:linear;

              • linear: 匀速
              • ease: 慢-快-慢 默认值
              • ease-in: 慢-快。
              • ease-out: 快-慢。
              • ease-in-out: 慢-快-慢。
            4. 延迟时间

              animation-delay: 0s;

            5. 循环次数

              设置动画播放的循环次数 animation-iteration-count: 2; infinite 为无限循环

            6. 循环方向

              animation-direction

              如在动画中定义了 0%:红色 100%:黑色 那么 当属性值为

              1. normal 默认值 红 -> 黑
              2. reverse 反向运行 黑 -> 红
              3. alternate 正-反-正… 红 -> 黑 -> 红…
              4. alternate-reverse 反-正-反… 黑 -> 红 -> 黑 …
              5. 以上与循环次数有关
            7. 动画等待或者结束的状态

              animation-fill-mode 设置动画在等待或者结束的时候的状态

              • forwards:动画结束后,元素样式停留在 100% 的样式
              • backwards: 在延迟等待的时间内,元素样式停留在 0% 的样式
              • both: 同时设置了 forwards和backwards两个属性值
            8. 暂停和播放

              animation-play-state 控制 播放 还是 暂停

              running 播放 paused 暂停

              复合写法

              animation: name duration timing-function delay iteration-count direction fill-mode;
              
              animation:动画名称 持续性时间 运动曲线 合适开始 播放次数 是否反方向 起始或结束的标志
              

              动画结束事件animationend

              元素在动画结束之后,会自动触发的事件 animationend

                  var div = document.querySelector("div");
                  div.addEventListener("animationend", function () {
                    console.log("div的动画结束之后,触发");
                  })
              

              css3兼容处理

              css3涉及到较多的新属性,某些低版本(如ie8以及以下)的浏览器对css3的支持程度不够,因此需要做以下处理

              添加对应的浏览器的前缀 常见前缀如下

              • 谷歌 -webkit
              • 火狐 -moz
              • IE -ms

              如对 border-radius 进行兼容性处理

                    -webkit-border-radius: 30px 10px;
                    -moz-border-radius: 30px 10px;
                    -ms-border-radius: 30px 10px;
              	  // border-radius 一定要放在最后
                    border-radius: 30px 10px;
              

              如果发现添加前缀也解决不了兼容性问题,那么就不要使用该css3属性

              3D转换

              3d移动 translate3d

              1. transform:translate3d(x,y,z) 其中 x y z 分别指要移动的轴的方向的距离
              2. translform:translateX(100px) 仅仅是移动在x轴上移动
              3. translform:translateY(100px) 仅仅是移动在Y轴上移动
              4. translform:translateZ(100px) 仅仅是移动在Z轴上移动

            视距 perspertive

            perspertive 就是用来设置 物体 的距离

            写在被观察元素的父盒子里

            左手准则

            要判断某元素沿着x轴是怎么旋转的

            1. 左手的手拇指指向 x轴的正方向
            2. 其余手指的弯曲方向就是该元素沿着x轴旋转的方向了

            3d旋转 rotate3d

            语法:

            1. transform:rotateX(45deg); 沿着x轴正方向旋转 45度
            2. transform:rotateY(45deg) 沿着y轴正方向旋转 45deg
            3. transform:rotateZ(45deg) 沿着Z轴正方向旋转 45deg
            4. transform:rotate3d(x,y,z,deg) 沿着自定义轴旋转 deg为角度 了解即可

            3D缩放 scale3d

            语法:

            1. transform: scale3d(1 ,1,2); 宽,高 缩放一倍,厚度放大两倍
            2. transform: scaleX(1) 只缩放宽
            3. transform: scaleY(1) 只缩放高
            4. transform: scaleZ(1) 只缩放厚

            视距原点 perspective-origin

            视距原点 可以设置 人 站在x轴和y轴的位置

            1. 视距原点和视距一样,也是设置给要观察元素的父元素
            2. perspective-origin:center center; 默认值是元素的中心点
            3. perspective-origin:10px; 指定了一个参数的时候,第二个参数默认为center 也就是50%;
            4. perspective-origin:10% %; 百分比都是相对于自身的宽度和高度

            转换样式(3D呈现) transform-style

            控制子元素是否开启3维立体环境

            • transform-style: flat; 平面模式 - 不开启3维立体环境
            • transform-style: preserve-3d; 3维立体环境

            3.流式布局

            布局视口 layout viewport

            移动设备的浏览器都默认设置了一个布局视口,用于解决早期的PC端页面在手机上显示的问题。

            视觉视口 visual viewport

            它是用户正在看到的网站的区域。注意:是网站的区域。

            我们可以通过缩放去操作视觉视口,但不会影响布局视口,布局视口仍保持原来的宽度。

            理想视口 ideal viewport

            理想视口,对设备来讲,是最理想的视口尺寸

            需要手动添写meta视口标签通知浏览器操作

            meta视口标签的主要目的:布局视口的宽度应该与理想视口的宽度一致,简单理解就是设备有多宽,我们布局的视口就多宽

            总结:我们开发最终会用理想视口,而理想视口就是将布局视口的宽度修改为视觉视口

            meta标签

            "viewport" content="width=device-width, initial-scale=1.0,maximum-scale=1.0, minimum-scale=1.0, user-scalable=no">
            
            属性 解释
            width 宽度设置的是viewport宽度,可以设置device-width特殊值
            initial-scale 初始缩放比,大于0的数字
            maximum-scale 最大缩放比,大于0的数字
            minimum-scale 最小缩放比,大于0的数字
            user-scalable 用户是否可以缩放,yes或no(1或0)

            最标准的viewport设置

            • 视口宽度和设备保持一致
            • 视口的默认缩放比例1.0
            • 不允许用户自行缩放
            • 最大允许的缩放比例1.0
            • 最小允许的缩放比例1.0

            二倍图

            物理像素&物理像素比

            物理像素点指的是屏幕显示的最小颗粒,是物理真实存在的。

            物理像素比:一个px的能显示的物理像素点的个数,称为物理像素比或屏幕像素比

            背景缩放background-size

            background-size 属性规定背景图像的尺寸

            background-size: 背景图片宽度 背景图片高度;
            

            单位: 长度|百分比|cover|contain;

            cover把背景图像扩展至足够大,以使背景图像完全覆盖背景区域。

            contain把图像图像扩展至最大尺寸,以使其宽度和高度完全适应内容区域

            CSS3盒子模型

            传统模式宽度计算:盒子的宽度 = CSS中设置的width + border + padding

            CSS3盒子模型: 盒子的宽度= CSS中设置的宽度width 里面包含了 border 和 padding

            /*CSS3盒子模型(用这个)*/
            box-sizing: border-box;
            /*传统盒子模型*/
            box-sizing: content-box;
            

            移动端特殊样式

                /*CSS3盒子模型*/
                box-sizing: border-box;
                -webkit-box-sizing: border-box;
                /*点击高亮我们需要清除清除  设置为transparent 完成透明*/
                -webkit-tap-highlight-color: transparent;
                /*在移动端浏览器默认的外观在iOS上加上这个属性才能给按钮和输入框自定义样式*/
                -webkit-appearance: none;
                /*禁用长按页面时的弹出菜单*/
                img,a { -webkit-touch-callout: none; }
            

            流式布局方式

            流式布局,就是百分比布局,也称非固定像素布局。

            通过盒子的宽度设置成百分比来根据屏幕的宽度来进行伸缩,不受固定像素的限制,内容向两侧填充。

            4.flex布局

            • flex 是 flexible Box 的缩写,意为"弹性布局",用来为盒状模型提供最大的灵活性,任何一个容器都可以指定为 flex 布局。
            • 当我们为父盒子设为 flex 布局以后,子元素的 float、clear 和 vertical-align 属性将失效。
            • flex布局又叫伸缩布局 、弹性布局 、伸缩盒布局 、弹性盒布局
            • 采用 Flex 布局的元素,称为 Flex 容器(flex

            container),简称"容器"。它的所有子元素自动成为容器成员,称为 Flex 项目(flex
            item),简称"项目"。

            总结:就是通过给父盒子添加flex属性,来控制子盒子的位置和排列方式

            父项常见属性

            • flex-direction:设置主轴的方向
            子属性 属性值
            row 默认值从左到右
            row-reverse 从右到左
            column 从上到下
            column-reverse 从下到上
            • justify-content:设置主轴上的子元素排列方式
            子属性 属性值
            flex-start 默认值,从头部开始,如果主轴是X,则从左往右
            flex-end 从尾部开始排列
            center 在主轴居中对齐,如果主轴是X轴,水平居中
            space-around 平分剩余空间
            space-bet 先两边贴边再平分剩余空间
            • flex-wrap:设置子元素是否换行

            默认项目都排在一条线(又称”轴线”)上。

            flex-wrap属性定义,flex布局中默认是不换行的

            nowrap 不换行

            wrap 换行

            • align-items:设置侧轴上的子元素排列方式(单行)

            flex-start 从头部开始

            flex-end 从尾部开始

            center 居中显示

            stretch 拉伸

            • align-content:设置侧轴上的子元素的排列方式(多行)

            只能用于子项出现 换行 的情况(多行),在单行下是没有效果的。

            子属性 属性值
            flex-start 默认值在侧轴的头部开始排列
            flex-end 从侧轴尾部开始排列
            center 在侧轴中间显示
            space-around 子项在侧轴平分剩余空间
            space-bet 子项在侧轴先两边贴边再平分剩余空间
            stretch 设置子项元素高度平分父元素高度
            • flex-flow:复合属性,相当于同时设置了 flex-direction 和 flex-wrap
            flex-flow:row wrap;
            

            子项常见属性

            • flex子项目占的份数

            flex 属性定义子项目分配剩余空间,用flex来表示占多少份数。

            .item {
                flex: ; /* 默认值 0 */
            }
            
            • align-self控制子项自己在侧轴的排列方式

            align-self 属性允许单个项目有与其他项目不一样的对齐方式,可覆盖 align-items 属性。

            默认值为 auto,表示继承父元素的 align-items 属性,如果没有父元素,则等同于 stretch。

            span:nth-child(2) {
                  /* 设置自己在侧轴上的排列方式 */
                  align-self: flex-end;
            }
            
            • order属性定义子项的排列顺序(前后顺序)

            数值越小,排列越靠前,默认为0。

            注意:和 z-index 不一样。

            5.rem布局

            rem单位

            rem (root em)是一个相对单位,类似于em,em是父元素字体大小。

            不同的是rem的基准是相对于html元素的字体大小。

            比如,根元素(html)设置font-size=12px; 非根元素设置width:2rem; 则换成px表示就是24px。

            媒体查询

            • 用 @media开头 注意@符号
            • mediatype 媒体类型
            • 关键字 and not only
            • media feature 媒体特性必须有小括号包含
            @media mediatype and|not|only (media feature) {
                CSS-Code;
            }
            

            mediatype 查询类型

            ​ 将不同的终端设备划分成不同的类型,称为媒体类型

            all 用于所有设备

            print 用于打印机和打印预览

            scree 用于电脑屏幕,平板电脑,只能手机等

            关键字

            ​ 关键字将媒体类型或多个媒体特性连接到一起做为媒体查询的条件。

            • and:可以将多个媒体特性连接到一起,相当于“且”的意思。
            • not:排除某个媒体类型,相当于“非”的意思,可以省略。
            • only:指定某个特定的媒体类型,可以省略。

            媒体特性

            width 定义输出设备中页面可见区域的宽度

            min-width 定义输出设备中页面最小可见区域宽度

            max-width 定义输出设备中页面最大可见区域宽度

            less 基础

            Less安装

            ①安装nodejs,可选择版本(8.0),网址:http://nodejs.cn/download/

            ②检查是否安装成功,使用cmd命令(win10是window+r 打开运行输入cmd) —输入“node –v”查看版本即可

            ③基于nodejs在线安装Less,使用cmd命令“npm install -g less”即可

            ④检查是否安装成功,使用cmd命令“ lessc -v ”查看版本即可

            Less 使用之变量

            变量是指没有固定的值,可以改变的。因为我们CSS中的一些颜色和数值等经常使用。

            @变量名:值;
            
            • 必须有@为前缀
            • 不能包含特殊字符
            • 不能以数字开头
            • 大小写敏感
            @color: pink;
            

            Less 编译 vocode Less 插件

            Easy LESS 插件用来把less文件编译为css文件

            安装完毕插件,重新加载下 vscode。

            只要保存一下Less文件,会自动生成CSS文件。

            Less 嵌套 :如果遇见 (交集|伪类|伪元素选择器) ,利用&进行连接

            Less 运算

            任何数字、颜色或者变量都可以参与运算。就是Less提供了加(+)、减(-)、乘(*)、除(/)算术运算。

            • 乘号(*)和除号(/)的写法
            • 运算符中间左右有个空格隔开 1px + 5
            • 对于两个不同的单位的值之间的运算,运算结果的值取第一个值的单位
            • 如果两个值之间只有一个值有单位,则运算结果就取该单位

            6.响应式布局

            使用媒体查询针对不同宽度的设备进行布局和样式的设置,从而适配不同设备的目的。

            设备的划分情况:

            • 小于768的为超小屏幕(手机)
            • 768~992之间的为小屏设备(平板)
            • 992~1200的中等屏幕(桌面显示器)
            • 大于1200的宽屏设备(大桌面显示器)

            父容器版心的尺寸划分

            • 超小屏幕(手机,小于 768px):设置宽度为 100%
            • 小屏幕(平板,大于等于 768px):设置宽度为 750px
            • 中等屏幕(桌面显示器,大于等于 992px):宽度设置为 970px
            • 大屏幕(大桌面显示器,大于等于 1200px):宽度设置为 1170px

            Bootstrap

            Bootstrap 来自 Twitter(推特),是目前最受欢迎的前端框架。Bootstrap 是基于HTML、CSS 和 JAVASCRIPT 的,它简洁灵活,使得 Web 开发更加快捷。

            bootstrap基本使用

            1. 创建文件夹结构

            2. 创建 html 骨架结构

            3. 引入相关样式文件

              
              
              
            4. 书写内容

            bootstrap布局容器

            .container

            • 响应式布局的容器 固定宽度
            • 大屏 ( >=1200px) 宽度定为 1170px
            • 中屏 ( >=992px) 宽度定为 970px
            • 小屏 ( >=768px) 宽度定为 750px
            • 超小屏 (100%)

            .container-fluid

            • 流式布局容器 百分百宽度
            • 占据全部视口(viewport)的容器。

            bootstrap栅格系统

            • 按照不同屏幕划分为1~12 等份
            • 行(row) 可以去除父容器作用15px的边距
            • xs-extra small:超小; sm-small:小; md-medium:中等; lg-large:大;
            • 列(column)大于 12,多余的“列(column)”所在的元素将被作为一个整体另起一行排列
            • 每一列默认有左右15像素的 padding
            • 可以同时为一列指定多个设备的类名,以便划分不同份数 例如 class=“col-md-4 col-sm-6”

            列偏移

            使用 .col-md-offset-* 类可以将列向右侧偏移。这些类实际是通过使用 * 选择器为当前元素增加了左侧的边距(margin)。

             
              
            1
            2

            列排序

            通过使用 .col-md-push-* 和 .col-md-pull-* 类就可以很容易的改变列(column)的顺序。

             
              
            往左侧推
            往右侧推

            响应式(隐藏)工具

            类名 超小屏 小屏 中屏 大屏
            .hidden-xs 隐藏 可见 可见 可见
            .hidden-sm 可见 隐藏 可见 可见
            .hidden-md 可见 可见 隐藏 可见
            .hidden-lg 可见 可见 可见 隐藏

            语法: class="hidden-xs“

            与之相反的是 visible-xs/sm/md/lg

            四.js基础

            1.数据类型

            JS组成

            ECMAScript——JavaScript语法

            DOM——页面文档对象模型

            BOM——浏览器对象模型

            数据存储单位

            大小关系:bit < byte < kb < GB < TB<.....
            
            • 位(bit): 1bit 可以保存一个 0 或者 1 (最小的存储单位)
            • 字节(Byte):1B = 8b
            • 千字节(KB):1KB = 1024B
            • 兆字节(MB):1MB = 1024KB
            • 吉字节(GB): 1GB = 1024MB
            • 太字节(TB): 1TB = 1024GB

            输入输出语句

            方法 说明 归属
            alert(msg) 浏览器弹出警示框 浏览器
            console.log(msg) 浏览器控制台打印输出信息 浏览器
            prompt(info) 浏览器弹出输入框,用户可以输入 浏览器

            alert() 主要用来显示消息给用户,console.log() 用来给程序员自己看运行时的消息。

            声明变量

            //  声明变量  
            var age; //  声明一个 名称为age 的变量     
            

            赋值

            age = 10; // 给 age  这个变量赋值为 10          
            

            变量的初始化

            var age  = 18;  // 声明变量同时赋值为 18          
            
            声明一个变量并赋值, 我们称之为变量的初始化。
            

            数据类型简介

            • Nunber 数字型,包含整型和浮点型,在JS中八进制前面加0,十六进制前面加 0x
            alert(Number.MAX_VALUE); // 1.7976931348623157e+308
            alert(Number.MIN_VALUE); // 5e-324
            alert(Infinity);  // Infinity 无穷大
            alert(-Infinity); // -Infinity 无穷小
            alert(NaN);       // NaN , Not a number,代表一个非数值
            

            isNaN用来判断一个变量是否为非数字的类型,返回 true 或者 false

            语法: var 变量名A = isNaN(变量名B)

            • String 字符串型

              转义符 解释说明
              \n 换行符,n 是 newline 的意思
              \ \ 斜杠 \
              ’ 单引号
              " ”双引号
              \t tab 缩进
              \b 空格 ,b 是 blank 的意思

            字符串长度 —— 语法:语法: var 变量名A = 变量名B.length

            字符串拼接

            ​ 多个字符串之间可以使用 + 进行拼接,其拼接方式为 字符串 + 任何类型 = 拼接之后的新字符串

            ​ 拼接前会把与字符串相加的任何类型转成字符串,再拼接成一个新的字符串

            ​ 如果变量两侧都有字符串拼接,口诀“引引加加 ”,删掉数字,变量写加中间

            • Boolean 布尔值类型,如true、false,等价于1和0、
            • Undefined 未定义——一个声明后没有被赋值的变量会有一个默认值undefined
            • Null 空值——一个声明变量给 null 值,里面存的值为空

            获取变量数据类型

            typeof 可用来获取检测变量的数据类型

            var num = 18;
            console.log(typeof num) // 结果 number      
            

            数据类型转换

            • 转换为字符串

              1.toString() 语法:alert(变量名.toString())

              2.String()强制转换 语法:alert(String(变量名))

              3.加号拼接字符串:和字符串拼接的结果都是字符串(隐式转换)

            • 转换为数字型

              1.parseInt(string)函数 语法:parseInt(’string‘)

              2.parseFloat(string)函数 语法:parseInt(’string‘)

              3.Number()强制转换 语法:Numer(‘string’)

              4.js隐式转换:利用算术运算隐式转换为数值型 比如:‘12’-0

            • 转换为布尔型

              Boolean()函数 语法:Boolean(‘string’)

            关键字

            包括:break、case、catch、continue、default、delete、do、else、finally、for、function、if、in、instanceof、new、return、switch、this、throw、try、typeof、var、void、while、with 等。
            

            2.运算符、流程控制、循环

            递增运算符

            ++num 前置递增,就是自加1,类似于 num = num + 1,但是 ++num 写起来更简单。

            使用口诀:先自加,后返回值

            num++ 后置递增,就是自加1,类似于 num = num + 1 ,但是 num++ 写起来更简单。

            使用口诀:先返回原值,后自加

            比较运算符

            < > <== >== == != === !==

            逻辑运算符

            与&& 或|| 非!

            流程控制

            if 语句

            // 适合于检查多重条件。
            if (条件表达式1) {
                语句1} else if (条件表达式2)  {
                语句2} else if (条件表达式3)  {
               语句3....
            } else {
                // 上述条件都不成立执行此处代码
            }
            

            三元表达式

            表达式1 ? 表达式2 : 表达式3;
            

            switch分支流程控制

              switch( 表达式 ){ 
                  case value1:
                      // 表达式 等于 value1 时要执行的代码
                      break;
                  case value2:
                      // 表达式 等于 value2 时要执行的代码
                      break;
                  default:
                      // 表达式 不等于任何一个 value 时要执行的代码
              }
            

            注意: 执行case 里面的语句时,如果没有break,则继续执行下一个case里面的语句。

            for循环

            for(初始化变量; 条件表达式; 操作表达式 ){
                //循环体
            }
            

            while循环

            while (条件表达式) {
                // 循环体代码 
            }
            

            do-while循环

            do {
                // 循环体代码 - 条件表达式为 true 时重复执行循环体代码
            } while(条件表达式);
            

            continue

            continue 关键字用于立即跳出本次循环,继续下一次循环(本次循环体中 continue 之后的代码就会少执行一次)

            break

            立即跳出整个循环(循环结束)

            3.数组、函数

            创建数组

            • 利用 new 创建数组

              var 数组名 = new Array()var arr = new Array();   // 创建一个新的空数组
              

              注意 Array () ,A 要大写

            • 利用数组字面量创建数组

              //1. 使用数组字面量方式创建空的数组
              var  数组名 = []//2. 使用数组字面量方式创建带初始值的数组
              var  数组名 = ['小白','小黑','大黄','瑞奇'];
              

            数组中新增元素

              数组[ 数组.length ] = 新数据;
            

            函数的使用

            声明函数

            // 声明函数
            function 函数名() {
                //函数体代码
            }
            

            调用函数

            // 调用函数
            函数名();  // 通过调用函数名来执行函数体代码
            

            函数的参数

            • 形参:函数定义时设置接收调用时传入
            • 实参:函数调用时传入小括号内的真实数据

            函数的返回值

            return 语句

            • 在使用 return 语句时,函数会停止执行,并返回指定的值
            • 如果函数没有 return ,返回的值是 undefined

            arguments的使用

            当不确定有多少个参数传递的时候,可以用 arguments 来获取

            arguments展示形式是一个伪数组,可以进行遍历

            • 具有 length 属性
            • 按索引方式储存数据
            • 不具有数组的 push , pop 等方法

            4.作用域、预解析、对象

            JavaScript(es6前)中的作用域有两种:

            ​ 全局作用域 在函数内部没有声明直接赋值的变量属于全局变量

            ​ 局部作用域(函数作用域)

            预解析

            • 预解析:在当前作用域下, JS 代码执行之前,浏览器会默认把带有 var 和 function 声明的变量在内存中进行提前声明或者定义。

            • 代码执行: 从上到下执行JS语句。

              预解析会把变量和函数的声明在代码执行之前执行完成。

            对象

            所有的事物都是对象,对象是由属性和方法组成的

            • 属性:事物的特征,在对象中用属性来表示(常用名词)
            • 方法:事物的行为,在对象中用方法来表示(常用动词)

            创建对象的三种方式

            1.利用字面量创建对象

            var 对象名 = {
               属性1:属性值1;
              属性2:属性值2;
              .......
                sayHi : function(){
                    alert('大家好啊~');
                }
            };
            

            调用对象——对象名.属性名 或 对象名[‘属性名’]

            调用对象方法——对象名.方法名()

            2.利用 new Object 创建对象

            var 对象名 = new Obect();
            

            通过内置构造函数Object创建对象,此时变量已经保存了创建出来的空对象

            通过对象操作属性和方法的方式,来为对象增加属性和方法

            比如——对象名1.属性1=’XXX‘;

            3.利用构造函数创建对象

            function 构造函数名(形参1,形参2,形参3) {
                 this.属性名1 = 参数1;
                 this.属性名2 = 参数2;
                 this.属性名3 = 参数3;
                 this.方法名 = 函数体;
            }
            

            构造函数的调用格式

            var obj = new 构造函数名(实参1,实参2,实参3)
            

            以上代码中,obj即接收到构造函数创建出来的对象

            遍历对象

            其语法如下:
            
            for (var 变量 in 对象名字) {
                // 在此执行代码
            }
            

            5.内置对象

            Math对象

            属性、方法名 功能
            Math.PI 圆周率
            Math.floor() 向下取整
            Math.ceil() 向上取整
            Math.round() 四舍五入版 就近取整 注意 -3.5 结果是 -3
            Math.abs() 绝对值
            Math.max()/Math.min() 求最大和最小值
            Math.random() 获取范围在[0,1)内的随机数
            // Math随机数方法  包含两端的2个数字
            function getRandom(min, max) {
              return Math.floor(Math.random() * (max - min + 1)) + min; 
            }
             console.log(getRandom(1, 10));
            

            日期对象

            • 获取当前时间必须实例化:
            var now = new Date();
            
            • 获取指定时间的日期对象
            var future = new Date('2019/5/1');//或者 ('2019-10-10 8:8:8')
            
             // 返回当前年份
                    console.log(date.getFullYear());
                    // 返回当前月份 数值比实际月份小1  需要+1
                    console.log(date.getMonth() + 1);
                    // 返回当前日期是本月的多少日
                    console.log(date.getDate());
                    // 返回当前日期是周几  注意:返回当前是周几  周日返回值为0
                    console.log(date.getDay());
                     // 返回当前小时
                    console.log(date.getHours());
            		  // 返回当前分钟
                    console.log(date.getMinutes());
            		  // 返回当前秒钟
                    console.log(date.getSeconds());
            
            • 获取总毫米数

            基于1970年1月1日(世界标准时间)起的毫秒数

            获取总毫秒数如下

            // 实例化Date对象
            var now = new Date();
            // 1. 用于获取对象的原始值
            console.log(date.valueOf())	
            console.log(date.getTime())	
            // 2. 简单写可以这么做
            var now = + new Date();			
            // 3. HTML5中提供的方法,有兼容性问题
            var now = Date.now();
            

            数组对象

            检测是否为数组

            1.instanceof 可以判断一个对象是否是某个构造函数的实例 返回值为true或者false

            语法:数组名 instanceof Array

            比如:console.log(arr instanceof Array);

            2**.Array.isArray(数组名)**用于判断一个对象是否为数组 返回值为true或者false 是 HTML5 中提供的方法

            添加删除数组元素

            方法名 说明 返回值
            push(参数1…) 末尾添加一个或多个元素–数组名.push(要添加的) 新的长度
            pop() 删除最后一个元素,数组长度减一 删除的元素值
            unshift(参数1…) 开头添加一个或多个元素 新的长度
            shift() 删除第一个元素,数组长度减一 第一个元素值

            注意:push、unshift为增加元素方法;pop、shift为删除元素的方法

            数组排序

            方法名 说明
            reverse() 颠倒数组中元素顺序
            sort() 对数组的元素进行排序

            注意:sort方法需要传入参数来设置升序、降序排序

            • 如果传入“function(a,b){ return a-b;}”,则为升序
            • 如果传入“function(a,b){ return b-a;}”,则为降序

            数组转换为字符串

            1.toString() 把数组转换成字符串,逗号分隔每一项

            2.join(‘分隔符’) 把数组中的所有元素转换为一个字符串

            注意:二者均返回一个字符串,join方法如果不传入参数,则按照 “ , ”拼接元素

            数组对象转换为字符串格式

            JSON.stringify()

            其他方法

            数组连接 concat(‘连接内容’)

            数组截取字符串 slice(截取的起始位置,截取的数量)

            数组替换 replace(‘被替换的字符’,‘替换为的字符’) 只会替换第一个

            数组根据索引号删除相关内容 splice(索引号,从索引号处开始要删除的数量 )

            字符串对象

            js 会把基本数据类型包装为复杂数据类型

            字符串转换为数组对象

            JSON.parse()

            字符串操作方法

            连接字符串 str.concat(‘连接内容’)

            查找字符串 str.substr(start,length) 从start位置开始,length取的个数

            截取字符串 slice(start,end) 从start位置开始,截取到end位置,end取不到

            替换字符串 str.replace(‘被替换的字符’,‘替换为的字符’) 只会替换第一个

            字符转换为数组 str.split(‘分隔符’)

            五.Web API

            API是给程序员提供的一种工具,以便能更轻松的实现想要完成的功能

            1.获取元素、事件基础、操作元素

            获取元素

            根据ID获取

            语法:document.getElementById(id)
            返回值:元素对象 或 null
            

            根据标签名获取元素

            语法:document.getElementsByTagName('标签名')  或者 element.getElementsByTagName('标签名') 
            返回值:元素对象集合(伪数组,数组元素是元素对象)
            

            根据类名获取元素 (h5新增)

            document.getElementsByClassName(‘类名’) //返回元素对象集合

            根据选择器获取元素 (h5新增)

            document.querySelector(‘选择器’) //返回第一个元素对象

            document.querySelectorAll(‘选择器’) //根据指定选择器返回

            获取body元素

            document.body

            获取html元素

            document.documentElement

            事件基础

            事件三要素

            • 事件源(谁):触发事件的元素
            • 事件类型(什么事件): 例如 click 点击事件
            • 事件处理程序(做啥):事件触发后要执行的代码(函数形式),事件处理函数

            执行事件的步骤

            1.获取事件源

            2.注册事件(绑定事件)

            3.添加事件处理程序(采取函数赋值形式)

            常见的鼠标事件

            鼠标事件 触发条件
            onclick 鼠标点击左键触发
            onmouseover 鼠标经过触发
            onmouseout 鼠标离开触发
            onfocus 获得鼠标焦点触发
            onblur 失去鼠标焦点触发
            onmousemove 鼠标移动触发

            修改元素内容(获取或设置)

            element.innerText 从起始到终止位置的内容,但不识别html标签,空格和换行也会去掉

            element.innerHTML 从起始到终止位置的内容,但识别html标签,空格和换行也会保留

            属性操作

            获取属性的值: 元素对象.属性名

            设置属性的值: 元素对象.属性名=值

            样式属性操作

            element.style 行内样式操作

            element.className 类名样式操作

            2.自定义属性操作、节点操作

            排他思想

            如果有同一组元素,我们想要某一个元素实现某种样式, 需要用到循环的排他思想算法:

            1. 所有元素全部清除样式(干掉其他人)
            2. 给当前元素设置样式 (留下我自己)
            3. 注意顺序不能颠倒,首先干掉其他人,再设置自己

            自定义属性操作

            获取属性值

            1.element.属性 //获取内置属性(元素本身自带的属性)

            2.element.getAttribute(’属性值’) //主要获得自定义的属性,程序员自定义的属性

            设置属性值

            1.element.属性 = ‘值’ //设置内置属性值

            2.element.setAttribute(’属性值’,‘值’) //主要设置自定义的属性

            移出属性

            element.removeAttribute(‘属性’);

            H5自定义属性

            H5规定自定义属性data-开头作为属性名并且赋值

            比如:element.setAttribute('data-index',2)
            

            获取H5自定义属性

            element.dataset.属性名

            element.dataset[’‘属性名’]

            节点操作

            元素节点 nodeType为1 //实际开发中的主要操作对象

            属性节点 nodeType为2

            文本节点 nodeType为3(包含文字、空格、换行等)

            父级节点

            node.parentNode //返回最近的一个父节点,没有则返回null

            子节点

            1.parentNode.childNodes //会返回所有节点

            2.parentNode.children //只返回子元素节点,其余节点不返回,重点使用这个

            第1个子节点:parentNode.firstElementChild

            最后一个子节点:parentNode.lastElementChild

            兄弟节点

            node.nextElementSibling 返回下一个兄弟元素节点

            node.previousElementSibling 返回上一个兄弟元素节点

            创建节点

            document.createElement(‘tagName’)

            添加节点

            node.appendChild(节点名) //将一个节点添加到指定父节点的子节点列表末尾,类似于css里的after伪元素

            node.insertBefore(节点名,指定元素) //将一个节点添加到父节点指定的子节点前面,类似于css里的before伪元素

            删除节点

            node.removeChild(child)
            

            说明:node.removeChild() 方法从 node节点中删除一个子节点,返回删除的节点。

            复制(克隆)节点

            node.cloneNode() ; // 括号为空或者里面是false 浅拷贝 只复制标签不复制里面的内容

            node.cloneNode(true); //括号为true 深拷贝 复制标签复制里面的内容

            document.write创建元素

            • 语法:

              • document.write()
              • element.innerHTML
              • document.createElement()
            • 区别:

              1. document.write 是直接将内容写入页面的内容流,界面加载完成之后,再写入,这样它会导致页面全部重绘
              2. innerHTML 是将内容写入某个 DOM 节点,不会导致页面全部重绘
              3. innerHTML 创建多个元素效率更高(不要拼接字符串,采取数组形式拼接),结构稍微复杂
              4. createElement() 创建多个元素效率稍低一点点,但是结构更清晰
              5. 总结不同浏览器下,innerHTML 效率要比 creatElement 高

            3.事件高级

            方法事件监听addEventListener()

            同一个元素同一个事件可以注册多个监听器(事件处理程序)

            // 参数1:事件类型,它是字符串 必定加引号 而且不带on
            // 参数2:事件处理程序
            btns[1].addEventListener('click', function() {
            	alert(22);
            })
            btns[1].addEventListener('click', function() {
            	alert(33);
            })
            

            attachEvent()事件监听

            • 语法:
             eventTarget.attachEvent(eventNameWithOn, callback) 
             比如: btns[2].attachEvent('onclick', function() {
                    alert(11);
                }) //  attachEvent ie9以前的版本支持  这里的事件需要带on
            

            删除事件(解绑事件)

            1. eventTarget.removeEventListener(type, listener[, useCapture]);
             //针对addEventListener()
            2. eventTarget.detachEvent(eventNameWithOn, callback);
            //针对attachEvent()
            

            DOM 事件流

            1. 捕获阶段
            2. 当前目标阶段
            3. 冒泡阶段

            事件发生时会在元素节点之间按照特定的顺序传播,这个传播过程即 DOM 事件流

            注意:

            1. JS 代码中只能执行捕获或者冒泡其中的一个阶段。
            2. onclick 和 attachEvent 只能得到冒泡阶段。(理解:只在冒泡阶段触发)
            3. addEventListener(type, listener[, useCapture])第三个参数如果是 true,表示在事件捕获阶段调用事件处理程序;如果是 false(不写默认就是false),表示在事件冒泡阶段调用事件处理程序。
            4. 实际开发中我们很少使用事件捕获,我们更关注事件冒泡
            5. 有些事件是没有冒泡的,比如 onblur、onfocus、onmouseenter、onmouseleave

            事件对象

              eventTarget.onclick = function(event) {
                 // 这个 event 就是事件对象,我们还喜欢的写成 e 或者 evt 
              } 
              eventTarget.addEventListener('click', function(event) {
                // 这个 event 就是事件对象,我们还喜欢的写成 e 或者 evt 
              }

            事件对象的属性和方法

            事件对象属性方法 说明
            e.target 返回触发事件的对象 标准
            e.srcElement 返回触发事件的对象 非标准 ie6-8使用
            e.type 返回事件的类型 比如click mouseover 不带on
            e.cancelBubble=true 该属性阻止冒泡排序 非标准 ie6-8使用
            e.returnValue=false 阻止默认事件(默认行为) 非标准 ie6-8使用 比如不让链接跳转
            e.preventDefault() 阻止默认事件(默认行为) 标准 比如不让链接跳转
            e.stopPropagation() 阻止冒泡排序

            e.target 和 this 的区别

            • this 是事件绑定的元素(绑定这个事件处理函数的元素) 。
            • e.target 是事件触发的元素(比如click事件中点击的对象)。

            阻止默认行为

            1. e.preventDefault(); //标准写法 一般用这个
            2. e.returnValue = false; // 低版本浏览器 ie678
            3. return false; //return后面的不执行
                <a href="http://www.baidu.com">百度</a>
                <script>
                    // 2. 阻止默认行为 让链接不跳转 
                    var a = document.querySelector('a');
                    a.addEventListener('click', function(e) {
                         e.preventDefault(); //  dom 标准写法
                    });
                    // 3. 传统的注册方式
                    a.onclick = function(e) {
                        // 普通浏览器 e.preventDefault();  方法
                        e.preventDefault();
                        // 低版本浏览器 ie678  returnValue  属性
                        e.returnValue = false;
                        // 我们可以利用return false 也能阻止默认行为 没有兼容性问题
                        return false;
                    }
                </script>
            

            阻止事件冒泡

            1. e.stopPropagation() //标准写法
            2. e.cancelBubble = true; //非标准写法
             var son = document.querySelector('.son');
            		// 给son注册单击事件
                    son.addEventListener('click', function(e) {
                        alert('son');
                        e.stopPropagation(); 
                        window.event.cancelBubble = true; 
                    }, false);
            
            • 阻止事件冒泡的兼容性处理
              if(e && e.stopPropagation){
                  e.stopPropagation();
              }else{
                  window.event.cancelBubble = true;
              }
            

            事件委托

            事件监听器设置在其父节点上,然后利用冒泡原理影响设置每个子节点。

            禁止鼠标右键菜单

            contextmenu事件:鼠标右键菜单事件。主要控制应该何时显示上下文菜单(右键菜单),主要用于程序员取消默认的上下文菜单

            document.addEventListener('contextmenu', function(e) {
            	e.preventDefault();
            })
            

            禁止鼠标选中

            selectstart 事件:鼠标选中事件,用于界面文字防止选中

            document.addEventListener('selectstart', function(e) {
                e.preventDefault();
            })
            

            鼠标事件对象

            鼠标事件对象 说明
            e.clientX 返回鼠标相对于浏览器窗口可视区的X坐标
            e.clientY 返回鼠标相对于浏览器窗口可视区的Y坐标
            e.pageX 返回鼠标相对于整个文档页面的X坐标 IE9+支持
            e.pageY 返回鼠标相对于整个文档页面的Y坐标 IE9+支持
            e.screenX 返回鼠标相对于电脑屏幕的X坐标
            e.screenY 返回鼠标相对于电脑屏幕的Y坐标

            常用键盘事件

            键盘事件 触发条件
            onkeyup 某个键盘按键被松开时触发
            onkeydown 被按下时触发
            onkeypress 被按下时触发 但不识别功能键 比如ctrl shift 箭头等
            onkeyCode 返回该键的ASCII值

            如果使用addEventListener 不需要加 on

            三个事件的执行顺序是: keydown – keypress — keyup (按下–按住–抬起

            keyCode判断用户按下哪个键

                <script>
                    // 键盘事件对象中的keyCode属性可以得到相应键的ASCII码值
                    document.addEventListener('keyup', function(e) {
                        console.log(e.keyCode);
                        // 我们可以利用keycode返回的ASCII码值来判断用户按下了那个键
                        if (e.keyCode === 65) {
                            alert('您按下的a键');
                        } else {
                            alert('您没有按下a键')
                        }
                    })
                    document.addEventListener('keypress', function(e) {
                        // console.log(e);
                        console.log(e.keyCode);
                    })
                </script>
            
            1. onkeydown 和 onkeyup 不区分字母大小写,通过keyCode属性获取到的a 和 A 得到的都是65
            2. onkeypress 区分字母大小写 ,通过keyCode属性获取到的 a 是 97 和 A 得到的是65
            3. 但是在我们实际开发中,我们更多的使用keydown和keyup, 它能识别所有的键(包括功能键)

            4.BOM、JS执行机制、元素偏移量 offset

            BOM(Browser Object Model)即浏览器对象模型,它提供了独立于内容而与浏览器窗口进行交互的对象,其核心对象是 window

            页面(窗口)加载事件

            第一种——语法:

            window.onload = function(){}
            或者 
            window.addEventListener("load",function(){});
            
            1. 有了 window.onload 就可以把 JS 代码写到页面元素的上方,因为 onload 是等页面内容全部加载完毕,再去执行处理函数。
            2. window.onload 传统注册事件方式 只能写一次,如果有多个,会以最后一个 window.onload 为准。
            3. 如果使用 addEventListener 则没有限制

            第二种——语法:

            document.addEventListener('DOMContentLoaded',function(){})
            

            DOMContentLoaded 事件触发时,仅当DOM加载完成,不包括样式表,图片,flash等等。

            调整窗口大小事件

            语法

             window.onresize = function(){}
            
             window.addEventListener("resize",function(){});
            

            window.onresize 是调整窗口大小加载事件, 当触发时就调用的处理函数。

            window.innerWidth 当前屏幕的宽度

            定时器

            setTimeout()

             window.setTimeout(回调函数, [延迟的毫秒数]);
            
            1. window 可以省略。
            2. 这个调用函数可以直接写函数,或者写函数名或者采取**字符串‘函数名()’**三种形式。第三种不推荐
            3. 因为定时器可能有很多,所以我们经常给定时器赋值一个标识符。

            清除定时器:

             window.clearTimeout(定时器名字)
            

            setInterval() 闹钟定时器

             window.setInterval(回调函数, [间隔的毫秒数]);
            

            和setTimeout用法类似

            清除定时器:

             window.clearInterval(intervalID);
            

            this指向问题

            1. 全局作用域或者普通函数中this指向全局对象window(注意定时器里面的this也指向window)
            2. 方法调用中谁调用this指向谁
            3. 构造函数中this指向构造函数的实例(通过构造函数new出来的对象)

            location对象

            获取或设置窗体的 URL,并且可以用于解析 URL

            URL 的一般语法格式为:

             protocol://host[:port]/path/[?query]#fragment
            
             http://www.itcast.cn/index.html?name=andy&age=18#link
            

            location 对象的属性

            location 对象属性 返回值
            location.href 获取或设置整个URL
            location.host 返回主机(域名)
            location.port 返回端口号
            location.pathname 返回路径
            location.search 返回参数
            location.hash 返回片段 #后面内容 常见于链接 锚点

            location对象的常见方法

            location对象方法 返回值
            location.assign() 和href一样,可以跳转页面
            location.replace() 替换当前页面,因为不记录历史,所以不能后退
            location.reload() 重新加载页面,相当于刷新按钮或者F5 如果参数为true 强制刷新

            navigator对象

            navigator 对象包含有关浏览器的信息,它有很多属性,我们最常用的是 userAgent,该属性可以返回由客户机发送服务器的 user-agent 头部的值

            下面前端代码可以判断用户那个终端打开页面,实现跳转

            if((navigator.userAgent.match(/(phone|pad|pod|iPhone|iPod|ios|iPad|Android|Mobile|BlackBerry|IEMobile|MQQBrowser|JUC|Fennec|wOSBrowser|BrowserNG|WebOS|Symbian|Windows Phone)/i))) {
                window.location.href = "";     //手机
             } else {
                window.location.href = "";     //电脑
             }
            

            history对象

            与浏览器历史记录进行交互。该对象包含用户(在浏览器窗口中)访问过的URL

            history对象方法 作用
            back() 后退功能
            forward() 前进功能
            go(参数) 前进后退功能 参数是1则前进1个页面 参数是-1 后退1个页面

            JS执行机制

            同步:先做一件事情,然后再做另一件事情。他是单线程,一个人依次做多件事情

            异步:是两件事情同时去做,他是多线程,多个人同时做多个事情

            元素偏移量 offset

            offset属性 作用
            element.offsetParent 返回该元素带有定位的父元素 如果父级都没有定位则返回body
            element.offsetTop 返回该元素相对带有定位父元素上方的偏移量
            element.offsetLeft 返回该元素相对带有定位父元素左边的偏移量
            element.offsetWidth 返回自身padding、边框、内容区的宽度
            element.offsetHeight 返回自身padding、边框、内容区的高度

            注意:返回的数值都不带单位

            offset 与 style 区别

            offset:想要获取元素大小位置,用offset更合适

            style:想要给元素更改值,则需要用style改变

            获取鼠标在盒子内的坐标

            1. 我们在盒子内点击,想要得到鼠标距离盒子左右的距离。
            2. 首先得到鼠标在页面中的坐标(e.pageX, e.pageY)
            3. 其次得到盒子在页面中的距离 ( box.offsetLeft, box.offsetTop)
            4. 用鼠标距离页面的坐标减去盒子在页面中的距离,得到 鼠标在盒子内的坐标
            5. 如果想要移动一下鼠标,就要获取最新的坐标,使用鼠标移动
            var box = document.querySelector('.box');
            box.addEventListener('mousemove', function(e) {
            var x = e.pageX - this.offsetLeft;
            var y = e.pageY - this.offsetTop;
            this.innerHTML = 'x坐标是' + x + ' y坐标是' + y;
            })
            

            5.元素可视区 client 、元素滚动 scroll、动画函数封装

            client

            通过 client系列的相关属性可以动态的得到该元素的边框大小、元素大小等

            client系列属性 作用
            element.clientTop 返回元素上边框的大小
            element.clientLeft 返回元素左边框的大小
            element.clientWidth 返回自身包括padding、内容区的宽度,不含边框,返回数值不带单位
            element.clientHeight 返回自身包括padding、内容区的高度,不含边框,返回数值不带单位

            立即执行函数

            1. (function(){})()
            2. (function(){}())

            创建一个独立的作用域,避免了命名冲突问题

            pageshow

            • 这个事件在页面显示时触发,无论页面是否来自缓存。
            • 在重新加载页面中,pageshow会在load事件触发后触发;
            • 根据事件对象中的persisted来判断是否是缓存中的页面触发的pageshow事件
            • persisted:判断页面是否来自缓存,如果是返回true,如果不是返回false
            • 注意这个事件给window添加

            元素滚动 scroll

            scroll系列属性 作用
            element.scrollTop 返回被卷去的上侧距离
            element.scrollLeft 返回被卷去的左侧距离
            element.scrollWidth 返回自身实际的宽度,不含边框
            element.scrollHeight 返回自身实际的高度,不含边框

            返回数值均不带单位

            • 当滚动条向下滚动时,页面上面被隐藏掉的高度,我们就称为页面被卷去的头部。
            • 滚动条在滚动时会触发 onscroll事件

            页面被卷去的头部

            可以通过window.pageYOffset 获得 如果是被卷去的左侧window.pageXOffset

            注意,元素被卷去的头部是element.scrollTop , 如果是页面被卷去的头部 则是 window.pageYOffset

            页面被卷去的头部兼容性解决方案

            需要注意的是,获取页面被卷去的头部高度,有兼容性问题,因此通常有如下几种写法:

            1. 声明了 DTD,使用 document.documentElement.scrollTop
            2. 未声明 DTD,使用 document.body.scrollTop
            3. 新方法 window.pageYOffset和 window.pageXOffset,IE9 开始支持
            function getScroll() {
                return {
                  left: window.pageXOffset || document.documentElement.scrollLeft || document.body.scrollLeft||0,
                  top: window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop || 0
                };
             } 
            //使用的时候  getScroll().left
            

            mouseenter 和mouseover的区别

            mouseover 鼠标经过自身盒子会触发,经过子盒子还会触发。mouseenter 只会经过自身盒子触发,因为mouseenter不会冒泡。

            跟mouseenter搭配鼠标离开 mouseleave 同样不会冒泡

            简单动画函数封装

            function animate(obj目标对象, target目标位置){…}

            给不同元素记录不同定时器

            核心原理:利用 JS 是一门动态语言,可以很方便的给当前对象添加属性。

             function animate(obj, target) {
                        // 当我们不断的点击按钮,这个元素的速度会越来越快,因为开启了太多的定时器
                        // 解决方案就是 让我们元素只有一个定时器执行
                        // 先清除以前的定时器,只保留当前的一个定时器执行
                        clearInterval(obj.timer);
                        obj.timer = setInterval(function() {
                            if (obj.offsetLeft >= target) {
                                // 停止动画 本质是停止定时器
                                clearInterval(obj.timer);
                            }
                            obj.style.left = obj.offsetLeft + 1 + 'px';
            
                        }, 30);
                    }
            

            动画函数多个目标值之间移动

            <script>
                    // 缓动动画函数封装obj目标对象 target 目标位置
                    // 思路:
                    // 1. 让盒子每次移动的距离慢慢变小, 速度就会慢慢落下来。
                    // 2. 核心算法:(目标值 - 现在的位置) / 10 做为每次移动的距离 步长
                    // 3. 停止的条件是: 让当前盒子位置等于目标位置就停止定时器
                    function animate(obj, target) {
                        // 先清除以前的定时器,只保留当前的一个定时器执行
                        clearInterval(obj.timer);
                        obj.timer = setInterval(function () {
                            // 步长值写到定时器的里面
                            // 把我们步长值改为整数 不要出现小数的问题
                            // var step = Math.ceil((target - obj.offsetLeft) / 10);
                            var step = (target - obj.offsetLeft) / 10;
                            step = step > 0 ? Math.ceil(step) : Math.floor(step);
                            if (obj.offsetLeft == target) {
                                // 停止动画 本质是停止定时器
                                clearInterval(obj.timer);
                            }
                            // 把每次加1 这个步长值改为一个慢慢变小的值  步长公式:(目标值 - 现在的位置) / 10
                            obj.style.left = obj.offsetLeft + step + 'px';
            
                        }, 15);
                    }
                    var span = document.querySelector('span');
                    var btn500 = document.querySelector('.btn500');
                    var btn800 = document.querySelector('.btn800');
            
                    btn500.addEventListener('click', function () {
                        // 调用函数
                        animate(span, 500);
                    })
                    btn800.addEventListener('click', function () {
                        // 调用函数
                        animate(span, 800);
                    })
                        // 匀速动画 就是 盒子是当前的位置 +  固定的值 10 
                        // 缓动动画就是  盒子当前的位置 + 变化的值(目标值 - 现在的位置) / 10)
                </script>
            

            动画完整版代码

             <script>
                    // 缓动动画函数封装obj目标对象 target 目标位置
                    // 思路:
                    // 1. 让盒子每次移动的距离慢慢变小, 速度就会慢慢落下来。
                    // 2. 核心算法:(目标值 - 现在的位置) / 10 做为每次移动的距离 步长
                    // 3. 停止的条件是: 让当前盒子位置等于目标位置就停止定时器
                    function animate(obj, target, callback) {
                        // console.log(callback);  callback = function() {}  调用的时候 callback()
            
                        // 先清除以前的定时器,只保留当前的一个定时器执行
                        clearInterval(obj.timer);
                        obj.timer = setInterval(function () {
                            // 步长值写到定时器的里面
                            // 把我们步长值改为整数 不要出现小数的问题
                            // var step = Math.ceil((target - obj.offsetLeft) / 10);
                            var step = (target - obj.offsetLeft) / 10;
                            step = step > 0 ? Math.ceil(step) : Math.floor(step);
                            if (obj.offsetLeft == target) {
                                // 停止动画 本质是停止定时器
                                clearInterval(obj.timer);
                                // 回调函数写到定时器结束里面
                                if (callback) {
                                    // 调用函数
                                    callback();
                                }
                            }
                            // 把每次加1 这个步长值改为一个慢慢变小的值  步长公式:(目标值 - 现在的位置) / 10
                            obj.style.left = obj.offsetLeft + step + 'px';
            
                        }, 15);
                    }
                    var span = document.querySelector('span');
                    var btn500 = document.querySelector('.btn500');
                    var btn800 = document.querySelector('.btn800');
            
                    btn500.addEventListener('click', function () {
                        // 调用函数
                        animate(span, 500);
                    })
                    btn800.addEventListener('click', function () {
                        // 调用函数
                        animate(span, 800, function () {
                            // alert('你好吗');
                            span.style.backgroundColor = 'red';
                        });
                    })
                        // 匀速动画 就是 盒子是当前的位置 +  固定的值 10 
                        // 缓动动画就是  盒子当前的位置 + 变化的值(目标值 - 现在的位置) / 10)
                </script>
            

            节流阀

            当上一个函数动画内容执行完毕,再去执行下一个函数动画,让事件无法连续触发,利用回调函数,添加一个变量来控制,锁住函数和解锁函数

            1. 开始设置一个变量var flag= true;
            2. If(flag){flag = false; do something} 关闭水龙头
            3. 利用回调函数动画执行完毕, flag = true 打开水龙头

            返回顶部

            1. 页面滚动了多少,可以通过 window.pageYOffset 得到
            2. 最后是页面滚动,使用 window.scroll(x,y) 不带单位 直接写数字

            6.移动端和插件的使用、本地存储

            常见的触屏事件

            触屏touch事件 说明
            touchstart 手指触摸到一个DOM元素时触发
            touchmove 手指在一个DOM元素上滑动时触发
            touchend 手指从一个DOM元素上移开时触发

            触摸事件对象(TouchEvent)

            TouchEvent 是一类描述手指在触摸平面(触摸屏、触摸板等)的状态变化的事件。这类事件用于描述一个或多个触点,使开发者可以检测触点的移动,触点的增加和减少,等等

            触摸列表 说明
            touches 正在触摸屏幕的所有手指的一个列表
            targetTouches 正在触摸当前DOM元素上的手指的一个列表
            changedTouches 手指状态发生了改变的列表,从无到有,从有到无的变化

            因为平时我们都是给元素注册触摸事件,所以重点记住 targetTocuhes

            移动端拖动元素

             <script>
                    // (1) 触摸元素 touchstart:  获取手指初始坐标,同时获得盒子原来的位置
                    // (2) 移动手指 touchmove:  计算手指的滑动距离,并且移动盒子
                    // (3) 离开手指 touchend:
                    var div = document.querySelector('div');
                    var startX = 0; //获取手指初始坐标
                    var startY = 0;
                    var x = 0; //获得盒子原来的位置
                    var y = 0;
                    div.addEventListener('touchstart', function(e) {
                        //  获取手指初始坐标
                        startX = e.targetTouches[0].pageX;
                        startY = e.targetTouches[0].pageY;
                        x = this.offsetLeft;
                        y = this.offsetTop;
                    });
            
                    div.addEventListener('touchmove', function(e) {
                        //  计算手指的移动距离: 手指移动之后的坐标减去手指初始的坐标
                        var moveX = e.targetTouches[0].pageX - startX;
                        var moveY = e.targetTouches[0].pageY - startY;
                        // 移动我们的盒子 盒子原来的位置 + 手指移动的距离
                        this.style.left = x + moveX + 'px';
                        this.style.top = y + moveY + 'px';
                        e.preventDefault(); // 阻止屏幕滚动的默认行为
                        //如果不阻止,当粉色盒子滚出界面之后会出现滚动条
                    });
                </script>
            

            注意: 手指移动也会触发滚动屏幕所以这里要阻止默认的屏幕滚动 e.preventDefault();

            transitionend

            监听过渡完成的事件对象

            语法: element.addEventListener(‘transitionend’,函数);

            classList 属性

            返回元素的类名。但是ie10以上版本支持

            添加类:

            element.classList.add(’类名’);

            focus.classList.add('current');
            

            移除类:

            element.classList.remove(’类名’);

            focus.classList.remove('current');
            例:ol.querySelector('.sty').classList.remove('sty');
            

            切换类:

            element.classList.toggle(’类名’); 有这个类名则移除,没有则添加

            focus.classList.toggle('current');
            

            注意:以上方法里面,所有类名都不带点

            click 延时解决方案

            移动端 click 事件会有 300ms 的延时,原因是移动端屏幕双击会缩放(double tap to zoom) 页面。

            解决方案:

            ​ 1. 禁用缩放: 浏览器禁用默认的双击缩放行为并且去掉300ms 的点击延迟。

              <meta name="viewport" content="user-scalable=no">
            

            ​ 2.利用touch事件自己封装这个事件解决300ms 延迟。

            ​ 原理就是:

            ​ 当我们手指触摸屏幕,记录当前触摸时间

            ​ 当我们手指离开屏幕, 用离开的时间减去触摸的时间

            ​ 如果时间小于150ms,并且没有滑动过屏幕, 那么我们就定义为点击

            代码如下:

            //封装tap,解决click 300ms 延时
            function tap (obj, callback) {
                    var isMove = false;
                    var startTime = 0; // 记录触摸时候的时间变量
                    obj.addEventListener('touchstart', function (e) {
                        startTime = Date.now(); // 记录触摸时间
                    });
                    obj.addEventListener('touchmove', function (e) {
                        isMove = true;  // 看看是否有滑动,有滑动算拖拽,不算点击
                    });
                    obj.addEventListener('touchend', function (e) {
                        if (!isMove && (Date.now() - startTime) < 150) {  // 如果手指触摸和离开时间小于150ms 算点击
                            callback && callback(); // 执行回调函数
                        }
                        isMove = false;  //  取反 重置
                        startTime = 0;
                    });
            }
            //调用  
              tap(div, function(){   // 执行代码  });
            

            ​ 3.使用插件:fastclick 插件解决300ms 延迟

              
              
            

            Swiper 插件

            中文官网地址: https://www.swiper.com.cn/

            其他移动端常见插件

            lsuperslide: http://www.superslide2.com/

            l iscroll: https://github.com/cubiq/iscroll

            ​ 1.打开demo实例文件,查看需要引入的相关文件,并且引入

            ​ 2.复制demo实例文件中的结构html,样式css以及js代码

            移动端视频插件

            zy.media.js

            Bootstrap

            Bootstrap JS插件使用步骤:

            1.引入相关js 文件

            2.复制HTML 结构

            3.修改对应样式

            4.修改相应JS 参数

            本地存储

            1、容量较大,sessionStorage约5M、localStorage约20M

            2、只能存储字符串,可以将对象JSON.stringify() 编码后存储

            window.sessionStorage (session:会话)

            1、生命周期为关闭浏览器窗口

            2、在同一个窗口(页面)下数据可以共享

            3、以键值对的形式存储使用

            存储数据:

            sessionStorage.setItem('key', 存的内容)
            

            获取数据:

            sessionStorage.getItem('key')
            

            删除数据:

            sessionStorage.removeItem('key')
            

            清空数据:(所有都清除掉)

            sessionStorage.clear()
            

            window.localStorage

            1、声明周期永久生效,除非手动删除 否则关闭页面也会存在

            2、可以多窗口(页面)共享(同一浏览器可以共享)

            3、以键值对的形式存储使用

            存储数据:

            localStorage.setItem('key', value)
            

            获取数据:

            localStorage.getItem('key')
            

            删除数据:

            localStorage.removeItem('key')
            

            清空数据:(所有都清除掉)

            localStorage.clear()
            

            change事件

            当选框发生改变的时候可以使用change事件

            六.jQuery

            1.选择器、样式操作、效果

            jQuery 对象本质是: 利用$对DOM 对象包装后产生的对象(伪数组形式存储)

            注意:

            只有 jQuery 对象才能使用 jQuery 方法,DOM 对象则使用原生的 JavaScirpt 方法。

            jQuery 的下载**

            jQuery的官网地址: https://jquery.com/,官网即可下载最新版本。

            各个版本的下载:https://code.jquery.com/

            jQuery的入口函数

            ​ jQuery中常见的两种入口函数:

            // 第一种: 简单易用。
            $(function () {   
                ...  // 此处是页面 DOM 加载完成的入口
            }) ; 
            
            // 第二种: 繁琐,但是也可以实现
            $(document).ready(function(){
               ...  //  此处是页面DOM加载完成的入口
            });
            

            相当于原生 js 中的 DOMContentLoaded

            jQuery 对象和 DOM 对象转换

            // 1.DOM对象转换成jQuery对象,方法只有一种
            var box = document.getElementById('box');  // 获取DOM对象
            var jQueryObject = $(box);  // 把DOM对象转换为 jQuery 对象
            
            // 2.jQuery 对象转换为 DOM 对象有两种方法:
            //   2.1 jQuery对象[索引值]
            var domObject1 = $('div')[0]
            
            //   2.2 jQuery对象.get(索引值)
            var domObject2 = $('div').get(0)
             
            

            总结:实际开发比较常用的是把DOM对象转换为jQuery对象

            jQuery 选择器

            $("选择器")   //  里面选择器直接写 CSS 选择器即可,但是要加引号 和CSS选择器写法一致
            

            筛选选择器

            语法 用法 描述
            :first $(‘li:first’) 获取第一个li元素
            :last $(‘li:last’) 获取最后一个li元素
            :eq(index) $(‘li:eq(2)’) 获取li元素中索引号为2的元素,index从0开始
            :odd $(‘li:odd’) 获取li元素中索引号为奇数的元素
            :even $(‘li:even’) 获取li元素中索引号为偶数的元素

            筛选方法

            语法 用法 说明
            parent() $(‘li’).parent(); 查找父级
            children(‘选择器’) $(“ul”).children(“li”); 查找最近一级的亲儿子 相当于$(“ul>li”)
            find(‘选择器’) $(“ul”).find(“li”); 相当于$(“ul li”) 和后代选择器一样
            siblings(‘选择器’) $(".first").siblings(“li”); 查找兄弟节点,不包括自身
            nextAll([expr]) $(".first").nextAll(); 查找当前元素之后所有的兄弟元素
            prevAll([expr]) $(".first").prevAll(); 查找当前元素之前所有的兄弟元素
            hasClass(class) $(“div”).hasClass("protected"0; 检查当前的元素是否含有某个特定的类,如果有 返回true
            eq(index) $(“li”).eq(2); 相当于$(‘li:eq(2)’),index是从0开始的

            jQuery样式操作

            排他思想

            // 想要多选一的效果,排他思想:当前元素设置样式,其余的兄弟元素清除样式。
            $(this).css(“color”,”red”);
            $(this).siblings().css(“color”,””);
            

            隐式迭代

            // 遍历内部 DOM 元素(伪数组形式存储)的过程就叫做隐式迭代。
            // 简单理解:给匹配到的所有元素进行循环遍历,执行相应的方法,而不用我们再进行循环,简化我们的操作,方便我们调用。
            $('div').hide();  // 页面中所有的div全部隐藏,不用循环操作
            
            
            // 以前的js是不允许对于一组对象之间操作的,只能对一个元素对象进行操作
            var divs = document.getElementsByTagName('div');
            divs.style.backgroundColor = 'red'; // 错误
            divs[0].style.backgroundColor = 'red'; // 正确
            

            链式编程

            // 链式编程是为了节省代码量,看起来更优雅。
            //原代码
            $(this).css('color', 'red');
            $(this).sibling().css('color', ''); 
            //链式编程的代码
            $(this).css('color', 'red').sibling().css('color', ''); 
            
            //jq的操作方法: css(),hide(),show()等等,会将调用者返回
            //jq的筛选方法,会将筛选完的对象返回。 非筛选方法(操作方法),会将调用者(jq对象)返回
            

            jQuery 得到当前元素索引号

            $(this).index();

            jQuery弹窗(类似alert)

            var isC = confirm('您确定要退出吗') //点击后返回布尔值

            jQuery操作 css 方法

            // 1.参数只写属性名,则是返回属性值
            var strColor = $(this).css('color');
            
            // 2.  参数是属性名,属性值,逗号分隔,是设置一组样式,属性必须加引号,值如果是数字可以不用跟单位和引号
            $(this).css('color'', 'red');
            
            // 3.  参数可以是对象形式,方便设置多组样式。属性名和属性值用冒号隔开, 属性可以不用加引号
            $(this).css({ "color":"white","font-size":"20px"});
            

            jQuery设置类样式

            // 1.添加类
            $("div").addClass("current");  // className,classList
            
            // 2.删除类
            $("div").removeClass("current");
            
            // 3.切换类  没有就添上  有就移除
            $("div").toggleClass("current");
            

            原生 JS 中 className 会覆盖元素原先里面的类名,jQuery 里面类操作只是对指定类进行操作,不影响原先的类名

            jQuery 效果

            显示、隐藏、二者切换

            显示

            语法: show( [ speed ,[easing],[fn] ] ) 参数都可以省略

            1.speed: 按照某种速度显示,默认normal,还有slow、fast,要带引号,也可直接设置毫秒数(不带单位)

            2.easing: 用来指定切换效果,默认swing,还有linear,要带引号

            3.fn: 回调函数,在动画完成时执行的函数,每个元素执行一次

            隐藏

            语法: hide( [ speed ,[easing],[fn] ] ) 参数都可以省略

            1.speed: 按照某种速度显示,默认normal,还有slow、fast,要带引号,也可直接设置毫秒数(不带单位)

            2.easing: 用来指定切换效果,默认swing,还有linear,要带引号

            3.fn: 回调函数,在动画完成时执行的函数,每个元素执行一次

            切换

            语法: toggle( [ speed ,[easing],[fn] ] ) 参数都可以省略

            1.speed: 按照某种速度显示,默认normal,还有slow、fast,要带引号,也可直接设置毫秒数(不带单位)

            2.easing: 用来指定切换效果,默认swing,还有linear,要带引号

            3.fn: 回调函数,在动画完成时执行的函数,每个元素执行一次

            滑动

            下拉滑动

            语法: slideDown( [ speed ,[easing],[fn] ] ) 参数都可以省略

            1.speed: 按照某种速度显示,默认normal,还有slow、fast,要带引号,也可直接设置毫秒数(不带单位)

            2.easing: 用来指定切换效果,默认swing,还有linear,要带引号

            3.fn: 回调函数,在动画完成时执行的函数,每个元素执行一次

            上拉滑动

            语法: slideUp( [ speed ,[easing],[fn] ] ) 参数都可以省略

            1.speed: 按照某种速度显示,默认normal,还有slow、fast,要带引号,也可直接设置毫秒数(不带单位)

            2.easing: 用来指定切换效果,默认swing,还有linear,要带引号

            3.fn: 回调函数,在动画完成时执行的函数,每个元素执行一次

            滑动切换

            语法: slideToggle( [ speed ,[easing],[fn] ] ) 参数都可以省略

            1.speed: 按照某种速度显示,默认normal,还有slow、fast,要带引号,也可直接设置毫秒数(不带单位)

            2.easing: 用来指定切换效果,默认swing,还有linear,要带引号

            3.fn: 回调函数,在动画完成时执行的函数,每个元素执行一次

            淡入淡出 (透明度动画)

            淡入

            语法: fadeIn( [ speed ,[easing],[fn] ] ) 参数都可以省略

            1.speed: 按照某种速度显示,默认normal,还有slow、fast,要带引号,也可直接设置毫秒数(不带单位)

            2.easing: 用来指定切换效果,默认swing,还有linear,要带引号

            3.fn: 回调函数,在动画完成时执行的函数,每个元素执行一次

            淡出

            语法: fadeOut( [ speed ,[easing],[fn] ] ) 参数都可以省略

            1.speed: 按照某种速度显示,默认normal,还有slow、fast,要带引号,也可直接设置毫秒数(不带单位)

            2.easing: 用来指定切换效果,默认swing,还有linear,要带引号

            3.fn: 回调函数,在动画完成时执行的函数,每个元素执行一次

            淡入淡出切换

            语法: fadeToggle( [ speed ,[easing],[fn] ] ) 参数都可以省略

            1.speed: 按照某种速度显示,默认normal,还有slow、fast,要带引号,也可直接设置毫秒数(不带单位)

            2.easing: 用来指定切换效果,默认swing,还有linear,要带引号

            3.fn: 回调函数,在动画完成时执行的函数,每个元素执行一次

            修改透明度

            语法: fadeTo( [ speed , opacity ,[easing],[fn] ] ) 参数都可以省略

            1. opacity 透明度,必须写,取值0~1之间
            2. speed: 必须写 按照某种速度显示,默认normal,还有slow、fast,要带引号,也可直接设置毫秒数(不带单位)
            3. easing: 用来指定切换效果,默认swing,还有linear,要带引号
            4. fn: 回调函数,在动画完成时执行的函数,每个元素执行一次
            <body>
                <button>淡入效果</button>
                <button>淡出效果</button>
                <button>淡入淡出切换</button>
                <button>修改透明度</button>
                <div></div>
                <script>
                    $(function() {
                        $("button").eq(0).click(function() {
                            // 淡入 fadeIn()
                            $("div").fadeIn(1000);
                        })
                        $("button").eq(1).click(function() {
                            // 淡出 fadeOut()
                            $("div").fadeOut(1000);
                        })
                        $("button").eq(2).click(function() {
                            // 淡入淡出切换 fadeToggle()
                            $("div").fadeToggle(1000);
                        });
                        $("button").eq(3).click(function() {
                            //  修改透明度 fadeTo() 这个速度和透明度要必须写
                            $("div").fadeTo(1000, 0.5);
                        });
                    });
                </script>
            </body>
            

            自定义动画

            语法:animate( params, [speed ] , [easing] , [fn] )

            1.params:想要改变的样式属性,以对象形式传递,必须写

            2.speed: 按照某种速度显示,默认normal,还有slow、fast,要带引号,也可直接设置毫秒数(不带单位)

            3.easing: 用来指定切换效果,默认swing,还有linear,要带引号

            4.fn: 回调函数,在动画完成时执行的函数,每个元素执行一次

            <body>
                <button>动起来</button>
                <div></div>
                <script>
                    $(function() {
                        $("button").click(function() {
                            $("div").animate({
                                left: 500,
                                top: 300,
                                opacity: .4,
                                width: 500
                            }, 500);
                        })
                    })
                </script>
            </body>
            

            停止动画排队

            动画或者效果一旦触发就会执行,如果多次触发,就造成多个动画或者效果排队执行

            停止动画排队的方法为:stop() ;

            • stop() 方法用于停止动画或效果。
            • stop() 写到动画或者效果的前面, 相当于停止结束上一次的动画。

            总结: 每次使用动画之前,先调用 stop() ,在调用动画。

            事件切换

            hover([over,]out)     // 其中over和out为两个函数
            
            • over:鼠标移到元素上要触发的函数(相当于mouseenter)
            • out:鼠标移出元素要触发的函数(相当于mouseleave)
            • 如果只写一个函数,则鼠标经过和离开都会触发它

            2.属性、元素、尺寸、位置操作

            jQuery 属性操作

            获取和设置元素固有属性值 prop()

            1.获取元素固有属性: element.prop(‘属性名’);

            2.设置元素固有属性: element.prop(‘属性名’,‘属性值’);

            ​ 注意:prop() 除了普通属性操作,更适合操作表单属性:disabled / checked / selected 等。

            获取和设置元素自定义属性值 attr()

            1.获取元素自定义属性: element.attr(‘属性名’);

            2.设置元素自定义属性: element.attr(‘属性名’,‘属性值’);

            数据缓存 data()

            1.获取数据缓存: element.date(‘数据名’);

            2.设置数据缓存: element.date(‘数据名’,‘数据值’);

            选择器 :checked

            例:console.log($(".j-checkbox:checked").length);

            jQuery 文本属性值

            常见操作有三种:html() / text() / val() ; 分别对应JS中的 innerHTML 、innerText 和 value 属性

            普通元素内容html()

            1.html() //获取元素内容

            2.html(‘内容’) //设置元素内容

            普通元素文本内容text()

            1.text() //获取元素的文本内容

            2.text(‘内容’) //设置元素的文本内容

            表单的值val()

            1.val() //获取表单的值

            2.val(‘内容’) //设置表单的值

            注意:html() 可识别标签,text() 不识别标签

            选择器parents

            parents(‘选择器’) 可以返回指定祖先元素

            保留几位小数

            num.toFixed(位数)

            jQuery 元素操作

            遍历元素

            1. $(‘选择器’).each(function ( index , ele ) {…;} ) index是索引号,ele是每个DOM元素对象
            2. $.each( object , function ( index , ele ) { …; } )

            ​注意:此方法用于遍历 jQuery 对象中的每一项,回调函数中元素为 DOM 对象,想要使用 jQuery 方法需要转换。

            演示代码

            <body>
                <div>1</div>
                <div>2</div>
                <div>3</div>
                <script>
                    $(function() {
                        // 如果针对于同一类元素做不同操作,需要用到遍历元素(类似for,但是比for强大)
                        var sum = 0;
                        var arr = ["red", "green", "blue"];
                        // 1. each() 方法遍历元素 
                        $("div").each(function(i, domEle) {
                            // 回调函数第一个参数一定是索引号  可以自己指定索引号号名称
                            // console.log(i);
                            // 回调函数第二个参数一定是 dom 元素对象,也是自己命名
                            // console.log(domEle);  // 使用jQuery方法需要转换 $(domEle)
                            $(domEle).css("color", arr[i]);
                            sum += parseInt($(domEle).text());
                        })
                        console.log(sum);
                        // 2. $.each() 方法遍历元素 主要用于遍历数据,处理数据
                        // $.each($("div"), function(i, ele) {
                        //     console.log(i);
                        //     console.log(ele);
                        // });
                        // $.each(arr, function(i, ele) {
                        //     console.log(i);
                        //     console.log(ele);
                        // })
                        $.each({
                            name: "andy",
                            age: 18
                        }, function(i, ele) {
                            console.log(i); // 输出的是 name age 属性名
                            console.log(ele); // 输出的是 andy  18 属性值
                        })
                    })
                </script>
            </body>
            

            创建、添加、删除

            1.创建

            $(’

          7. ')

            2.内部添加

            element.append(’ 内容 ') 把内容放入匹配元素内部最后面,类似于appendChild

            element.prepend(’ 内容 ') 把内容放入匹配元素内部最前面,类似于

            3.外部添加

            element.after(’ 内容 ') //把内容放入目标元素后面

            element.before(’ 内容 ') //把内容放入目标元素前面

            4.删除

            element.remove() //删除匹配的元素(自身)

            element.empty() //删除匹配的元素集合中所有的子节点

            element.html(’’) //清空匹配的元素内容

            jQuery 尺寸、位置操作

            尺寸操作

            语法 用法
            width()/height() 取得匹配元素宽度或高度,只算width/height
            innerWidth()/innerHeight() 取得匹配元素宽度或高度,包含padding
            outWidth()/outHeight() 取得匹配元素宽度或高度,包含paddin、border
            outWidth(true)/outHeight(true) 取得匹配元素宽度或高度,包含paddin、border、margin

            如果参数为数字,则是修改相应值

            jQuery 位置操作

            jQuery的位置操作主要有三个: offset()、position()、scrollTop()/scrollLeft()

            1.offset()设置或获取元素偏移

            和父亲没有关系,是相对于文档的偏移坐标

            该方法有2个属性left、top。offset().top/left 用于获取距离文档顶部/左侧的距离

            可以设置元素的偏移: offset( { top:10,left:10 } )

            2.position()获取元素偏移

            和父亲有关系,是相对于父亲的偏移坐标,如果父亲都没有定位,则以文档为准

            该方法有2个属性left、top。offset().top/left 用于获取距离文档顶部/左侧的距离

            该方法只能获取数据,不可以进行设置

            3.scrollTop()/scrollLeft()设置或获取元素被卷去的头部或左侧

            不加参数是获取,加参数则是设置被卷去的头部,参数不带单位

            代码演示

            <body>
                <div class="father">
                    <div class="son"></div>
                </div>
                    
                <div class="back">返回顶部</div>
                <div class="container"></div>
               
                <script>
                    $(function() {
                        // 1. 获取设置距离文档的位置(偏移) offset
                        console.log($(".son").offset());
                        console.log($(".son").offset().top);
                        // $(".son").offset({
                        //     top: 200,
                        //     left: 200
                        // });
                  
                        // 2. 获取距离带有定位父级位置(偏移) position   如果没有带有定位的父级,则以文档为准
                        // 这个方法只能获取不能设置偏移
                        console.log($(".son").position());
                        // $(".son").position({
                        //     top: 200,
                        //     left: 200
                        // });
                  
                  		// 3. 被卷去的头部
                  		$(document).scrollTop(100);
                        // 被卷去的头部 scrollTop()  / 被卷去的左侧 scrollLeft()
                        // 页面滚动事件
                        var boxTop = $(".container").offset().top;
                        $(window).scroll(function() {
                            // console.log(11);
                            console.log($(document).scrollTop());
                            if ($(document).scrollTop() >= boxTop) {
                                $(".back").fadeIn();
                            } else {
                                $(".back").fadeOut();
                            }
                        });
                        // 返回顶部
                        $(".back").click(function() {
                            // $(document).scrollTop(0);
                            $("body, html").stop().animate({
                                scrollTop: 0
                            });
                            // $(document).stop().animate({
                            //     scrollTop: 0
                            // }); 不能是文档而是 html和body元素做动画
                        })
                    })
                </script>
            </body>
            

            页面滚动事件

            $(window).scroll( function () {…} )

            3.事件、插件

            jQuery 事件处理

            on() 绑定事件

            语法: element.on( ‘事件类型’, ’ 元素的子元素选择器 ’ , fn(){…} );

            1.可绑定多个事件

            例:

            $(' 选择器').on( { 
            	click : function () {},
            	mouseover: function () {},
            	.......  });
            

            2.可以进行事件委派操作,把需要加给子元素身上的事件绑定在父元素身上

            $(' ul').on( 'click','li',function () { ...... }  );
            

            3.动态创建的元素,用click()这种没法绑定事件,on()可以给动态生成的元素绑定事件,通过事件委托绑定的事件,可以对未来元素生效

            off() 解绑事件

            off()方法可以移除通过on()方法添加的事件

            1.$(’ p ').off() //解绑p元素所有事件

            2.$(’ p ‘).off(’ click ') //解绑p元素上面的点击事件

            3.$(’ ul ‘).off(’ click ‘,’ li’) //解绑事件委托

            只触发一次的事件

            element.one();

            trigger() 自动触发事件

            1.element.click()

            2.element.trigger(‘事件类型’)

            3.element.triggerHandler(‘事件类型’) //这一种不会触发元素的默认行为 而上面的会

            jQuery 事件对象

            element.on( ‘事件类型’, ’ 元素的子元素选择器 ’ , fn( e ){…} );

            阻止默认行为:e.preventDefault()或者return false

            阻止冒泡:e.stopPropagation()

            jQuery 插件

            jQuery 插件常用的网站:

            1. jQuery 插件库 http://www.jq22.com/
            2. jQuery 之家 http://www.htmleaf.com/

            插件的使用三点: 1. 引入css. 2.引入JS 3.引入html。 (有的简单插件只需引入html和js,甚至有的只需引入js)

            七.JS高级

            1.对象与类

            对象

            对象是由属性和方法组成的:是一个无序键值对的集合,指的是一个具体的事物

            属性:事物的特征,在对象中用属性来表示(常用名词)

            方法:事物的行为,在对象中用方法来表示(常用动词)

            类抽象了对象的公共部分,它泛指某一大类(class)对象特指某一个, 通过类实例化一个具体的对象

            创建类

            语法:
            class name{
            constructor( ){ ..... }
            .....
            }
            var 变量名 = new name();
            

            constructor构造函数

            可以接受传递过来的参数,同时返回实例对象 ,只要 new 生成实例时,就会自动调用这个函数, 如果我们不写这个 函数,类也会自动生成这个函数

            类创建添加属性和方法

             // 1. 创建类 class  创建一个 明星类
                    class Star {
                        // 类的共有属性放到 constructor 里面
                        constructor(uname, age) {
                            this.uname = uname;
                            this.age = age;
                        }
                        sing(song) {
                            // console.log('我唱歌');
                            console.log(this.uname + song);
            
                        }
                    }
            
                    // 2. 利用类创建对象 new
                    var ldh = new Star('刘德华', 18);
                    var zxy = new Star('张学友', 20);
                    console.log(ldh);
                    console.log(zxy);
                    // (1) 我们类里面所有的函数不需要写function 
                    //(2) 多个函数方法之间不需要添加逗号分隔
                    ldh.sing('冰雨');
                    zxy.sing('李香兰')
            

            类的继承

            class son extends father { … }

             // 1. 类的继承
                    // class Father {
                    //     constructor() {
            
                    //     }
                    //     money() {
                    //         console.log(100);
            
                    //     }
                    // }
                    // class Son extends Father {
            
                    // }
                    // var son = new Son();
                    // son.money();
                    class Father {
                        constructor(x, y) {
                            this.x = x;
                            this.y = y;
                        }
                        sum() {
                            console.log(this.x + this.y);
            
                        }
                    }
                    class Son extends Father {
                        constructor(x, y) {
                            super(x, y); //调用了父类中的构造函数
                        }
                    }
                    var son = new Son(1, 2);
                    var son1 = new Son(11, 22);
                    son.sum();
                    son1.sum();
            

            关键字super

            用于访问和调用对象父类上的函数,必须在子类this之前调用

             // super 关键字调用父类普通函数
                    class Father {
                        say() {
                            return '我是爸爸';
                        }
                    }
                    class Son extends Father {
                        say() {
                            // console.log('我是儿子');
                            console.log(super.say() + '的儿子');
                            // super.say() 就是调用父类中的普通函数 say()
                        }
                    }
                    var son = new Son();
                    son.say();
                    // 继承中的属性或者方法查找原则: 就近原则
                    // 1. 继承中,如果实例化子类输出一个方法,先看子类有没有这个方法,如果有就先执行子类的
                    // 2. 继承中,如果子类里面没有,就去查找父类有没有这个方法,如果有,就执行父类的这个方法(就近原则)
                    // 3.如果子类想要继承父类的方法,同时在自己内部扩展自己的方法,利用super 调用 父类的构造函数,super 必须在子类this之前调用
            

            this的指向

            1. constructor中的this指向的是new出来的实例对象
            2. 自定义的方法,一般也指向的new出来的实例对象
            3. 绑定事件之后this指向的就是触发事件的事件源

            insertAdjacentHTML( ‘position’ , text)

            可以直接把字符串格式添加到父元素中,和element.append(‘内容’)和element.prepend(‘内容’)类似

            position插入的位置:

            1.beforebegin: 元素自身前面 2.afterend: 元素自身后面

            3.afterbegin: 元素内部第一个子节点之前 4.beforeend: 元素内部最后一个子节点之后

            text: 插入的内容

            鼠标双击事件

            element.ondblclick 但双击会默认选中文字 解决方法插入下面代码:

             // 双击禁止选定文字
                 window.getSelection ? window.getSelection().removeAllRanges() : document.selection.empty();
            

            双击文本框让文字内容处于选中状态

            input.select();

            2.构造函数和原理、继承、新增方法

            构造函数和原型

            静态成员和实例成员

            实例成员 :构造函数内部通过this添加的成员

            静态成员:在构造函数本身上添加的成员 比如:构造函数名.静态成员名 = ’ 内容 ';

            ,静态成员只能 通过构造函数来访问 比如:构造函数名.静态成员名

            构造函数原型prototype

            构造函数通过原型分配的函数是所有对象所共享的,每一个构造函数都有一个prototype 属性,指向另一个对象。这个 prototype就是一个对象,这个对象的所有属性和方法,都会被构造函数所拥有

            可以把那些不变的方法,直接定义在 prototype 对象上,这样所有对象的实例就可 以共享这些方法

            对象原型

            对象都会有一个属性 _ _ proto _ _ 指向构造函数的 prototype 原型对象,之所以我们对象可以使用构造函数 prototype 原型对象的属性和方法,就是因为对象有 _ _ proto_ _ 原型的存在

            _ _ proto_ _对象原型和原型对象 prototype 是等价的

            _ _ proto_ _对象原型的意义就在于为对象的查找机制提供一个方向,或者说一条路线,但是 它是一个非标准属性,因此实际开发中,不可以使用这个属性,它只是内部指向原型对象 prototype

            constructor构造函数

            对象原型( _ _ proto_ _)和构造函数(prototype)原型对象里面都有一个属性 constructor 属性 ,constructor 我们称为构造函数,因为它指回构造函数本身。

            constructor 主要用于记录该对象引用于哪个构造函数,它可以让原型对象重新指向原来 的构造函数。

            一般情况下,对象的方法都在构造函数的原型对象中设置。如果有多个对象的方法,我们可 以给原型对象采取对象形式赋值,但是这样就会覆盖构造函数原型对象原来的内容,这样修 改后的原型对象 constructor 就不再指向当前构造函数了。此时,我们可以在修改后的 原型对象中,添加一个 constructor 指向原来的构造函数

            原型链

            ①ldh 对象实例 ——(ldh._ _ proto_ _ )——>

            ②Str原型对象 prototype ——(prototype. _ _ proto_ _ )——>

            ③ object原型对象prototype ——(prototype. _ _ proto_ _ )——>

            ④null

            构造函数实例和原型对象三角关系

            ①ldh 对象实例 ——(ldh._ _ proto_ _ )——>

            ②Str原型对象 prototype ——(star.prototype.constructor)——>

            ③构造函数 ——>①

            ③构造函数 ——( star.prototype )——> ② Str原型对象 prototype

            原型对象中this指向

            构造函数中的this和原型对象的this,都指向我们new出来的实例对象

            继承

            call()

            语法:函数名.call( thisArg, arg1 , arg2…)

            thisArg:当前调用函数this的指向对象

            arg1 , arg2…:传递的其他参数

            子构造函数继承父构造函数中的属性借用原型对象继承方法

             
            
            

            ES5新增方法

            forEach遍历数组

            arr.forEach(function(value, index, array) {
            //参数一是:数组元素
            //参数二是:数组元素的索引
            //参数三是:当前的整个数组  })
            //相当于数组遍历的 for循环 没有返回值
            

            filter过滤数组

            var arr = [1,2,3,4,5];
            arr.filter(function(value, index, array) {
            //参数一是:数组元素
            //参数二是:数组元素的索引
            //参数三是:当前的整个数组
              	return value <=2;
            })
            console.log(newArr);//[1,2] //返回值是一个新数组
            

            some查找数组

            some 查找数组中是否有满足条件的元素
            var arr = [10, 30, 4];
            var flag = arr.some(function(value,index,array) {
            //参数一是:数组元素
            //参数二是:数组元素的索引
            //参数三是:当前的整个数组
            	return value < 3;   }); 
            console.log(flag);//false返回值是布尔值,只要查找到满足条件的一个元素就立马终止循环
            

            some和forEach区别

            1.如果查询数组中唯一的元素, 用some方法更合适,在some 里面 遇到 return true 就 是终止遍历 迭代效率更高

            2.在forEach 里面 return 不会终止迭代

            去除字符串两端的空格

            str.trim()

            获取对象的属性名

            Object.keys(对象名) //获取到当前对象中的属性名 ,返回值是一个数组

            Object.defineProperty设置或修改对象中的属性

            Object.defineProperty(对象名,'修改或新增的属性名',{
            		value:修改或新增的属性的值,
            		writable:true/false,//如果值为false 不允许修改这个属性值          					enumerable: false,//enumerable 如果值为false 则不允许遍历                  configurable: false  //configurable 如果为false 则不允许删除这个属性  属性是否可以被删除或是否可以再次修改特性 }) 
            

            3.this、严格模式、高阶函数、闭包、递归、正则表达式

            函数内部的this指向

            调用方式 this指向
            普通函数调用 window
            构造函数调用 实例对象 原型对象里面的方法也指向实例对象
            对象方法调用 该方法所属对象
            事件绑定方法 绑定事件对象
            window
            window

            改变函数内部 this 指向

            1.call()方法

            语法:函数名.call( thisArg, arg1 , arg2…)

            thisArg:当前调用函数this的指向对象

            arg1 , arg2…:传递的其他参数

            2.apply()方法

            语法:fun.apply( thisArg, [argsArray] )

            thisArg: 在fun函数运行时指定的this值

            argsArray: 传递的值,为数组形式

            3.bind()方法

            语法:fun.bind( thisArg, arg1,arg2… ) //不会调用函数,但能改变函数内部this指向

            thisArg: 在fun函数运行时指定的this值

            arg1 , arg2…:传递的其他参数

            返回由指定的this值和初始化参数改造的原函数拷贝

            三者的异同

            共同点 : 都可以改变this指向

            不同点: 1.call 和 apply 会调用函数, 并且改变函数内部this指向;

            1. call 和 apply传递的参数不一样,call传递参数使用逗号隔开,apply使用数组传递
            2. 3.bind 不会调用函数, 可以改变函数内部this指向.

            开启严格模式

            在所有语句或者函数内部最前面添加 ’ use strict ';

            高阶函数

            高阶函数是对其他函数进行操作的函数,它接收函数作为参数或将函数作为返回值输出。

            闭包

            闭包(closure)指有权访问另一个函数作用域中变量的函数。简单理解就是 ,一个作 域可以访问另外一个函数内部的局部变量。

            代码示例:
              
            

            递归

            如果一个函数在内部可以调用其本身,那么这个函数就是递归函数。简单理解:函 数内部自己调用自己, 这个函数就是递归函数

            代码示例:
             
            

            正则表达式的创建

            var rg = /123/;
            

            正则表达式测试

            var rg = /123/; 
            console.log(rg.test(123));//匹配字符中是否出现123  出现结果为true console.log(rg.test('abc'));//匹配字符中是否出现123 未出现结果为false
            

            边界符

            1.^:表示匹配行首的文本(以谁开始)

            2.$:表示匹配行尾的文本(以谁结束)

            如果 ^和 $ 在一起,表示必须是精确匹配。

            var rg = /abc/; // 正则表达式里面不需要加引号 不管是数字型还是字符串型 
            // /abc/ 只要包含有abc这个字符串返回的都是true 
            console.log(rg.test('abc')); 
            console.log(rg.test('abcd')); 
            console.log(rg.test('aabcd')); 
            console.log('‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐'); 
            var reg = /^abc/; console.log(reg.test('abc')); // true console.log(reg.test('abcd')); // true
            console.log(reg.test('aabcd')); // false
            console.log('‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐');
            var reg1 = /^abc$/; // 精确匹配 要求必须是 abc字符串才符合规范 console.log(reg1.test('abc')); // true
            console.log(reg1.test('abcd')); // false
            console.log(reg1.test('aabcd')); // false
            console.log(reg1.test('abcabc')); // false
            

            字符类

            字符类表示有一系列字符可供选择,只要匹配其中一个就可以了。所有可供选择的字符 都放在方括号内。

            [ ]方括号

            表示有一系列字符可供选择,只要匹配其中一个就可以了

            var rg = /[abc]/; // 只要包含有a 或者 包含有b 或者包含有c 都返回为true console.log(rg.test('andy'));//true
            console.log(rg.test('baby'));//true
            console.log(rg.test('color'));//true
            console.log(rg.test('red'));//false
            var rg1 = /^[abc]$/; // 三选一 只有是a 或者是 b  或者是c 这三个字母才返回  true console.log(rg1.test('aa'));//false
            console.log(rg1.test('a'));//true
            console.log(rg1.test('b'));//true
            console.log(rg1.test('c'));//true
            console.log(rg1.test('abc'));//true ‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐var reg = /^[a‐z]$/ //26个英文字母任何一个字母返回 true  ‐ 表示的是a 到z 的范 围   console.log(reg.test('a'));//true
            console.log(reg.test('z'));//true
            console.log(reg.test('A'));//false ‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐
            //字符组合
            var reg1 = /^[a‐zA‐Z0‐9]$/; // 26个英文字母(大写和小写都可以)任何一个字母返回  true   ‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐
            //取反 方括号内部加上 ^ 表示取反,只要包含方括号内的字符,都返回 false 。 var reg2 = /^[^a‐zA‐Z0‐9]$/;
            console.log(reg2.test('a'));//false
            console.log(reg2.test('B'));//false
            console.log(reg2.test(8));//false
            console.log(reg2.test('!'));//true
            

            量词符

            量词 说明
            * 重复>=0次
            + 重复>=1次
            ? 重复0次或1次
            {n} 重复n次
            {n,} 重复>=n次
            {n,m} 重复n到m次

            预定义类

            预定类 说明
            \d 匹配0-9之间任一数字,相当于[0-9]
            \D 匹配所有0-9以外的字符,相当于[ ^0-9]
            \w 匹配任意的字母、数字和下划线, 相当于[A-Za-z0-9]
            \W 匹配所有字母、数字和下划线以外的字符, 相当于[ ^A-Za-z0-9]
            \s 匹配空格(包括换行符、制表符、空格符等),相当于[\t\r\n\v\f]
            \S 匹配非空格的字符,相当于[ ^\t\r\n\v\f]

            正则替换replace

            replace() 方法可以实现替换字符串操作,用来替换的参数可以是一个字符串或是一个正 则表达式

            stringObject.replace( / 表达式 / switch, replacement )

            表达式 :被替换的字符串或正则表达式

            switch:g–全局匹配; i–忽略大小写; gi–全局匹配+忽略大小写

            replacement:替换为的字符串

            返回值是一个替换完毕的新字符串

            4.ES6语法

            let

            1.使用let关键字声明的变量才具有块级作用域,使用var声明的变量不具备块级作用 域特性

            2.使用let关键字声明的变量没有变量提升,要先声明才能使用

            const

            用来声明常量,常量就是值(内存地址)不能变化的量

            1.具有块级作用域 ,声明 const时候必须要给定值

            2.如果是常量不能重新进行赋值,如果是基本数据类型,不能更改值,如果是复杂数据 类型,不能更改地址值

            解构赋值

            ES6中允许从数组中提取值,按照对应位置,对变量赋值,对象也可以实现解构

            1.解构赋值就是把数据结构分解,然后给变量进行赋值

            2.如果结构不成功,变量跟数值个数不匹配的时候,变量的值为undefined

            3.数组解构用中括号包裹,多个变量用逗号隔开,对象解构用花括号包裹,多个变量用 逗号隔开

            箭头函数

            () => {} //():代表是函数; =>:必须要的符号,指向哪一个代码块;{}:函数体
            const fn = () => {}//代表把一个函数赋值给fn
            

            1.函数体中只有一句代码,且代码的执行结果就是返回值,可以省略大括号

            2.如果形参只有一个,可以省略小括号

            3.箭头函数不绑定this关键字,箭头函数中的this,指向的是函数定义位置的上下文this

            剩余参数

            function sum (first, ...args) {
            	console.log(first); // 10      
            	console.log(args); // [20, 30]   
            }  
            sum(10, 20, 30);
            

            Array 的扩展方法

            扩展运算符 //扩展运算符可以将数组或者对象转为用逗号分隔的参数序列

            let ary = [1, 2, 3];
            ...ary  // 1, 2, 3
            console.log(...ary);    // 1 2 3,相当于下面的代码
            console.log(1,2,3)
            

            构造函数方法:Array.from()

            将伪数组或可遍历对象转换为真正的数组

            //定义一个集合
            let arrayLike = {
            	'0': 'a',    
            	'1': 'b',    
            	'2': 'c',    
            	length: 3 
            }; 
            //转成数组
            let arr2 = Array.from(arrayLike); // ['a', 'b', 'c']
            

            该方法还可以接受第二个参数,作用类似于数组的map方法,用来对每个元素进行处理, 将处理后的值放入返回的数组

            find()

            用于找出第一个符合条件的数组成员,如果没有找到返回undefined

            let ary = [{
            	id: 1,
            	name: '张三'
            }, {
            	id: 2,
            	name: '李四'
            }];
            let target = ary.find((item, index) => item.id == 2);//找数组里面符合条件 的值,当数组中元素id等于2的查找出来,注意,只会匹配第一个
            

            findIndex()

            用于找出第一个符合条件的数组成员的位置,如果没有找到返回-1

            let ary = [1, 5, 10, 15];
            let index = ary.findIndex((value, index) => value > 9);
            console.log(index); // 2
            

            includes()

            判断某个数组是否包含给定的值,返回布尔值。

            [1, 2, 3].includes(2) // true
            [1, 2, 3].includes(4) // false
            

            String 的扩展方法

            模板字符串 //用反引号

            let name = '张三';  let sayHello = `hello,my name is ${name}`; // hello, my name is zhangsan模板字符串中可以解析变量、换行、调用函数
            

            startsWith() 和 endsWith()

            表示参数字符串是否在原字符串的头部/尾部,返回布尔值

            repeat()

            repeat方法表示将原字符串重复n次,返回一个新字符串

            Set 数据结构

            类似于数组,但是成员的值都是唯一的,没有重复的值。

            const  常量名 = new Set();
            

            包含的方法:

            1.add(value):添加某个值,返回 Set 结构本身

            2.delete(value):删除某个值,返回一个布尔值,表示删除是否成功

            3.has(value):返回一个布尔值,表示该值是否为 Set 的成员

            4.clear():清除所有成员,没有返回值

            八.node

            Node环境 中的 Javascript

            node.js:Javascript的服务器端运行环境,可以让程序员使用Javacript来实现服务器端的编程,没有浏览器和HTML的概念,没有 BOM 和 DOM

            Node中的js组成:ECMAScript核心 + 全局成员 +核心API模块

            ​ 全局成员:console、setInterval、setTimeout…

            ​ 核心API模块:Node平台提供的一些API,是Node独有的

            node下载网站http://nodejs.cn/

            REPL环境

            打开任意终端,输入node并回车,就能进入

            按两次ctrl + c 退出REPL环境

            npm

            全局包

            1. **如何安装全局包:**运行 npm install 包名 -g 即可;其中 -g 参数,表示 把包安装到全局目录中的意思;
            2. 全局包的安装目录:`C:\Users\用户目录\AppData\Roaming\npm
            3. **如何卸载全局包:**要卸载某个全局的包,直接运行npm uninstall 包名 -g即可;其中 uninstall 表示卸载的意思;

            本地包

            1. **注意:**如果拿到一个空项目,必须在当前项目根目录中,先运行 npm init或者npm init -y 命令,初始化一个package.json的配置文件,否则包无法安装到本地项目中;
            2. **如何安装本地包:**运行npm i 包名 --save 即可安装本地包;都安装到了当前项目的 node_modules目录下;
              • 如果大家用的是npm 5.x的版本,可以不指定--save命令,如果用的是 npm 3.x 的版本,则需要手动指定 --save
            3. package-lock.json文件中记录了曾经装过的包的下载地址,方便下次直接下载包,能够加快装包的速度,提升装包的体验;
            4. **如何卸载本地包:**使用 npm uninstall/remove 包名 -S/-D即可卸载指定的本地包;

            其它常用命令

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

            解决 npm 下载慢问题

            1. 如何安装cnpm:运行 npm i cnpm -g 即可;
            2. 如何使用cnpm:在装包的时候,只需要把 npm 替换成 cnpm 即可,例如:
              • 使用 npm 安装 jquery:运行 npm i jquery -S
              • 使用 cnpm 安装 jquery: 运行 cnpm i jquery -S

            安装node_modules里的插件

            npm install --save

            1.fs文件、path路径、第三方模块、模块查找规则

            fs文件系统

            const fs = require(‘fs’); //导入fs文件操作模块

            文件读取

            fs.readFile( __dirname + '/文件路径'[, '编码格式默认为null'] , function(err对象,data读取成功的结果 ){ 
              if(err) return console.log(err.message);	//如果err为null 就证明读取成功了 如果为true 则失败
            console.log( data ); });
            
            

            文件写入

            fs.writeFile( __dirname + '/文件路径', 写入内容[, '编码格式默认为utf-8'] , function(err){
               if(err) return console.log(err.message); //如果文件写入失败则报错
              console.log( '文件写入成功' );
            } )  //要写入的文件不存在则直接写入,如果已经存在则会覆盖之前的文件
            

            文件内容追加

            fs.appendFile(__dirname + '/文件路径', 追加内容[, '编码格式默认为utf-8'] , function(err){
            if(err) return console.log(err.message); //如果文件内容追加失败则报错
              console.log( '文件内容追加成功' );
            })
            

            如果要追加的文件路径不存在,则会先创建这个文件,再向创建的文件中追加内容

            fs模块操作文件时路径问题

            解决方案:使用node中提供的 __dirname 表示当前这个文件所处的磁盘目录

            还有一种 __filename 表示当前这个文件的完整路径,包含了具体的文件名

            读取文件信息

            fs.stat(__dirname + '/文件路径', function(err, stats){
            if(err) return console.log(err.message); //如果文件内容追加失败则报错
              console.log( '文件内容读取成功' );
              console.log( stats.size );	//文件大小
              console.log( stats.birthtime );	//创建时间
              console.log( stats.isFile );	//判断是否为文件
              console.log( stats.isDirectory);	//判断是否为目录
            })
            

            复制文件

            fs.copyFile( '被拷贝的源文件路径,包含文件名称', '拷贝出的目标文件路径,包含名称'[,拷贝操作修饰符默认0],function(err){
            if(err) return console.log(err.message); //如果拷贝失败则报错
               console.log( '拷贝成功' );
            } )	//如果要拷贝出的目标文件已经存在则会覆盖,如果不存在则会新建
            

            路径操作

            path.join([…paths])

            const path = require('path')
            path.join(__dirname, '相对路径')
            

            其他:

            const path = require('path')
            
            // console.log(path.sep) // 路径分隔符
            
            const str = 'c:/a/b/c/1.txt'
            
            console.log(path.basename(str)) // 获取文件名称的
            console.log(path.dirname(str)) // 获取文件所在的路径的
            console.log(path.extname(str)) // 获取文件的扩展名
            

            Javascript 的单线程和异步

            Javascript 的解析和执行一直是单线程的,但是**宿主环境(浏览器或node)**是多线程的;

            异步任务是由宿主环境开启子线程完成,并通过事件驱动、回调函数、队列,把完成的任务, 交给主线程执行;

            Javascript解析引擎,一直在做一个工作,就是从任务队列里提取任务,放到主线程里执行

            CommonJS 规范

            1. 作用:是一套 Javascript 的模块化规范,规定了 模块的特性各模块之间如何相互依赖
            2. 用途:Node.js 中使用了 CommonJS 规范;
            3. 特点:同步加载模块;不适合在浏览器端使用;
            4. CommonJS规范都定义了哪些内容:wiki 对于 Modules 的描述

            模块作用域 和 全局作用域

            在Node.js中有两个作用域,分别是 全局作用域 和 模块作用域;

            1. 全局作用域使用 global 来访问,类似于浏览器中的window

            2. 每个 Javascript 文件,都是一个单独模块,每个模块都有自己独立的作用域,因此:模块中的成员,默认无法被其它模块访问。

            3. 如果在某个模块内部,想为 全局的 global 作用域挂载一些属性,需要显示的调用global.***来挂载;

            4. 注意:在开发中,一般情况下,不推荐使用global全局作用域来共享成员,会存在全局变量污染问题;

              var b = 20
              
              // console.log(global.b)
              global.b = b
              
              global.say = function () {
                console.log('这是挂载到全局的 say 方法')
              }
              
              console.log(global.b)
              global.say()
              

            模块作用域

            1. module(模块标识)

              module 属性是 Common JS 规范中定义的,它是一个对象,表示当前这个具体的 js 模块;

            2. require(引用模块)

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

            3. exports(暴露模块成员)

              每一个模块中,如果想要把自己的一些私有成员,暴露给别人使用,那么,必须实现一个 exports 对象,通过exports对象,可以方便的把模块内私有的成员,暴露给外界使用;

            module.exports 和 exports 的关系

            1. module.exportsexports 默认引用了同一个空对象;
            2. module.exportsexports 作用一致,都可以向外暴露成员;
            3. 一个模块作用域中,向外暴露私有成员时,永远以 module.exports 为准;
            module.exports = {}
            

            模块成员的分类

            模块成员,根据一些区别,又可以分为三大类: 核心模块、第三方模块、用户自定义模块

            1.核心模块

            1. 什么是核心模块:
              • 随着Node.js的安装包,一同安装到本地的模块,叫做核心模块;
              • 例如:fspath等模块,都是由Node.js官方提供的核心模块;
              • 只要大家在计算机中,安装了Node这个应用程序,那么,我们的计算机中就已经安装了所有的 核心模块;
            2. 如何使用核心模块require('核心模块标识符')

            2.第三方模块

            1. 什么是第三方模块:

              • 一些非官方提供的模块,叫做第三方模块;
              • 注意,第三方模块,并不在我们的计算机上;
              • 如果大家需要使用某些第三方模块,必须去一个叫做 NPM 的网站上搜索并下载才能使用;
            2. 如何使用第三方模块:

              • 先从 npm 官网上下载指定的第三方模块

              • 使用 require('第三方模块的名称标识符')来导入这个模块

              • 根据 第三方模块的 官方文档,尝试使用

              • npm install package => 用npm命令安装(下载)第三方模块 (文件模块)

              • gulp

                gulp的安装:

                1. 定位终端到项目目录 执行 npm install gulp -s 本地安装gulp的库文件
                2. 执行 npm install gulp-cli -g 全局安装gulp的命令行工具

                gulp的插件:

                1. gulp-htmlmin:html代码压缩 安装 npm install --save gulp-htmlmin
                2. gulp-file-include:html公共模块提取 npm install gulp-file-include
                3. gulp-less:less语法转化 npm install gulp-less
                4. gulp-csso:css压缩 npm install gulp-cssgo
                5. gulp-babel:JavaScript语法转化 npm install --save-dev gulp-babel @babel/core @babel/preset-env
                6. gulp-uglify:压缩混淆js代码 npm install --save-dev gulp-uglify
                7. !!!!!!注意!Gulp 4最大的变化就是你不能像以前那样传递一个依赖任务列表 如果Gulp是4.0的版本需要手动指定版本号 比如 npm install [email protected] -D

                gulp语法:

                ​ 1.gulp.task() 建立gulp任务

                ​ 2.gulp.src() 获取任务要处理的文件

                ​ 3.gulp.dest() 输出文件

                ​ 4.gulp.watch() 监控文件的变化

            3. 如何卸载

              npm unintall package => 用npm命令卸载包

            3.用户自定义模块

            1. 什么是用户模块:
              • 程序员在自己项目中写的 Javascript 文件,就叫做 用户自定义模块;
            2. 如何使用用户模块:require('路径标识符')

            模块查找规则

            • 当require方法接收不带路径的模块名字
              • Node.js会假设它是系统模块
              • Node.js会去node_modules文件夹中
                • 首先看是否有该名字的JS文件
                • 再看是否有该名字的文件夹
                • 如果是文件夹看里面是否有index.js
                • 如果没有index.js查看该文件夹中的package.json中的main选项确定模块入口文件
                • 否则找不到报错
            • 当require方法接收带路径的模块名字
              • require方法接收相对路径,相对于当前文件
              • 先找同名JS文件再找同名JS文件夹
              • 找文件夹中index.js否则去package.js中查找main选项确定入口文件
              • 否则找不到报错

            package.json

            项目描述文件,记录当前项目信息,例如项目名称、版本、作者、github地址、当前项目依赖了哪些第三方模块,目的是方便他人了解项目信息,下载项目依赖文件。

            该文件一般被放置在项目的根目录下,使用npm init命令生成。

            项目依赖

            在项目的开发阶段和线上运营阶段,都需要依赖的第三方包,称为项目依赖。

            使用npm install 包名命令下载的文件会默认被添加到package.json文件的dependencies字段中。

            开发依赖

            在项目的开发阶段需要依赖,线上运营阶段不需要依赖的第三方包,称为开发依赖。

            使用npm install 包名 --save-dev命令将包添加到package.json文件的devDependencies字段中。

            只安装项目运行依赖(dependencies)

            npm install --production
            

            为什么记录依赖项

            1. Node.js中下载的第三方包文件拥有非常多的细碎文件,将项目通过移动硬盘传递给别人时传输速度非常慢.
            2. 使用git工具管理项目时,不希望git管理node_modules文件夹,也不会将其上传到github中.

            当其他人获取到项目时,可以在项目根目录下执行npm install 命令,npm工具会自动去package.json文件中查找项目依赖文件并下载.

            1. 当项目上线以后,可以直接运行npm install --production下载项目依赖,避免下载项目开发依赖。

            2.服务器、http、静态资源、promise、异步函数

            创建web服务器

            // 引用系统模块
            const http = require('http');
            // 创建web服务器
            const server = http.createServer();
            // 当客户端发送请求的时候
            server.on('request', (req, res) => {
            	// 设置响应头
            	res.writeHead(200, {
            		'Content-Type': 'text/html;charset=utf8'
            	});
            	// 设置响应体
            	res.write('

            哈哈哈

            '
            ); // 结束请求 res.end(); }); // 监听3000端口 server.listen(3000, error => { if (!error) { console.log('服务器已启动,监听3000端口,请访问 localhost:3000') } });

            http协议

            req.url //获取请求地址

            req.headers //获取请求报文

            req.method //获取请求方法

            http状态码

            • 200请求成功
            • 404请求的资源没有找到
            • 500服务器端有错误
            • 400客户端请求有语法错误

            内容类型

            • text/plain
            • text/html
            • text/css
            • application/javascript
            • image/jpeg
            • application/json

            GET传参

            参数被放置在地址栏中,格式为:name=zhangsan&age=20

            // 处理get参数
            const url = require('url');
            let { query } = url.parse(req.url, true);
            

            POST传参

            参数被放置在请求体中,格式和GET参数相同。

            // 处理post参数
            // 由于post传递的参数数据量比较大,在网络中并不是一次性传递完成的,而是分成了多次传递
            // 所以在接收的时候也需要分为多次接收
            // 在NodeJs中接收post参数需要使用事件完成
            const querystring = require('querystring');
            router.post('/add', (req, res) => {
                //接收post请求参数
                let formData = '';
                req.on('data', chunk => formData += chunk);//开始接受
                req.on('end', async() => {//接受完
                  //querystring.parse(formData) 把字符串转换为对象
                    await Student.create(querystring.parse(formData))
                    res.writeHead(301, {
                        Location: '/list'
                    })
                    res.end()
                })
            })
            

            路由

            路由是指URL地址与程序的映射关系,更改URL地址可以改变程序的执行结果。简单说就是请求什么响应什么。

            // 1.引入系统模块http
            // 2.创建网站服务器
            // 3.为网站服务器对象添加请求事件
            // 4.实现路由功能
            // 	1.获取客户端的请求方式
            // 	2.获取客户端的请求地址
            const http = require('http')
            const url = require('url')
            const app = http.createServer()
            app.on('request', (req, res) => {
                const method = req.method.toLowerCase()
                const pathname = url.parse(req.url).pathname
              //let { pathname, query } = url.parse(req.url, true) //返回值为对象
                    // 防止中文乱码
                res.writeHeader(200, {
                    'Content-Type': 'text/html; charset=utf-8'
                })
                if (method === 'get') {
                    if (pathname === '/' || pathname === '/index') {
                        res.end('首页')
                    } else if (pathname === '/list') {
                        res.end('列表页')
                    } else {
                        res.end('无结果')
                    }
                }
                if (method === 'post') {
            
                }
            })
            app.listen(3000)
            console.log('to http://127.0.0.1:3000')
            

            客户端请求方式

            1. 浏览器地址栏
            2. Form表单提交
            3. link标签的href属性
            4. script标签的src属性
            5. image标签的src属性

            静态资源获取

            服务器端不需要处理,可以直接响应给客户端的资源就是静态资源,例如CSS、JavaScript、image文件

            const http = require('http');
            const url = require('url');
            const path = require('path');
            const fs = require('fs');
            const mime = require('mime');
            
            const app = http.createServer();
            app.on('request', function(req, res) {
                //获取用户请求路径
                let pathname = url.parse(req.url).pathname
                pathname = pathname == '/' ? '/default.html' : pathname
                let paths = path.join(__dirname, 'public' + pathname)
                let type = mime.getType(paths)
                fs.readFile(paths, (err, date) => {
                    if (err !== null) {
                        // 防止中文乱码
                        res.writeHeader(404, { //text/html能识别html标签;text/plain表示普通的文本字符串
                            'Content-Type': 'text/html; charset=utf-8'
                        })
                        res.writeHeader(200, {
                            'content-Type': type
                        })
                        return res.end('报错')
                    }
                    res.end(date)
                })
            })
            app.listen(3000, '127.0.0.1', function() {
                console.log('server running at http://127.0.0.1:3000');
            })
            

            promise

            Promise出现的目的是解决Node.js异步编程中回调地狱的问题

            //下面是用promise 读取静态资源文件
            const promisify = require('util').promisify;
            const fs = require('fs');
            /* let promise = new Promise((dome1, dome2) => {
                fs.readFile('./views/1.text', 'utf-8', (err, date) => {
                    if (err !== null) {
                        dome2(err)
                    } else {
                        dome1(date)
                    }
                })
            })
            promise.then((date) => {
                    console.log(date);
                })
                .catch((err) => {
                    console.log(err);
            
                }) */
            function p1() {
                return new Promise((dome1, dome2) => {
                    fs.readFile('./views/1.text', 'utf-8', (err, date) => {
                        if (err !== null) {
                            dome2(err)
                        } else {
                            dome1(date)
                        }
                    })
                })
            }
            function p2() {
                return new Promise((dome1, dome2) => {
                    fs.readFile('./views/2.text', 'utf-8', (err, date) => {
                        if (err !== null) {
                            dome2(err)
                        } else {
                            dome1(date)
                        }
                    })
                })
            }
            p1().then((date) => {
                    console.log(date);
                    return p2()
                })
                .then((date) => {
                    console.log(date);
                })
            

            异步函数

            异步函数是异步编程语法的终极解决方案,它可以让我们将异步代码写成同步的形式,让代码不再有回调函数嵌套,使代码变得清晰明了

            const fn = async () => {};
            async function fn () {}
            

            async关键字

            1. 普通函数定义前加async关键字 普通函数变成异步函数
            2. 异步函数默认返回promise对象
            3. 在异步函数内部使用return关键字进行结果返回 结果会被包裹的promise对象中 return关键字代替了resolve方法
            4. 在异步函数内部使用throw关键字抛出程序异常
            5. 调用异步函数再链式调用then方法获取异步函数执行结果
            6. 调用异步函数再链式调用catch方法获取异步函数执行的错误信息

            await关键字

            1. await关键字只能出现在异步函数中
            2. await promise await后面只能写promise对象 写其他类型的API是不不可以的
            3. await关键字可是暂停异步函数向下执行直到promise返回结果

            promisify改造函数

            //下面是异步函数读取文件代码示例:
            const fs = require('fs');
            // 改造现有异步函数api 让其返回promise对象 从而支持异步函数语法
            const promisify = require('util').promisify;
            // 调用promisify方法改造现有异步API 让其返回promise对象
            const readFile = promisify(fs.readFile);
            
            async function run() {
                let n1 = await readFile('./views/1.text', 'utf-8')
                let n2 = await readFile('./views/2.text', 'utf-8')
                console.log(n1);
                console.log(n2);
            
            }
            run()
            

            异步函数示例代码如下:

            // 1.在普通函数定义的前面加上async关键字 普通函数就变成了异步函数
            // 2.异步函数默认的返回值是promise对象
            // 3.在异步函数内部使用throw关键字进行错误的抛出
            // await关键字
            // 1.它只能出现在异步函数中
            // 2.await promise 它可以暂停异步函数的执行 等待promise对象返回结果后再向下执行函数
            
            // async function fn() {
            //     throw '发生了错误'
            //     return 123
            // }
            // fn().then((date) => {
            //         console.log(date);
            //     })
            //     .catch((err) => {
            //         console.log(err);
            //     })
            async function p1() {
                return 'p1'
            }
            async function p2() {
                return 'p2'
            }
            async function p3() {
                return 'p3'
            }
            async function run() {
                console.log(await p1());
                console.log(await p2());
                console.log(await p3());
            }
            run()
            

            3.数据库mongodb

            MongoDB数据库安装

            Node.js通常使用MongoDB作为其数据库,具有高性能,易使用,存储数据方便等特点,完全使用JavaScript语法即可操作。下载

            MongoDB可视化软件

            MongoDB可视化操作软件,使用图形界面操作数据库的一种方式。下载

            Mongoose第三方包

            使用Node.js操作MongoDB数据库需要依赖Node.js第三方包mongoose,使用npm install mongoose命令下载

            数据库连接

            const mongoose = require('mongoose');
            // 数据库连接 27017是mongodb数据库的默认端口
            // mongoose.connect('mongodb://账号名:密码@localhost:27017/数据库名字', { useNewUrlParser: true })
            mongoose.connect('mongodb://likai:550@localhost:27017/blog', { useNewUrlParser: true })
                .then(() => console.log('数据库连接成功'))
                .catch(() => console.log('数据库连接失败'));
            

            创建集合

            //连接数据库
            const mongoose = require('mongoose')
            mongoose.connect('mongodb://localhost/playground', { useNewUrlParser: true })
                .then(() => {
                    console.log('数据库连接成功');
                })
                .catch((err) => {
                    console.log(err, '数据库连接失败');
                })
            //创建集合规则(类似于设计数据库表结构)
            const courseSchema = new mongoose.Schema({
                    name: String,
                    author: String,
                    ispub: Boolean
                })
            //使用规则创建集合,第一个参数是集合名称(第一个字母要大写) 第二个参数是集合规则
            const Course = mongoose.model('Course', courseSchema)
            

            添加数据

            //第一种插入数据方式
            // const dome1 = new Course({
            //     name: 'kk',
            //     author: 'student',
            //     ispub: true
            // })
            // dome1.save()
            
            //第二种插入数据方式
            Course.create({
                    name: 'qiuqiu',
                    author: 'student',
                    ispub: true
                })
                .then(doc => {
                    console.log(doc);
                })
                .catch(err => {
                    console.log(err);
                })
            

            查找

            //1.全部查询
            // User.find().then(date => {
            //     console.log(date);
            // })
            User.find({
                _id: '5c09f267aeb04b22f8460968'
            }).then(date => {
                console.log(date); //输出值是个数据
            })
            User.findOne({
                    // _id: '5c09f236aeb04b22f8460967'
                }).then(date => {
                    console.log(date); //输出值是个集合,并且是集合中的第一条
                })
            //2.范围查询
            User.find({
                    age: { $gt: 20, $lt: 50 }
                }).then(date => {
                    console.log(date);
            
                })
            //3.包含查询
            User.find({
                    hobbies: { $in: ['足球'] }
                }).then(date => {
                    console.log(date);
                    console.log('-----------');
                })
            //4.字段查询,多个字段中间以空格隔开,前面加 - 表示不查询该字段
            User.find().select('name age -_id').then(date => {
                    console.log(date); //返回值为数组包含数条集合
                    console.log('-----------');
                })
            //5.将查找的数据进行升序排序,若降序排列,在字段名前面加 - ,下面以年龄为示例
            User.find().sort('age').then(date => {
                    console.log(date); //返回值为数组包含数条集合
                })
            //6.skip()跳过多少条数据,  llimit()限制查询结果的数量
            User.find().skip(2).limit(2).then(date => {
                console.log(date); //返回值为数组包含数条集合
            })
            

            删除

            // 查找到一条文档并且删除
            // 返回删除的文档
            // 如何查询条件匹配了多个文档 那么将会删除第一个匹配的文档
            User.findOneAndDelete({ _id: '5c09f267aeb04b22f8460968' })
                .then(date => {
                    console.log(date);
                })
                // 删除多条文档
                //返回值为{ n:4, ok:1 }  n为删除的数量,ok为1表示删除成功
                // User.deleteMany({ _id: '5c09f267aeb04b22f8460968' })
                //     .then(date => {
                //         console.log(date);
                //     })
            

            修改

            //修改单个,返回值{ n: 1, nModified: 1, ok: 1 } n代表受影响的数据个数, nModifie表示修改的数据个数, ok为1表示成功
            User.updateOne({ name: '赵六' }, { name: '赵云' })
                .then(date => {
                    console.log(date);
                })
                //修改多个
            User.updateMany({}, { age: 88 })
                .then(date => {
                    console.log(date);
                })
            

            验证规则

            // 创建集合规则,并添加规则验证
            const pot = new mongoose.Schema({
                title: {
                    type: String,
                    required: [true, '请传入文章标题'], //必选字段,第二参数为报错时提示信息
                    maxlength: 10, //传入字符串最大长度
                    minlength: 2, //传入字符串最小长度
                    trim: true //去除字符串两端的空格
            
                },
                age: {
                    type: Number,
                    min: 2, //数值最小值
                    max: 100 //数值最大值
                },
                publishDate: {
                    type: Date,
                    default: Date.now // 默认值
                },
                category: {
                    type: String,
                    // 枚举 列举出当前字段可以拥有的值
                    enum: {
                        values: ['html', 'css', 'javascript', 'node.js'],
                        message: '分类名称要在一定的范围内才可以'
                    }
                },
                author: {
                    type: String,
                    validate: {
                        validator: v => {
                            // 返回布尔值
                            // true 验证成功,false 验证失败
                            // v 要验证的值
                            return v && v.length > 4
                        },
                        message: '传入的值不符合验证规则' // 自定义错误信息
                    }
                }
            });
            

            多集合联合查询(集合关联)

            通常不同集合的数据之间是有关系的,例如文章信息和用户信息存储在不同集合中,但文章是某个用户发表的,要查询文章的所有信息包括发表用户,就需要用到集合关联。

            // 用户集合
            const User = mongoose.model('User', new mongoose.Schema({ name: { type: String } })); 
            // 文章集合
            const Post = mongoose.model('Post', new mongoose.Schema({
                title: { type: String },
                // 使用ID将文章集合和作者集合进行关联
                author: { type: mongoose.Schema.Types.ObjectId, ref: 'User' }
            }));
            //联合查询
            Post.find()
                  .populate('author')
                  .then((err, result) => console.log(result));
            

            在catch中获取错误信息

            Post.create({title:'aa', age: 60, category: 'java', author: 'bd'})
            	.then(result => console.log(result))
            	.catch(error => {
            		// 获取错误信息对象
            		const err = error.errors;
            		// 循环错误信息对象
            		for (var attr in err) {
            			// 将错误信息打印到控制台中
            			console.log(err[attr]['message']);
            		}
            	})
            

            数据库导入文档数据

            mongoimport -d 数据库名称 -c 集合名称 --file '要导入的数据文件名(包含路径)'
            

            mongoDB数据库添加账号

            1. 以系统管理员的方式运行powershell
            2. 连接数据库 mongo
            3. 查看数据库 show dbs
            4. 切换到admin数据库 use admin
            5. 创建超级管理员账户 db.createUser()
            6. 切换到blog数据 use blog
            7. 创建普通账号 db.createUser()
            8. 卸载mongodb服务

            ​ 停止服务 net stop mongodb

            ​ mongod --remove

            ​ 9.创建mongodb服务

            ​ mongod --logpath=“C:\Program
            Files\MongoDB\Server\4.1\log\mongod.log” --dbpath=“C:\Program
            Files\MongoDB\Server\4.1\data” --install –-auth

            ​ 10.启动mongodb服务 net start mongodb

            ​ 11.在项目中使用账号连接数据库

            ​ mongoose.connect(‘mongodb://likai:550@localhost:27017/blog’, { useNewUrlParser: true })

            ​ mongoose.connect(‘mongodb://账号名:密码@localhost:27017/数据库名字’, { useNewUrlParser: true })

            创建项目数据库账号

            1.mongo

            2.use admin

            3.db.auth(‘root’,‘root’)

            4.use 项目使用的数据库名

            5.db.createUser({user:‘likai’,pwd:‘550’,roles:[‘readWrite’]})

            6.exit

            4.模板引擎、Express

            art-template下载

            高性能 JavaScript 模板引擎,使用npm install art-template命令下载。

            通过调用模板引擎提供的template函数,告知模板引擎将特定模板和特定数据进行拼接,最终返回拼接结果

            //导入模板引擎
            const template = require('art-template');
            const path = require('path')
                // 设置模板的根目录
            template.defaults.root = path.join(__dirname, 'views');
            // 配置模板的默认后缀
            template.defaults.extname = '.html';
                // template方法是用来拼接字符串的
                // 参数1. 模板路径 绝对路径
                // 参数2. 要在模板中显示的数据 对象类型
                // 返回拼接好的字符串
            const html = template('index.art'), {
                name: '张三',
                age: 20
            })
            console.log(html);
            

            模板语法

            标准语法: {{ 数据 }}
            原始语法:<%= 数据  %>
            

            原文输出

            如果数据中携带HTML标签,默认不会解析标签,会将其转义后输出。使用以下方式可以解析标签。

            标准语法: {{ @数据 }}
            原始语法:<%- 数据  %>
            

            条件判断

             
             {{if 条件}} ... {{/if}}
             {{if v1}} ... {{else if v2}} ... {{/if}}
             
             <% if (value) { %> ... <% } %>
             <% if (v1) { %> ... <% } else if (v2) { %> ... <% } %>
            

            数据循环

            <!-- 标准语法 --> 
            {{each 数据}}
                 {{$index}} {{$value}}
             {{/each}}
              <!-- 原始语法 -->
             <% for(var i = 0; i < target.length; i++){ %>
                 <%= i %> <%= target[i] %> //带等号表示输出
             <% } %>
            

            子模板

            使用子模板可以将网站公共区块(头部、底部)抽离到单独的文件中。

              
             {{include '模板路径'}}
              
             <% include('模板路径') %>
            

            模板继承

            使用模板继承可以将网站HTML骨架抽离到单独的文件中,其他页面模板可以继承骨架文件。

            {{extend './layout.html'}}//要继承的html文件
            {{block 'head'}} ... {{/block}} //内容填充
            

            模板配置

            下载: npm install dateformat
            

            代码示例:

            const dateformat = require('dateformat');
            // 导入模板变量 用于处理日期格式的方法
            template.defaults.imports.dateformat = dateformat;
            //日期格式 {{dateformat($value.name名,'yyyy-mm-dd')}}
            

            第三方模块 router

            功能:实现路由

            使用步骤:

            1. 获取路由对象

            2. 调用路由对象提供的方法创建路由

            3. 启用路由,使路由生效

              const getRouter = require('router')
              const router = getRouter();//创建路由
              
              router.get('/list', async(req, res) => {
                  let student = await Student.find() //查询学生信息
                  let html = template('list.art', {
                      students: student
                  })
                  res.end(html)//最后要有一个返回值
              })
              
              app.on('request', (req, res) => {
                  router(req, res, () => {} )
              })
              

            实现静态资源访问

            • 第三方模块serve-static

              1. 引入serve-static模块获取创建静态资源(比如css,js等)服务功能的方法

              2. 调用方法创建静态资源服务并指定静态资源服务目录

              3. 启用静态资源服务功能

                const serveStatic = require('serve-static')
                const serve = serveStatic('静态资源目录')
                app.on('request', () => { 
                    serve(req, res)
                })
                app.listen(3000)
                

            Express

            Express是一个基于Node平台的web应用开发框架,提供一系列强大特性,帮助你创建各种 Web应用。

            使用npm install express 进行本地安装。

            中间件

            使用app.use()方法定义中间件。

            • 该方法可以传递一个函数作为参数,表示任何任何请求都会经过该中间件,都会执行该参数内部的代码。

              app.use((req, res, next) => {
                  console.log(req.url);
                  next();
              });
              
              • 中间件函数有三个参数,分别为请求对象req、响应对象res、释放控制权方法next。
              • 中间件函数中的代码执行完成之后需要调用next()方法,才能开始执行下一个中间件,否则请求将挂起。
            • 该方法的第一个参数也可以是请求路径,表示只有该请求路径才会经过该中间件。

              app.use('/user', (req, res, next) => {
                 console.log(req.method);
                 next();
              });
              

            中间件错误处理

            app.get('/index', (req, res, next) => {
            	// throw new Error('程序发生了未知错误')
            	fs.readFile('./01.js', 'utf8', (err, result) => {
            		if (err != null) {
            			next(err)
            		}else {
            			res.send(result)
            		}
            	})
              })
            // 下面是错误处理
            app.use((err, req, res, next) => {
            	res.status(500).send(err.message);
            })
            

            异步函数错误捕捉

            const express = require('express');
            const fs = require('fs');
            const promisify = require('util').promisify;
            const readFile = promisify(fs.readFile);
            
            app.get('/index', async (req, res, next) => {
            	try {
            		await readFile('./aaa.js')
            	}catch (ex) {
            		next(ex);
            	}
            })
            

            构建模块化路由

            第一种:在同一个页面

             const express = require('express') 
             // 创建路由对象
             const home = express.Router();
             // 将路由和请求路径进行匹配
             app.use('/home', home);
              // 在home路由下继续创建路由
             home.get('/index', () => {
                      //  /home/index
                     res.send('欢迎来到博客展示页面');
             });
            

            第二种:在多个页面

             // home.js
             const express = require('express') 
             // 创建路由对象
             const home = express.Router(); 
             home.get('/index', () => {
                 res.send('欢迎来到博客展示页面');
             });
             module.exports = home;
            
             // admin.js
             const express = require('express') 
             // 创建路由对象
             const admin = express.Router();
             admin.get('/index', () => {
                 res.send('欢迎来到博客管理页面');
             });
             module.exports = admin;
            
             // app.js
            const express = require('express');
            // 创建网站服务器
            const app = express();
             const home = require('./route/home.js');
             const admin = require('./route/admin.js');
             app.use('/home', home);
             app.use('/admin', admin);
            // 端口监听
            app.listen(3000);
            console.log('to http://127.0.0.1:3000')
            

            获取get请求参数

            // 引入express框架
            const express = require('express');
            // 创建网站服务器
            const app = express();
            
            app.get('/index', (req, res) => {
                // 获取get请求参数
                res.send(req.query)
            })
            // 端口监听
            app.listen(3000);
            console.log('to http://127.0.0.1:3000')
            

            获取post请求参数

            Express中接收post请求参数需要借助第三方包 body-parser

            // 引入express框架
            const express = require('express');
            const bodyParser = require('body-parser');
            // 创建网站服务器
            const app = express();
            // 拦截所有请求
            // extended: false 方法内部使用querystring模块处理请求参数的格式
            // extended: true 方法内部使用第三方模块qs处理请求参数的格式
            app.use(bodyParser.urlencoded({extended: false}))
            
            app.post('/add', (req, res) => {
            	// 接收post请求参数
            	res.send(req.body)
            })
            // 端口监听
            app.listen(3000);
            console.log('to http://127.0.0.1:3000')
            

            app.use方法

            // 引入express框架
            const express = require('express');
            const bodyParser = require('body-parser');
            // 创建网站服务器
            const app = express();
            
            app.use(fn({ a: 2 }))
            
            function fn(obj) {
                return function(req, res, next) {
                    if (obj.a == 1) {
                        console.log(req.url)
                    } else {
                        console.log(req.method)
                    }
                    next()
                }
            }
            
            app.get('/', (req, res) => {
                    // 接收post请求参数
                    res.send('ok')
                })
                // 端口监听
            app.listen(3000);
            console.log('to http://127.0.0.1:3000')
            

            路由参数

            // 引入express框架
            const express = require('express');
            const bodyParser = require('body-parser');
            // 创建网站服务器
            const app = express();
            
            app.get('/index/:id/:name/:age', (req, res) => {
              // 客户端请求时地址栏应该写成这样
            // http://localhost:3000/list/12/zhangsan /20
              
                // 接收post请求参数
                res.send(req.params)
            })
            // 端口监听
            app.listen(3000);
            console.log('to http://127.0.0.1:3000')
            

            express静态资源

            通过 Express 内置的 express.static 可以方便地托管静态文件,例如图片、CSS、JavaScript 文件等。

            app.use(express.static('public'));
            

            现在,public 目录下面的文件就可以访问了。

            http://localhost:3000/images/kitten.jpg
            http://localhost:3000/css/style.css
            http://localhost:3000/js/app.js
            http://localhost:3000/images/bg.png
            http://localhost:3000/hello.html
            

            express模板引擎

            使用npm install art-template express-art-template命令进行安装。

            const express = require('express');
            const path = require('path');
            const app = express();
            // 1.当渲染后缀为art的模板时 所使用的模板引擎是什么
            //  参数1模板后缀,参数2使用的模板引擎
            app.engine('art', require('express-art-template'))
                // 2.告诉express框架模板存放的位置是什么
            app.set('views', path.join(__dirname, 'views'))
                // 3.告诉express框架模板的默认后缀是什么
            app.set('view engine', 'art');
            
            app.get('/index', (req, res) => {
                // 1. 拼接模板路径
                // 2. 拼接模板后缀
                // 3. 哪一个模板和哪一个数据进行拼接
                // 4. 将拼接结果响应给了客户端
                // 第一个参数模板的路径(包含名字),第二个参数是一个对象
                res.render('index', {
                    msg: 'message'
                })
            });
                // 端口监听
            app.listen(3000);
            console.log('to http://127.0.0.1:3000')
            

            app.locals

            const express = require('express');
            const path = require('path');
            const app = express();
            // 模板配置
            app.engine('art', require('express-art-template'))
            app.set('views', path.join(__dirname, 'views'))
            app.set('view engine', 'art');
            //将变量设置到app.locals对象中,这个数据在所有的模板中到可以获得到
            app.locals.users = [{
                name: 'zhangsan',
                age: 20
            }, {
                name: '李四',
                age: 30
            }]
            
            app.get('/index', (req, res) => {
                res.render('index', {
                    msg: '首页'
                })
            });
             // 端口监听
            app.listen(3000);
            console.log('to http://127.0.0.1:3000')
            

            5.博客blog知识点

            密码加密bcrypt

            哈希斯加密是单程加密方式

            在加密的密码中加入随机字符串可以增加密码被破解的难度

            //导入bcrypt模板
            const bcrypt = require('bcrypt')
            //生成随机字符串 gen => generate生成 salt盐
            let salt = await bcrypt.genSalt(10)
            //使用随机字符串对密码进行加密
            let pass = await bcrypt.hash('明文密码',salt)
            
            //密码比对,返回布尔值
            let isEqual = await bcrypt.compare('明文密码','加密密码')
            

            bcrypt依赖的其他环境

            1.python 2.x

            2.node-gyp 安装命令:npm install -g node-gyp

            3.windows-build-tools(window系统需要安装)

            安装命令:npm install --global --production windows-build-tools

            cookie与session

            cookie:浏览器在电脑硬盘中开辟的一块空间,在客户端,主要供服务器端存储数据。

            • cookie中的数据是以域名的形式进行区分的。
            • cookie中的数据是有过期时间的,超过时间数据会被浏览器自动删除。
            • cookie中的数据会随着请求被自动发送到服务器端。

            session:实际上就是一个对象,存储在服务器端的内存中,在session对象中也可以存储多条数据,每一条数据都有一个sessionid做为唯一标识。

            在node中使用express-session模块实现session功能

            const session = require('express-session');
            app.use(session({ secret: 'secret key' }));
            

            在app.js中引入模块

            // 导入express-session模块
            const session = require('express-session');
            // 配置session
            app.use(session({
            	secret: 'secret key',
            	saveUninitialized: false,
            	cookie: {
            		maxAge: 24 * 60 * 60 * 1000
            	}
            }));
            

            在用户页面从session中获取数据

            // 创建用户列表路由
            admin.get('/user',(req,res)=>{
              res.render('admin/user',{
                msg:req.session.username
              })
            })
            

            实现退出功能

            1.删除session

            2.删除cookie

            3.重定向到用户登录页面

            module.exports = (req, res) => {
            	// 删除session
            	req.session.destroy(function () {
            		// 删除cookie
            		res.clearCookie('connect.sid');
            		// 重定向到用户登录页面
            		res.redirect('/admin/login');
            	});
            }
            

            express的页面重定向

              res.redirect('/admin/user')
            

            joi

            JavaScript对象的规则描述语言和验证器

            安装 npm install joi

            const Joi = require('joi');
            const schema = {//alphanum()字母字符串
                username: Joi.string().alphanum().min(3).max(30).required().error(new Error(‘错误信息’)),
                password: Joi.string().regex(/^[a-zA-Z0-9]{3,30}$/),
                access_token: [Joi.string(), Joi.number()],//表示两种类型都可以
                birthyear: Joi.number().integer().min(1900).max(2013),//integer()整数
                email: Joi.string().email()//邮箱格式
              //valid(0, 1)值必须为0或1
                static: Joi.number().valid(0, 1).error(new Error('状态值非法'))
            };
            async function run () {
            	try {
            		// 实施验证
            		await Joi.validate({ username: 'abc', birthyear: 1994 }, schema);
            	}catch (ex) {
            		console.log(ex.message);
            		return;
            	}
            	console.log('验证通过')
            

            formidable

            作用:解析表单,支持get请求参数,post请求参数、文件上传

            安装: npm install formidable

             // 引入formidable模块
             const formidable = require('formidable');
             // 创建表单解析对象
             const form = new formidable.IncomingForm();
             // 设置文件上传路径
             form.uploadDir = "/my/dir";
             // 是否保留表单上传文件的扩展名
             form.keepExtensions = true;
             // 对表单进行解析
             form.parse(req, (err, fields, files) => {
                 // fields 存储普通请求参数(普通表单数据)
                     // files 存储上传的文件信息
             });
            

            FileReader

            //文件读取 
            var reader = new FileReader();
             reader.readAsDataURL('文件');
             reader.onload = function () {
                 console.log(reader.result); 
             }
            

            数据分页 mongoose-sex-page

            const pagination = require('mongoose-sex-page');
            // page 指定当前页
                // size 指定每页显示的数据条数
                // display 指定客户端要显示的最多页码数
                // exec 向数据库中发送查询请求
                // 查询所有文章数据
            pagination(集合构造函数).page(1) .size(20) .display(8) .exec();
            

            config

            作用:允许开发人员将不同运行环境下的应用配置信息抽离到单独的文件中,模块内部自动判断当前应用的运行环境,

            并读取对应的配置信息,极大提供应用配置信息的维护成本,避免了当运行环境重复的多次切换时,手动到项目代码

            中修改配置信息

            使用步骤:

            1. 使用npm install config命令下载模块
            2. 在项目的根目录下新建config文件夹
            3. 在config文件夹下面新建default.json、development.json、production.json文件
            4. 在项目中通过require方法,将模块进行导入
            5. 使用模块内部提供的get方法获取配置信息
            {
            	"db": {
            		"user": "itcast",
            		"host": "localhost",
            		"port": "27017",
            		"name": "blog"
            	}
            }
            
            mongoose.connect(`mongodb://${config.get('db.user')}:${config.get('db.pwd')}@${config.get('db.host')}:${config.get('db.port')}/${config.get('db.name')}`, {useNewUrlParser: true })
            	.then(() => console.log('数据库连接成功'))
            	.catch(() => console.log('数据库连接失败'))
            

            将敏感配置信息存储在环境变量中

            1. 在config文件夹中建立custom-environment-variables.json文件
            2. 配置项属性的值填写系统环境变量的名字
            3. 项目运行时config模块查找系统环境变量,并读取其值作为当前配置项属于的值
             { 
                 "db": {
                       "pwd": "APP_PWD"
                 }
             }
            

            九.Ajsx

            它是浏览器提供的一套方法,可以实现页面无刷新更新数据,提高用户浏览网站应用的体验。

            1.运行原理、Ajax封装、模板引擎

            1. 创建ajax对象

               var xhr = new XMLHttpRequest();
              
            2. 告诉 Ajax 请求地址以及请求方式

              xhr.open('get', 'http://www.example.com');
              
            3. 发送请求

              xhr.send();
              
            4. 获取服务器端给与客户端的响应数据

               xhr.onload = function () {
                   console.log(xhr.responseText);
               }
              

            服务端响应的数据格式

            在真实的项目中,服务器端大多数情况下会以 JSON对象作为响应数据的格式。当客户端拿到响应数据时,要将 JSON 数据和 HTML 字符串进行拼接,然后将拼接的结果展示在页面中。

            在 http 请求与响应的过程中,无论是请求参数还是响应内容,如果是对象类型,最终都会被转换为对象字符串进行传输。

            JSON.parse() // 将 json 字符串转换为json对象
            

            传递get请求参数

             <script type="text/javascript">
                    // 获取按钮元素
                    var btn = document.getElementById('btn');
                    // 获取姓名文本框
                    var username = document.getElementById('username');
                    // 获取年龄文本框
                    var age = document.getElementById('age');
                    // 为按钮添加点击事件
                    btn.onclick = function() {
                        // 创建ajax对象
                        var xhr = new XMLHttpRequest();
                        // 获取用户在文本框中输入的值
                        var nameValue = username.value;
                        var ageValue = age.value;
                        // 拼接请求参数
                        var params = 'username=' + nameValue + '&age=' + ageValue;
                        // 配置ajax对象
                        //get请求是不能提交json对象数据格式的
                        xhr.open('get', 'http://localhost:3000/get?' + params);
                        // 发送请求
                        xhr.send();
                        // 获取服务器端响应的数据
                        xhr.onload = function() {
                            console.log(xhr.responseText)
                        }
                    }
                </script>
            

            传递post请求参数

             <script type="text/javascript">
                    // 获取按钮元素
                    var btn = document.getElementById('btn');
                    // 获取姓名文本框
                    var username = document.getElementById('username');
                    // 获取年龄文本框
                    var age = document.getElementById('age');
                    // 为按钮添加点击事件
                    btn.onclick = function() {
                        // 创建ajax对象
                        var xhr = new XMLHttpRequest();
                        // 获取用户在文本框中输入的值
                        var nameValue = username.value;
                        var ageValue = age.value;
                        // 拼接请求参数
                        var params = 'username=' + nameValue + '&age=' + ageValue;
                        // 配置ajax对象
                        xhr.open('post', 'http://localhost:3000/post');
                        // 设置请求参数格式的类型(post请求必须要设置)
                        xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
                        // 发送请求
                        xhr.send(params);
                        // 获取服务器端响应的数据
                        xhr.onload = function() {
                            console.log(xhr.responseText)
                        }
                    }
                </script>
            

            请求参数的格式

            1. application/x-www-form-urlencoded

               name=zhangsan&age=20&sex=男
              
            2. application/json

              {name: 'zhangsan', age: '20', sex: '男'}
            

            Ajax 状态码

            在创建ajax对象,配置ajax对象,发送请求,以及接收完服务器端响应数据,这个过程中的每一个步骤都会对应一个数值,这个数值就是ajax状态码。

            <script type="text/javascript">
                    var xhr = new XMLHttpRequest();
                    //状态码
                    // 0 已经创建了ajax对象 但是还没有对ajax对象进行配置
                    console.log(xhr.readyState);
                    xhr.open('get', 'http://localhost:3000/readystate');
                    // 1 已经对ajax对象进行配置 但是还没有发送请求
                    console.log(xhr.readyState);
            
                    // onreadystatechange事件 当ajax状态码发生变化的时候触发
                    xhr.onreadystatechange = function() {
                        // 2 请求已经发送了
                        // 3 已经接收到服务器端的部分数据了
                        // 4 服务器端的响应数据已经接收完成
                        console.log(xhr.readyState);
                        // 对ajax状态码进行判断 如果状态码的值为4就代表数据已经接收完成了
                        if (xhr.readyState == 4) {
                            console.log(xhr.responseText);
                        }
                    }
            
                    xhr.send();
                </script>
            

            错误处理

            1. 网络畅通,服务器端能接收到请求,服务器端返回的结果不是预期结果。

            可以判断服务器端返回的状态码,分别进行处理。xhr.status 获取http状态码

            ​ 2.网络畅通,服务器端没有接收到请求,返回404状态码。

            检查请求地址是否错误。

            ​ 3.网络畅通,服务器端能接收到请求,服务器端返回500状态码。

            服务器端错误,找后端程序员进行沟通。

            ​ 4.网络中断,请求无法发送到服务器端。

            会触发xhr对象下面的onerror事件,在onerror事件处理函数中对错误进行处理

            低版本 IE 浏览器的缓存问题

            **问题:**在低版本的 IE 浏览器中,Ajax 请求有严重的缓存问题,即在请求地址不发生变化的情况下,只有第一次请求会真正发送到服务器端,后续的请求都会从浏览器的缓存中获取结果。即使服务器端的数据更新了,客户端依然拿到的是缓存中的旧数据。

            **解决方案:**在请求地址的后面加请求参数,保证每一次请求中的请求参数的值不相同。

            xhr.open('get', 'http://www.example.com?t=' + Math.random());
            

            Ajax封装

            发送一次请求代码过多,发送多次请求代码冗余且重复

            将请求代码封装到函数中,发请求时调用函数即可

             <script>
                    function ajax(obj) {
                        //存储的是默认值
                        var defaults = {
                                type: 'get',
                                url: '',
                                date: {},
                                header: {
                                    'Content-Type': 'application/x-www-form-urlencoded'
                                },
                                success: function() {},
                                error: function() {}
                            }
                            //使用obj对象中的属性覆盖defaults对象中的属性
                        Object.assign(defaults, obj);
            
                        //创建ajax对象
                        var xhr = new XMLHttpRequest()
                            //拼接请求参数的变量
                        var params = ''
                            //循环用户传递进来的对象格式参数
                        for (var attr in defaults.date) {
                            //将参数转换为字符串格式
                            params += attr + '=' + defaults.date[attr] + '&'
                        }
                        //将参数最后面的&截取掉,并重新赋值给params变量
                        params = params.substr(0, params.length - 1)
                            //判断请求方式
                        if (defaults.type == 'get') {
                            defaults.url = defaults.url + '?' + params
                        }
            
                        //配置ajax对象
                        xhr.open(defaults.type, defaults.url)
            
                        //如果请求方式是post
                        if (defaults.type == 'post') {
                            // 用户希望的向服务器端传递的请求参数的类型
                            var ContentType = defaults.header['Content-Type']
                                //设置请求参数格式的类型
                            xhr.setRequestHeader('Content-Type', ContentType)
                                // 判断用户希望的请求参数格式的类型
                                // 如果类型为json
                            if (ContentType == 'application/json') {
                                // 向服务器端传递json数据格式的参数
                                xhr.send(JSON.stringify(defaults.date))
                            } else {
                                // 向服务器端传递普通类型的请求参数
                                xhr.send(params)
                            }
                        } else {
                            xhr.send()
                        }
                        //监听xhr对象下面的onload事件
                        //当xhr对象接收完响应数据后触发
                        xhr.onload = function() {
                            // 获取响应头中的数据 xhr.getResponseHeader()
                            var contentType = xhr.getResponseHeader('Content-Type')
                                //服务器端返回的数据
                            var responseText = xhr.responseText
            
                            // 如果响应类型中包含applicaition/json
                            if (contentType.includes('application/json')) {
                                //将JSON字符串转换为JSON对象
                                responseText = JSON.parse(responseText)
                            }
                            // 当http状态码等于200的时候
                            if (xhr.status == 200) {
                                // 请求成功 调用处理成功情况的函数
                                defaults.success(responseText)
                            } else {
                                // 请求失败 调用处理失败情况的函数
                                defaults.error(responseText, xhr)
                            }
                        }
                    }
            
                    ajax({
                        //求情方式
                        type: 'get',
                        //请求地址
                        url: 'http://localhost:3000/responseData',
                        success: function(date) {
                            console.log('这里是success函数');
                            console.log(date);
                        },
                        error: function(date, xhr) {
                            console.log('这里是err函数' + date);
                            console.log(xhr);
            
                        }
                    })
            
                    /*
            			请求参数要考虑的问题
            				1.请求参数位置的问题
            					将请求参数传递到ajax函数内部, 在函数内部根据请求方式的不同将请求参数放置在不同的位置
            					get 放在请求地址的后面
            					post 放在send方法中
            
            				2.请求参数格式的问题
            					application/x-www-form-urlencoded
            						参数名称=参数值&参数名称=参数值
                                    name=zhangsan&age=20
                                    
            					application/json
                                    {name: 'zhangsan', age: 20}
                                    
            					1.传递对象数据类型对于函数的调用者更加友好
            					2.在函数内部对象数据类型转换为字符串数据类型更加方便
            		*/
                </script>
            

            模板引擎

            作用:使用模板引擎提供的模板语法,可以将数据和 HTML 拼接起来。

            官方地址:
            https://aui.github.io/art-template/zh-cn/index.html

            模板引擎使用步骤

             <!-- 1. 将模板引擎的库文件引入到当前页面 -->
                <script src="/js/template-web.js"></script> 
            
            <div id="container"></div>
            
                <!-- 2.准备art-template模板 -->
                <script type="text/html" id="tpl">
                    <h1>{{username}} {{age}}</h1>
                </script>
                <script type="text/javascript">
                    // 3.告诉模板引擎将那个数据和哪个模板进行拼接
                    // 1) 模板id 2)数据 对象类型
                    // 方法的返回值就是拼接好的html字符串
                    var html = template('tpl', {
                        username: 'zhangsan',
                        age: 30
                    });
                    document.getElementById('container').innerHTML = html;
                </script>
            

            2.formData、同源跨域

            FormData 对象的作用

            1. 模拟HTML表单,相当于将HTML表单映射成表单对象,自动将表单对象中的数据拼接成请求参数的格式。
            2. 异步上传二进制文件

            FormData使用方法

             <!-- 创建普通的html表单 -->
                <form id="form">
                    <input type="text" name="username">
                    <input type="password" name="password">
                    <input type="button" id="btn" value="提交">
                </form>
                <script type="text/javascript">
                    // 获取按钮
                    var btn = document.getElementById('btn');
                    // 获取表单
                    var form = document.getElementById('form');
                    // 为按钮添加点击事件
                    btn.onclick = function() {
                        // 将普通的html表单转换为表单对象
                        var formData = new FormData(form);
                        // 创建ajax对象
                        var xhr = new XMLHttpRequest();
                        // 对ajax对象进行配置
                        xhr.open('post', 'http://localhost:3000/formData');
                        // 发送ajax请求
                        xhr.send(formData);
                        // 监听xhr对象下面的onload事件
                        xhr.onload = function() {
                            // 对象http状态码进行判断
                            if (xhr.status == 200) {
                                console.log(xhr.responseText);
                            }
                        }
                    }
                </script>
            
            //入口文件app.js
            const formidable = require('formidable');
            app.post('/formData', (req, res) => {
                // 创建formidable表单解析对象
                const form = new formidable.IncomingForm();
                // 解析客户端传递过来的FormData对象
                form.parse(req, (err, fields, files) => {
                    res.send(fields);
                });
            });
            

            注意

            1. Formdata 对象不能用于 get 请求,因为对象需要被传递到 send 方法中,而 get 请求方式的请求参数只能放在请求地址的后面。
            2. 服务器端 bodyParser 模块不能解析 formData 对象表单数据,我们需要使用formidable模块进行解析。

            formData 对象的实例方法

            1. 获取表单对象中属性的值

               formData.get('key');
              
            2. 设置表单对象中属性的值

              formData.set('key', 'value');
              
            3. 删除表单对象中属性的值

              formData.delete('key');
              
            4. 向表单对象中追加属性值

              formData.append('key', 'value');
              

              注意:set 方法与 append 方法的区别是,在属性名已存在的情况下,set 会覆盖已有键名的值,append会保留两个值。

            formData二进制文件上传

            // 实现文件上传的路由
            app.post('/upload', (req, res) => {
                // 创建formidable表单解析对象
                const form = new formidable.IncomingForm();
                // 设置客户端上传文件的存储路径
                form.uploadDir = path.join(__dirname, 'public', 'uploads');
                // 保留上传文件的后缀名字
                form.keepExtensions = true;
                // 解析客户端传递过来的FormData对象
                form.parse(req, (err, fields, files) => {
                    // 将客户端传递过来的文件地址响应到客户端
                    res.send({
                        path: files.attrName.path.split('public')[1]
                    });
                });
            });
            
             <div class="container">
                    <div class="form-group">
                        <label>请选择文件</label>
                        <input type="file" id="file">
                        <div class="padding" id="box">
                            <!--<img src="" class="img-rounded img-responsive">-->
                        </div>
                        <div class="progress">
                            <div class="progress-bar" style="width: 0%;" id="bar">0%</div>
                        </div>
                    </div>
                </div>
                <script type="text/javascript">
                    // 获取文件选择控件
                    var file = document.getElementById('file');
                    // 获取进度条元素
                    var bar = document.getElementById('bar');
                    // 获取图片容器
                    var box = document.getElementById('box');
                    // 为文件选择控件添加onchanges事件
                    // 在用户选择文件时触发
                    file.onchange = function() {
                        // 创建空的formData表单对象
                        var formData = new FormData();
                        // 将用户选择的文件追加到formData表单对象中
                        formData.append('attrName', this.files[0]);
                        // 创建ajax对象
                        var xhr = new XMLHttpRequest();
                        // 对ajax对象进行配置
                        xhr.open('post', 'http://localhost:3000/upload');
                        // 在文件上传的过程中持续触发
                        xhr.upload.onprogress = function(ev) {
                                // ev.loaded 文件已经上传了多少
                                // ev.total  上传文件的总大小
                                var result = (ev.loaded / ev.total) * 100 + '%';
                                // 设置进度条的宽度
                                bar.style.width = result;
                                // 将百分比显示在进度条中
                                bar.innerHTML = result;
                            }
                            // 发送ajax请求
                        xhr.send(formData);
                        // 监听服务器端响应给客户端的数据
                        xhr.onload = function() {
                            // 如果服务器端返回的http状态码为200
                            // 说明请求是成功的
                            if (xhr.status == 200) {
                                // 将服务器端返回的数据显示在控制台中
                                var result = JSON.parse(xhr.responseText);
                                // 动态创建img标签
                                var img = document.createElement('img');
                                // 给图片标签设置src属性
                                img.src = result.path;
                                // 当图片加载完成以后
                                img.onload = function() {
                                    // 将图片显示在页面中
                                    box.appendChild(img);
                                }
                            }
                        }
            
                    }
                </script>
            

            同源

            如果两个页面拥有相同的协议、域名和端口,那么这两个页面就属于同一个源,其中只要有一个不相同,就是不同源

            同源政策是为了保证用户信息的安全,防止恶意的网站窃取数据。最初的同源政策是指
            A 网站在客户端设置的 Cookie,B网站是不能访问的。

            JSONP

            jsonp 是 json with padding 的缩写,它不属于 Ajax 请求,但它可以模拟 Ajax 请求

            //封装的JSONP方法
            function jsonp(options) {
                // 动态创建script标签
                var script = document.createElement('script');
                // 拼接字符串的变量
                var params = '';
            
                for (var attr in options.data) {
                    params += '&' + attr + '=' + options.data[attr];
                }
            
                // myJsonp0124741
                var fnName = 'myJsonp' + Math.random().toString().replace('.', '');
                // 它已经不是一个全局函数了
                // 我们要想办法将它变成全局函数
                window[fnName] = options.success;
                // 为script标签添加src属性
                script.src = options.url + '?callback=' + fnName + params;
                // 将script标签追加到页面中
                document.body.appendChild(script);
                // 为script标签添加onload事件
                script.onload = function() {
                    document.body.removeChild(script);
                }
            }
            

            CORS 跨域资源共享

            第三方插件cors 可实现跨域请求

            const cors = require('cors')
            app.use(cors())
            

            CORS:全称为 Cross-originresource sharing,即跨域资源共享,它允许浏览器向跨域服务器发送 Ajax 请求,克服了 Ajax 只能同源使用的限制。

            // 拦截所有请求
            app.use((req, res, next) => {
                // 1.允许哪些客户端访问我
                // * 代表允许所有的客户端访问我
                // 注意:如果跨域请求中涉及到cookie信息传递,值不可以为*号 比如是具体的域名信息
                res.header('Access-Control-Allow-Origin', 'http://localhost:3000')
                    // 2.允许客户端使用哪些请求方法访问我
                res.header('Access-Control-Allow-Methods', 'get,post')
                    // 允许客户端发送跨域请求时携带cookie信息
                res.header('Access-Control-Allow-Credentials', true);
                next();
            });
            

            withCredentials属性

            在使用Ajax技术发送跨域请求时,默认情况下不会在请求中携带cookie信息。

            withCredentials:指定在涉及到跨域请求时,是否携带cookie信息,默认值为false

            Access-Control-Allow-Credentials:true 允许客户端发送请求时携带cookie

               // 当发送跨域请求时,携带cookie信息
               xhr.withCredentials = true;
            

            第三方模块request

            // 向其他服务器端请求数据的模块request
            const request = require('request');
            app.get('/server', (req, res) => {
                request('http://localhost:3001/cross', (err, response, body) => {
                    res.send(body);
                })
            });
            

            Jquery中的Ajax

            基本使用

              <script src="/js/jquery.min.js"></script>
                <script>
                    $('#btn').on('click', function() {
                        $.ajax({
                            // 请求方式
                            type: 'post',
                            // 请求地址
                            url: '/base',
                            // 请求成功以后函数被调用
                            success: function(response) {
                                // response为服务器端返回的数据
                                // 方法内部会自动将json字符串转换为json对象
                                console.log(response);
                            },
                            // 请求失败以后函数被调用
                            error: function(xhr) {
                                console.log(xhr)
                            }
                        })
                    });
                </script>
            

            传递请求参数

            //在 $.ajax({})中
            data: JSON.stringify(params),
                  // 指定参数的格式类型
                  contentType: 'application/json',
            

            beforeSend方法

            //在 $.ajax({})中  
            // 在请求发送之前调用
             beforeSend: function() {
                alert('请求不会被发送')
                // 请求不会被发送
                return false;
                            }
            

            serialize方法

            作用:将表单中的数据自动拼接成字符串类型的参数

            var params = $('#form').serialize();
            // name=zhangsan&age=30
            
              // 将表单中用户输入的内容转换为对象类型
                    function serializeObject(obj) {
                        // 处理结果对象
                        var result = {};
                        // [{name: 'username', value: '用户输入的内容'}, {name: 'password', value: '123456'}]
                        var params = obj.serializeArray();
            
                        // 循环数组 将数组转换为对象类型
                        $.each(params, function(index, value) {
                                result[value.name] = value.value;
                            })
                            // 将处理的结果返回到函数外部
                        return result;
                    }
            

            发送jsonp请求

            $.ajax({
                url: 'http://www.example.com',
                // 指定当前发送jsonp请求
                dataType: 'jsonp',
                // 修改callback参数名称
                jsonp: 'cb',
                // 指定函数名称
                jsonCallback: 'fnName',
                success: function (response) {} 
            })
            

            $.get

            作用: 用于发送get请求

            $.get('http://www.example.com', {name: 'zhangsan', age: 30}, function (response) {}) 
            

            $.post

            作用: 用于发送post请求

            $.post('http://www.example.com', {name: 'lisi', age: 22}, function (response) {})
            

            全局事件

               // 当页面中有ajax请求发送时触发
                    $(document).on('ajaxStart', function() {
                        NProgress.start()
                    })
            
              // 当页面中有ajax请求完成时触发
                    $(document).on('ajaxComplete', function() {
                        NProgress.done()
                    })
            

            RESTful 风格的API

            GET POST PUT DELETE
            获取数据 添加数据 更新数据 删除数据

            XML基础

            XML是什么?

            XML 的全称是 extensible markup language,代表可扩展标记语言,它的作用是传输和存储数据。

            XML DOM

            XML DOM 即 XML 文档对象模型,是 w3c 组织定义的一套操作 XML 文档对象的API。浏览器会将 XML 文档解析成文档对象模型

             <button id="btn">发送请求</button>
                <div id="container"></div>
                <script type="text/javascript">
                    var btn = document.getElementById('btn');
                    var container = document.getElementById('container');
            
                    btn.onclick = function() {
                        var xhr = new XMLHttpRequest();
                        xhr.open('get', '/xml');
                        xhr.send();
                        xhr.onload = function() {
                            // xhr.responseXML 获取服务器端返回的xml数据
                            var xmlDocument = xhr.responseXML;
                            var title = xmlDocument.getElementsByTagName('title')[0].innerHTML;
                            container.innerHTML = title;
                        }
                    }
                </script>
            

            十.博客项目

            1.git

            Git是一个分布式版本管理控制系统(缩写VCS),它可以在任何时间点,将文档的状态作为更新记录保存起来,也可以在任何时间点,将更新记录恢复回来。

            • 安装完后,右键会出现git菜单,选中 Git Bash Here,弹出命令窗口
            • 输入命令 git --version 查看git版本

            git使用前配置

            1. 配置提交人姓名:git config --global user.name 提交人姓名
            2. 配置提交人姓名:git config --global user.email 提交人邮箱
            3. 查看git配置信息:git config --list

            git使用

            1. git init` 初始化git仓库
            2. git status 查看文件状态
            3. git add 文件列表 追踪文件
            4. git commit -m 提交信息 向仓库中提交代码
            5. git log 查看提交记录
            6. git checkout 文件 撤销,用暂存区中的文件覆盖工作目录中的文件
            7. git rm --cached 文件名 将文件从暂存区中删除
            8. git reset --hard 提交ID 恢复git仓库中指定版本的项目

            git分支

            • git branch 查看分支
            • git branch 分支名称 创建分支
              • 在哪条分支上输入的命令,就是在哪条分支上进行的创建
              • git branch develop -创建了一个develop的分支
            • git checkout 分支名称 切换分支
              • git checkout develop -切换到develop分支
              • 注意:当切换分支的时候,需要把暂存区里面的文件进行提交,不然会暂存区里面的文件会跟着到切换的这条分支上
              • 当切换会主分支的时候,就看不到其他分支里面的文件了
            • git merge 要合并进来的分名 合并分支
              • 如果当前分支的工作已经完成,就可以合并到到其他分支
              • 需要分清谁要合并谁,例如我们在开发分支上完成了功能,应该合并到主分支上,所以我们要站在主分支角度来进行合并
              • 虽然进行了合并,但是开发分支还是存在
            • git branch -d 分支名称 删除分支(分支被合并后才允许删除)(-D 强制删除)
              • 分支工作已经完成,就可以进行删除
              • git branch -d develop
              • 如果分支没有进行合并,那么默认是不能被删除,这是由于git有分支保护机制
              • 如果想强行删除,把-d 改成-D : git branch -D develop

            git暂时保存更改

            在git中,可以暂时提取分支上所有的改动并存储,让开发人员得到一个干净的工作副本,临时转向其他工作。

            • 存储临时改动: git stash
            • 恢复改动: git stash pop

            Github

            访问github首页,点击 Sign up 连接。(注册)

            1. git remote add 远程仓库地址别名 远程仓库地址

            2. git push -u 远程仓库地址或别名 本地分支名称:

              -u 记住推送地址及分支,下次推送只需要输入git push即可

            多人协作开发

            因为A已经创建了远程的仓库,所以程序员B就不需要创建仓库,直接把远程的仓库克隆一份到本地即可

            git clone 远程仓库地址
            

            A将远程仓库中的最新内容拉取到本地

            拉取利用pull命令,拉取是读操作,不需要校验身份

            git pull origin master
            

            git忽略清单

            将不需要被git管理的文件名字添加到此文件中,在执行git命令的时候,git就会忽略这些文件

            git忽略清单文件名称叫: .gitignore

            仓库的详细说明

            在仓库根目录添加一个 readme.md 文件即可,在里面写上内容,push到服务器后,默认在github里面就能看到仓库的详细说明了

            git相关命令整理

            git config --global user.name  //配置姓名
            git config --global user.email  //配置邮箱
            git config --list  //查看配置信息
            git init 	//初始化本地仓库
            git status 	 //查看文件状态
            git add 文件名 	//添加某个文件到暂存区,如果写 . 代表当前文件夹下所有的文件、
            git commit -m 日志说明   //提交到本地仓库
            git log    //查看提交记录
            git checkout 文件名    //撤销,让暂存区文件覆盖工作区间文件
            git rm --cached 文件名   	//在暂存区移除相应文件
            git reset --hard 提交ID  	//恢复到指定版本
            git branch      //查看分支
            git branch develop  //创建分支
            git checkout 分支名  //切换分支
            git merge  要合并的分支名//合并分支
            git branch -d 分支名称  //删除分支
            git clone 地址 //克隆远程仓库
            git push 地址 分支名  //往服务器推送
            git pull 地址  //将服务器代码拉取到本地
            git remote add 名称 地址 //给地址取别名
            git push -u origin 分支名  //把该分支推送到云端仓库
            ssh-keygen  //生成一对密钥
            

            十一.Vue

            1.指令

            v-cloak

            防止页面加载时出现闪烁问题

            <script type="text/css">
                    [v - cloak] { display: none; }
            </script>
             <div id="app" v-cloak>
            </div>
            

            v-text

            • v-text指令用于将数据填充到标签中,作用于插值表达式类似,但是没有闪动问题
            • 如果数据中有HTML标签会将html标签一并输出
            • 注意:此处为单向绑定,数据对象上的值改变,插值会发生变化;但是当插值发生变化并不会影响数据对象的值
             <div v-text='msg'></div>
             <div v-text>{{msg}}</div>
            

            v-html

            • 用法和v-text 相似 但是他可以将HTML片段填充到标签中
            • 可能有安全问题, 一般只在可信任内容上使用 v-html永不用在用户提交的内容上
            • 它与v-text区别在于v-text输出的是纯文本,浏览器不会对其再进行html解析,但v-html会将其当html标签解析后输出。
             <div v-html='msg1'></div>
            

            v-pre

            • 显示原始信息跳过编译过程
            • 跳过这个元素和它的子元素的编译过程。
            • 一些静态的内容不需要编译加这个指令可以加快渲染
            <div v-pre>{{msg}}</div>
            

            v-once

            执行一次性的插值【当数据改变时,插值处的内容不会继续更新】

              <!-- 即使data里面定义了msg 后期我们修改了 仍然显示的是第一次data里面存储的数据即 Hello Vue.js  -->
                 <span v-once>{{ msg}}</span>    
            <script>
                new Vue({
                    el: '#app',
                    data: {
                        msg: 'Hello Vue.js'
                    }
                });
            </script>
            

            v-model

            双向数据绑定

            • 当数据发生变化的时候,视图也就发生变化
            • 当视图发生变化的时候,数据也会跟着同步变化

            v-model是一个指令,限制在