admin管理员组文章数量:1547178
使用markdown语法: # HTML ## 基本标签 ### 块级标签 * `div` 分区标签 * `p` 段落标签 * 标题标签`<h1-h3>` 有强调 `<h4-h6>` * `pre` 保留格式 * `ul>li` 无序列表 * `ol>li` 有序列表 * dl>dt+dd 定义列表 ### 行内标签 - 文本样式标签 - `strong` b 加粗 (strong语义上强化,常用strong) - `del` 删除 - `i` em 倾斜 常用i - span 分区标签 - 图片标签 img (可以设置宽高,替代元素) 标签属性 src(图片地址) alt(图片出不来提示) title(鼠标放上提示) 图片路径 <!-- 图片及文件的查找规则,同级'./'或者省略'./'查找 --> <!-- 图片及文件的查找规则,子目录'./'查找 --> <!-- 图片及文件的查找规则,向父级查找.通过'../'查找 --> <!-- 图片及文件的查找规则,向父级的父级查找.通过'../../'查找 --> <!-- 网络资源 直接复制链接 --> <!-- 绝对路径 根目录'/'--> - `sub`下标 `sup` 上标 - 超链接 a - target 目标打开方式 _blank 新标签 _parent 在框架里面使用 _self 默认值 _top 在框架里使用 ``` <a href="#id"></a> <!-- p{内容$(占位符)}* --> 注释快捷键 ctrl+/ <!-- 以后有用用这个 --> <a href="#">空链接</a> <!-- 以后没有用这个空链接 --> <a href="javascript:void(0)">空链接</a> <a href="javascript:;">空链接</a> ``` ### HTML预留字符 + ` ;` 空格 + `$gt;` 小于号 < + `>` 大于号> + `¥` ·¥·元 + `©` 版权 © ## 列表 ### 表格 + border 边框 + cellspacing 去掉单元格空隙 + cellpadding 单元格内填充 + tr 行 td 列 colspan(将列合并,就是横合并,横合并减少同行td) rowspan(将行合并,就是上下合并,下一个tr中的td减少) > tr 里面不可以写div table等东西,td可以包含 ```html (1)colspan 横合并两个单元格 <td colspan="2">单元格</td> <td>单元格</td> <td>单元格</td> <td>单元格</td> 本来五个td,因为合并了两个,所以四个td (2)rowspan 上下合并 <tr rowspan="2"> <td>单元格</td> <td>单元格</td> <td>单元格</td> <td>单元格</td> <td>单元格</td> </tr> <tr> <td>单元格</td> <td>单元格</td> <td>单元格</td> </tr> 上下合并,所以下面这个少两个td (3) td里面包裹table,上边合并单元格时,下边的td也需要合并单元格,才能对齐,然后在包裹table。在写表格样式时也需要先将所有样式清零。然后设置宽度,用margin居中。 <style> table{ border-spacing: 0; border-collapse: 0; } //清空格式 .table1{ width: 800px; margin: 0 auto; } //设置宽度,居中 table tr td{ border: 1px solid #ccc; padding: 5px 10px;} //设置边框 .table1 table{ width: 800px; } 设置包裹的宽度和整体相同 .tds{ padding: 0; } .table1 table tr td{ border: 0; } 将边框清0,自己写边框,不然容易重叠。 </style> <table class="table1"> <caption>费用报销单</caption> <tr> <td width="200" align="center">费用项目</td> //为一开始的文字设置宽度 <td width="100">类别</td> <td width="100">金额</td> <td width="200" rowspan="2" align="center">负责人(签章)</td> <td rowspan="2"></td> </tr> <tr> <td></td> <td></td> <td></td> </tr> <tr> <td colspan="4" >合计:人民币(大写) 拾 万 千 百 拾 元 角 分 (小写)¥ 元</td> </tr> <tr> <td colspan="4"> <table class="tds"> <tr> <td width="500" style="border-right: 1px solid #ccc;">总经理签字:</td> <td style="border-right: 1px solid #ccc;">财务负责人签字:</td> <td>报销人:</td> </tr> <tr style="border-top: 1px solid #ccc;">//单个加边,不然容易重复合并单元线 <td style="border-right: 1px solid #ccc;">财务审核:</td> <td colspan="2">部门签字:</td> </tr> </table> </td> </tr> </table> ``` + caption 表头 thead头 tr>th tbody 身体 tr>td 表格中一定要写tbody tfoot 尾 + 写表格table tr th(td)必须一起写 ### 类表格 + 将普通标签转换为表格标签,就可以借用表格的样式布局 + 常用 的结构:display:table>display:table-cell ``` //设置一个表格类 main{ display: table; width: 100%; height: 300px; } // 设出一个行,加上边框 div{ display: table-cell; //一行几个元素,一行分成几个相同的块 border: 3px solid blueviolet; } .div1,.div3{ width: 150px; } <body> <main> <div class="div1">1</div> <div class="div2">2</div> <div class="div3">3</div> </main> </body> ``` ### 列表 + ul 无序列表 ol有序列表 >li + li 中可嵌套p div 等 ul ol 中不可 > 首先先写一个盒子,定好几个盒子,盒子的内容用什么标签,写CSS时先清除样式,设置宽度,高度,设置margin居中,然后使用弹性布局浮动居中,之后再将宽度等分。弹性布局横向,是使用布局的父级写display:flex,而浮动是是谁布局写谁。 ```html <style> /* *通配符 */ *{ /* 初始化样式 清除标签不可控的内外边距 */ /* m0+p0 */ margin: 0; padding: 0; } /* 如果使用列表标签,先清除默认样式 */ ol,ul,li{ list-style: none; } /* 如果使用a标签,先初始化a标签的样式 */ a{ color: gray; text-decoration: none; } //初始化所有标签,后面好写 div{ width: 1200px; height: 80px; background-color: bisque; /* 模块在父空间居中 */ margin: 0 auto; /* 一个定宽的元素被设置了外边距自动后,会在父元素空间内平分剩余空间 */ } div ul{ /* 使用弹性布局,排列 */ /* 给要横排显示的列表li父元素设置弹性布局 */ display: flex; } div ul li{ width: 200px; text-align: center; padding-top: 20px; } </style> <div class="box"> <ul> <li> <a href=""> <h3>精选</h3> <p>猜你喜欢</p> </a> </li> <li> <a href=""> <h3>精选</h3> <p>猜你喜欢</p> </a> </li> </ul> ``` + dl>dt&dd (dt与dd同级,但是dt写小标算是) dl内可以嵌套一个dt,n个dd ,dt里面不可以不能插入div等一系列标签,dd可以,如果使***用span等一系列的行内元素写class,设置宽高一些东西,需要display:inline-block,转换为行内块元素,不然设置宽高无效***。 ```HTML <style> /* 初始化样式/样式重置 */ *{ margin: 0; padding: 0; } a{ color: #333; text-decoration: none; } /* 布局 */ .link-box{ width: 1200px; margin: 0 auto; /* 一个定宽的元素被设置了外边距自动后,会在父元素空间内平分剩余空间 */ background-color: #efefef; /*弹性布局浮动 是需要浮动元素的父元素 写让他横排 例如:dl整个浮动 弹性布局需要写在它的父元素.link-box里面*/ display: flex; } .link-box dl{ width: 240px; } .link-box dl dt{ font-size: 14px; } .link-box dl dd a{ font-size: 12px; color: #666; } .link-box dl dd a:hover{ color: crimson; } </style> <div class="link-box"> <dl> <dt>购物指南</dt> <dd><a href="#">购物流程</a></dd> <dd><a href="#">购物流程</a></dd> <dd><a href="#">购物流程</a></dd> <dd><a href="#">购物流程</a></dd> <dd><a href="#">购物流程</a></dd> <dd><a href="#">购物流程</a></dd> </dl> <dl> <dt>购物指南</dt> <dd><a href="#">购物流程</a></dd> <dd><a href="#">购物流程</a></dd> <dd><a href="#">购物流程</a></dd> <dd><a href="#">购物流程</a></dd> <dd><a href="#">购物流程</a></dd> <dd><a href="#">购物流程</a></dd> </dl> ``` ### 表单 + 表单 input type 类型决定标签 + input 和button对齐常用属性 vertical-align: bottom; 底部对齐 + type: text password 密码 radio(单选)name 名称必须相同 checkbox 复选框 file 选择文件 date 时间 button 按钮 submit 提交按钮 reset 重置按钮 image 图片按钮 不常用 + button type: submit 提交按钮 reset 重置按钮 + 下拉框 lable select > option + placeholder默认提示 + 文本域 textarea <textarea name="" id="" cols="30" rows="10">内容</textarea> <!-- cols设行 rows 设列 --> ```html <form action=""> 用户名:<input type="text"><br> 密码:<input type="password"><br> <!-- checked 默认选中 --> <input type="radio"name="sex" id="male">//name必须相同,才只能选一个 <!-- 点男可以被点上 for要指向id内容 --> <label for="male">男</label><br> <label><input type="radio"name="sex" id="male">女</label><br> <label><input type="radio" name="sex" id="felm">中性</label><br> 爱好: <label> <input type="checkbox" name="" id="">足球 <input type="checkbox" name="" id="">篮球 <input type="checkbox" name="" id="">羽毛球 <input type="checkbox" name="" id="">乒乓球 </label> <br> <!-- 语义化 --> <!-- 四个按钮 button submit(提交数据,刷新页面) reset(重置表单数据)image图片按钮--> <!-- value 值 --> <input type="button" value="按钮1"> <input type="submit" value="提交按钮"> <input type="reset" value="重置按钮"> <input type="image" src="" alt=""> <!-- button --> <button type="submit">提交</button> <button type="button">按钮</button> <!-- 下拉框 --> <label for="">生日:</label> <select> <option value=""请选择</option> <option value="">2022</option> <option value="">2021</option> </select>年 </form> ``` ## 常用样式 ### 文本样式 + color 字体颜色 + font-size:字体大小 + font-family:设置字体 + font-weight:字体加粗 + font-style:字体倾斜 + text-align:文本对齐方式 + text-decoration:文本装饰(下划线) + text-transform:lowercase 字母大写变小写 + text-indent:首行缩进 + line-height:行高 + justify-content: space-around; 均匀排列每个元素 *每个元素周围分配相同的空间* + transition: 0.3s;滑动 + opacity: 0.5;背景色透明 + overflow:hidden 隐藏溢出内容 scroll 添加滚动条 + cursor: pointer;鼠标变成手 + word-spacing:设置单词距离 + (/* 下面三句话为组合,/* 文字太长省略出现... */一定要给宽度样式 */ white-space:nowrap; overflow: hidden; text-overflow: ellipsis;) + letter-spacing:字间距 + object-fit: cover:强制图片不变形 + white-space: nowrap; 强制文本不换行 + vertical-align:middle 垂直居中 {display:table-cell搭配用可以} + transition: 2s linear; 过渡:使标签样式按照动画过程变化,1s表示时间 linear表示匀速 注:width/height=content+padding+border + ``` //文字在线上 <fieldset class="card-header"> <legend> <h3>我们的服务</h3> <p>PFOGRAM HIGHLIGHTS</p> </legend> </fieldset> ``` #### 媒体查询 + 媒体查询,根据条件使用特定的样式集合 ,screen 判断条件,判断展示页面的屏幕是不是普通的显示器(pc,ipad,mobile),max-width 当前浏览器窗口小于指定值。也可使用网格布局设置写出,可参考苹果官网 + 最大最小值:/* 尺寸的最大最小限定 */ max-width: 900px; min-width: 100px; min-height: 100px; max-height:900px ```HTML <!-- col-[size]-[num] 用于创建列。size 控制不同窗口尺寸下的样式,num控制对应的列数(就是份数-6就是十二份占六份,占1/2,4占1/3) --> <!-- 在col-lg中 大型台式电脑尺寸时,占6/12=1/2,col-md中型台式电脑尺寸时4/12=1/3占屏幕1/3,col-sm小型平板是占1/2, --> @media screen and (max-width:1200px) { body { background-color: lightsalmon; height:300px; } @media screen and (max-width:500px) { .col-sm-12{ width: 100%; } } <ul> <li class="col-lg-6 col-sm-12"> <div class="item"></div></li> <li class="col-lg-6 col-sm-12"> <div class="item"></div></li> <li class="col-lg-6 col-sm-12"> <div class="item"></div></li> </ul> ``` ### css样式 #### css选择器 | 选择器 | 例子 | 描述 | | :------------------------------ | -------------------------------------------------------- | :----------------------------------------------------------- | | 通配符选择器 * | *{ } | 选中所有 | | 标签选择器 body p h1-h6 ul li a | body{ } | 根据标签选中范围 | | id选择器 | <id="c"> | #c 前缀用点 id 选择器不能重名 | | 类名选择器(class) | <class="a" > | .a 前缀用点 | | 并列选择器 | ul,ol{ list-style:none } | 并集 ul和ol全部用此样式,用逗号 | | 后代选择器 | ul li{ } | 使用空格隔开 | | 子选择器 | h1 > strong | 用于选择直接的紧邻子标签/选择器 h1 > strong 可以解释为“选择作为 h1 元素子元素的所有 strong 元素”。(父子关系) | | 相邻选择器 ~ | h1 ~ p { **color:** blue; **font-size:** 18px; } | 兄弟元素之间无需紧邻,二者有相同的父元素 | | 紧邻选择器+ | h1 + p { **color:** blue; **font-size:** 18px; } | 用于选择位置靠后的紧邻兄弟标签,二者有相同的父元素 | | 属性选择器 | input[type="text"] { **color:** blue; } | 属性选择器用来匹配具有特定属性的元素。属性选择器的定义方式与标签选择器相似,只不过需要在标签的后面使用方括号`[ ]`来指定标签具有的属性信息,如下所示: | + 伪元素 利用样式在页面上添加内容,伪造标签 before after #### 伪类选择器 | 选择器 | 例子 | 描述 | | :------------- | ------------------------------------------------------------ | :----------------------------------------------------------- | | :active | a:active{ box-shadow: 0 0 5px #222; } | 鼠标按下效果 | | :hover | a/div:hover{color:red } .box-bttom:hover .select{display: block;} | 鼠标悬停效果 滑动到box-bttom:的层时select的层显示 | | :link | .a:link{ color:red } | 当前地址没有被浏览器访问过颜色红色 | | :visited | .a:visited{ color:red } | 当前的链接地址被访问过(在浏览器中) | | :focus | input:focus{border: 5px solid blue}; | 表单获取焦点(鼠标点上去)时 ,input 框变色 | | :checked | input:checked{color: chartreuse; } | 匹配处于选中状态的 <input> 元素 | | :nth-child(n) | ul li:nth-child(3){ } | 选中父元素的第3个子元素 | | nth-of-type(n) | .li:nth-of-type(2){ color: salmon; } | 匹配父元素的第二个子元素/nth-of-type 分类型查找 | | :nth-child(4n) | ul li:nth-child(4n){ text-decoration: overline; } | 选择4的倍数 | | :first-of-type | ul li:first-of-type{ font-weight: bold; } | 匹配父元素中的第一个加粗元素 | | :last-of-type | p:last-of-type | 匹配父元素中的最后一个 <p> 元素 | #### 伪元素 | 伪元素 | 例子 | 例子描述 | | ------------ | --------------------------------------------------------- | --------------------------- | | ::after | p::after | 在每个 <p> 元素之后插入内容 | | ::before | p::before | 在每个 <p> 元素之前插入内容 | | 清除浮动 | .a::before,.a::after{content:"",clear:both,display:block} | | | 点击写小弹框 | 可以写在内容中来写 | | #### 选择器权重 + 浏览器只会展示权重最高的样式 + 行内style>id>class>tag/* + *通配符 全选 权重0 + 标签选择器 (权重1) + 类选择器 (权重10) + id选择器 (权重100) + 父子选择器 #p del (权重叠加) + importment权重无限大 ## 布局 ### 盒模型 + width 宽 + height 高 + padding 内填充(字与盒子距离) + margin外边框 ( [深入理解css中的margin属性 - Wayne-Zhu - 博客园 (cnblogs)](https://wwwblogs/zhuzhenwei918/p/6124263.html) ) + border 边框:1px soild red; + border-radious:圆角 + border-collapse: collapse 合并表格相邻边框, 相邻的两个边框会合并为一个单一的边框 + background-color:背景颜色 + background-image:url();背景图片 + background-repeated:no-repeate 图片背景不重复 + background-position: center center; //图片位置 + background-size: auto 70%; // 设置背景图像的尺寸 + outline:1px soild red 轮廓线 + display:block/inline-block/inline + box-sizing: border-box; 边框盒模型 + /*内容溢出:隐藏 */ overflow: hidden; /* ,有内容超出才处理,无法单独使用,允许用户调整大小 */ resize: both; ``` //小三角 <title>小三角</title> <style> .sighn{ width: 0px; height: 0px; border-left: 5px solid transparent; border-top: 5px solid transparent; border-right: 5px solid transparent; border-bottom: 5px solid #000; } </style> </head> <body> <div class="sighn"></div> </body> ``` ### 弹性布局 + display:flex 弹性布局 需要浮动的父元素写弹性布局 ``` /* 对齐方式 */ justify-content: center; /* 居中排列 */ justify-content: start; /* 从行首开始排列 */ justify-content: end; /* 从行尾开始排列 */ justify-content: flex-start; /* 从行首起始位置开始排列 */ justify-content: flex-end; /* 从行尾位置开始排列 */ justify-content: left; /* 一个挨一个在对齐容器得左边缘 */ justify-content: right; /* 元素以容器右边缘为基准,一个挨着一个对齐, */ /* 基线对齐 */ justify-content: baseline; justify-content: first baseline; justify-content: last baseline; /* 分配弹性元素方式 */ justify-content: space-between; /* 均匀排列每个元素 首个元素放置于起点,末尾元素放置于终点 */ justify-content: space-around; /* 均匀排列每个元素 每个元素周围分配相同的空间 */ justify-content: space-evenly; /* 均匀排列每个元素 每个元素之间的间隔相等 */ justify-content: stretch; /* 均匀排列每个元素 'auto'-sized 的元素会被拉伸以适应容器的大小 */ /* 溢出对齐方式 */ justify-content: safe center; justify-content: unsafe center; /* 全局值 */ justify-content: inherit; justify-content: initial; justify-content: unset; ``` | 值 | 描述 | 测试 | | :------------ | :----------------------------------------------------------- | :----------------------------------------------------------- | | flex-start | 默认值。从行首起始位置开始排列。 | [测试 »](https://www.runoob/try/playit.php?f=playcss_justify-content&preval=flex-start) | | flex-end | 从行尾位置开始排列。 | [测试 »](https://www.runoob/try/playit.php?f=playcss_justify-content&preval=flex-end) | | center | 居中排列。 | [测试 »](https://www.runoob/try/playit.php?f=playcss_justify-content&preval=center) | | space-between | 均匀排列每个元素,首个元素放置于起点,末尾元素放置于终点。 | [测试 »](https://www.runoob/try/playit.php?f=playcss_justify-content&preval=space-between) | | space-evenly | 均匀排列每个元素,每个元素之间的间隔相等。 | [测试 »](https://www.runoob/try/playit.php?f=playcss_justify-content&preval=space-evenly) | | space-around | 均匀排列每个元素,每个元素周围分配相同的空间。 | [测试 »](https://www.runoob/try/playit.php?f=playcss_justify-content&preval=space-around) | | initial | 设置该属性为它的默认值。请参阅 [*initial*](https://www.runoob/cssref/css-initial.html)。 | [测试 »](https://www.runoob/try/playit.php?f=playcss_justify-content&preval=initial) | | inherit | 从父元素继承该属性。请参阅 [*inherit*](https://www.runoob/cssref/css-inherit.html)。 | | ### 浮动 + 指定元素脱离原本的文档流沿着容器的左侧或右侧进行排列,允许其他行内(块)对自身进行行环绕排列(MDN)float:left/right 浮动,浮动是谁要浮动则写在哪里,不写父类。 eg:ul>li li写浮动,ul写清除浮动 + 使用原则1.如果使用浮动,就要将同级的标签全部设为浮动 2.一定要记得清除浮动 + 浮动会造成容器的高度塌陷 1.容器标签使用overfiow 2.容器标签在前后缀上转成block并添加clear样式,需要清除浮动的父类写清除。如下代码,div需要清除浮动,使用main来写清除浮动样式。 .a::before, .a::after{content:"",clear:both,display:block} · ``` // 当左边是图片,右边是文字时,可以写图片左浮动,使文字围绕图片在右边 如果中间自适应,则两边需要左浮动,右浮动,如果横排并列,直接都左浮动就可以 双飞翼布局 /* main{ background-color: rgb(224, 183, 183); height: 300px; } .div1{ float: left; width: 150px; height: 200px; border: 5px solid blue; overflow: hidden; } .div2{ float: right; width: 150px; height: 200px; border: 5px solid orange; } .div3{ height: 200px; border: 5px solid blueviolet; margin: 0 150px; } main::before; main::before{ content:""; display:block; clear:both } </style> </head> <body> <main> <div class="div1">1</div> <div class="div2">2</div> <div class="div3">3</div> </main> </body> </html> ``` ### 背景图位置(精灵图) + 参考0113 百度作业,苹果官网 + 设置背景图片(图片精灵,需要用background-postion:来调整出我们想要的图片) 1.首先设置一个<div class=""></div>,写一个样式添加背景图片 background-image: url('./img/nicon.png');背景图片要包裹写在背景里的内容 2.设置背景图片父级的宽高,浮动,相对定位等,在列表中就设置li的 3.设置图片的宽高,(最好用百分数写),绝对位置设置图片的位置。 4.清除浮动 5.放在图片上,出现弹框,写出前后缀,记得写display:none,在写hover里面display:block。 6.经常写背景图片要记住 ``` .a{ // 一般根据相对定位来写图片位置,给紧邻的父级写出 position:relative position:absolute; // 图片定位在哪里,图片在父元素中居中 right:0; left:0; margin: 0 auto; //写背景图片固定搭配 background-image: url(); background-repeat: no-repeat; //图片不重复 background-position: center center; //图片位置 background-size: auto 70%; // 图片大小 } ``` ### 定位 #### 相对定位 position:relative 1.使用相对定位的元素不会影响周围元素的布局 2.元素移动的基准点在标签布局的原有位置 可以使用left/top/right/bottom样式控制元素的水平方向和垂直方向的移动距离 距离是由元素边框和原位置的相同方向的边界之间的距离(不脱离文档流) 3.原有空间位置时会被保留的,后续的元素不会进行递补 4.定位元素的垂直层级关系是在普通元素的上方 #### 绝对定位 position:absolute(脱离文档流) 1.拥有绝对定位样式的元素原有的空间是不保留的,后续的元素会正常递补 2.绝对定位元素的默认移动基准点是body标签的左上角 3.可以自定义绝对定位元素的基准点,规则是获取 距离自己最近的 拥有非静态定位样式的 父级(上层)元素 4.移动距离的设定也是以自身标签的边界和定位事基准元素的边界距离 5.绝对定位元素的层叠关系也在普通元素的上方 水平向右正方向 水平向下正方向 6.添加有绝对定位样式的元素自身的特性会发生变化,元素的大小默认取决于内容的大小 如果设置有宽高,就以设置样式为准(行内标签不用改成行内块元素了) ``` #outer { position: relative; width: 500px; height: 500px; background-color: rgb(199, 196, 5); overflow: hidden; resize: both; /* 重置标签大小 */ } #inner { position: absolute; /* 居中 */ left: 0; right: 0; top: 0; bottom: 0; margin: auto; /* 居中,不用写固定值 */ width: 100px; height: 100px; background-color: rgb(51, 132, 185); } /* 绝对定位元素的外边距事根据定位位置进行偏移的 就是绝对定位中left 50px,margin20 居左叠加20,在原有的基础上又移动*/ /* 想要使用绝对定位居中处理,需要将各方向的值圈定出合适的区域, 同时将对应方向的外边距都设置成auto值,就可以实现居中 */ </style> </head> <body> <div id="outer"> <div id="inner"> </div> </div> </body> </html> ``` #### 固定定位 position: fix; (脱离文档流) 能够控制元素固定在浏览器窗口的某个位置 定位基准点就是窗口的左上角 其他的特性和绝对定位相同 #### 粘性定位 position: sticky; 是相对定位和固定定位的结合体 根据指定的位置,如果容器标签和浏览器窗口边缘的距离大于设置的距离时, 元素以相对定位特点展示 如果小于指定的距离值,就会以固定定位进行展示 如果容器标签离开浏览器窗口区域,这个标签也会滚动消失 ``` <style> .item-header{ position: sticky; top: 0; background-color: rgb(190, 243, 43); } </style> </head> <body> <div class="list"> <div class="item"> <div class="item-header"> 分段标题1 </div> <ul> <li>1</li> <li>2</li> <li>3</li> <li>4</li> <li>5</li> <li>6</li> <li>7</li> <li>8</li> <li>9</li> <li>10</li> </ul> </div> <div class="item"> <div class="item-header"> 分段标题2 </div> <ul> <li>1</li> <li>2</li> <li>3</li> <li>4</li> <li>5</li> <li>6</li> <li>7</li> <li>8</li> <li>9</li> <li>10</li> </ul> </div> <div class="item"> <div class="item-header"> 分段标题3 </div> <ul> <li>1</li> <li>2</li> <li>3</li> <li>4</li> <li>5</li> <li>6</li> <li>7</li> <li>8</li> <li>9</li> <li>10</li> </ul> </div> <div class="item"> <div class="item-header"> 分段标题4 </div> <ul> <li>1</li> <li>2</li> <li>3</li> <li>4</li> <li>5</li> <li>6</li> <li>7</li> <li>8</li> <li>9</li> <li>10</li> </ul> </div> <div class="item"> <div class="item-header"> 分段标题5 </div> <ul> <li>1</li> <li>2</li> <li>3</li> <li>4</li> <li>5</li> <li>6</li> <li>7</li> <li>8</li> <li>9</li> <li>10</li> </ul> </div> </div> </body> </html> ``` ### 网格布局 + bootstrap:Bootstrap 中的网格系统的基础是由media和float搭配实现的。其中列偏移效果是使用增加左侧外边距方式完成的(可写伸缩屏,也可参考苹果官网那个页面) ``` <!-- bootstrap.min.css 提供全部样式 --> <link rel="stylesheet" href="bootstrap/css/bootstrap.min.css"> <!-- bootstrap 的正常使用依赖于 jquery --> <script src="bootstrap/js/jquery.min.js"></script> <!-- bootstrap.min.js 提供框架中的动态效果 --> <script src="bootstrap/js/bootstrap.min.js"></script> 图库标的使用,和文字一样 <link rel="stylesheet" href="font-awesome/css/font-awesome.min.css"> <style> .fa{ font-size: 20px; color: royalblue; } </style> </head> <body> <p> 使用font-awesome 图标需要添加“fa fa- ”这样的类名,具体的样式修改和普通文字一样 </p> <i class="fa fa-user-circle-o" aria-hidden="true"></i> <span>用户</span> ``` + 网格布局 ``` 网格的基本写法 参考0114 //网格初始格式 style{ .row .col{ float: left; min-height: 1px; } .row::before, .row::after{ content: ''; clear: both; display: block; } .row .col-0 { display: none; } .row .col-1 { width: 8.333%; } .row .col-2 { width: 16.666%; } .row .col-3 { width: 25%; } .row .col-4 { width: 33.333%; } .row .col-5 { width: 41.666%; } .row .col-6 { width: 50%; } .row .col-7 { width: 58.333%; } .row .col-8 { width: 66.666%; } .row .col-9 { width: 75%; } .row .col-10 { width: 83.333%; } .row .col-11 { width: 91.666%; } .row .col-12 { width: 100%; } } //引用bootscript浮动格式和宽度样式 <div class="container"> <!-- .row 创建水平行 --> <div class="row"> <!-- 大屏时他们占9/12的屏幕 中屏时他们占9/12的屏幕 9与3是同一层级,占满屏 和列的用法差不多--> <div class="col-lg-9 col-md-9"> <!-- 在9/12的屏幕下.row 创建水平行 --> <div class="row"> <!-- 在9/12的屏幕下,将9/12的屏幕分为四等份 3/12=1/4 --> <div class="col-md-3 col">3/12/10</div> <div class="col-md-3 col">3/12/10</div> <div class="col-md-3 col">3/12/10</div> <div class="col-md-3 col">3/12/10</div> </div> </div> <!-- 大屏时他们占3/12的屏幕 中屏时他们占3/12的屏幕 9与3是同一层级,共同占满屏--> <div class="col-lg-3 col-md-3"> </div> </div> <h3>列嵌套</h3> //创建一个行 <div class="row"> <div class="col-md-10 col" > 在占屏幕的4/5的前提下,把这4/5都在分为四等分 <div class="row"> <div class="col-md-3 col">3/12/10</div> <div class="col-md-3 col">3/12/10</div> <div class="col-md-3 col">3/12/10</div> <div class="col-md-3 col">3/12/10</div> </div> </div> <div class="col-md-2 col">2</div> <div class="col-md-10 col">10</div> <div class="col-md-2 col">2</div> </div> ···································································································· ``` ### 图标库 + 百度上找阿里图标库,在文件中查找 ``` <i class="iconfont"></i> //iconfont是固定的 <div class="iconfont icon-guanbijiantou"></div> <i class="iconfont icon-guanbijiantou"></i> ``` # Javascript ### 数据类型 ##### 基本类型 + 数字类型 Number var a = 1; var b = -1.5; //负号紧跟数字前面 var c = 123456e5; //科学计数法 + 字符串类型 String 表示一些文本信息,在字符串中书写空格也是会保留的 对于长字符串,常规的书写格式不允许换行 var d = '这是一个字符串'; var e = 'this is a string'; var f ='<div> </div>'; var g = "字符串里面也有'引号'" var h = 'dsfde \'a \'gfhudk'; //对于一些特殊字符,可以使用\’转义符号 + 布尔类型 Boolean 只有两个值:真 假。表示条件的计算结果 var i = true; var j = false; + 未定义 undefined 只有一个值,表示没有定义具体值的变量和属性 // var k = undefined; var k; + 空 null 只有一个值,表示,没有具体的结果 var m =document.getElementById('aaa'); ##### 引用数据类型 + 对象类型 Object // 表示一系列相关基本数据的集合 /* 对象的语法格式: { 属性名:属性值, 属性名:属性值, ... } 属性名也要遵从变量名的定义规则 */ var n ={ brand: '联想', weight: 1500, isRed: false, address: {} }; + 数据结构 数组Array :保存一系列 有顺序要求的 数据类型相同或功能相似的 数据 var p = [1,2,3,4,5]; ##### 命名规则 + 变量名和属性名的命名规则 + 可以使用(大小写)字母、数字、_、$这些符号 + 不能使用数字开头 + 不能使用汉字 + 长名称的中间不要使用空格 document.getElementById() + 当需要使用多个单词才能定义名称时,最好使用 小驼峰命名法 + 除去第一个单词,后面的单词首字母都大写 常见错误 + 符号书写了中文符号 + 是用来错误的定义名称(没定义就使用,使用时写错名称) + 没有遵从具体的数据类型用法(逻辑错误) + 没有遵从基本的使用规范 + 对于变量的声明,要遵从先声明再使用的逻辑 + var k; //不建议声明变量时,不设定初始值 ### 属性运算符 ``` var obj = { username: '张三', age: '22', friend: { username: '李四' } }; // 从对象中获取需要的属性值,使用 点操作符 通过属性名进行获取 console.log(obj.username); console.log(obj.age); // 点操作符在 赋值 号的右边使用,执行的是获取逻辑 var username = obj.friend.username; console.log(username); // 点操作符在 赋值 号的左边使用,执行的是设置逻辑 obj.username = '王五'; console.log(obj); // 在一个对象中扩展属性 obj.sex = '男'; console.log(obj); // 也可以使用[]的方式扩展或获取属性 var h = 'height'; obj[h] = 170; console.log(obj); console.log(obj[h] ); // 从数组中取出需要的数据 var arr = [ 'm','n']; // 需要通过数据存储的索引值(数据在数组的排序位置,默认从0开始) console.log(arr[0]); console.log(arr.length);//获取数组的长度,表示数组内部存储了多少个值 arr[20] = 'o'; console.log(arr); console.log(arr.length); ``` ### 运算符 ##### 算数运算符 + 加法 + ``` //数字之间的加法计算执行的是数学逻辑 //字符串之间的加法计算执行的是拼接逻辑 var a = 1, b = 2; var c = a + b; console.log(c); var d = 'hello ', e = 'world'; var f = d + e; console.log(f); var g = 200 + 100 + 'px'; console.log(g); // 数字和字符串之间的加法计算,会先将数字隐藏性的转换成字符串,在进行拼接 //隐式类型转换;在计算过程中,JS 自动根据类型的差异进行向相同类型转换的过程 //计算机在进行普通计算时,是会有误差的,无法消除 console.log(0.1 + 0.2); ``` + 减法 - ``` //减法计算都是优先将数据转换成数字类型在进行计算 //只有纯数字组成的字符串才可以进行正常转换 console.log(5 - 6); // -1 console.log(5 - '6');//-1 console.log('5' - '6');//-1 console.log('a' - 'b'); //NAN :not a number //当出现无法转换成数字的内容出现在计算过程中时,计算结果都是NaN //只要有NaN参与的计算,结果都是NaN. console.log(NaN + 5 - 10);// NAN ``` + 乘法 * 除法/ 求余% ``` /数据类型转化逻辑和减法一样 console.log(5 * '6');//30 console.log('5' * '6'); //30 console.log('5' / NaN);//NAN console.log(5 / '6');//0.8333333 console.log(5 / 0); //Infinity无限的 console.log(10 % 3); //1 ``` ##### 赋值/比较运算符 ``` 赋值运算: var a = 1; //a = a + 5; a += 5; //效果完全相同,就是特定写法下的简写方式 console.log(a); // -= *= /= %/ 逻辑完全相同 ar i = 0; //i += 1 ; //++ 自增符号,控制变量的值加1 i++; console.log(i); ++i; console.log(i); var j = 0; console.log(j++); // 0 console.log(j); // 1 var m = 0; console.log(++m); // 1 console.log(m); // 1 // 如果 ++ 在后,就会先将变量的值作为表达式的计算结果,然后在进行加一操作 for(i=0 ;i<10;i++ ){ ++在后,会运算到i<10,就进行括号内运算,之后i++,在i<10循环 } //如果 ++ 在前 就会先进性加一操作,然后将新的变量值作为表达式结果 自减 -- 比较运算: //比较运算符计算的结果都是布尔值 // 大于 > 小于 < 大于等于>= 小于等于<= console.log(5 > 9); //false console.log(10 > 4); // true console.log(6 >= 6); // true //字符串之间的比较本质是按照 字母的 ASCII 码进行逐位比较 console.log('aba' > 'aaa');//ttrue var x = 50; //这里书写的逻辑和数学中的逻辑是完全不同的 // 会优先计算第一个比较符的结果,等到一个布尔值,在和第三个数字作比较 // true 可以当作 1 来看待,false 可以看作 0 看待 console.log(1 < x < 9); //true // 相等运算符 // == 相等 === 全等 !=不等 !==全不等 // === 全等 值与类型的变量比较 console.log(1 == 1); //true console.log(1 == '1'); //字符串和数字做双等比较,会优先将字符串转换成数字,在进行比较 false //双等号尽量不使用,因为会出现隐式类型转换,将两侧的数据转换成想同类型,在进行值比较 console.log(1 === '1'); false //优先使用全等号,先判断类型是否相同,在判断值是否相同 console.log(1 != '1'); //用法同双等 true console.log(1 !== '1'); //用法同全等 true console.log(null==undefined); //true null 与 undefined 都是假值false,所以相等 console.log(null===undefined); // false 类型不同,不相等 console.log(2==true);//数字与布尔值转换优先转换布尔值,true转换为1,1与2不相等 console.log(NaN===NaN); // NaN和任何值都不相等,包括自己 false ``` ##### 逻辑运算符 ``` // 真值:自身为 true 或者可以被转换为 true 的值叫真值,其他都叫假值 // 假值常见的有6个:false、空字符窜 ''、null 、 undefined、 NaN、数字 0 // 与,并且 && // 可以将多个表达式串联到一起, //只有每一个表达式的值都是 true 或者可以转换为true. 整体计算的结果是最后一个表达式的结果 // 如果表达式中存在假值,就返回一个假值表达式的结果 var phone={ color:'red', price:1500 } var pay = phone.color==='red' && phone.price < 2000 console.log(pay); true var m = 1 + 6 && 7 - 9; console.log(m); //-2 console.log(NaN && 0 && false);//NAN var x = 5; 1 < x && x < 9 // 或 || // 可以将多个表达式串联到一起 //只有每一个表达式的值都是 false 或者可以转换为false.整体计算的结果是最后一个表达式的结果 // 如果表达式中存在真值,就返回一个真值表达式的结果 console.log(null || 0 || false); //false console.log(null || 0 || true || 100); // true // 非,取反 ! // 会先将计算的值进行布尔值转换,然后再取反 console.log(!true); //false console.log(4 < 5 && 100 > 90 || 0 || !NaN);//true ``` ##### js的隐式转换 + 大多数情况下,隐式转换都遵循这个规则,当然有特殊情况,特殊情况特殊对待就行了,当使用==判等时,会转成同类型再比较 对象---》字符串 ---》数值 布尔 ---》数值 ###### 对象和布尔值比较 + 对象和布尔值进行比较时,对象先转换为字符串,然后再转换为数字,布尔值直接转换为数字 ``` [] == true; //false []转换为字符串'',然后转换为数字0,true转换为数字1,所以为false ``` ###### **对象和字符串比较** + 对象和字符串进行比较时,对象转换为字符串,然后两者进行比较。 ``` [1,2,3] == '1,2,3' // true [1,2,3]转化为'1,2,3',然后和'1,2,3', so结果为true; ``` ###### **对象和数字比较** + 对象和数字进行比较时,对象先转换为字符串,然后转换为数字,再和数字进行比较。 ``` [1] == 1; // true `对象先转换为字符串再转换为数字,二者再比较 [1] => '1' => 1 所以结果为true ``` ###### **字符串和数字比较** + 字符串和数字进行比较时,字符串转换成数字,二者再比较。 ``` '1' == 1 // true ``` ###### **字符串和布尔值比较** + 字符串和布尔值进行比较时,二者全部转换成数值再比较。 ``` '1' == true; // true ``` ###### **布尔值和数字比较** + 布尔值和数字进行比较时,布尔转换为数字,二者比较。 ``` true == 1 // true ``` ##### 字符串连接符与算术运算符隐式转换规则混淆 + 将字符串连接符(+ : 只要+号两边有一边是字符串)与算术运算符(+:两边都是数字)的隐式转换搞混淆 + 1.字符串连接符+:会把其他数据类型调用String()方法转成字符串然后拼接 ``` //+是字符串连接符: String(1) + 'true' = '1true' console.log ( 1 + "true" );//1true var bar=true; console.log(bar+"xyz") // truexyz ``` + 2.算术运算符+ :会把其他数据类型调用Number()方法转成数字然后做加法计算 ``` //+是算术运算符 : 1 + Number(true) = 1 + 1 = 2 console.log ( 1 + true );//2 // +是算术运算符 : 1 + Number(undefined) = 1 + NaN = NaN console.log ( 1 + undefined );// NaN // +是算术运算符 : 1 + Number(null) = 1 + 0 = 1 console.log ( 1 + null );//1 ``` + 字符串连接符- ,将字符串转换为数字 ``` var bar=true alert("1"-bar); //0 alert("1" - 23 +false) //-22 将字符串转为数组,布尔值转为数组 ``` ### 函数的基本用法 ##### 声明式函数和赋值型函数 + 声明式函数(具有函数名) ``` function fo(){ console.log('fo');} // 调用函数:执行内部的语句 fo(); ``` + 赋值型函数(匿名函数) ``` // 把函数作为一个值使用 var fn = function () { console.log('fn'); } fn(); var obj = { x:function(){ console.log('x'); }}; obj.x(); ``` ##### 形参和实参 ``` // 声明函数时书写的小括号用于 声明函数内部需要的参数的 :形参 (提供给函数内部逻辑的变量) // 执行函数时书写的小括号用于 为函数的参数传递具体的值 :实参 (满足函数执行时需要是的具体值) function sayHi(username){ console.log(username + '说 你好!'); } sayHi('小米'); // 当为函数设计多个形参时,具体的实参要和形参顺序对应(函数的参数是由于顺序要求的) function sub(a, b){ console.log(a,b); // 10, 5 console.log(a - b); // 10 } sub(10,5); // 如果传递的实参数量小于形参数量,没有获取到值的参数按undefined处理 sub(50); // 50 undefined // 如果传递的实参数量大于形参数量,形参按顺序结束值之后,多余的值会被忽略 sub(100,50,20); // 100,50 ``` ##### arguments ``` function sum(){ // 函数在执行时,内部会初始化一个参数对象,作用就是收集函数所有的实参,放置在一个类数组对象中 // 主要是应对函数参数数量不确定的场景 console.log(arguments);} sum(1,2); sum(1,2,3,4,5); ``` ##### 函数的返回值 ``` // 能够将函数内部的值传递到函数的外部,通过 return关键字把内部值传到外部 // return 中断函数的执行 function add(x,y){ return x + y; console.log('return 后面的代码不会执行') } var s = add(100, 300); console.log(s); function fx(){ // return 后无东西,函数执行的结果按underfined(未定义) 处理 return;} var y = fx(); // 如果函数内部没有给定返回值,函数执行的结果按underfined(未定义) 处理 console.log(y); ``` ### 函数的作用域 + 全局和局部作用域 ``` // 作用域:限制声明变量能够使用的范围 // var 、 function、 函数的形参也是声明 // 全局作用域:当前页面在浏览器内部运行时,所有js代码整体运行的环境(只有一个) // 局部作用域: 函数声明时,大括号({})圈定的范围叫做局部作用域(词法作用域) // 在全局作用域中声明的变量称为 全局变量 // 全局变量可以在声明之后的任意位置被使用 // 在局部作用域中声明的变量称为 局部变量 // 只能在当前函数范围内被使用 var a = 1; console.log('全局变量a',a); function fo(){ var b = 2; 在局部找到声明,则为局部函数,未找到声明,直接赋值,为全局变量 console.log('全局变量a',a); console.log('局部变量b',b); return b; } fo(); // 2 // console.log('局部变量b',b); // error b是未定义的 这个引用的b是全局变量的,但是全局变量未定义 ``` + 函数内部变量值的查找过程 ``` var x = 1; function outer(){ var x = 10 ; var y=2; function inner(){ var z = 3; console.log(x, y, z); } inner(); } outer(); console.log(x); // 10 2 3 // 1.优先在当前函数内部作用域中查找有没有对应变量的声明,如果有,就获取对应的值 // 2.如果没有,就去创建这个函数所在的作用域中查找 // 3. 重复步骤1-2,一只查找到全局作用域 // 4.如果找到最后都没有发现变量声明,就会报错 ``` ### 流程控制语句 ##### if 条件语句(范围限定) ``` /* 语法结构 if(判断条件表达式){ 当条件为真时,执行的代码片段 }else{ 当条件为假时,执行的代码片段 } if语句的组合写法 if() {} if() {} else {} if() {} else if() {} else {} */ eg:var x = 70; if (x > 80) { console.log('x > 80'); } else if (x > 60) { console.log('x > 60'); } else if (x > 40) { console.log('x > 40'); } // 嵌套写法 var p = { color: 'black', price: 1900 } if (p.color === 'black') { if (p.price < 2000) { console.log('买它'); } else { console.log('太贵了,不想要'); } } else { console.log('不是黑色,不想要'); } //条件语句的{} 不会创建局部作用域 //建议:现阶段一般不要再非函数 {} 里面声明变量,如果确实需要声明,也不要在 {} 外部使用 // 返回值 = 条件 ? 条件为真时实际计算的表达式 : 条件为假时实际计算的表达式 n = (m > 10) ? (m * 2) : (m / 2); ``` ##### switch... case... + switch 声明条件语句,将判断的值一次和内部 case 定义的值作全等比较 如果相等,就执行对应 case 后面的代码片段 如果不相等,就继续判断下一个 case 的值 如果都不想等,就默认执行 default 定义的语句 内部 break 用于控制跳出条件语句 一般用于判断 枚举值(设置特定值) 的逻辑 ``` var day = 2; switch (day) { // 可以将多个判断值进行合并,共用同一个代码片段(原因就是再上一个判断值后面没有 break ) case 1: // { // console.log('今天星期一'); // break; // } case 2: { console.log('今天星期二'); break; } case 3: { console.log('今天星期三'); break; } // 最后的 default 是可选的,类似于 if 语句中最后的 else default: { console.log('其他日期'); } } ``` ### 循环语句 ##### for 循环语句 + 使用场景:有明确的重复次数 语法结构: for(声明计数的起始值; 判断循环结束的条件, 比较次数是否达到临界值; 累加次数 ){ 需要循环执行的代码片段 } 执行顺序: 1. 先执行声明次数的语句,获取到次数变量 2. 判断是否满足结束循环的条件, 3. 如果条件为真,就执行一次循环代码 4. 次数累加步骤 5. 再次判断循环条件,重复执行 2-4 步骤 6. 一直执行到条件判断为假,结束循环 计次变量是可以在循环体内部使用的,每循环都表示当前的次数 ``` for(var i=0;i < 10; i++){ console.log('重复', i); } console.log('循环结束', i); var arr = ['a', 'b', 'c']; for(var j=0; j < arr.length; j++){ var item = arr[j]; console.log(item,j); } function sum(){ console.log(arguments); var ret = 0; for(var i=0; i <arguments.length; i++){ var item = arguments[i]; ret += item; } return ret; } var s= sum(4,5,6,7,8); console.log(s); ``` ##### while 循环 + 使用场景:没有次数要求,只要满足条件就会结束 语法结构: while(是否进行下一循环的判断条件){ 条件为真时执行的循环代码 } 循环体内部一定要有不断修改判断条件的代码,否则就会造成死循环 ``` //需求:一次减3,小于2就停下来 var m = 10; var n = 0; while (m >= 2) { // 几次停下来 n++; m -= 3; // if(m < 2){ // break; // } console.log(m); } console.log(n); ``` ##### do{ }...while() + do { 循环体 }while(判断条件); 先执行一次循环体,在进行循环判断决定是否循环 会保证循环代码至少执行一次 ``` // 提前中断循环 for( var h = 0; h < 10; h++){ if(h === 3){ // 跳过当前循环剩余步骤,直接进入下一循环 continue; } if(h >= 7){ //提前结束循环 break; } console.log(h); } ``` ### 数据类型的判断 ##### typeof + typeof 返回一个字符串,表示对应数据的类型 ,可以判断基本类型数据(除了 null)和函数 ``` var type = typeof 123; console.log(type); // number console.log(typeof NAN); // number console.log(typeof 'abc'); // string console.log(typeof true); // boolen console.log(typeof undefined); // undefined console.log(typeof function () { }); // function console.log(typeof null); // object console.log(typeof []); // object console.log(typeof {}); // object ``` ##### instanceof + instance 实例:通过对应类型构造函数创造出的结果叫实例, + 可以简单的区分出引用数据类型 console.log(123 instanceof Number); // false console.log('abc' instanceof String); //false console.log(true instanceof Boolean); //false console.log([] instanceof Array); // true console.log({} instanceof Object); // true console.log(function(){} instanceof Function); // true console.log([] instanceof Object); // true ##### Object.prototype.toString.call() ``` // 万能方法 function getType(data){ return Object.prototype.toString.call(data).toLowerCase().slice(8,-1); } console.log(getType('abc')); // string console.log(getType(123)); // number console.log(getType(true)); // boolen console.log(getType(null)); // null console.log(getType(undefined)); // undefined console.log(getType([])); // array console.log(getType({})); // object console.log(getType(function(){})); // function console.log(getType(/a/)); // regexp 正则表达式 console.log(getType(new Date())); // date console.log(getType(document.body)); // htmlbodyelement ``` ### 数据类型的特点 + 两大类型: 1.基本类型: Number,number,boolean,null,underfined,string 2.引用数据类型:bject [Array 数据结构] 通过一个地址找到值 ##### 基本类型: + 存储的位置是在内存的栈区,存储的内容就是实际声明的值 + 基本类型的值是不可变的,一旦创建完成,就无法再修改 + 日常的修改操作实际是以原数据为基础,创建新值的过程 var a = 1; var b = 1; var str = 'Hello!' var ret = str.toUpperCase(); // 小写变大写 console.log(ret); //HELLO console.log(str); //hello console.log(a === b); // 在进行值的比较时,就是直接使栈区内存储用具体的值进行比较 var c = b; console.log(c); // 1 // 在使用赋值号进行值传递时,会将对应的值复制一份,传递给新的变量 // 赋值就是复制 b = 5; console.log(c); // 1 // 当原始的变量值发生修改时,新的变量值是不受影响的 ##### 引用数据类型: + 数据存储的位置是在内存的堆区,堆区存储的数据是允许随意的扩大或缩小 + 对应的变量名和数据在堆区中的地址还是存储在栈区的 ``` var obj = {}; console.log(obj); // {} obj.x = 1; console.log(obj); // {x:1} // 引用数据类型的值是可以被修改的 var obj2 = obj; console.log(obj2); // {x:1} obj.x = 5; console.log(obj2); // {x:5} // 引用类型数据在做赋值数据传递时,实际是将栈区中存储的数据地址赋值一份传达过去 // 实际的值没有发生任何变化 obj2.x = 10; console.log(obj2); // {x:10} // 当其中一个变量修改数据时,其他的变量引用结果都会受到影响 function fn(data) { return data; } var m = 100; var n = fn(m); console.log(n); // 100 var o = {}; function fo(data) { data.h = 100; return data; } // data=o; var p = fo(o); console.log(o);// {h:100} console.log(p === o);// true // 函数形参接受的值都是实参变量在栈区中存储的内容(基本类型值、引用类型地址) // 当两个变量在比较时 // 如果两个变量都是基本类型数据,比较的直接就是栈区中的值 // 如果都是引用类型数据,比较的是栈区中存储的地址 console.log({} === {}); // false console.log(1 === 1); // true var i = {}; var j = i; console.log(i === j);// true ``` ### 预编译(变量提升) + js 代码在执行时是分两个阶段的:1.预编译阶段 2.执行阶段 + 变量提升 预编译阶段对普通变量声明的操作:(变量提升)(var a;) 当代码要在解释器环境运行前,解释器会先扫描一边代码(不是运行) 会先将所有声明变量提取出来,放置在所有代码的最前面,并且会先给定一个初始值为 undefined ``` //书写 console.log(a); // undefined var a =1 ; console.log(a); // 1 //真正执行 // var a = undefined; //js运行自己做的步骤 // console.log(a); // var a =1 ; // console.log(a);函数提升 ``` ### 函数提升 预编译阶段对声明式函数的操作:(函数提升) 在执行代码之前,会先将代码扫描一遍,将所有声明式函数提取到最前面 并且给定代码定义好的值 ``` // 书写代码 fn(); // fn function fn(){ console.log('fn'); } fn(); //fn // 真正执行过程 // function fn(){ // console.log('fn'); // } // fn(); // fn(); fo(); // fo2 function fo(){ console.log('fo1'); } fo(); // fo2 function fo() { console.log('fo2'); } fo(); // fo2 // 在 js 中,函数是一等公民 // 会先进行变量提升,在进行函数提升,优先保留函数声明的结果 ba(); //ba1 var ba = function(){ console.log('ba1'); } ba();// ba1 function ba(){ console.log('ba2'); } ba();// ba2 // 只要书写代码时,遵从先声明后使用的基本原则,就可以避免提升效果带来的问题 // 同时也要避免函数和变量使用相同的名字 ``` #### 代码执行过程和错误执行顺序 ##### 代码执行过程 + 代码大体的执行顺序是按照 预编译 的结果逐行执行的 + 预编译阶段是按照 作用域的划分和script标签 分段执行的, + 每一段都会先进性预编译,再走执行阶段 ``` <script> // 可以写在头部,和body之后,怕出错后边的运行不了,可多写几个script console.log('head'); // head var x=100; // console.log(y); // error y没有定义 </script> <script> console.log('body'); // body var y = 200 ; var a = 1; console.log(x); //100 function fn() { var b = 2; console.log(a, b);// 1,2 } console.log(a);// 1 fn(); // 当网页中的 js 代码开始运行时 // 会先将全局作用域中的声明进行提升效果 // 然后立刻执行全局作用域中的代码 // 当执行的过程中,触发函数的执行,会激活函数定义的局部作用域 // 接下来会对函数内部的代码进行预编译(声明提升,初始化内部特定的对象 this 和 arguments)和执行 // 当函数内部代码执行结束后,如果函数内部的值没有外部的变量引用、就会销毁这个作用域和内部所有声明的值 // 这个销毁的逻辑称为 垃圾回收机制 // 最后,全局作用域中声明的值只有在全局作用域销毁时(页面关闭时)才会被回收 </script> ``` ##### 错误执行顺序 1.被动错误:语法错误 2.主动错误:使用错误抛出语句 ``` // 当出现错误时,会中断代码执行,错误之前的代码是可以正常运行的 // 错误捕获语句 当 try 语句出现错误时,会被后续的catch 捕获错误 不会影响后续代码执行 <script> try { console.log(x); //X is not undefined // throw new Error('错误'); } catch (error) { console.log(error); } console.log(2); </script> <script> // 上一个标签的错误不会影响下一个标签的运行 console.log(y); </script> <script> console.log('正常输出'); </script> ``` ### 字符串常用方法 + sbustr()原数组改变,其余都不变 + charAt(5),查找第五个字符 5长度。indexof(5)查找第五个字符串的位置,5长度。 substr(2,5)在索引值2后边截5个数,5长度,substr(2)截去前两个。 ##### 字符串转换类型 tostring() + 将任何类型的数据都转换为字符串(参考数据常用类型文件夹) + 原数组不改变 ``` var str ='string' console.log(str.length);//6 console.log(str[2]); //r console.log(str[20]); // undefined //toString() 转换为字符串 var num = 100; console.log(typeof num.toString()); // string // console.log((100).toString()); // console.log(100.5.toString()); console.log(typeof ('' + 100)); // string ``` ##### split()用于分割字符串 + 执行后返回一个数组 + 参数1:是根据指定内容进行截断,并且该内容会去除 + 原数组不改变 + 参数2:指定返回数组的长度,可选。若指定长度小于等于实际分割长度,则按分割结果从索引值 0 位置截取指定长度数组返回;若指定长度超出实际分割长度,则返回实际分割数组,不会额外加长。 ``` 传递空字符串作为参数,可以打散这个长字符串,变成数组 var str = 'abcab'; var ret = str.split(''); console.log(ret); // ['a','b','c','a','b'] ['I','love','you','do','you','love','me'] result = str.split(',', 3); // ['I','love','you'] ``` ##### indexOf():查找字符首次出现位置 + 返回某个字符在字符串指定范围内首次出现的位置 + 从字符串的开头(或指定位置)开始查找,找到第一个匹配的子字符串后返回该子字符(串)的首字符在整个字符串中的对应索引值;找不到返回 -1。 + 参数 1: 必需,进行查找的字符 + 参数 2: 可选。开始查找的起始位置,默认为0。合理取值是 [0, length),且必须为整数。 + 查找是正方向进行的。 + 查找范围是 [start, length) + 原数组不改变 + 参数 2 是可以为 任意整数的,即使指定位置不存在字符。 ``` var str = 'abcabcabc'; var ret = str.indexOf('c', 4);//从第四个位置之后找,合理值[0,length),且必须为整数,查找方向从正方形进行的 console.log(ret); //5 ``` ##### lastIndexOf():查找字符最后出现位置 - 参数 1: 必需,进行查找的字符 - 参数 2: 可选。开始查找的起始位置,默认为字符的长度。合理取值是 [0, length),且必须为整数 - 查找方向是反方向进行的 - 查找范围是 [0, start) ``` // 原数组不改变 var str = 'I,love,you,do,you,love,me'; var index = null; index = str.lastIndexOf('love'); // 18 index = str.lastIndexOf('lave'); // -1 index = str.lastIndexOf('love', 16); // 2 ``` ##### charAt()查找指定位置字符 + 查找位置取值范围为 [0, length),必须为整数 ``` var str = 'abcabcabc'; console.log(str); console.log(str.charAt(5)); // 索引值超出范围 按 空字符串 返回 ``` ##### concat() 拼接 + 可以有传递多个参数,合并多个字符串 + 若参数为费字符串,则方法内部会先强制转为字符串,然后拼接。 + 原数组不改变,返回新的字符串 ``` var str = 'abc'; var ret = str.concat('def', 'g'); console.log(ret, str); ``` ##### replace() 替换 + 有两个参数,执行后返回新的字符串(原数组不改变) + 参数 1:需要被替换的子字符串,可以是指定字符串,还可以是**正则表达式**。对于正则表达式来说首先会根据是否全局匹配(全局/.../g)决定替换行为,如果是全局的则替换全部替换,非全局的只有替换首个匹配的字符串。 + 参数 2:替换字符串或**生成替换字符串的函数**。推荐使用函数。每次匹配到进行替换时都会执行该函数,返回值作为替换的新值。 > 参数 2 如果为函数,则函数参数的规定: > > - 参数 1 为每次匹配到的子字符串 > - 参数 2 为匹配到的子字符串的首字符的索引值位置 > - 参数 3 为进行匹配替换的字符串本身 ``` var str = 'abcabcabc'; var ret=str.replace(/b/g,'e'); // 将 b 换成 e g全局匹配 正则表达式 console.log(ret); // 复杂使用 var str = "I,love,you,Do,you,love,me"; var result = null, i = 0; result = str.replace(/o/g, function () { return ++i; }); // I,l1ve,y2u,D3,y4u,l5ve,me ``` ##### slice() 截取 + slice() 提取字符串的某个部分,并以新的字符串返回被提取的部分。(原数组不变) + 传递两个参数:slice(start, end) - 参数1:截取的起始位置,必需 - 参数2:截取的结束位置,可选。**若未指定此参数,则要提取的子字符串包括 start 到原字符串结尾的字符串。** - 参数可以是负数,那么它规定的是从字符串的尾部开始算起的位置。(从尾部开始算是从 -1 开始的) - 实际索引值较小的位置必须写在前面,否则结果为 空字符串 - 剩余字符串区段是 [start, end) ``` var str = "abcdefghijklmn"; // 虽然参数可以传递负数,但是要保证参数对应的实际索引值,大的数要在第二个参数上 var ret = str.slice(1,-2); // 从第一个到正数11个 (倒数第五个位置截取) console.log(ret); var str = '0123456789'; var str1 = str.slice(2); // '23456789' var str2 = str.slice(2, 6); // '2345' var str3 = str.slice(-2); // '89' var str4 = str.slice(-6, -4); // '45' ``` ##### substr() 方法 截取 + 字符串中抽取从开始索引值开始的指定数目的字符,作为一个新的字符串返回(原数组不变) + 传递两个参数:substr(start, length) - 参数 1:截取的起始位置,必须。如果是负数,那么该参数声明从字符串的尾部开始算起的位置。 - 参数 2:截取的长度,可选。如果省略了该参数,那么返回从指定的开始位置到结尾的字串。 - 截取的长度区段都是正向的。如果指定的长度超过剩余长度,返回剩余的子字符串 - 剩余的字符串区段是 [start, start + length) - ECMAscript 没有对该方法进行标准化,因此反对使用它。但是所有浏览器都支持。 ``` var str = '0123456789'; var str1 = str.substr(2, 5); // '23456' var str2 = str.substr(-7, 5); // '34567' var str3 = str.substr(3); // '3456789' var str4 = str.substr(-3); // '789' console.log(str,str1,str2,str3,str4); ``` ##### substring() 方法 截取 + 用于提取两个指定索引值之间的子字符串 + 传递两个参数:substring(start, end) - 参数1:截取的起始位置。必需。非负整数。 - 参数2:截取的结束位置。非必需,非负整数。如果省略该参数,那么返回的子字符串会一直到字符串的结尾。 - 索引值较小的位置必须写在前面 - 剩余字符串区段是 [start, end) - 只能正向截取,是 slice 的阉割版,原数组不变 ``` var str = '0123456789'; var str1 = str.substring(2, 6); // '2345' var str2 = str.substring(2); // '23456789' ``` ##### toLowerCase() toUpperCase() 字符串大小写转换 ``` var str ='aBCd'; console.log(str.toLowerCase()); console.log(str.toUpperCase()); ``` ##### trim() 去除空格,只能去除两端的空格 ``` console.log(' fafaffaf gaggag '.trim()); console.log(' fafaffaf gaggag '.replace(/ /g,'')); // 利用正则去掉全部空格 ``` ### 回调函数callback/cb ##### 普通回调函数 + 当一个普通函数作为另一个函数的参数被使用时,这个函数就叫做回调函数 + 接受参数的函数 习惯称为 主函数 ``` function fo() { console.log('fo'); } function fn(cb) { console.log('fn'); cb();//执行fo();实参为fo=形参cb } // fo 是 fn 的回调函数 fn(fo); ``` ##### 在实参位上声明函数 ``` // 当函数执行时,直接在 实参 位上进行函数声明 fn(function () { console.log('匿名函数'); }); ``` ##### 函数强调先后顺序 ``` function putFood(cb) { // ... console.log('油热好了'); cb(); } function putEggs() { // .... console.log('鸡蛋炒熟了'); } function putMeat() { // ... console.log('肉炒好了'); } // 当需要做的两件事情有非常严格的先后顺序要求 // 就可以为第一件事情的函数设计一个回调函数参数,然后将第二件事情的函数传递进去 // 这样就可以保证一定是第一件事做完,才做第二件事。 // 什么时候需要为主函数设计回调函数 // 当发现主函数内部的某一段特定步骤需要被更换成不同的类型内容时,就可以把这段内容设计成回调函数 // 当主函数执行时,再通过回调函数确定主函数指定步骤内容 putFood(putEggs); putFood(putMeat); ``` ##### 回调函数的参数提供 ``` function f1(a) { console.log('f1 的参数a:', a); } var d = 200; function f2(b, cb) { console.log('f2 的参数b:', b); //f2 的参数b: b var d = 100; // 回调函数的参数要有主函数内部提供 // 因为回调函数是在主函数内部执行的,只有执行时才能明确实参的值 var c = b + 5; cb(c); // f1 的参数a: b5 } f2('b', f1); f2('B', function (c) { console.log('匿名函数可以设计参数获取主函数内部的值', c);//B5 console.log(d); //200 }); ``` ##### 回调函数的参数问题 ``` function f3(y) { // x 的值希望从主函数内部获取 // y 的值由自身决定 return function (x) { console.log(x, y); // 20 100 } } function f4(m, cb) { var n = m * 5; cb(n);//n=20 带入x } f4(4, f3(100));//y=100 ``` ##### 回调函数的返回值 ``` function f5() { return 'f5' } function f6(cb) { var str = cb(); console.log(str);// f5 return 'f6'; } var str = f6(f5); console.log(str);//f6 ``` ### 数组常用方法 + 会修改原数组的方法:push/pop/shift/unshift/sort/reverse/splice #### 栈方法(后进先出) ##### push() 方法 增加尾 + 数组末尾追加一个或更多元素,返回的是数组新的长度 + 传递参数数量不定,可以传递 0 到多个,参数之间使用 , 隔开 + 改变了原有数组,不会返回新数组 ``` var fruits = ['Banana', 'Orange', 'Apple', 'Mango']; var length = fruits.push('Kiwi'); console.log(length); // 5 console.log(fruits); // ['Banana', 'Orange', 'Apple', 'Mango', 'Kiwi'] ``` ##### pop() 方法 删除尾 + 向数组中删除最后一个元素并且返回该元素 + 不需要传递参数 + 改变了原有数组,不会返回新数组 + 如果数组为空就返回 undefined ``` var fruits = ['Banana', 'Orange', 'Apple', 'Mango']; var item = fruits.pop(); console.log(item); // 'Mango' console.log(fruits); // ['Banana', 'Orange', 'Apple'] ``` ``` var fruits = []; var item = fruits.pop(); console.log(item); // undefined console.log(fruits); // [] ``` #### 队列方法 ##### shift() 方法 删除头 + 把数组的第一个元素删除,并作为返回值返回 + 不需要传递参数 + 改变了原有数组,不会返回新数组 + 如果数组为空就返回 undefined ``` var fruits = ['Banana', 'Orange', 'Apple', 'Mango']; var item = fruits.shift(); console.log(item); // 'Banana' console.log(fruits); // ['Orange', 'Apple', 'Mango'] ``` ``` var fruits = []; var item = fruits.shift(); console.log(item); // undefined console.log(fruits); // [] ``` ``` var fruits = ['Banana', 'Orange', 'Apple', 'Mango']; var aa= fruits.unshift('Lemon', 'Pineapple'); console.log(aa); // 6 返回的为长度 console.log(fruits); // ['Lemon', 'Pineapple', 'Banana', 'Orange', 'Apple', 'Mango'] ``` #### 转换方法 ##### join() 方法 元素转换为字符串 + 用于把数组中的所有元素转换一个字符串并进行连接 + 参数可选,为自定义分隔符,默认为 , + 在转换时,内部的空值和未定义值会去除,但是 分隔符会被保留 + 对于非字符串数据会被强制转为字符串 + 返回一个新的字符串,不会改变原数组 ``` var fruits = ['Banana', 'Orange', 'Apple', 'Mango']; var energy = fruits.join(); console.log(fruits); // ['Banana', 'Orange', 'Apple', 'Mango'] console.log(energy); // 'Banana,Orange,Apple,Mango' ``` ``` var fruits = ['Banana', 'Orange', 'Apple', 'Mango']; var energy = fruits.join('|'); console.log(fruits); // ['Banana', 'Orange', 'Apple', 'Mango'] console.log(energy); // 'Banana|Orange|Apple|Mango' ``` 特殊元素转化 ``` var fruits = ['Banana', '', 123, NaN, undefined, null, () => { }, { name: 'szx', age: 28 }, []]; var energy = fruits.join(); console.log(energy); // 'Banana,,123,NaN,,,() => { },[object Object],' ``` #### 重排序方法 ##### sort() 方法 数组排序 + 用于对数组的元素进行排序 + 可传递一个参数 + 默认排序顺序为按字母升序。为了实现排序,sort() 方法会对每个数组项调用 toString() 转型方法,然后比较得到字符串,以确定如何排序。(实质按照首字母 ASCII 码顺序进行排列,首字母相同比较第二个,依次类推) + 参数可选,非必需。 + 若传递参数,参数必须是一个函数,且函数须有两个参数。sort() 方法会自动把数组中元素两两传入函数中,根据函数返回值进行排序。如果想让第一个参数应该位于第二个之前则返回一个负数;如果想让第一个参数位于第二个之后则返回一个正数;如果两个参数想保持原有顺序,返回 0。(可以自定义排序方法,本质上最终目的还是两个具体的值之间进行比大小) + 改变了原有数组,不会返回新数组 ``` var arr = [5, 8, 3, 4]; var ret = arr.sort(function (a, b) { return a - b; }); console.log(arr === ret); // 如果希望从小到大排列,将返回 a - b的结果 // 从大到小排就返回 b - a ``` ``` var fruits = ['Banana', 'Orange', 'Apple', 'Mango']; fruits = fruits.sort(); console.log(fruits) // ['Apple', 'Banana', 'Mango', 'Orange'] ``` ``` var fruits = [ { name: 'Banana', price: 13 }, { name: 'Orange', price: 8 }, { name: 'Apple', price: 20 }, { name: 'Mango', price: 4 } ] fruits = fruits.sort((val1, val2) => { if (val1.price < val2.price) { return -1; } else if (val1.price > val2.price) { return 1; } else { return 0; } }); console.log(fruits) // [{ name: 'Mango', price: 4 }, { name: 'Orange', price: 8 }, { name: 'Banana', price: 13 }, { name: 'Apple', price: 20 }] ``` ##### reverse()方法 颠倒 + 用于颠倒数组中元素的顺序,无参数 + 只是将数组中的现有排列顺序进行反向,和元素的值无关 + 改变了原有数组,不会返回新数组 ``` var fruits = ['Banana', 'Orange', 'Apple', 'Mango']; fruits.reverse(); console.log(fruits); // ['Mango', 'Apple', 'Orange', 'Banana'] ``` #### 操作方法 ##### concat() 方法 拼接 + 连接两个或多个数组,可传递多个参数 + 参数数据类型不作限制。若类型不是数组,则连接后作为一个数组的元素。 + 不会改变现有的数组,而返回连接后的新数组。 ``` var hege = ['Cecilie', 'Lone']; var stale = ['Emil', 'Tobias', 'Linus']; var kai = 'Robin'; var children = hege.concat(stale, kai); console.log(hege); // ['Cecilie', 'Lone'] console.log(children); // ['Cecilie', 'Lone', 'Emil', 'Tobias', 'Linus', 'Robin'] ``` ##### splice() 方法 插入、删除或替换数组的元素 + 插入、删除或替换数组的元素 + 功能强大,增删改都可以,可传递3个参数,splice(start, length, newItem) + 参数1:必需。规定从何处添加/删除元素。该参数是开始插入和(或)删除的数组元素的下标,必须是数字。添加从指定的开始位置进行添加,删除时会删除开始位置的元素 + 参数2:可选。规定应该删除多少元素。必须是非负整数,可以是 0。如果未规定此参数,则删除从 index 开始到原数组结尾的所有元素 + 参数3:可选。要添加到数组的新元素,新元素使用分隔符 , 隔开,数量不限 + 改变了原有数组,不会返回新数组 ###### 插入元素 ``` var fruits = ['Banana', 'Orange', 'Apple', 'Mango']; fruits.splice(2, 0, 'Lemon', 'Kiwi'); console.log(fruits); // ['Banana', 'Orange', 'Lemon', 'Kiwi', 'Apple', 'Mango'] // 从下标为 2 的元素开始,删除 0 个元素,插入指定新元素 ``` ###### 删除元素 ``` var fruits = ['Banana', 'Orange', 'Apple', 'Mango']; fruits.splice(2, 1); console.log(fruits); // ['Banana', 'Orange', 'Mango'] // 从下标为 2 的元素开始,删除 1 个元素 ``` ``` var fruits = ['Banana', 'Orange', 'Apple', 'Mango']; fruits.splice(2); console.log(fruits); // ['Banana', 'Orange'] // 从下标为 2 的元素开始,后续全部删除 ``` ###### 替换元素 ``` var fruits = ['Banana', 'Orange', 'Apple', 'Mango']; fruits.splice(2, 1, 'Lemon', 'Kiwi'); console.log(fruits); // ['Banana', 'Orange', 'Lemon', 'Kiwi', 'Mango'] // 从下标为 2 的元素开始,先删除 1 个元素,再插入指定新元素 ``` ##### slice() 方法 截取 + 从已有的数组中截取选定的元素,组成新的数组返回 + 传递两个参数,slice(start, end) + 参数 1:必需。规定从何处开始选取。如果是负数,那么它规定从数组尾部开始算起的位置。也就是说,-1 指最后一个元素,-2 指倒数第二个元素,以此类推。 + 参数 2:可选。规定从何处结束选取。该参数是数组片断结束处的数组下标。如果没有指定该参数,那么截取的数组包含从 start 位置 到数组结束的所有元素。如果这个参数是负数,那么它规定的是从数组尾部开始算起的元素 + 截取的范围是 [start, end) + 截取方向为正向截取。指定位置的实际索引值较小的必须放在前面,否则截取的为 空数组 + 不会改变原数组,会返回新的数组 ``` var fruits = ['Banana', 'Orange', 'Lemon', 'Apple', 'Mango']; var arr1 = fruits.slice(1, 3); // ['Orange', 'Lemon'] var arr2 = fruits.slice(2); // ['Lemon', 'Apple', 'Mango'] var arr3 = fruits.slice(-5, -2); // ['Banana', 'Orange', 'Lemon'] console.log(fruits); // ['Banana', 'Orange', 'Lemon', 'Apple', 'Mango'] ``` #### 遍历方法 ##### forEach()方法 + 调用数组的每个元素,并将元素传递给回调函数。 + 传递两个参数 forEach(function(currentValue, index, arr), thisValue) + 参数1:必需,回调函数。 > - 此函数的要求: > - 参数 1:必需,进行逻辑处理的当前元素,数组中的每个元素都会被依次传入 > - 参数 2:可选,当前元素的索引值 > - 参数 3:可选,当期元素属于的数组对象 > - 注意不要写成 箭头函数,否则无法指定当前函数的 this 指向;this 默认指向 window - 参数 2:可选。对象作为回调函数的 this 的值。如果省略了 thisValue,this 默认指向 window - 对数组中的每个元素都执行一次指定的函数(callback),函数不需要设置返回值,只是依次让筛选出每个元素执行同一个操作 - 对于空数组是不会执行回调函数的 ``` // 遍历数组 // forEach()方法 调用数组的每个元素,并将元素传递给回调函数 // 只是将数组中的每一项内容通过回调函数传递给你 // 和普通的 for 操作相比,不可以提前结束循环 arr.forEach(function (item, index, origin) { // console.log(item,index); }); ``` ``` // forEach()方法 调用数组的每个元素,并将元素传递给回调函数 // 只是将数组中的每一项内容通过回调函数传递给你 // 和普通的 for 操作相比,不可以提前结束循环 arr.forEach(function (item, index, origin) { // console.log(item,index); }); ``` ``` function _forEach(arr, cb){ for(var i=0; i<arr.length; i++){ cb(arr[i],i);} } ``` _forEach(arr,function (item,index){ console.log(item,index); }); ##### every() 方法 + 检测数组所有元素是否都符合指定条件(通过函数提供),// every 和 && 计算逻辑非常相似,只有每一个元素都满足时才会返回 true, 只要有一个不满足,就会返回 false , 并且后续的元素就不再判断了 ``` // item:数组中的每一项 index:索引值 var ret = arr.every(function (item, index) { console.log(item, index); return item.price < 4; }); console.log(ret);//false ``` ``` function _every(arr, cb) { for (var i = 0; i < arr.length; i++) { if (!cb(arr[i], i)) { console.log(i); return false; } } return true; } var ret = _every([1, 2, 3, 4, 5], function (item, index) { return item < 3; }); console.log(ret); ``` ##### some() 方法 + 检测数组中的元素是否满足指定条件(通过函数提供), + some 和 || 计算逻辑非常相似,只要有个元素都满足时才会返回 true,并且后续的元素就不再判断了, 只有都不满足条件时,才会返回 false ``` var ret = arr.some(function (item, index) { console.log(item, index) return item.price > 40; }); console.log(ret); ``` ``` function _some(arr, cb) { for (var i = 0; i < arr.length; i++) { if (cb(arr[i], i)) { console.log(i); return true; } } return false; } var ret= _some([1, 2, 3, 4, 5], function (item, index) { return item > 3; }); console.log(ret); ``` ##### findIndex()方法 + 获取满足指定条件的第一个数据的索引值 + 只能从头开始查找 ``` var index=arr.findIndex(function (item, index) { return item.price === 3; }); console.log(index); ``` ##### find()方法 + 获取满足指定条件的第一个数据 ``` var ret= arr.find(function (item, index) { return item.price === 3; }); console.log(ret); ``` ##### filter() 方法 + 在数组中筛选满足条件的元素,组成新数组返回 + 过滤筛选, 满足条件的结果会放在新数组内部, ``` var ret = arr.filter(function (item, index) { console.log(item, index) return item.price > 4; }); console.log(ret); ``` ``` function _filter(arr, cb) { // 声明一个新的数组,保存后续筛选好的内容 var ret = []; for (var i = 0; i < arr.length; i++) { var nn = arr[i]; if (cb(nn, i)) { ret.push(nn); } } return ret; } var t = _filter([4, 5, 6, 7], function (item, index) { return item === 6; }); console.log(t); ``` ##### map() 方法 + 返回一个新数组,数组中的元素为原始数组元素调用函数处理后的值 ``` var arr = [5, 8, 3, 4]; var ret=arr.map(function (item, index) { item.price+=5; return item.price; }); console.log(arr);// [5, 8, 3, 4] console.log(ret); //[10,13,8,9] ``` ``` function _map(arr, cb) { var ret = []; for (var i = 0; i < arr.length; i++) { ret.push(cb(arr[i], i)); } return ret; } var ret = _map([1, 2, 3, 4, 5], function (item) { return item * 3; }); console.log(ret); ``` ##### reduce() + 法接收一个函数作为累加器,将数组中的每个值(从左到右)依次开始累加,最终计算为一个值 ``` var arr = [1,4,7,2,5,8]; // reduce 方法逻辑:将上一循环的结果作为下一循环的起始值 var ret= arr.reduce(function(total,item,index){ // total:表示上一循环的结果 // item:当前这一循环对应的数组元素内容 // index: 当前这一循环对应的索引值 console.log(total,item,index); // 要求要有一个返回值,返回这循环计算结果 if(index % 2 === 0){ return total + item; }else{ return total - item; } },0);//0起始值 console.log(ret); ``` ``` // reduce // 循环累加函数,将上一循环结构作为下一循环的起始值 // 第二个参数可选, // 如果给定有值,累加起始值以给定值为准 // 如果没有,把数组的第 0 项作为累加起始值 function _reduce(arr, cb, init) { var total, start; // 判断参数传递的数量,验证 累加起始值参数 init 是否给定有值 if (arguments.length >= 3) { // 如果有,给定的起始值就作为累加综合的初始值 total = init; // 循环从 0 项开始,从第一个参数开始加 a[0];加前一项,起始值; start = 0; } else { // 如果没有,累加总和初始值按数组第 0 项处理, total = arr[0]; // 循环从第一项开始.从第二个参数开始加 a[1];加前一项,则加a[0]; start = 1; } ``` for (var i = start; i < arr.length; i++) { var item = arr[i]; // 回调函数 cb 表示每一循环的执行过程, // 需要接受上一循环的结果和这一循环的元素作为计算基础值 // 函数的返回值就是这一循环计算的结果,更新到 total 变量上 // 作为下一循环的参数 total = cb(total, item, i); } return total; } var ret = _reduce(['a', 'b', 'c', 'd'], function (total, item, index) { console.log(total, item, index); return total + item; }); console.log(ret); #### 对象常用方法 ##### for ... in... + 使用 for...in... 语句循环遍历对象中的可枚举属性,依次输出 ``` /* for(属性名变量 in 对象){} 属性名的获取顺序会由于浏览器的不同可能会导致结果不一样 */ for (var key in obj) { // key相当于所有obj变量属性名 console.log('for in', key); } ``` ``` var obj = {a: 1, b: 2}; for(x in obj) { //obj中所有的属性名统称x console.log(x); // 依次输出 a, b, 类型为 字符串 } for(x in obj) { console.log(obj.x); // 依次输出 undefined, undefined,无法通过 . 操作符来获取对应的属性值 // 因为使用了点操作符则认为 x 是 obj 的属性名,并不是使用 a 和 b 属性名 } for(x in obj) { console.log(obj[x]); // 依次输出 1, 2,可以通过 [] 的方式来读取对应的属性,从而获取属性值 } ``` ``` var o = { a: 1, b: 2 }; // 以 o 为原型创建 obj,其中 o 的属性均可枚举 var obj = Object.create(o); // 设置 obj 自身可枚举的属性 obj.c = 3; for(var prop in obj) { console.log(prop); } // c, a, b 先将自身的可枚举属性进行遍历,再对原型中的可枚举属性进行遍历 ``` ##### Object.keys(obj) + 单纯的获取对象自身的属性名,然后存储到数组中 ``` var obj = { x: 1, y: 2} var keys = Object.keys(obj); console.log(keys); // ['x', 'y'] ``` ``` var obj = { x: 1, y: 2} / 以obj 为原型创建一个新对象 var child = Object.create(obj); console.log(child); child.z = 3; console.log(child); // for in 循环处理会获取对象自身内部的属性之外,还会获取自身原型链上的属性 // for in 的获取结果要大于对象自身的数据 for (var key in child) { console.log(key, child[key]);//z 3 x 1 y 2 } console.log(Object.keys(child)); Object.keys(child).forEach(function (key) { console.log(key, child[key]); //[z 3] }); ``` ##### Object.assign() + 用于将所有可枚举的属性的值从一个或多个源对象复制到目标对象。它将返回目标对象。 + **Object.assign(target, ...sources)** 传递参数数量不定,可以传递 2 个 到 多个,参数之间使用 , 隔开 - 改变了目标对象,并返回目标对象 - 参数 1:target,目标对象 - 剩余参数:需要进行复制的多个源对象 ###### 复制 + 将想要的属性合并进空一个新的空对象中,相当于复制 ``` var target = {}; var objSource = { a: 1 }; var copy = Object.assign(target, objSource); console.log(copy); // { a: 1 } console.log(target); // { a: 1 } console.log(target === copy); // true ``` ###### 合并(浅合并) + 如果目标对象与被合并对象具有相同的属性名,则属性将被新增的同名属性覆盖。再后来的同名属性将类似地覆盖早先的属性。其中函数属性也可以被合并和覆盖。 ``` var obj1 = { a: 1 } var obj2 = { a: 2, c: 3, fn: 'fun' }; var obj3 = { fn: function () { console.log('fn') } }; Object.assign(obj1, obj2, obj3); console.log(obj1); // { a: 2, c: 3, fn: fn() } obj1.fn(); // fn ``` ##### Object.defineProperties(obj, detail) + 可以一次性定义多个属性 传递两个参数 - 参数 1: 需要进行定义属性的对象 - 参数 2: 需要进行定义的属性及其对应的属性描述配置对象 ``` var aa={}; // 可以设置多个属性 Object.defineProperties(aa,{ a:{value:2, writable:true, // 允许被修改 enumerable:true, // 允许被枚举 枚举:一个个被取出来 configurable:true,}, b:{ value:26, writable:true, // 允许被修改 enumerable:true, // 允许被枚举 枚举:一个个被取出来 configurable:true, } }); console.log(aa);//{a: 2, b: 26} ``` ##### Object.defineProperty(obj, property, detail) + 一次只能定义一个属性 传递三个参数 - 参数 1: 需要进行定义属性的对象 - 参数 2: 进行定义的属性名 - 参数 3: 属性描述符,定义属性相关的配置信息对象 > - 参数 3 的配置信息对象的可用属性 > - value: 定义属性的值 > - configurable: 设置该属性是否可以被删除,默认是 false,即不可以被删除 > - writable: 设置该属性是否可以被修改,默认是 false,即不可以被修改 > - enumerable: 设置该属性是否可以被枚举,默认是 false,即不可以被枚举 > 注意,使用这种方式定义的属性,默认值都是 false。但是,使用字面量声明的对象,默认值都是 true,即可删,可改,可枚举 ``` var obj = {a: 1}; Object.defineProperty(obj, 'b', { value: 3, configurable: false }) delete obj.b console.log(obj); // { a: 1, b: 3 } 无法删除 ``` ``` var obj = {a: 1}; Object.defineProperty(obj, 'b', { value: 3, writable: false }) obj.b = 4 console.log(obj); // { a: 1, b: 3 } 无法修改 ``` ``` var obj = {a: 1}; Object.defineProperty(obj, 'b', { value: 3, writable: false }) obj.b = 4 console.log(obj); // { a: 1, b: 3 } 无法修改 ``` ###### 存取器函数 ``` // 目的是让 double 中的 x 是 obj 中的2倍 // 只要修改了 obj 的值,double 自动修改 var obj = { x: 1 }; var double = { x: 2 }; // 传统的关联数据写法 // function SetObjx(value){ // obj.x=value; // double.x=obj.x*2; // } // Setbjx(50); // console.log(double); ``` + 单向的数据关联 + 为 obj 创建一个代理对象 proxy,后续使用时就不要直接操作 obj,而是操作 proxy 对象进行代替 ``` var obj = { x: 1 }; var proxy = {}; Object.defineProperty(proxy, 'x', { configurable: true, enumerable: true, // 代理了 点操作 的获取行为 get: function () { console.log('获取 x 属性值'); return obj.x; //1 }, // 代理了 点操作符 的设置行为 set: function (value) { console.log('设置的新值', value); obj.x = value; double.x = value * 2; //5 为value } }); console.log(proxy.x);//1 // 完成了 obj.x => double.x 单向的数据关联 proxy.x = 5; console.log(double);//{x: 10} ``` + 数据双向关联 ``` var num = { a: 1, b: 2 }; var triple = {}; // 使用 keys 方法循环基础对象,获取每一个属性名,放在一个数组中 key:num 每一个属性名 Object.keys(num).forEach(function (key) { // 为目标对象根据对象的属性名创建代理属性 Object.defineProperty(triple, key, { configurable: true, enumerable: true, // 使用 set/get 函数代理 triple 对象属性的存取过程 // 但是triple 本身是不会直接存储对应的值 // 进行数据计算保存在 num 对象中, // 读取时,也是通过 num 重新计算出新值 get: function () { return num[key] * 3; }, set: function (value) { num[key] = value / 3; } }); }); console.log(triple); // {} 本身没有东西 console.log(triple.a);//3 console.log(triple.b);//6 ``` #### 时间对象Date() ##### Date的基本类型 var time= new Date() //获取当前时间 ``` time.getDate();//获取当天日期 time.getDay();//获取当天星期几 time.getMonth()+1; //获取当月月数 ``` | 方法 | 描述 | | ----------------- | ----------------------------------------------- | | getDate() | 从 Date 对象返回一个月中的某一天 (1 ~ 31)) | | getDay() | 从 Date 对象返回一周中的某一天 (0 ~ 6)) | | getMonth() | 从 Date 对象返回月份 (0 ~ 11) | | getFullYear() | 从 Date 对象返回四位数字的年份 | | getMinutes() | 返回 Date 对象的分钟 (0 ~ 59) | | getSeconds() | 返回 Date 对象的秒数 (0 ~ 59) | | getMilliseconds() | 返回 Date 对象的毫秒(0 ~ 999) | | getTime() | 返回 1970 年 1 月 1 日至今的毫秒数 | | getUTCDate() | 根据通用时间从 Date 对象返回月中的一天 (1 ~ 31) | | getUTCDay() | 根据通用时间从 Date 对象返回周中的一天 (0 ~ 6) | | setDate() | 设置 Date 对象中月的某一天 (1 ~ 31) | | setMonth() | 设置 Date 对象中月份 (0 ~ 11) | | setFullYear() | 设置 Date 对象中的年份(四位数字) | | setHours() | 设置 Date 对象中的小时 (0 ~ 23) | | setMinutes() | 设置 Date 对象中的分钟 (0 ~ 59) | | valueOf() | 返回 Date 对象的原始值 | ``` //计时器 var times=setInterval(() => { var newlate=new Date("2021-11-16").getTime(); var newtime=new Date().getTime(); var mesc = newtime-newlate; var time =(mesc/1000);// 毫秒/1000 var day = parseInt(time/86400);// 天 24*60*60*1000 var hour = parseInt(time/3600)-24*day;// 小时 60*60 总小时数-过去的小时数=现在的小时数 var minute=parseInt(time%3600/60);//分 -(day*24) 以60秒为一整份 取余 剩下秒数 秒数/60 就是分钟数 var second =parseInt(time%60);// 以60秒为一整份 取余 剩下秒数 h1.innerText=day+":"+hour+":"+minute+":"+second; }, 1000); ``` ##### Math基本类型 + 数学对象 math 是js 中的一个内置对象,不需要 new 创建,直接用即可 常用属性 | 属性 | 示例 | 描述 | | ------- | ------------ | ------------------------------------------------------- | | E | Math.E | 欧拉常数,也是自然对数的底数,约等于 `2.718` | | LN2 | Math.LN2 | 返回 2 的自然对数(约等于 0.693) | | LN10 | Math.LN10 | 返回 10 的自然对数(约等于 2.302) | | LOG2E | Math.LOG2E | 返回以 2 为底的 e 的对数(约等于 1.443) | | LOG10E | Math.LOG10E | 返回以 10 为底的 e 的对数(约等于 0.434) | | PI | Math.PI | 返回圆周率 π(约等于 3.14159) | | SQRT1_2 | Math.SQRT1_2 | Math.PIMath.PI返回返回 2 的平方根的倒数(约等于 0.707) | | SQRT2 | Math.SQRT2 | 返回 2 的平方根(约等于 1.414) | 常用方法 | 方法 | 示例 | 描述 | | -------- | ------------------------------------------------------------ | ------------------------------------------------------------ | | random() | Math.random() | 范围从[0,1), 如果取[5,10]之间的随机数 Math.floor((Math.random()*6)+5);()内不可写东西 | | floor() | Math.floor(4.5) | 向下取整。取值为4 | | ceil | Math.ceil(4.5) | 向上取整,取值为5 | | round | Math.round(4.5) | 四舍五入取整 取值5 | | parseInt | parseInt(4.6) | 向下取整,取4 | | cos() | Math.cos(1) Math.cos(Math.PI); // -1 | `cos` 方法返回一个 -1 到 1 之间的数值,表示角度(单位:弧度)的余弦值,参数是弧度制 0.5403023058681398 | | sin() | Math.sin(1) Math.sin(Math.PI / 2); // 1 | `sin` 方法返回一个 -1 到 1 之间的数值,表示给定角度(单位:弧度)的正弦值。// 0.8414709848078965 | | tan() | Math.tan(1) | 表示一个角的正切值 ,参数是弧度制 1.5574077246549023 | | acos() | Math.acos()Math.acos(-2); // NaN Math.acos(-1); // 3.141592653589793 | `acos` 方法以 -1 到 1 的一个数为参数,返回一个 0 到 pi (弧度)的数值。如果传入的参数值超出了限定的范围,将返回 `NaN` | | asin() | Math.asin(x) // x 为一个数值 | `asin` 方法接受 -1 到 1 之间的数值作为参数,返回一个(负二分之Π,正负二分之Π)弧度的数值。如果接受的参数值超出范围,则返回 `NaN`。 | | atan() | Math.atan(x) // x 为一个数值 | atant 返回一个 (负二分之Π,正负二分之Π)弧度之间的数值。 | | log() | Math.log(x) <br/>Math.log(-1); // NaN, out of range <br/>Math.log(0); // -Infinity Math.log(1); // 0 <br/>Math.log(10); // 2.302585092994046 | x是任意值 <br/>函数返回一个数的自然对数 如果指定的 `number` 为负数,则返回值为 `NaN`。 | | log10() | Math.log10(x) <br/>Math.log10(10) // 1 <br/>Math.log10(100) // 2 <br/>Math.log10("100")// 2<br/>Math.log10(1) // 0 | x是任意值 函数返回一个数字以 10 为底的对数. | | log() | Math.log2(x) x 为一个数值 <br/>Math.log2(1) // 0<br/> Math.log2(0) // -Infinity <br/> Math.log2(-2) // NaN Math.log2("1024")// 10 | 函数返回一个数字以 2 为底的对数.如果传入的参数小于 0, 则返回 `NaN` | | max() | Math.max() <br/>console.log(Math.max(1, 3, 2));// expected output: 3 console.log(Math.max(-1, -3, -2));// expected output: -1 | 函数返回一组数中的最大值。 | | min() | Math.min() | 返回零个或更多个数值的最小值 | | pow() | Math.pow() console.log(Math.pow(7, 3));<br/>// expected output: 343<br/>console.log(Math.pow(4, 0.5));<br/>// expected output: 2 | 函数返回基数(`base`)的指数(`exponent`)次幂,即 `base^exponent` | ## 常用界面操作 #### 视图打印 ``` document.write("abc"); // 直接在视图上渲染信息 document.writeln("xyz");// 在视图上渲染信息,最后添加换行符\n document.writeln("123") // 在视图渲染时,换行符会被显示为空格 document.write("<br>456<i id='i'>789</i>") // 可以在视图上动态渲染标签 ``` #### 修改标签内容 ``` <h6 id="myh6">abc </h6> <script> myh6.innerText = "新数据" </script> //在一个网页中。当你给标签设置id值之后,js中会自动生成一个同名变量,指向这个标签 console.log(myh6,i); ``` #### 创建一个标签 ``` var a= document.createElement("a"); a.innerHTML="百度一下,你就知道" ``` #### 标签设置属性 ``` a.href="http://www.baidu" a.id="a1"; ``` #### 修改标签元素的样式 ``` a.style.color="red"; ``` #### 把标签添加到视图上,放到某一个标签中作为子标签显示 ``` myh6.appendChild(a); ``` #### 循环创建一个ul列表 ``` var ul=document.createElement("ul") document.body.appendChild(ul) for(var i=0;i<5;i++){ var li =document.createElement("li"); //有内容才能显示 li.innerText=i; ul.appendChild(li); } ``` #### 通过标签名查找所有标签 ``` var list = document.getElementsByTagName("li"); console.log(list); //HTMLCollection 集合对象,类数组结构 for(var i=0;i<list.length;i++){ console.log(list[1]); } ``` #### 删除标签 ``` list[2].remove(); ``` ### 点击事件 #### 按钮点击事件 ``` <button οnclick="btnClick()">点我</button>// onclick 是点击事件 ,点击之后触发点击事件函数 <script> function btnClick(){ // 注意:1,警告框弹出时,代码暂停执行,点击确定后继续执行 alert("点击了按钮"); // 注意:2.在事件函数中,document.write 会重置文档内容 document.write("点击按钮时,显示的信息") } </script> ``` #### 输入框点击事件 ``` <input type="text" οninput="myInput()" id="input1"> function myInput(){ //input1.value获取输入框中的值 // 使用输入框标签元素打点调用value属性获取输入的信息,并显示到 ul 列表中第一个li标签上 list[0].innerText=input1.value } ``` ## Document Object Model文档对象模型 ### Dom概念 + OM是用于HTML的应用程序编程接口(API),DOM本质上是一种接口(API),是专门操作HTML文档的API + API: application programing interface 应用程序接口 常用的API: forEach, alert, 等对象,函数,属性 + DOM把整个页面映射为一个有层次结构的DOM节点树,把层次中的每一个组成部分都称之为节点, 所以在HTML文档中,所有的事物都被称作为DOM节点,元素节点、文本节点、注释节点、属性节点等, 标签元素在HTML文档中就被称之为元素节点,而我们要想通过js代码对页面(其实就是对标签元素)进行动态操作, 就先要去了解DOM节点,这样借助DOM提供的API,就可以对DOM节点进行增删改查 ### 节点 HTML文档中所有的事物都是DOM节点 + HTML 文档中的元素称为 元素节点 <html>,<head>,<body>,<title>等,即html中的标签 (其中<html>是<head>的父节点,<title>是<head>的子节点,<body>是<head>的兄弟节点。) + HTML 文档中的属性称为 属性节点 a标签的"href",以及"class"、"title"等都是属性节点 + HTML 文档中的文本称为 文本节点 + HTML 文档中的注释称为 注释节点 + HTML 文档中的文档本身称为 文档节点(根节点) + HTML 文档中空格和换行也是一个节点,一般划分为文本节点 nodeName属性是获取某一个节点的节点名称 + 元素节点的nodeName: 和元素名称一样(大写) + 属性节点的nodeName:和属性名一样 + 文本节点的nodeName: #text + 注释节点的nodeName:#comment + 文档节点的nodeName:#document nodeType属性,获取某一个节点的节点类型 + 元素节点的nodeType:1 对应 Node.ELEMENT_NODE + 属性节点的nodeType:2 对应 Node.ATTRIBUTE_NODE + 文本节点的nodeType:3 对应 Node.TEXT_NODE + 注释节点的nodeType:8 对应 Node.COMMENT_NODE + 文档节点的nodeType:9 对应 Node.DOCUMENT_NODE nodeValue属性,获取某一个节点的值,一般用于文本节点和属性节点 + 对于文本节点 nodeValue 属性包含文本 + 对于属性节点 nodeValue 属性包含属性值 + nodeValue对于文档节点和元素节点是不可用,使用textContent 代替 nodeValue 来获取元素节点的内容 关于节点(Node):HTML文档中包含各种标签元素,这些标签元素按照层级关系和结构, 大致可以分为:父元素,子元素,同胞元素,这些元素的层级关系和结构就构成了一个节点树的结构, 在节点树中,父元素、子元素、同胞元素, 都是元素节点, 又被称为 父节点(parentNode)、 子节点(childNode)、同胞节点(siblingNode)。 #### 元素节点 ``` var body = document.body; console.log(body.nodeName, body.nodeType, body.textContent); // BODY 1 console.log(1 == Node.ELEMENT_NODE); //true ``` #### 属性节点 ``` <div>div</div> <!-- 这是注释 --> 文字 <a href="http://www.baidu" id="a1">百度</a> <script> var body = document.body; console.log(body.children); //子元素属性 console.log(body.childNodes);// 子节点 9 个 ,包含元素节点,文本节点和注释节点,不包含属性节点 (那个输出的text是换行\n) var a =body.childNodes[5] console.log(a); console.log(a.href); // 调用属性节点 var attr =body.childNodes[5].attributes[0]; //第五个字节点的第一个属性 console.log(attr.nodeName,attr.nodeType,attr.nodeValue);//href 2 http://www.baidu </script> ``` #### 文本节点 ``` <div>div</div> <!-- 这是注释 --> 文字 <a href="http://www.baidu" id="a1">百度</a> <script> var text = body.childNodes[4]; console.log(text.nodeName,text.nodeType,text.nodeValue);//#text 3 文字 </script> ``` #### 注释节点 ``` <div>div</div> <!-- 这是注释 --> 文字 <a href="http://www.baidu" id="a1">百度</a> <script> var note = body.childNodes[3]; console.log(note.nodeName,note.nodeType,note.nodeValue); // #comment 8 这是注释 </script> ``` #### 文档节点(没有内容) ``` <div>div</div> <!-- 这是注释 --> 文字 <a href="http://www.baidu" id="a1">百度</a> <script> console.log(document.nodeName,document.nodeType,document.nodeValue);//#document 9 null </script> ``` ### Document的API #### Document 对象中的属性 | 属性 | 描述 | | ------------------------ | ---------------------------------------- | | document.body/head/title | 返回文档的 body 元素/head元素/文档标题 | | document.scripts | 返回页面中所有脚本的集合 | | document.all | 找到文档所有标签 | | document.documentElement | 返回文档的根节点html | | document.links | 返回对文档中所有 Area 和 Link 对象的引用 | | document.images | 返回文档中所有 Image 对象的引用 | | document.domain | 返回当前文档的域名 | | document.activeElement | 返回当前获取焦点的元素 script所有 | | document.documentURI | 设置或返回文档的位置 | #### Document 对象中的方法 | 方法 | 描述 | | --------------------------------- | ---------------------------------------- | | document.write() | 向文档中写入某些内容 | | document.createElement() | 创建一个元素节点 | | document.createTextNode() | 创建一个文本节点 | | document.createAttribute() | 为指定标签添加一个属性节点 | | document.createComment() | 创建一个注释节点 | | document.getElementsByClassName() | 通过Class 类名找到所有符合条件的元素集合 | | document.getElementById() | 通过id名找到所有符合条件的元素集合 | | document.getElementsByName() | 通过name 属性找到所有符合条件的节点列表 | | document.getElementsByTagName() | 通过标签名查找到所有符合条件的元素集合 | | document.querySelector() | 通过样式选择器找到第一个符合条件的元素 | | document.querySelectorAll() | 返回文档中具有指定 CSS 选择器的所有元素 | | document.renameNode() | 重命名元素或者属性节点 | | document.removeEventListener() | 移除文档中的事件句柄 | | document.addEventListener() | 向文档中添加事件 | | document.normalize() | 删除空文本节点,并合并相邻的文本节点 | | document.normalizeDocument() | 删除空文本节点,并合并相邻的节点 | ### 元素节点的API #### 元素对象中的属性 | 属性 | 方法 | | ------------------------------ | ------------------------------------ | | element.children | 查看元素中子元素的集合 | | element.attributes | 返回一个元素的属性数组 | | element.classList | 返回元素中类名组成的对象 | | element.className | 设置或返回元素的 class 属性 | | element.firstChild | 返回元素中的第一个子元素 | | element.id | 设置或者返回元素的 id | | element.innerHTML | 设置或者返回元素的内容 | | element.innerText | 设置或者返回元素文本内容 | | element.nodeName | 返回元素名称(大写) | | element.nodeType | 返回元素的节点类型 | | element.nodeValue | 返回元素的节点值 | | element.parentNode | 返回元素的父节点 | | element.parentElement | 返回元素父元素 | | element.previousSibling | 找到元素前边相邻的一个兄弟节点 | | element.previousElementSibling | 找到元素前边相邻的一个兄弟元素 | | element.style | 设置或返回元素的样式属性 | | element.title | 设置或返回元素的 title 属性 | | element.length | 返回对象的长度 | | element.textContent | 设置或返回某个元素以及其中的文本内容 | | element.tabIndex | 设置或返回元素的标签顺序 | | element.tagName | 以字符的形式返回元素的名称(大写) | | element.nextSibling | 找到元素后边相邻的一个兄弟节点 | | element.nextElementSibling | 找到元素后边相邻的一个兄弟元素 | #### 元素 对象中的方法 | 方法 | 描述 | | -------------------------------- | ------------------------------------------------------------ | | element.appendChild() | 为元素添加一个新的子元素 | | element.append() | 添加文本节点给body,作为最后(往后加的)一个子节点 | | element.getAttribute() | 通过属性名称获取指定元素的属性值 | | element.getAttributeNode() | 通过属性名称获取指定元素得属性节点 | | element.getElementsByTagName() | 通过标签名获取当前元素下的所有子元素的集合 | | element.getElementsByClassName() | 通过类名获取当前元素下的子元素的集合 | | element.querySelector() | 根据 CSS 选择器,返回第一个匹配的元素 | | document.querySelectorAll() | 根据 CSS 选择器,返回所有匹配的元素 | | element.removeAttribute() | 从元素中删除指定的属性 | | element.removeAttributeNode() | 从元素中删除指定的属性节点 | | element.removeChild() | 删除一个子元素 | | element.replaceChild() | 替换一个子元素 | | element.setAttribute() | 设置或者修改指定属性的值 | | element.setAttributeNode() | 设置或者修改指定的属性节点 | | element.insertBefore() | 在已有子元素之前插入一个新的子元素 | | element.isSameNode() | 检查当前元素与指定元素是否为同一元素 | | element.hasAttribute() | 判断元素是否具有指定的属性,若存在则返回 true,不存在则返回 false | | element.hasAttributes() | 判断元素是否存在任何属性,若存在则返回 true,不存在则返回 false | | element.hasChildNodes() | 判断一个元素是否具有子元素,有则返回 true,没有则返回 false | #### 元素的增删改查 ##### 元素的增加 + 简单的显示在页面 ``` document.write("<h1>标题</h1>") ``` + 创建一个标签并写入内容 ``` var h2 =document.createElement("h2") h2.innerText="二标题" ``` + 添加元素节点给body,作为最后(往后加的)一个子节点 ``` document.body.appendChild(h2) ``` + 添加文本节点给body,作为最后(往后加的)一个子节点 ``` document.body.append("text") ``` + 添加元素节点作为第一个子节点(存取到堆区,就只有一个对象) ``` document.body.prepend(h2) ``` + 添加文本节点,作为第一个子节点(存取在栈区,可添加) ``` document.body.prepend("text") ``` + 把一个新的元素节点插入到一个已有的节点前边 ``` var first = document.body.childNodes[0];//body的第一个子节点 var h3 =document.createElement("h3") h3.innerText="h3" document.body.insertBefore(h3,first) ``` ##### 元素删除 + 把一个元素自身删掉 ``` var h1 = document.getElementsByTagName("h1")[0] h1.remove() ``` + 通过父节点删除子节点 ``` document.body.removeChild(document.body.childNodes[0]) ``` ##### 元素修改 ``` var u=document.createElement("u") u.innerText="下划线" document.body.replaceChild(u, document.body.children[0]) // body.innerText="<h1>123</h1>" // 只能放文本 ,用字符串替换标签内部的信息 // body.innerHTML="<h1>123</h1>" // 用标签结构替换原有信息 ``` ##### 元素查找 + 直接找到根标签html ``` document.documentElement ``` + 直接找到body ``` document.body ``` + 直接找到head ``` document.head ``` + 找到文档中所有的标签 ``` document.all ``` + 通过id找到第一个符合条件的元素。是个类数组 ``` document.getElementById("d1") ``` + 通过类名查找,是个类数组 ``` document.getElementsByClassName(".d2") ``` + 通过标签名查找,元素集合,类数组 ``` document.getElementsByTagName("div") ``` + 通过name 属性找到所有符合条件的节点列表 ``` document.getElementsByName("4") ``` + 通过样式选择器找到第一个符合条件的元素 ``` document.querySelector("body .d2") ``` + 通过样式选择器找到所有符合条件的元素节点列表 ``` document.querySelectorAll("body .d2") ``` #### 查找标签将类数组遍历的三种方式getElementsByTagName() + 查找标签 有时获得的是元素集合HTMLCollection 或 节点列表NodeList, 他们都不是数组,而是类数组,可以通过以下三种方式遍历 ##### 1.for()循环遍历 ``` for(var i =0 ;i<d6.length;i++){ console.log(d6[i]); } ``` ##### 2.把类数组转化成数组,使用forEach()遍历 ``` Array.from(d6).forEach(function (item) { console.log(item); }) ``` ##### 3.使用 for of循环 ``` for(var item of d6){ // item 变量每一项(自己起名) d6要遍历的数组 console.log(item); } ``` ### 属性节点的API #### 特殊属性 + id href src 打点设置 ``` <div>div</div> <a href="">百度</a> <script> div.id ="d1" // id 属性可以直接打点设计 a.href ="www.baidu" // a 标签的 herf 属性和 img 标签的 src 属性都可以打点设置 console.log(div.id); // 其他属性不能打点设置 </script> ``` #### 普通属性 ``` 普通属性 name ,或自定义属性 <body> <div>div</div> <a href="">百度</a> <script> // 增 div.setAttribute("age", 10); // 设置普通属性 // 删 div.removeAttribute("id") // 删除属性 // 查 // 查普通属性值 console.log(div.getAttribute); console.log(div.attributes) // 查看所有属性 </script> </body> ``` #### class 属性 ``` <body> <div>div</div> <a href="">百度</a> <script> div.className ="d1"; //直接设置class(只能添加一个) div.classList.add("d2") // 添加class值 div.classList.remove("d1") // 删除class值 div.classList.replace("d2","d3") div.classList.toggle("d3") // d3 有就删除,没就增加 var bool = div.classList.contains("d3") //判断class 里面有没有d3,返回布尔值 </script> ``` #### style属性 ``` div.style.color= "red"; div.style.fontSize="30px" console.log(div.style.color); ``` ## 事件 ### 事件的概念 + 事件就是网页在展示过程中产生的一些用户行为和(浏览器)客户端行为 + 用户行为:用户点击,输入,拖拽等行为 + 客户端行为:窗口打开,关闭,数据上传下载,解析行为 ### 事件类型 + 鼠标事件 键盘类型 表单事件 window事件 拖拽事件 ### 事件结构 + 事件目标:事件发生在那个目标上,如点击的button就是事件目标 + 事件类型/事件名:在目标上发生了什么事件,如click指点击事件 + 事件函数:事件发生/触发时,调用的函数 如:myClick ### 事件触发流程 + 客户端或用户产生了固定的行为--->系统检测到行为的产生--->系统判断这个行为有没有默认操作(a标签的跳转) ---> 如果有默认操作,就立即执行,---> 如果没有默认操作,就去js中找对应的事件函数,能找到就立即调用,找不到就报错 ### 事件绑定的三种方式 + 方式一:在标签上使用 on+时间名=“函数名()”的结构绑定事件,注意:函数名后必须加() // 循环 ``` <button οnclick="myClick()" οnmοusemοve="myMove()"></button> <script> function myClick(){ console.log(button1); } </script> ``` + 方式二:在js 中找到事件目标,打点调用 on+事件名=函数名/匿名函数 注意:函数名后不能加() // 循环 ``` <button οnclick="myClick()" οnmοusemοve="myMove()"></button> <script> var button = document.querySeletor("button"); button.onclick =myClick; var button = document.querySeletor("button"); button.οnmοusemοve=function(){ console.log("点击button2") } <script> ``` + 方式三:在js 中找到事件目标,调用addEventListener()函数绑定事件 注意:addEventListener是新增事件函数,而不是替换 ``` <button οnclick="myClick()" οnmοusemοve="myMove()"></button> <script> 添加事件监听者,第一个参数是事件名,第二个参数是事件函数 button.addEventListener("click",myClick) button.addEventListener("click",function(){ console.log("点击button3")) <script> ``` ``` 第三种事件绑定是可以取消的, 注意:取消的参数和添加的参数必须一致才能取消 函数内存地址也必须要一致,也就是说,使用匿名函数添加的监听者无法取消监听 button.removeEventListener("click",myClick); button.addEventListener("click",function(){ console.log("点击button3")) // function 内存地址不一样,取消不了 ``` ``` 总结:三种绑定事件方式的区别 (1) 在同一个事件目标上多次绑定同一个事件,前两种方式绑定会相会覆盖,只有最后一次绑定生效, 第三种绑定方式不会覆盖,会给同一个事件绑定多个事件函数 (2) 方式一和方式二不可以取消,方式三可以 ``` ### 鼠标事件 #### 1.单击事件 click + click事件当用户在Element节点、document节点、window对象上,单击鼠标(或者按下回车键)时触发 + “鼠标单击”定义为,用户在同一个位置完成一次mousedown动作和mouseup动作。它们的触发顺序是:mousedown首先触发,mouseup接着触发,click最后触发。 ``` div.onclick = function (){ console.log("单击") } ``` #### 2.双击事件 dblclick + dblclick事件当用户在element、document、window对象上,双击鼠标时触发。该事件会在mousedown、mouseup、click之后触发。 ``` div.ondblclick = function(){ console.log("双击"); } ``` #### 3.鼠标按下mousedown ``` div.οnmοusedοwn=function(){ console.log("鼠标按下"); } ``` #### 4.鼠标抬起 mouseup ``` div.οnmοuseup=function(){ console.log("鼠标抬起"); } ``` #### 5.鼠标移动 mousemove + mousemove事件当鼠标在一个节点内部移动时触发。当鼠标持续移动时,该事件会连续触发。为了避免性能问题,建议对该事件的监听函数做一些限定,比如限定一段时间内只能运行一次代码。 ``` div.onmousemove = function(){ console.log("鼠标在这个div内部正在移动"); } ``` #### 6. 右键菜单 contextmenu ``` div.oncontextmenu = function(){ console.log("调出右键菜单"); } ``` #### 7.滑轮滚动 wheel + mousewheel”处理程序的事件对象有wheelDelta属性,其指定用户滚动滚轮有多远(根据这个判断滚动方向) ``` div.onwheel = function(){ console.log("滑轮滚动"); } ``` ``` window.onmousewheel = document.onmousewheel = scrollWheel; function scrollWheel(e){ e = e || window.event; if(e.wheelDelta) { //判断浏览器IE,谷歌滑轮事件 if(e.wheelDelta > 0) { //当滑轮向上滚动时 } else if(e.wheelDelta < 0) { //当滑轮向下滚动时 }; } else if(e.detail) { //Firefox滑轮事件 if(e.detail < 0) { //当滑轮向上滚动时 } else if(e.detail > 0) { //当滑轮向下滚动时 }; };} ``` #### 8.鼠标移入移出 onmouseenter / onmouseleave + onmouseenter / onmouseleave 不继承,鼠标在子标签上不会触发事件 ``` div.οnmοuseenter= function(){ console.log("鼠标移入"); } div.οnmοuseleave= function(){ console.log("鼠标移出"); } ``` #### 鼠标悬停 离开 mouseover/mouseout + mouseover/mouseout 会继承,鼠标在子标签上也会触发事件 ``` div.οnmοuseοver= function(){ console.log("鼠标悬停"); } div.οnmοuseοut= function(){ console.log("鼠标离开"); } ``` ### 键盘事件 #### keydown键盘按下 + 按下键盘时触发该事件。 (持续按下,会连续触发) ``` <body> <input type="text"> <script> var input =document.querySelector("input") //键盘按下(持续按下,会连续触发) input.onkeydown =function(){ console.log("键盘按下"); } </script> </body> ``` #### keyup 键盘抬起 + 松开键盘时触发该事件。 ``` <body> <input type="text"> <script> var input =document.querySelector("input") input.onkeyup =function(){ console.log("键盘抬起"); } </script> </body> ``` #### keypress 键盘长按 + 只要按下的键并非Ctrl、Alt、Shift和Meta,就接着触发keypress事件。 (建议使用keydown代替) ``` <body> <input type="text"> <script> var input =document.querySelector("input") input.onkeypress =function(){ console.log("键盘长按"); } </script> </body> ``` #### window窗口键盘事件 ``` window.onkeydown = function(e){ console.log("在浏览器窗口显示在上层时按下键盘",e); // 获取点击的键 console.log(e.key); // 有些键有默认行为,如f5会刷新页面,可以阻止事件默认行为 e.preventDefault(); // e.preventDefault();只能阻止页面级默认行为,系统级行为无法阻止,如电源键,window菜单键 ``` #### 监听组合键 ``` if(e.ctrlKey && e.key == "a"){ console.log("全选"); } // 需求:禁止网页内容被复制或下载保存 if(e.ctrlKey && e.key == "c"){ // e.preventDefault() // 阻止页面信息被复制 alert("请尊重作者版权") } if(e.ctrlKey && e.key == "s"){ // e.preventDefault() // 阻止页面信息被保存 alert("请尊重作者版权") } if( e.key == "f12"){ // e.preventDefault() // 阻止f12调控制台 alert("请尊重作者版权") } } window.oncontextmenu =function(e){ e.preventDefault() //阻止右键菜单 alert("请尊重作者版权") } ``` ### 表单事件 ``` <form action=""> <!-- 回顾:input的类型值有:checkbox,text,radio,file,image,submit,button,number, password, email, reset, range(滑动条) progress(滑动条) color time date --> <label for="myinput">账号</label> <input type="text" id="myinput"> <input type="radio" name="sex"> <input type="radio" name="sex"> <input type="checkbox"> <input type="reset"> <input type="submit"> <input type="color" id="color"> <button>提交</button> </form> ``` #### input 输入事件 + 会将输入过程都显示出来 ``` <input type="text" id="myinput"> var textInput = document.getElementById("myinput") // 1.input 输入事件 textInput.oninput =function(){ console.log("input",this.value); } ``` #### change 更新事件 + 当<input>、<select>和<textarea>的值发生变化时都会触发change事件。只有全部修改完成时它才会触发,这也是它和input事件的区别。 + 激活单选框(radio)或复选框(checkbox)时触发。 + 用户提交时触发。比如,从下列列表(select)完成选择,在日期或文件输入框完成选择。 + 当文本框或textarea元素的值发生改变,并且丧失焦点时触发。 ``` var textInput = document.getElementById("myinput") textInput.οnchange=function(){ console.log("change",this.value); } ``` #### focus 获取焦点事件 + 鼠标点击文本框获取焦点,触发函数 ``` var textInput = document.getElementById("myinput") textInput.οnfοcus=function(){ console.log("focus",this.value); } ``` #### blur失去焦点 + 鼠标移开,失去焦点 ``` var textInput = document.getElementById("myinput") textInput.οnblur=function(){ console.log("blur",this.value); } ``` #### select 选择事件 + 当<input>和<textarea>中选中文本时触发select事件。 ``` var textInput = document.getElementById("myinput") textInput.οnselect=function(){ console.log("select",e); } ``` #### reset 重置事件 + .重置事件 事件目标是form, 当表单重置(所有表单成员的值变回默认值)时触发 ``` var form =document.querySelector("form") form.οnreset=function(e){ //alter("即将重置") // var data = prompt("请说明你要重置的原因") var bool =confirm("确定要重置表单吗") if(!bool){ e.preventDefault() } } ``` #### sumbit 表单提交事件 + 事件目标是form, 当表单数据向服务器提交时触发。 ``` form.οnsubmit=function(e){ e.preventDefault() console.log(radio[0].value, radio[1].value); } ``` #### 单选框 radio + 单选框,可以绑定click,input,change事件,建议使用change ``` var radio =document.getElementsByName("sex") radio[0].οnchange=function(){ //radio的value值不管有没有选中,都是on console.log(this.value, radio[1].value); //单选或多选框通过checked属性获取选中状态 console.log(this.checked, radio[1].checked); } ``` + color 属性 ``` /总结:常用的表单事件有 //input,change,focus,blur,reset,submit,select color.onchange = function() { console.log(this.value); } ``` ### 事件参数Event #### Event 基本属性 ##### 1.event + 每一个事件被触发时,都会向事件函数中传入一个参数, 这个参数是事件信息对象, 里边包含了事件目标,和坐标等信息 ``` var div =document.querySelector("body div") div.onclick = function(event){ console.log(event)} // PointerEvent {isTrusted: true, pointerId: 1, width: 1, height: 1, pressure: 0, …} ``` ##### 2..event.type + 获取事件类型 ``` var div =document.querySelector("body div") div.onclick = function(event){ console.log(event.type)} // click ``` ##### 3.event.target + 获取事件触发目标, 谁触发了事件, 可以是事件目标div的子元素 ``` var div =document.querySelector("body div") div.onclick = function(event){ console.log(event.target)} ``` ##### 4.event.currentTarget + 获取事件目标本身,谁绑定了事件(将代码写在谁身上,onclick写在了div身上),总是事件目标div + 在事件函数中this指向事件目标 == event.currentTarget ``` var div =document.querySelector("body div") div.onclick = function(event){ console.log(event.target) console.log(this);} ``` ##### 5. preventDefault(); + 阻止默认行为 ``` div.ondragover = function(e){ e.preventDefault(); // 阻止默认行为 } form.οnsubmit=function(e){ e.preventDefault() // 阻止表单提交默认行为 console.log(radio[0].value, radio[1].value) } ``` #### Event 坐标 ##### **screenX,screenY** + screenX属性返回鼠标位置相对于屏幕左上角的水平坐标,单位为像素。 + screenY属性返回鼠标位置相对于屏幕左上角的垂直坐标,单位为像素。 ``` var div =document.querySelector("body div") div.onclick = function(event){ console.log(event.screenX, event.screenY)} ``` ##### **pageX、pageY** + pageX和pageY分别是触点相对HTML文档左边沿的X坐标和触点相对HTML文档上边沿的Y坐标。只读属性。 + 当存在滚动的偏移时,pageX包含了水平滚动的偏移,pageY包含了垂直滚动的偏移。 ``` console.log(event.pageX,event.pageY); ``` **clientX,clientY** + clientX属性返回鼠标位置相对于浏览器窗口左上角的水平坐标,单位为像素,与页面是否横向滚动无关。 + clientY属性返回鼠标位置相对于浏览器窗口左上角的垂直坐标,单位为像素,与页面是否纵向滚动无关。 ``` event.clientX,event.clientY ``` ##### layerX, layerY + 鼠标相对于非静态定位的父级元素左上角的坐标,类似于绝对定位 ``` event.layerX,event.layerY ``` ##### offsetX, offsetY + 鼠标相对于event.target触发事件的目标左上角的坐标 ``` console.log(event.offsetX,event.offsetY); ``` ##### **movementX,movementY** + movementX属性返回一个水平位移,单位为像素,表示当前位置与上一个mousemove事件之间的水平距离。在数值上,等于currentEvent.movementX = currentEvent.screenX - previousEvent.screenX。 movementY属性返回一个垂直位移,单位为像素,表示当前位置与上一个mousemove事件之间的垂直距离。在数值上,等于currentEvent.movementY = currentEvent.screenY - previousEvent.screenY。 ##### button、buttons + button属性指定当事件发生时哪个鼠标按键按下。 + buttons属性返回一个3个比特位的值,表示同时按下了哪些键。它用来处理同时按下多个鼠标键的情况。 ``` div.onmousedown =function(e){ // 左键 e.button ==0 e.button ==1 // 滚轮键 e.button ==1 e.button ==4 // 右键 e.button ==2 e.button ==2 console.log(e.button,e.buttons); } ``` ##### 阻止a标签默认跳转的行为 ``` <!-- 使用属性绑定事件时,如果需要参数e,需要传入event这个实参 --> <a href="http://www.baidu" οnclick="aClick(event)">baidu</a> function aClick(e){ console.log(e); // 2.阻止a标签的默认点击跳转的行为 e.preventDefault() } ``` ### DOM事件传播机制 + 一个事件从触发到响应,经历的流程是:先由根标签HTML触发事件, 然后一层一层向子标签传递这个事情,直到传递到事件目标button结束,这个过程叫挖洞过程, + 然后由事件目标(button)开始响应事件,并调用事件函数, 然后一层一层向父标签传递事件响应,直到html 根标签结束,这个过程叫冒泡过程 + 事件函数默认是在冒泡过程中调用的,可以通过addEventListener设置第三个参数为true,改为挖洞过程调用 + 对于事件传播流程的标签来说,挖洞总是在冒泡之前执行,对于最里层的事件目标也是如此,但火狐不这样认为,在火狐中,对于事件目标,挖洞函数和冒泡函数,谁先绑定谁先执行 #### 冒泡(合洋葱过程,从里层到外层) ``` div id="div"> <button id="btn">点我</button> <a href="http://www.baidu">百度一下</a> </div> <script> var button =document.getElementById("btn") var div=document.getElementById("div") var body =document.body; var html = document.documentElement; // 冒泡 button.addEventListener("click",function(){ console.log("1.点击button"); },false) div.addEventListener("click",function(){ console.log("2.点击div"); }, false) body.addEventListener("click",function(){ console.log("3.点击body"); }, false) html.addEventListener("click",function(){ console.log("4.点击html"); }, false) ``` #### 挖洞(剥洋葱过程,从外层到里层) ``` //挖洞 从 html->body->div->button true 判断在挖洞中触发事件 button.addEventListener("click",function(){ console.log("5.点击button"); },true) div.addEventListener("click",function(){ console.log("6.点击div"); }, true) body.addEventListener("click",function(){ console.log("7.点击body"); }, true) html.addEventListener("click",function(){ console.log("8.点击html"); }, true) // 结果:打印顺序:8,7,6,5,1,2,3,4 ``` ![](D:\培训\老师案例\0224 事件传播,挖洞,冒泡,事件委托\2,事件传播图.jpg) #### 冒泡挖洞实行具体案例 + 需求:div中有一个a 标签,点击 div 背景变蓝,点击a背景变红 + 错误写法 不管a还是div,都显示蓝色 原因:a标签修改红色之后,冒泡给了父标签div,又改成了蓝 ``` a.addEventListener("click",function(e){ e.preventDefault() document.body.style.backgroundColor="red" }) div.addEventListener("click",function(){ document.body.style.backgroundColor="blue" }) ``` + 方案一:阻止a标签的冒泡,不让div执行冒泡 ``` a.addEventListener("click", function(e){ e.preventDefault() // 阻止默认行为, 也就是a标签跳转 body.style.backgroundColor = "red" // 阻止a标签的事件传播, 不会阻止a自身的冒泡 // e.stopPropagation() // 立即阻止a标签的事件传播, 会把自身的冒泡也阻止掉 e.stopImmediatePropagation() console.log("a挖洞") },true); a.addEventListener("click", function(e){console.log("a冒泡")}, false) div.addEventListener("click", function(){ body.style.backgroundColor = "blue" }) ``` + 方案二, 让div事件函数在挖洞过程执行, 这样点击a时,a的红色会替换div的蓝色 ``` a.addEventListener("click", function(e){ e.preventDefault() // 阻止默认行为, 也就是a标签跳转 body.style.backgroundColor = "red" }); div.addEventListener("click", function(){ body.style.backgroundColor = "blue" },true) ``` ### 事件委托机制 + 通过e.target获取子标签来实现不同的结果,这种操作称之为:事件委托/事件代理 + 需求:点击button或i时,弹出点击这个标签的内容 ``` <div> <button>1</button> <button>2</button> <button>3</button> <button>4</button> <button>5</button> <button>6</button> <button>7</button> <button>8</button> <button>9</button> <button>10</button> <i>11</i> <i>12</i> <i>13</i> <i>14</i> <i>15</i> <i>16</i> <i>17</i> <i>18</i> <i>19</i> <i>110</i> </div> 方案一:给每一个 button 和 i 绑定点击事件 // var buttons = document.getElementsByTagName("button"); // for (var item of buttons) { // item.οnclick=function(){ // alert(this.innerText) // } // } // var is = document.getElementsByTagName("i"); // for (var item of is) { // item.οnclick=function(){ // alert(this.innerText) // } // } // 方案二:给父标签 div 绑定点击事件,来代理子标签button 和 i 的点击 var div = document.querySelector("body div") div.οnclick=function(e){ alert(e.target.innerText) if(e.target.nodeName == "BUTTON"){ console.log("点击了第"+ e.target.innerText+"个按钮"); } } // 方案二的原理: 根据事件传播机制,子标签的事件会冒泡给父标签,此时我们把本应该绑定在子标签上的事件, // 绑定给父标签,由父标签来影响子标签触发的事件 // 通过e.target获取子标签来实现不同的结果,这种操作称之为:事件委托/事件代理 ``` ### for循环中绑定事件 + 需求: 在循环中给按钮绑定事件,点击按钮打印循环的索引 + 错误写法:因为for循环执行时,事件函数只是绑定了,并没有触发调用,当按钮点击调用事件函数时,for循环早已结束,循环中的变量i 值已经变成最后的索引值加一,所以打印时,总是最后的索引值加一 ``` <body> <button>1</button> <button>2</button> <button>3</button> </body> var buttons = document.getElementsByTagName("button") for(var i=0;i<buttons.length;i++){ buttons[i].οnclick=function(){ console.log(this.index) //打印结果为3 } } ``` #### 使用let关键字 + 使用ES6中新语法let关键字定义变量i,let会定义块级作用域,每一次for循环都会创建一个新的i, 每一个i相互独立,互不影响,如:let 循环5次就有5个i的值,而var循环5次,只有最后一个i值 ``` for(let i=0;i<buttons.length;i++){ buttons[i].onclick =function(){ console.log(i); // 0,1,2 } } ``` #### 给循环变量的值自定义属性 + 再绑定事件之前,把循环变量的值用button的自定义属性记录下来,事件触发调用事件函数时,打印自定义属性即可 ``` 接上面 for(var i=0;i<buttons.length;i++){ buttons[i].index=i; button[i].onclick = function(){ console.log(i)//0,1,2 } } ``` #### 闭包 ##### 什么是闭包 + 通俗解释:一个函数的返回值返回了另一个函数,这种结构就叫闭包结构 + 书面解释:一个函数有权访问另一个函数内部的局部变量 ``` <body> <button>1</button> <button>2</button> <button>3</button> <button>4</button> <button>5</button> <script> function A(){ var count=0; function B(){ console.log(++count) } return B; } var b =A(); b();//1 b();//2 b();//3 </script> ``` ##### 闭包的作用? + 闭包可以使一个函数中的局部变量拥有和全局变量的部分特性,函数执行结束后,变量不会被js垃圾回收机制回收,清理,重置 ##### 闭包的用法 + 在循环中绑定事件时,使用闭包结构保留循环变量i的值,每次循环中i的值不被回收清理,更新,替换 ``` <body> <button>1</button> <button>2</button> <button>3</button> <button>4</button> <button>5</button> <script> var button =document.getElementsByTagName("button") for(var i=0;i<button.length;i++){ button[i].οnclick=method(i+1) } function method(index){ return function(){ console.log(index); } } </script> </body> ``` ##### 闭包的缺点 + 闭包会造成内存泄漏 + 内存泄漏:一个数据在使用完毕之后,没有被回收机制清理,依然占用内存,时可用内存越来越少,最终内存泄漏过多,会导致系统卡顿甚至崩溃 ### 计时器 + 计时器返回值特点: (1)是个不重复数字 (2)多个计时器返回的数字累加 (3)不同浏览器返回的数字不同,不一定从1开始 (4)可以通过clearInterval 或 clearTimeout 来清除/停止计时器,参数就是返回的数字 #### setTimeout + 在指定的时间后(单位为毫秒),执行某些代码,代码只会执行一次 ``` var timer1= setTimeout(function () { h1.innerText = h1.innerText * 1 + 1 }, 1000) ``` + 使用递归可以使setTimeout 像setInterval一样连续计时 ``` var num = 0; function method(){ console.log(++num); setTimeout(method,1000) } setTimeout(method,1000) ``` #### setInterval() + 按照指定的周期(以毫秒计)来调用函数或计算表达式。方法会不停地调用函数,直到 clearInterval() 被调用或窗口被关闭。 + 按照指定的周期(单位为毫秒)来重复执行某些代码,定时器不会自动停止,除非调用 clearInterval() 函数来手动停止或着关闭浏览器窗口 ``` var timer2= setInterval(function () { h1.innerText = h1.innerText * 1 + 1 }, 1000) ``` ``` //让h1 连续移动 var count = 0; var timer3= setInterval(function () { count += 100; h1.style.marginLeft = count + "px" if (count == 500) count = 0; }, 1000) ``` #### 计时器停止 + 注意:清楚计时器一定要在计时器计时结束之前结束,否则无效 + 清除函数的参数可以写但会变量timer和可以写返回的数字,但不建议用数字,因为不同的浏览器运行出来的数字不一样 ``` clearTimeout(timer1) clearInterval(2) ; ``` ### window事件 #### load加载事件 + load 是加载完成事件,当页面上所有的标签文本样式全部加载出来触发这个事件 ``` <body> <div id="d1"></div> <script> // console.log(d1,d2); // error:d2 is not defined window.onload =function(){ console.log(d1,d2); // div div } </script> </body> ``` #### resize 窗口尺寸 + resize 当浏览器窗口尺寸变化时,触发事件 ``` window.onresize =function(){ console.log(window.innerWidth,window.innerHeight); } ``` #### unload 在文档被完全卸载之后触发 + unloade 窗口上的标签,数据,文本被卸载后触发,网页关闭 ``` window.onunload =function(){ console.log("网页卸载");} ``` ### Dom的尺寸和位置 #### screen 屏幕尺寸 + 屏幕尺寸-屏幕可用尺寸 = 状态栏尺寸 ``` screen.width,screen.height //屏幕尺寸 screen.availWidth,screen.availHeight //屏幕可用尺寸 ``` #### window 窗口尺寸 + 窗口的外宽-窗口的内宽 = 浏览器窗口边框宽度(不同浏览器边框不同) + 窗口的外高-窗口的内高 = 控制台高度+菜单栏高度 ``` window.innerWidth,window.innerHeight // 窗口内宽(窗口可用尺寸) window.outerWidth,window.outerHeight // 窗口外宽(窗口宽度大小) ``` #### html 网页尺寸 + 网页宽度 = 窗口内高 + 在网页没有滚动条时:window.innerWidth=html.clientHeight=html.scrollHeight> html.offsetHeight + 在网页有滚动条时: window.innerWidth=html.clientHeight < html.scrollHeight = html.offsetHeight ``` var html = document.documentElement; html.clientWidth,html.clientHeight // 网页的可视高度 html.offsetWidth,html.offsetHeight // 网页的实际高度 html.scrollWidth,html.scrollHeight // 网页占用的高度 ``` #### 标签尺寸 + 关于标签尺寸 和网页尺寸对应,三个API 都可以获取标签尺寸,而且都一样 ``` var div = document.querySelector("div") div.clientWidth,div.clientHeight div.offsetWidth,div.offsetHeight div.scrollWidth,div.scrollHeight ``` #### offset位置 + 相对于非静态定位的父元素的坐标,对应绝对定位坐标 ``` document.body.style.position ="relative" console.log(div.offsetLeft,div.offsetTop); ``` #### client位置 + 标签内容相对于标签自身左上角的坐标 = 标签的边框宽度 ``` div.style.margin = "20px"; div.style.border = "10px solid" console.log(div.clientLeft,div.clientTop); ``` #### scroll位置 + 如果标签设置了overflow:scroll 溢出滚动,获取标签内容的滚动距离,一般给html标签设置 ``` div.scrollLeft,div.scrollTop ,html.scrollTop ``` ### Dom 滚动 #### onscroll 页面滚动 ##### 监听页面滚动 ``` window.οnscrοll= function(){ // 打印网页的滚动位置/坐标,要用html调用 console.log(html.scrollTop,html.scrollLeft) ``` ##### 判断网页滚动到底 + 网页滚动距离 + 显示窗口高度 == 网页总高度 说明触底 + 由于scroll事件触发会滚动多个像素触发一次,所以判断刚好相等不一定成立 ``` if(html.scrollTop+ html.clientHeight==html.offsetHeight){ console.log("网页触底1"); } ``` + 判断网页滚动到距离底部不到10px,说明触底(距离底部10px,说明触底,给页面缓冲区) + 网页滚动距离 + 显示窗口高度 >= 网页总高度-10 ``` if(html.scrollTop+ html.clientHeight>=html.offsetHeight){ console.log("网页触底2"); } ``` #### 修改滚动距离 ##### html.scrollTop + 直接设置网页滚动位置,属性赋值数字,单位默认px ``` btn1.οnclick=function(){ html.scrollTop=300; } ``` ##### window.scroll() + 水平垂直滚动,滚动到水平0,垂直500px的位置,不加单位px ``` btn2.οnclick=function(){ window.scroll(0,600) } ``` ##### window.scrollTo() + scrollTo()和scroll()用法相同都是滚动到指定位置 ``` btn3.οnclick=function(){ window.scrollTo(0,900) } ``` ##### window.scrollBy() + 在原有的位置处继续滚动一段距离 ``` btn4.οnclick=function(){ window.scrollBy(0,100) } ``` ##### scrollByLines() + 按行滚动,参数是行数,1表示普通文字的行高(谷歌不支持这个API) ``` btn5.οnclick=function(){ window.scrollByLines(1) } ``` ##### scrollByPages() + 按页滚动,参数是页数,1页表示显示区域高度(谷歌不支持这个API) ``` btn6.οnclick=function(){ window.scrollByPages(1) } ``` ##### scrollIntoView() + 获得h66在网页上的纵坐标,然后让网页滚动到纵坐标这个位置 html.scrollTop=h66.offsetTop 也可以使用scrollIntoView使一个元素直接滚动到网页顶部(谷歌不支持这个API) ``` btn7.οnclick=function(){ h66.scrollIntoView() } ``` ### js 动画 #### setInterval()实现 + 效果: 让小球运动,到达边缘循环移动 ``` <div id="box"></div> //样式需自己写 var x = 10; var y = 10; // 记录小球每次移动的值,正为右或下,负为左或上 setInterval(function () { if (box.offsetLeft > window.innerWidth - box.offsetWidth || box.offsetLeft<0) { x=-x; } if (box.offsetTop > window.innerHeight - box.offsetHeight || box.offsetTop<0) { y=-y; } box.style.left = box.offsetLeft + x + "px"; box.style.top = box.offsetTop + y + "px"; }, 500) ``` #### setTimeout 实现小球运动 ``` function move(){ if (box.offsetLeft > window.innerWidth - box.offsetWidth || box.offsetLeft<0) { x=-x; } if (box.offsetTop > window.innerHeight - box.offsetHeight || box.offsetTop<0) { y=-y; } box.style.left = box.offsetLeft + x + "px"; box.style.top = box.offsetTop + y + "px"; setTimeout(move,100) } setTimeout(move ,100) ``` #### requestAnimationFrame 实现小球运动(动画帧) + 使用requestAnimationFrame 实现小球运动,请求动画帧,类似于setTimeout 计时器 + 区别是:setTimeout 可自定义计时时间,requestAnimationFrame计时时间不能自定义,而是默认等于页面刷新一次的时间,约等于16.666ms,受硬件性能影响(节约性能) ``` function move(){ if (box.offsetLeft > window.innerWidth - box.offsetWidth || box.offsetLeft<0) { x=-x; } if (box.offsetTop > window.innerHeight - box.offsetHeight || box.offsetTop<0) { y=-y; } box.style.left = box.offsetLeft + x + "px"; box.style.top = box.offsetTop + y + "px"; requestAnimationFrame(move) } var raf = requestAnimationFrame(move) // 和 setTimeout 一样,可以取消动画帧调用 cancelAnimationFrame(raf) ``` ### Dom拖拽事件 + 拖拽事件针对的是拖拽的目标元素 #### dragstart 开始拖拽 ``` var h1 = document.querySelector("h1") h1.οndragstart=function(){ console.log("开始拖拽"); } ``` #### drag 正在拖拽 ``` var h1 = document.querySelector("h1") h1.οndrag=function(){ console.log("正在拖拽"); } ``` #### dragend 结束拖拽 + 由于主动松开鼠标,主动结束 ``` h1.οndragend=function(e){ console.log("结束拖拽"); } ``` + 拖拽事件针对的拖拽的区域元素 #### dragenter 拖入事件 + 拖入事件,事件目标不是被拖拽的元素,而是拖拽的区域元素 ``` var div =document.querySelector("div") div.ondragenter = function(){ console.log("有什么东西被拖入了div内部"); this.style.backgroundColor="pink"; } ``` #### dragover 内部拖动 + 内部拖动,事件目标不是被拖拽的元素,而是拖拽的区域元素 ``` div.ondragover = function(e){ e.preventDefault(); // 阻止默认行为,触发drop console.log("有什么东西正在div内部被拖动"); } ``` #### dragleave 拖出事件 + 拖出事件 事件目标不是被拖拽的元素,而是拖拽的区域元素 ``` div.οndragleave=function(){ console.log("有什么东西被拖出了div内部"); this.style.backgroundColor="white"; } ``` #### drop 丢入事件 + 丢入事件, 事件目标不是被拖拽的元素,而是拖拽的区域元素 + 特别注意:需要阻止这个元素的ondragover事件的默认行为,否则可能触发不了drop事件 ``` div.οndrοp=function(){ console.log("有什么东西被丢入了div内部"); this.appendChild(h1) ``` ### 函数的防抖和节流 + 用户每点一下,数字加一,如果用户连续点击,数字增加很快 + 当用户连续快速点击按钮时,让数字变化速度慢下来,使用事件防抖和事件节流来实现 #### 函数的节流 + 事件节流:当一个事件频繁触发时,降低事件响应的频率和次数 ##### 频率节流 + 时间触发固定 /n(正整数) 次,只响应一次 以降低相应频率,如:点击五次,响应一次 频率节流和事件触发的快慢无关,和触发的次数有关 + 常用于页面滚动事件节流,鼠标移动节流 ``` <button οnclick="increase()">点我</button> var count =0 function increase(){ count++; if(count%5==0){ h1.innerText = count / 5 } } ``` ##### 时间节流 + 在一段时间之内,无论事件触发几次(n>0),只响应一次 如:五秒内,做多响应一次 (时间节流和事件触发次数无关,和时间有关) + 常用于轮播图节流 + 在全局作用域定义变量记录等待状态 var waiting=false; + 在事件函数中先判断等待状态,如需等待, 返回 if(waiting) return; + 在事件响应结束(事件函数最后),开始等待状态 waiting=true; + 在计时器或动画结束后,结束等待状态 waiting=false ``` <button οnclick="increase()">点我</button> var waiting=false; // true表示离上一次响应还不到5秒,需要等待,false表示不需要等待,可以立即响应事件 function increase(){ // 判断是否需要等待,如果需要等待,返回不再执行这次响应 if(waiting) return; // 如果不需要等待,则立即响应事件 h1.innerText = ++count // 本次响应后,开始等待状态 waiting=true; // 5秒后结束等待状态 setInterval(function(){ waiting=false },5000); } ``` #### 事件防抖 + 当一个事件连续多次触发时,只执行最后一次响应 + 原理: 当一个事件被触发,不立即响应,而是等待一段时间在响应,如果这段时间内再次触发事件,则取消上次的响应等待,重新开始新的响应等待 + 常用于输入框输入时显示提示词,防止抖动 也用于数据请求,减少输入时无用的数据请求 + 网速较慢或服务器响应较慢时,加防抖为了防止上一个请求没结束就发下一个请求造成的干涉 + 移动端输入框,加防抖是为了减少数据请求,节省流量 ``` var timer; function increase(){ if(timer) clearTimeout(timer) function action(){ h1.innerText = ++count; } timer = setTimeout(action,1000) } ``` ### BOM + BOM:browser object model 浏览器对象模型,js中把浏览器窗口也认为是对象叫window + 在全局作用域中定义所有变量和函数都是window的属性和方法 ``` var count=1 function add(){ console.log(++count); } console.log(window.count); window.add() ``` + js中很多内置的对象和函数,也是window的属性和方法 ``` window.alert("警告"); console.log(window.Math); ``` + js中规定,window 的属性和方法可以直接调用,省略window. ``` console.log(location); ``` #### 页面跳转方式 ``` location.href = "http://www.baidu" // 替换当前页,没有历史记录 location.replace("http://www.baidu") // 替换当前页,没有历史记录 history.back() //返回历史记录中的上一页 history.forward() // 返回历史记录中的下一页 history.go(-1) //返回历史记录中的任一页,1下一页 -1上一页 open("http://www.baidu") //不关闭当前窗口,打开新窗口显示页面 ``` #### js刷新页面 ``` location.reload(); location.href="./02-BOM.html" location.replace("./02-BOM.html") history.go(0) ``` #### 浏览器领航员 navigator ``` console.log(navigator.userAgent); // 可以获取浏览器和系统信息 ``` #### 在全局范围内,this 指向window ``` console.log(this===window); //true ``` ## jQuery ### jquery 简介 #### jQuery 概念: + jQuery 是一个常用的JavaScript语法库,用于简化js编程 #### jquery 语法: + jQuery 中提供了两个全局变量$和jQuery,他们的值是同一个函数,按插件的命名规则,应该用jQuery命名,但为了简化,使用$代替也可以,一般使用$ ``` console.log($,jQuery); //相同 ``` + $这个函数返回值是一个对象,称之为jquery对象,jquery语法库中定义的几乎所有属性和方法都需要使用jquery对象调用 ``` $(); ``` + $() 参数可以是样式选择器,用于查找所有符合条件的标签,放入一个jquery对象结构中返回,jquery对象是一个类数组结构 ``` $("h1"),$("#myH1"),$("ul li") ``` + $()参数还可以是标签本身,会用jquery对象包裹这个js元素,然后就可以调用jquery的API了 ``` $(document.body) ``` ##### 通过索引取出jquery对象中的标签元素 ``` $(document.body)[0] ``` ##### 对jquery对象遍历 + 特别注意:js原生的foEeach循环回调第一个参数是item,jquery的each循环回调第一个参数是index + 可以把jquery对象转成数组,遍历 ``` $("ul li").toArray().forEach(function(item,index){ document.writeln(item.innerText+index) }) ``` + 可以直接对jquery进行遍历 ``` $("ul li").each(function(index,item){ document.writeln(item.innerText+index) }) ``` ### jquery 常用API #### 关于元素的增删改查 ##### 1.增 ``` $("body").append("<h1>大标题</h1>") // 在body结束位置插入标签 $("body").prepend("<h2>二标题</h2>")// 在body开始位置插入标签 $("<h3>3标题</h3>").appendTo("body") // 把h3标签插入到body结束位置 $("<h4>4标题</h4>").prependTo("body") // 把h3标签插入到body开始位置 ``` ##### 2.删 ``` $("h2").remove(); //删除所有h2标签 $("h1").detach(); // 删除所有h1标签 $("h3").empty(); //清空h3标签 (清空标签内内容) ``` ##### 3. 改 ``` $("h4").text("<i>h4</i>") // 设置标签文本 $("h3").html("<i>h3</i>") // 设置标签内容,会识别标签字符串 ``` ##### 4.查 ``` $("li")[2] //找到第三个li标签,得到的是一个li标签 var li3= $("li").eq(2) // 找到第三个li标签,得到一个新的jQuery对象 li3.parent() // 找父元素 li3.children() // 找子元素 li3.siblings() // 找到所有兄弟元素 li3.prev() //相邻的上一个兄弟元素 li3.prevAll() //找到前边所有的兄弟元素 li3.next() // 找相邻的下一个兄弟元素 li3.nextAll() // 找相邻的后边所有的兄弟元素 ``` #### 关于标签属性的操作 ##### 1.普通属性,attr() 可以设置所有属性 ``` $("h4").attr("age","10") // 设置属性 console.log( $("h4").attr("age"));//读取属性值 $("h4").attr("id","abc") // $("h4")[0].id="abc" ``` ##### 2.class属性 ``` $("h4").attr("class","a b") // 增加 $("h4").addClass("c") //增加 $("h4").removeClass("a")//删除 $("h4").toggleClass("c") // 删除 var bool=$("h4").hasClass("b") // 查看是否存在这个属性 ``` ##### 3.style 样式属性 ``` $("h4").css("font-size","40px") //参数可以是属性名和属性值 $("h4").css({ // 参数也可以是样式对象 color:"red", backgroundColor:"gray", // 属性如不叫引号用小驼峰 "border-radius":"20px" // 属性加引号用小写 }) ``` #### 关于jQuery动画 + animate 执行一个js动画, 三个参数 (1.必选,动画结束时的样式对象, 2.可选,动画的执行时间,默认400ms, 3.可选,动画执行结束时调用的回调函数) + 注意:jquery 动画不支持颜色和图形变换(旋转缩放)的动画 ``` $("h4").animate({ fontSize:"100px" },1000,function(){ console.log("动画执行结束"); }) ``` #### 关于jQuery 尺寸位置 ``` $("h4").width() // 获取标签宽度 $(window).innerWidth()//窗口内宽 $("html").height() //网页实际宽度 $("h4").offset() // 获取横纵坐标 ``` #### 关于事件dom + jquery 把js 大部分事件单独做了封装,事件的绑定都封装成了对应的函数,函数名和事件名重名,参数是事件函数,多个标签可以同时绑定,不需要循环 + drag 拖拽相关事件没有封装 ``` $("li").click(function(){ // alert(this.innerText) alert($(this).text()) }) ``` + 三种绑定页面加载事件的方式 ``` window.οnlοad=function(){} //原生 $(window).ready(function(){}) // jquery $(function(){}) // query简化 ``` #### jQuery 链式调用 + 链式调用:一个对象可以连续打点调用多个函数,这种结构叫链式调用结构 ``` $("h3").css("color","blue").attr("id","h3").animate({fontSize:"50px"}) ``` + 原理:jquery中每一个函数的返回值都是调用它的jQuery对象本身,所以一个函数调用后返回这个jQuery对象可以继续调用其他函数,形成一个链式结构 + 链式结构支持换行 ``` $("body").append("<h1>111</h1>").css("backgroundColor","orange") $("<h3>11111</h3>") .appendTo("body") .css("backgroundColor","yellow") .html("22222") ``` #### jquery动画插件 ##### 自定义属性 ``` // 自定义属性 加data-和不加data-的区别 // 不加data-时直接打点调用, 属性不会显示在标签上, 不能用attr()调用 document.body.age = "abc"; // 加data-时,使用dataset打点调用, 会显示到标签上, 可以用attr调用 document.body.dataset.age = 13 ``` + 如果用到jQuery插件,要注意先导入jQuery本身引用,再导入jQuery插件 + 自定义属性最好要有data- ,如果是数字可以直接 ``` <script src="https://code.jquery/jquery-3.6.0.js"></script> <script src="./jquery.smoove.js"></script> <style> div{ width: 300px; height: 300px; background-color: red; margin: 100px auto; } </style> </head> <body> <div></div> <div data-move-x="200px"></div> <div data-move-x="-200px"></div> <div data-move-y="200px"></div> <div data-rotate="180deg"></div> <div data-scale-x="3"></div> <div data-scale-x="3" data-scale-y="0" ></div> <div data-scale="0"></div> <div data-scale="0" data-rotate="360deg"></div> <div data-rotate-y="360deg"></div> </body> <script> // 给所有div添加滚出动画效果,默认透明度从0到1渐显 $("div").smoove() </script> ``` #### 自定义jQuery插件 ``` <script src="https://code.jquery/jquery-3.6.0.js"></script> <script src="./jquery.custom.js"></script> <body> <h1>1111</h1> <h2>2222</h2> <h2>2222</h2> <h3>3333</h3> <h3>3333</h3> <h3>3333</h3> </body> <script> // console.log(count);//报错,count不是一个全局变量 $("h1").myColor("red") $("h2").myColor("blue") $("h3").myColor("orange") </script> ``` ``` /** * 这是我自定义的jQuery插件 * * 插件的作用是给jQuery对象中的标签设置文字颜色 * * 插件更新于 2022-03-07 16:34:25 * * 版权:最终解释权归李月月所有 * */ // IIFE 立即调用函数表达式 // 自调用函数:函数定义之后立即调用,结构(匿名函数()) (function(){ console.log("执行了我的自定义插件"); var count=100; }()) // 函数自调用的好处:使立即执行的代码全部封装到一个局部作用域中,独立起来,不会影响全局作用域中的任何变量 // 用法:在封装插件时,建议使用函数的自调用结构,以避免污染全局作用域(全局作用域变量名冲突) (function($,window,document){ // 在jQuery插件中使用固定语法 $.fn 给jQuery添加自定义函数 $.fn.myColor = function(optopns){ alert("执行了自定义color",optopns,this) // this 指的是调用这个函数的jquery对象 this.css("color",optopns) } // jQuery,window,document 三个全局变量传入函数中作为参数,也就是局部变量使用,伪类减少全局变量调用 }(jQuery,window,document)) ``` ### 本地存储 #### webStorage + webStorage : 是浏览器端存储数据的一种前端技术,包含 localStorage 和 sassionStorage 这两个API #### localStorage长期存储/本地存储 + 长期存储/本地存储,在浏览器中存储的数据会长期存在,除非手动删除 常用来存储网站的浏览历史,搜索历史,收藏和书签 某些网站的账号等 #### sassionStorage会话存储/短期存储 + sassionStorage : 会话存储/短期存储,浏览器窗口一旦关闭,则立即删除,常用来存储一些网页的登录状态 #### localStorage 和 sassionStorage的增删改查 + localStorage 和 sassionStorage 都是 window的属性,用于本地存储数据,API相同,数据存储位置和时间长短不同 + 为什么打开一个新的窗口,同一个网页,会话存储sessionStorage数据不一致? + 会话存储的数据是在窗口上存的,一个窗口对应一个sessionStorage作用域, 对于不同的窗口,即使是同一个网页, 数据也不共用 + 本地存储的数据是在域名(IP地址)下存的, 一个域名网址对应一个localStorage作用域, 对于同一个域名下的不同网页可以共用一个localStorage, 不同域名下的localStorage相互隔离不通用 ##### 1.增 + 注意只支持字符串类型存储 ``` localStorage.setItem("name","张三") localStorage.setItem("sex",false) sessionStorage.setItem("age",20) sessionStorage.setItem("friend",{name:"李四"}) sessionStorage.setItem("friend",JSON.stringify(obj)) ``` ##### 2.删 ``` localStorage.removeItem("name") // 通过key删除数据 sessionStorage.removeItem("age") sessionStorage.clear() // 清空数据 ``` ##### 3.改 + 改 和增使用相同API, 无此key则添加,有此key则修改 ``` localStorage.setItem("sex", "true") localStorage.setItem("phone", "110") sessionStorage.setItem("age",30) ``` ##### 4.查 ``` localStorage.length // 查看数据长度 sessionStorage.length // 通过key值取出某一条数据 localStorage.getItem("sex") ``` ``` 遍历取出所有的数据 for(var i = 0; i < localStorage.length; i++ ){ var key = localStorage.key(i) console.log(localStorage.getItem(key)) } ``` ### cookie + 什么是cookie? + cookie 原意为 "甜饼" ,在js中表示浏览器文档中的一个数据字段,它的值是一段字符串,存储在浏览器中 + cookie有什么用 + 当用户访问网站时,cookie用来记录用户的重要信息,再次访问网站时,通过cookie识别用户信息,实现:自动登录,用户提醒,收藏,搜索历史等功能 + cookie默认是会话存储, 和sessionStorage相似, 窗口关闭则清理 #### cookie 和 webStorage的区别 + cookie 数据量小,整个域名内最多存储限制为4kB webStorage,数据量大,整个域名内最多存储限制为 5MB + cookie 不仅仅存在于浏览器本地,它可以随请求发给服务器,由服务器读取和修改 webStorage只能存储在浏览器本地,服务器无法读取和修改 + cookie 是传统的前端技术,很早就用了,html5新增了webStorage功能 + cookie是document的属性,而webStorage是window的属性 #### cookie的用法 + 谷歌浏览器不支持file://协议打开cookie, 要使用服务器环境打开 + cookie虽然是一个字符串, 但字符串中是键值对结构 ``` document.cookie = "name=张三" ``` + cookie值是键值对结构,赋值的新键值对不会覆盖老键值对,会同时存在 ``` document.cookie = "age=20" ``` + cookie键值对中键是唯一的, 赋值已有的键会会把对应值更新 ``` document.cookie = "age=30" ``` + 如果数据没有设置键, 默认键为空, ``` document.cookie = "李四" document.cookie = "王五" ``` + 我们可以给cookie添加数据是,设置cookie的有效期, 和localStorage相似, 在过期之前,cookie不会被清理 + 在键值对后使用expires设置过期时间点, 到达这个时间点, cookie此键值对被清理 ``` console.log(new Date) document.cookie = "sex=男;expires=Date Thu Mar 10 2022 09:58:08 GMT+0800" // 例子: 设置一个有效期为1小时的cookie值 var now = new Date() now.setHours(now.getHours() + 1) document.cookie = "sex=男;expires="+now // 例子: 设置一个有效期为1小时的cookie值 // 也可以使用max-age设置cookie有效时常,默认单位秒,支持计算 document.cookie = "phone=110;max-age=60*60" console.log(document.cookie) ``` + 需求: 从本地cookie中取出年龄age值 + startsWith 判断字符串是否以某一段字符开头 ``` var arr = document.cookie.split("; ") console.log(arr) var str = arr.find(function(item){ return item.startsWith("age=") }) console.log(str) console.log(str.split("=")[1]) ``` ### 装箱和拆箱 ##### 装箱 + 把值类型转化成引用类型的过程 JSON.parse() + 从一个字符串中解析出json对象 ``` //定义一个字符串 var data='{"name":"goatling"}' //解析对象 JSON.parse(data) 结果是: name:"goatling" ``` ##### 拆箱 + 把引用类型转化成值类型的过程 JSON.stringfy() + 从一个对象中解析出字符串 ``` var data={name:'goatling'} JSON.stringify(data) 结果是: '{"name":"goatling"}' ``` ##### 深浅复制 + 浅拷贝 + 浅拷贝是创建一个新对象,这个对象有着原始对象属性的一份精确拷贝 + 如果属性是基本类型,拷贝的就是基本类型的值;如果属性是引用类型,拷贝的就是内存地址 + 如果其中一个对象改变了这个地址,就会影响到另一个对象 + 重新在堆中创建内存,拷贝前后对象的基本数据类型互不影响,但对象的引用类型因共享一块内存,会互相影响 + 深拷贝 + 将一个对象从内存中完整的拷贝一份出来,从堆内存中开辟一个的区域存放(创建一个新的堆区,中存放值,与前面的堆内存存放的堆区不是一个) + 且修改新对象不会影响到原对象 ``` 深复制 复制堆区且 function copy2(data, deep = false) { // 深拷贝:基本数据类型拷贝数据本身 if (deep) { if (getType(data) == "array") { // 深拷贝数组或对象的第二种写法 只能对引用类型用 return JSON.parse(JSON.stringify(data)); } else if (getType(data) == "object") { // 深拷贝 数组或对象的第二种写法 return JSON.parse(JSON.stringify(data)); } // 浅拷贝 else { return data; } } } ``` ### 正则表达式 #### 正则表达式的含义 + 正则表达式:regular expression 也叫规则表达式 用于字符串的检索和判断 + 使用正则来判断一个字符串是否符合一定规则或是否包含一定规则的字符 + 正则匹配的字符串数据来源1,用户输入,2,数据请求 3,本地读取 #### 方括号 | 字符 | 描述 | | ------------------------------------------------------------ | ---------------------------------- | | [abc\] | 查找方括号之间的任何字符。 | | [[^abc\]](http://www.w3school/jsref/jsref_regexp_charset_not.asp) | 查找任何不在方括号之间的字符。 | | [0-9] | 查找任何从 0 至 9 的数字。 | | [a-z] | 查找任何从小写 a 到小写 z 的字符。 | | [A-Z] | 查找任何从大写 A 到大写 Z 的字符。 | | [A-z] | 查找任何从大写 A 到小写 z 的字符。 | | [adgk] | 查找给定集合内的任何字符。 | #### 元字符 | 字符 | 描述 | | ------------ | ------------------------------------------------------------ | | ^ | 匹配输入字符串的开始位置。 | | $ | 匹配一个字符串的结束(是否以某个字符结束) | | . | 匹配任意一位字符 | | * | 匹配它前边字符任意长度,例如,zo* 能匹配 "z" 以及 "zoo"。* 等价于{0,}。 | | + | 匹配它前边字符至少一个, 长度>=1 例如,'zo+' 能匹配 "zo" 以及 "zoo",但不能匹配 "z"。+ 等价于 {1,}。 | | ? | 匹配前边的字符0个或1个(可有可无) | | \d | 匹配一位数字 等价于 [0-9] | | {n} | 匹配n个它前边的字符 例如,'o{2}' 不能匹配 "Bob" 中的 'o',但是能匹配 "food" 中的两个 o。 | | {n,} | 匹配至少n个它前边的字符 'o{2,}' 不能匹配 "Bob" 中的 'o',但能匹配 "foooood" 中的所有 o。' | | {n,m} | 匹配至少n个,最多m个它前边的字符 例如,"o{1,3}" 将匹配 "fooooood" 中的前三个 o。 | | \w | 匹配任意数字,字母或下划线 等价于 [0-9a-zA-Z_] | | \W | 匹配非字母、数字、下划线。等价于 [^0-9a-zA-Z _ 。 | | [0123456789] | 匹配一位或0位数字 | | [abc] | 匹配a或b或c或没有ab | | \ | 转义, 把正则语法转译成普通字符 比如 \* 匹配*这个字符 | | x\|y | 匹配 x 或 y。例如,'z\|food'能匹配 "z" 或 "food"。'(z\|f)ood'则匹配 "zood" 或 "food"。 | #### 修饰符 | 修饰符 | 含义 | 描述 | | :----- | :------------------------------------- | :----------------------------------------------------------- | | i | ignore - 不区分大小写 | 将匹配设置为不区分大小写,搜索时不区分大小写: A 和 a 没有区别。 | | g | global - 全局匹配 | 查找所有的匹配项。 | | m | multi line - 多行匹配 | 使边界字符 **^** 和 **$** 匹配每一行的开头和结尾,记住是多行,而不是整个字符串的开头和结尾。 | | s | 特殊字符圆点 **.** 中包含换行符 **\n** | 默认情况下的圆点 **.** 是 匹配除换行符 **\n** 之外的任何字符,加上 **s** 修饰符之后, **.** 中包含换行符 \n。 | #### 正则表达式语法 ##### 变量创建 /正则语法/ ``` var myReg1 = /\d/ //匹配一个数字,只要字符串中包含数组都可 ``` ##### new 关键字创建 ``` var myReg2 = new RegExp(/\d+/) // 匹配至少连续一个数字 ``` #### 正则对象操作函数 ##### exec() 函数 + 用正则去匹配一个字符串,查找一个字符串中符合正则的字符 + exec() 这个函数不支持全局匹配 + exec() 是正则对象的函数 ``` <input type="text" id="input"> <button οnclick="regular()">开启正则</button> function regular() { var string = input.value; var myReg2 = new RegExp(/\d+/) var result = myReg2.exec(string) console.log(2, result); } ``` ##### test()函数 + 用于正则判断,返回布尔(bool)值 ``` var myReg9 = /^1[356789]\d{9}$/ // 手机号正则 result = myReg9.test(string) console.log(9, result); var myReg10 = /^[0-9a-zA-Z]{3,}@\w{2,5}\.(com|net|cn)$/ // 邮箱正则 result = myReg10.test(string) console.log(10, result); // 密码规则:以大写字母开头,只能包含数字字母下划线,长度范围[6,18] var myReg11 = /^[A-Z]\w{5,17}/ // 密码正则 // 昵称正则:只能是汉字,数字,字母,下划线,横杠,长度[4-8] var myReg12 =/^(\w|-|[\u4e00-\u9fa5]){4,8}$/ // 判断文件类型正则: 判断一个字符串是不是视频文件名 // 注意:要把文件名中不能出现的字符给排除掉 var myReg13 =/^[^\\/:\*\?"<>\|]+\.(mp4|flv|wmv|avi|mov)$/i ``` #### 字符串操作函数 ##### match() + 在字符串内检索指定的值,或找到一个或多个正则表达式的匹配。返回一个由匹配结果组成的数组 + 传递一个参数:match(regexp) + 必须,一个正则表达式 + 返回数组的内容依赖于 regexp 是否具有全局标志 g。如果没有全局标志,返回一个类数组对象。如果有全局匹配标志,则返回匹配结果组成的数组。如果没找到匹配结果返回 null 。 ``` var str = 'I,love,you,Do,you,love,me'; var pattern = /love/; var arr = str.match(pattern); // ["love", index: 2, input: "I,love,you,Do,you,love,me"] ``` ``` var str = 'I,love,you,Do,you,love,me'; var pattern = /love/g; var arr = str.match(pattern); // ["love", "love"] ``` ``` var str = 'I,love,you,Do,you,love,me'; var pattern = /hate/; var arr = str.match(pattern); // null ``` ``` var myReg3 = /\d/g // 匹配字符串中的每一位数字 result = string.match(myReg3) console.log(3, result) var myReg4 = /\d+/g // 匹配字符串中的每个连续数字 result = string.match(myReg4) console.log(4, result) ``` ``` // g和i可以一起添加到正则最后 var myReg7 = /[xyz]/gi // 找到的所有的大小写字母x和y和z result = string.match(myReg7) console.log(7,result) ``` ##### replace() + 需要被替换的子字符串,可以是指定字符串,还可以是**正则表达式**。对于正则表达式来说首先会根据是否全局匹配(全局/.../g)决定替换行为,如果是全局的则替换全部替换,非全局的只有替换首个匹配的字符串。 + replace 函数可以使用正则替换,参数1可换成正则表达式 + replace的第二个参数可以写成回调函数 ``` // 字符串替换,默认把第一个a替换为b string.replace("a","b") // replace 函数可以使用正则替换,参数1可换成正则表达式 var myReg14 = /草|卧 *槽|傻逼|马化腾|fuck|SB/ig // 匹配敏感字符 result=string.replace(myReg14,"*") document.writeln(result) ``` ``` result =string.replace(myReg14,function(item){ console.log(item); // 参数item 是匹配的结果 // 返回值是要替换的结果 if(item=="fuck") return "f**k" return item.replace(/[^ ]/g,"*") }) document.writeln(result) ``` ##### split() + 字符串裁剪函数split的参数可以是正则表达式 ``` string = 'a-b_c=d*e.f' result = string.split(/[-_=\*\.]/) console.log(result) } ``` ##### search() + search() 方法用于检索字符串中指定的子字符串,或检索与正则表达式相匹配的子字符串。 + 返回值:与指定查找的字符串或者正则表达式相匹配的 String 对象起始位置。 + 如果没有找到任何匹配的子串,则返回 -1。
本文标签: 知识点
版权声明:本文标题:前端知识点总结 内容由热心网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:https://m.elefans.com/xitong/1727191901a1101518.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论