浏览器 | 内核 | 备注 |
---|---|---|
IE | Trident | IE、猎豹安全、360极速浏览器、百度浏览器 |
firefox | Gecko | 可惜这几年已经没落了,打开速度慢、升级频繁、猪一样的队友flash、神一样的对手chrome。 |
Safari | webkit | 现在很多人错误地把 webkit 叫做 chrome内核(即使 chrome内核已经是 blink 了)。苹果感觉像被别人抢了媳妇,都哭晕再厕所里面了。 |
chrome | Chromium/Blink | 在 Chromium 项目中研发 Blink 渲染引擎(即浏览器核心),内置于 Chrome 浏览器之中。Blink 其实是 WebKit 的分支。大部分国产浏览器最新版都采用Blink内核。二次开发 |
Opera | blink | 现在跟随chrome用blink内核。 |
Web标准构成:主要包括结构(Structure)、表现(Presentation)和行为(Behavior)三个方面。
web标准小结
head 头部. 标题 title 文档标题
标签名 | 定义 | 说明 |
---|---|---|
标题标签 | 作为标题使用,并且依据重要性递减 | |
段落标签 | 可以把 HTML 文档分割为若干段落 | |
|
水平线标签 | 没啥可说的,就是一条线 |
换行标签 | ||
div标签 | 用来布局的,但是现在一行只能放一个div | |
span标签 | 用来布局的,一行上可以放好多个span |
标签 | 显示效果 |
---|---|
b或strong | 粗体 |
i或em | 斜体 |
s或del | 加删除线 |
u或ins | 加下划线 |
b 只是加粗 strong 除了可以加粗还有 强调的意思, 语义更强烈。
属性 | 属性值 | 描述 |
---|---|---|
src | URL | 图像的路径 |
alt | 文本 | 图像不能显示时的替换文本 |
title | 文本 | 鼠标悬停时显示的内容 |
width | 像素 | 设置图像的宽度 |
height | 像素 | 设置图像的宽度 |
border | 数字 | 设置图像边框的宽度 |
**注意: **
标签可以拥有多个属性,必须写在开始标签中,位于标签名后面。
属性之间不分先后顺序,标签名与属性、属性与属性之间均以空格分开。
采取 键值对 的格式 key=“value” 的格式
链接标签
文字或图片
属性 | 作用 |
---|---|
href | 用于指定链接目标的url地址,(必须属性)当为标签应用href属性时,它就具有了超链接的功能 |
target | 用于指定链接页面的打开方式,其取值有_self和_blank两种,其中_self为默认值,__blank为在新窗口中打开方式。 |
相对路径
路径分类 | 符号 |
---|---|
同一级路径 | |
下一级路径 | “/” |
上一级路径 | “…/” |
锚点定位
base标签
预格式化文本pre
标签可定义预格式化的文本。被包围在标签 元素中的文本通常会保留空格和换行符。而文本也会呈现为等宽字体。
特殊字符
大于号 >
小于号 <
空格  
表格作用:
存在即是合理的。 表格的现在还是较为常用的一种标签,但不是用来布局,常见显示、展示表
格式数据
**总结: **
表格的主要目的是用来显示特殊数据的
一个完整的表格有表格标签(table),行标签(tr),单元格标签(td)组成,没有列的标签
表格属性 重点记住 cellspacing 、 cellpadding
属性名 | 含义 | 常用属性值 |
---|---|---|
border | 设置表格的边框(border="0"为无边框) | 像素值 |
cellspacing | 设置单元格与单元格边框之间的空白间距 | 像素值(默认为2像素) |
cellpadding | 设置单元格内容与单元格边框之间的空白间距 | 像素值(默认为1像素) |
width | 设置表格宽度 | 像素值 |
height | 设置表格高度 | 像素值 |
align | 这是表格在网页中的水平对齐方式 | left、center、right |
表头单元格标签th
表格标题caption
合并单元格
合并的顺序我们按照 先上 后下 先左 后右 的顺序
列表
无序列表ul
1.
中只能嵌套,直接在
标签中输入其他标签或者文字的做法是不被允许的。
2. 与 之间相当于一个容器,可以容纳所有元素。
有序列表ol
自定义列表
标签名 | 定义 | 说明 |
---|---|---|
|
无序标签 | 里面只能包含li 没有顺序,我们以后布局中最常用的列表 |
|
有序标签 | 里面只能包含li 有顺序, 使用情况较少 |
|
自定义列表 | 里面有2个兄弟, dt 和 dd |
表单
input控件
type的属性 | 描述 |
---|---|
text | 文本框 |
password | 密码框 |
radio | 单选按钮 |
checkbox | 复选框 |
button | 普通按钮 |
submit | 提交按钮 |
reset | 重置按钮 |
image | 图像形式提交按钮 |
file | 文件域 |
属性 | 属性值 | 描述 |
---|---|---|
name | 由用户自定义 | 控件的名称 |
value | 由用户自定义 | input控件中的默认文本值 |
size | 正整数 | input控件在页面中的显示宽度 |
checked | checked | 定义选择控件默认被选中的项 |
maxlength | 正整数 | 控件允许输入的最多字符数 |
checked="checked"表示就默认选中了
label标签
作用: 用于绑定一个表单元素, 当点击label标签的时候, 被绑定的表单元素就会获得输入焦点。
1.第一种用法就是用label直接包括input表单。
用户名:
2.第二种用法 for 属性规定 label 与哪个表单元素绑定
男
textarea文本域
<textarea >
文本内容
textarea>
作用:
通过textarea控件可以轻松地创建多行文本输入框.
cols=“每行中的字符数” rows=“显示的行数” 我们实际开发不用
select下拉列表
选项1 选项2 选项3 ...form表单域
各种表单控件属性 | 属性值 | 作用 |
---|---|---|
action | url地址 | 用于指定接收并处理表单数据的服务器程序的url地址。 |
method | get/post | 用于设置表单数据的提交方式,其取值为get或post。 |
name | 名称 | 用于指定表单的名称,以区分同一个页面中的多个表单。 |
行内样式
<标签名 style=“属性1:属性值1; 属性2:属性值2; 属性3:属性值3;”> 内容 标签名>
内部样式
外部样式
属性 | 作用 |
---|---|
rel | 定义当前文档与被链接文档之间的关系,在这里需要指定为“stylesheet”,表示被链接的文档是一个样式表文件。 |
type | 定义所链接文档的类型,在这里需要指定为“text/CSS”,表示链接的外部文件为CSS样式表。我们都可以省略 |
href | 定义所链接外部样式表文件的URL,可以是相对路径,也可以是绝对路径。 |
选择器 CSS选择器干啥的? 选择标签用的, 把我们想要的标签选择出来
选择器 | 作用 | 缺点 | 使用情况 | 用法 |
---|---|---|---|---|
标签选择器 | 可以选出所有相同的标签,比如p | 不能差异化选择 | 较多 | p { color:red;} |
类选择器 | 可以选出1个或者多个标签 | 可以根据需求选择 | 非常多 | .nav { color: red; } |
id选择器 | 一次只能选择器1个标签 | 只能使用一次 | 不推荐使用 | #nav {color: red;} |
通配符选择器 | 选择所有的标签 | 选择的太多,有部分不需要 | 不推荐使用 | * {color: red;} |
文字文本样式font
属性 | 表示 | 注意点 |
---|---|---|
font-size | 字号 | 我们通常用的单位是px 像素,一定要跟上单位,谷歌浏览器默认的文字大小为16px,最小为12px |
font-family | 字体 | 实际工作中按照团队约定来写字体 p{font-family: Arial,“Microsoft Yahei”, “微软雅黑”;} |
font-weight | 字体粗细 | 记住加粗是 700 或者 bold , 不加粗 是 normal 或者 400 记住数字不要跟单位 数值在100-900之间 |
font-style | 字体样式 | 记住倾斜是 italic 不倾斜 是 normal 工作中我们最常用 normal |
font | 字体连写 | 1. 字体连写是有顺序的 不能随意换位置 2. 其中字号 和 字体 必须同时出现 写法: 选择器 { font: font-style font-weight font-size/line-height font-family;}必须有font-size和font-family属性 |
css外观属性
属性 | 表示 | 注意点 |
---|---|---|
color | 颜色 | 我们通常用 十六进制 比如 而且是简写形式 #fff |
line-height | 行高 | 控制行与行之间的距离 |
text-align | 水平对齐 | 可以设定文字水平的对齐方式 left左对齐(默认);right右对齐;center居中对齐 |
text-indent | 首行缩进 | 通常我们用于段落首行缩进2个字的距离 text-indent: 2em; 1em 就是一个字的宽度 如果是汉字的段落, 1em 就是一个汉字的宽度 |
text-decoration | 文本修饰 | 记住 添加 下划线 underline ; 取消下划线 none; |
复合选择器
选择器 | 作用 | 特征 | 使用情况 | 隔开符号及用法 |
---|---|---|---|---|
后代选择器 | 用来选择元素后代 | 是选择所有的子孙后代 | 较多 | 符号是空格 .nav a |
子代选择器 | 选择 最近一级元素 | 只选亲儿子 | 较少 | 符号是**>** .nav>p |
交集选择器 | 选择两个标签交集的部分 | 既是 又是 | 较少 | 没有符号 p.one |
并集选择器 | 选择某些相同样式的选择器 | 可以用于集体声明 | 较多 | 符号是逗号 .nav, .header |
链接伪类选择器 | 给链接更改状态 | 较多 | 重点记住 a{} 和 a:hover 实际开发的写法 |
伪类选择器
标签显示模式display
元素模式 | 元素排列 | 设置样式 | 默认宽度 | 包含 |
---|---|---|---|---|
块级元素block | 一行只能放一个块级元素 | 可以设置宽度高度 | 容器的100% | 容器级可以包含任何标签 |
行内元素inline | 一行可以放多个行内元素 | 不可以直接设置宽度高度 | 它本身内容的宽度 | 容纳文本或则其他行内元素 |
行内块元素inline-block | 一行放多个行内块元素 | 可以设置宽度和高度 | 它本身内容的宽度 |
行高line-height
CSS 背景(background)
属性 | 作用 | 值 |
---|---|---|
background-color | 背景颜色 | 预定义的颜色值/十六进制/RGB代码 语法:background-color:颜色值; 默认的值是 transparent 透明的 |
background-image | 背景图片 | url(图片路径), none(无背景图,默认的) background-image : none | url (url) |
background-repeat | 是否平铺 | repeat 背景图像在纵向和横向上平铺(默认的) /no-repeat 不平铺 /repeat-x 在横向上平铺/repeat-y 在纵向平铺 |
background-position | 背景位置 | length(百分比,长度值)/position(方位名词 : top | center | bottom | left | center | right) 分别是x 和 y坐标, 切记 如果有 精确数值单位,则必须按照先X 后Y 的写法 |
background-attachment | 背景固定还是滚动 | scroll(随对象内容滚动) / fixed(背景图像固定) |
背景简写 | 更简单 | background: 背景颜色 背景图片地址 背景平铺 背景滚动 背景位置; 他们没有顺序 |
背景透明 | 让盒子半透明 | background: rgba(0,0,0,0.3); 后面必须是 4个值,最后一个参数是alpha 透明度 取值范围 0~1之间,低于 ie9 的版本是不支持的 |
CSS层叠性
CSS继承性
子标签会继承父标签的某些样式,如文本颜色和字号。
想要设置一个可继承的属性,只需将它应用于父元素即可。
CSS优先级 权重
标签选择器 | 计算权重公式 |
---|---|
继承或者 * | 0,0,0,0 |
每个元素(标签选择器) | 0,0,0,1 |
每个类,伪类 | 0,0,1,0 |
每个ID | 0,1,0,0 |
每个行内样式 style="" | 1,0,0,0 |
每个!important 重要的 | ∞ 无穷大 |
数位之间没有进制 比如说: 0,0,0,5 + 0,0,0,5 =0,0,0,10 而不是 0,0, 1, 0, 所以不会存在10个div能赶上一个类选择器的情况。
盒子边框border
属性 | 作用 |
---|---|
border-width | 定义边框粗细,单位是px |
border-style | 边框的样式 |
border-color | 边框颜色 |
边框的样式:
综合写法border : border-width || border-style || border-color
border: 1px solid red; 没有顺序
表格的细线边框border-collapse:collapse
通过表格的cellspacing="0"
,将单元格与单元格之间的距离设置为0,
但是两个单元格之间的边框会出现重叠,从而使边框变粗
通过css属性:
table{ border-collapse:collapse; }
内边距padding
值的个数 | 表达意思 |
---|---|
1个值 | padding:上下左右内边距; |
2个值 | padding: 上下内边距 左右内边距 ; |
3个值 | padding:上内边距 左右内边距 下内边距; |
4个值 | padding: 上内边距 右内边距 下内边距 左内边距 ; |
盒子的实际的大小 = 内容的宽度和高度 + 内边距 + 边框
如果没有给一个盒子指定宽度, 此时,如果给这个盒子指定padding, 则不会撑开盒子。
外边距(margin)
margin属性用于设置外边距。 margin就是控制盒子和盒子之间的距离,和padding类似。
margin可以让一个块级盒子实现水平居中必须:
清除元素的默认内外边距
{
padding:0; / 清除内边距 /
margin:0; / 清除外边距 */
}
外边距合并
1.相邻块元素垂直外边距的合并
2.嵌套块元素垂直外边距的合并(塌陷)
解决方案:
圆角边框border-radius(CSS3)
语法:border-radius:length; 让正方形length=50%则为圆形 , 对于长方形设置为高度的一半
盒子阴影box-shadow(CSS3)
box-shadow:水平阴影 垂直阴影 模糊距离(虚实) 阴影尺寸(影子大小) 阴影颜色 内/外阴影;
CSS 提供了 3 种机制来设置盒子的摆放位置,分别是
普通流(标准流:块级元素,行内元素,行内块元素)
浮动 (让盒子从普通流中浮起来 —— 让多个盒子(div)水平排列成一行)
定位(将盒子定在某一个位置 自由的漂浮在其他盒子的上面)
在 CSS 中,通过 float
中文, 浮 漏 特 属性定义浮动,语法如下:
选择器 { float: 属性值; }
属性值 | 描述 |
---|---|
none | 元素不浮动(默认值) |
left | 元素向左浮动 |
right | 元素向右浮动 |
float —— 浮漏特
特点 | 说明 |
---|---|
浮 | 加了浮动的盒子是浮起来的,漂浮在其他标准流盒子的上面。 |
漏 | 加了浮动的盒子是不占位置的,它原来的位置漏给了标准流的盒子。 |
特 | 特别注意:浮动元素会改变display属性, 类似转换为了行内块,但是元素之间没有空白缝隙 |
浮动元素与兄弟盒子的关系
在一个父级盒子中,如果前一个兄弟盒子是:
清除浮动
父级盒子很多情况下,不方便给高度,但是子盒子浮动就不占有位置,最后父级盒子高度为0,就影响了下面的标准流盒子。清除浮动主要为了解决父级元素因为子级浮动引起内部高度为0 的问题。清除浮动之后, 父级就会根据浮动的子盒子自动检测高度。父级有了高度,就不会影响下面的标准流了。
1.使用after伪元素清除浮动
.clearfix:after { content: “”; display: block; height: 0; clear: both; visibility: hidden; }
.clearfix {zoom: 1;} / IE6、7 专有 */
2.使用双伪元素清除浮动
.clearfix:before,.clearfix:after {
content:"";
display:table;
}
.clearfix:after {
clear:both;
}
.clearfix {
*zoom:1;
}
CSS属性书写顺序
建议遵循以下顺序:
定位也是用来布局的,它有两部分组成:定位=定位模式+边偏移
在 CSS 中,通过 top
、bottom
、left
和 right
属性定义元素的边偏移:(方位名词)
定位模式 (position) 语法:选择器 { position: 属性值; }
定位模式(position) | 是否脱标占有位置 | 移动位置基准 | 模式转换(行内块) | 使用情况 |
---|---|---|---|---|
静态static | 不脱标,正常模式 | 正常模式 | 不能 | 几乎不用 |
相对定位relative | 不脱标,占有位置 | 相对自身位置移动 | 不能 | 基本单独使用 |
绝对定位absolute | 完全脱标,不占有位置 | 相对于定位父级移动位置 | 能 | 要和定位父级元素搭配使用 |
固定定位fixed | 完全脱标,不占有位置 | 相对于浏览器移动位置 | 能 | 单独使用,不需要父级 |
子绝父相 —— 子级是绝对定位,父级要用相对定位。
绝对定位的盒子居中
position:relative;
top:50%;
left:50%;
transform: translate(-50%,-50%);
堆叠顺序(z-index)
注意:z-index
只能应用于相对定位、绝对定位和固定定位的元素,其他标准流、浮动和静态定位无效。
透明度
opacity:0~1;
元素的显示与隐藏
display 显示
display 设置或检索对象是否及如何显示。
display: none 隐藏对象
display:block 除了转换为块级元素之外,同时还有显示元素的意思。
特点: 隐藏之后,不再保留位置。
visibility 可见性
设置或检索是否显示对象。
visibility:visible ; 对象可视
visibility:hidden; 对象隐藏
特点: 隐藏之后,继续保留原有位置。
overflow 溢出
属性值 | 描述 |
---|---|
visible | 不剪切内容也不添加滚动条 |
hidden | 不显示超过对象尺寸的内容,超出的部分隐藏掉 |
scroll | 不管超出内容否,总是显示滚动条 |
auto | 超出自动显示滚动条,不超出不显示滚动条 |
三者关系比较
属性 | 区别 | 用途 |
---|---|---|
display | 隐藏对象,不保留位置 | 配合后面js做特效,比如下拉菜单,原先没有,鼠标经过,显示下拉菜单, 应用极为广泛 |
visibility | 隐藏对象,保留位置 | 使用较少 |
overflow | 只是隐藏超出大小的部分 | 1. 可以清除浮动 2. 保证盒子里面的内容不会超出该盒子范围 |
鼠标样式cursor
属性值 | 描述 |
---|---|
default | 小白 默认 |
pointer | 小手 |
move | 移动 |
text | 文本 |
not-allowed | 禁止 |
轮廓线 outline
语法:outline: none;
防止拖拽文本域resize
语法:
vertical-align垂直对齐
让文字居中对齐,是 text-align: center;
vertical-align 垂直对齐,它只针对于行内元素或者行内块元素
语法:vertical-align : baseline |top |middle |bottom
图片、表单和文字对齐
语法:vertical-align : middle
去除图片底侧空白缝隙
原因:
图片或者表单等行内块元素,他的底线会和父级盒子的基线对齐。
就是图片底侧会有一个空白缝隙。
解决的方法就是:
溢出的文字省略号显示
先强制一行内显示文本
white-space: nowrap;
超出的部分隐藏
overflow: hidden;
文字用省略号替代溢出的部分
text-overflow: ellipsis;
精灵技术
首先我们知道,css精灵技术主要针对于背景图片,插入的图片img 是不需要这个技术的。
滑动门
一般的经典布局都是这样的:
<li>
<a href="#">
<span>导航栏内容span>
a>
li>
css样式
*{
padding:0;
margin:0;
}
body{
background: url(images/wx.jpg) repeat-x;
}
.father {
padding-top:20px;
}
li {
padding-left: 16px;
height: 33px;
float: left;
line-height: 33px;
margin:0 10px;
background: url(./images/to.png) no-repeat left ;
}
a {
padding-right: 16px;
height: 33px;
display: inline-block;
color:#fff;
background: url(./images/to.png) no-repeat right ;
text-decoration: none;
}
li:hover,
li:hover a {
background-image:url(./images/ao.png);
}
总结:
CSS三角形
阻止链接跳转
需要给href添加 javascript:void(0); 或者 javascript:;
网站ico图标
1.使用ico图标
首先把favicon.ico 这个图标放到根目录下。
再html里面, head 之间 引入 代码。
2.制作ico图标
我们可以自己做的图片,转换为 ico图标,以便放到我们站点里面。
方法步骤:
总结:
代码:
注意:
网站优化三大标签
1.网页title 标题
一般不超过28个中文,最先出现的词语权重高,主关键词出现3次,辅关键词出现1次
2.Description 网站说明
电商网:
注意点:
3.Keywords 关键字
Keywords是页面关键词,是搜索引擎关注点之一。Keywords应该限制在6~8个关键词左右,电商类网站可以多 少许。
电商网:
字体图标iconfont
可以做出跟图片一样可以做的事情,改变透明度、旋转度,等…
但是本质其实是文字,可以很随意的改变颜色、产生阴影、透明效果等等…
本身体积更小,但携带的信息并没有削减。
几乎支持所有的浏览器
UI设计人员给我们svg文件,我们需要转换成我们页面能使用的字体文件, 而且需要生成的是兼容性的适合各个浏览器的。
推荐网站: http://icomoon.io
IcoMoon成立于2011年,推出的第一个自定义图标字体生成器,它允许用户选择他们所需要的图标,使它们成一字型。 内容种类繁多,非常全面,唯一的遗憾是国外服务器,打开网速较慢。
http://www.iconfont.cn/
这个是阿里妈妈M2UX的一个icon font字体图标字库,包含了淘宝图标库和阿里妈妈图标库。可以使用AI制作图标上传生成。 一个字,免费,免费!!
在样式里面声明字体: 告诉别人我们自己定义的字体(一定注意字体文件路径的问题)
@font-face {
font-family: 'icomoon';
src: url('fonts/icomoon.eot?7kkyc2');
src: url('fonts/icomoon.eot?7kkyc2#iefix') format('embedded-opentype'),
url('fonts/icomoon.ttf?7kkyc2') format('truetype'),
url('fonts/icomoon.woff?7kkyc2') format('woff'),
url('fonts/icomoon.svg?7kkyc2#icomoon') format('svg');
font-weight: normal;
font-style: normal;
}
给盒子使用字体
span {
font-family: "icomoon";
}
过渡transition
过渡动画: 是从一个状态 渐渐的过渡到另外一个状态
语法格式:
transition: 要过渡的属性 花费时间 运动曲线 何时开始;
属性 | 描述 | CSS |
---|---|---|
transition | 简写属性,用于在一个属性中设置四个过渡属性。 | 3 |
transition-property | 规定应用过渡的 CSS 属性的名称。 | 3 |
transition-duration | 定义过渡效果花费的时间。默认是 0。 | 3 |
transition-timing-function | 规定过渡效果的时间曲线。默认是 “ease”。 | 3 |
transition-delay | 规定过渡效果何时开始。默认是 0。 | 3 |
运动曲线 默认是 ease 匀速:lineaar 逐渐慢下来:ease 加速:ease-in 减速:ease-out 先加后减速:ease-in-out
获得焦点元素
:focus 伪类 选择器用于选取获得焦点的元素 。 我们这里主要针对的是 表单元素
:hover
命令行
盘符: 就可以进入某个盘符
dir 列出目录中的所有文件
cd 切换文件夹(目录)
md/mkdir 创建文件夹
rd/rmdir 删除文件夹
创建文件
删除文件
小技巧
自动补全
曾经使用过的命令
cls 清屏 (CLear Screen)
exit 退出
快捷键 ctrl + c 终止当前操作
notepad 记事本
calc 计算器
gulp
Gulp.js 是一个自动化构建工具,开发者可以使用它在项目开发过程中自动执行常见任务。
安装
安装node.js
https://nodejs.org/
检测node 是否安装成功
node -v
npm install -g cnpm --registry=https://registry.npm.taobao.org
检测安装cnpm 是否成功
cnpm -v
安装gulp
gulp中文网
gulp官网
# 全局安装
cnpm install gulp -g
检测安装成功 gulp
gulp -v
本地环境搭建体验
以下内容首先打开命令行,然后切换到项目的根目录,输入以下命令并运行
初始化
# 在当前目录自动生成一个package.json文件
cnpm init -y
安装插件
# 当前项目中安装gulp
cnpm install gulp --save-dev
# 压缩html的插件
cnpm install gulp-htmlmin --save-dev
# 压缩css的插件
cnpm install gulp-cssmin --save-dev
# 自动打开浏览器,并实时刷新插件(浏览器同步测试工具)
cnpm install browser-sync --save-dev
配置文件
在当前项目的根目录中创建一个gulpfile.js文件,如链接中文件
gulpfile.js
演示自动化构建
# 自动化压缩和复制文件到发布目录dist
gulp build
# 开启测试用的服务器
gulp dev
语义化标签
h5表单属性
placeholder:占位符-提示信息
autofocus:自动获得焦点-一般页面中放1个
autocomplete 自动完成
autocomplete=on
关闭 autocomplete =off
multiple:可以多选文件提交
一起使用form属性,可以将输入标签放在表单的外面,还受到表单的管理
required:必填验证
novalidate:关闭验证
pattern:自定义验证-通过编写正则表达式自定义验证规则 一般和required同时使用
audio 音频标签
语法:
<audio src="小猪佩奇.mp3" autoplay> audio>
支持的格式
格式 | MIME-type |
---|---|
MP3 | audio/mpeg |
Ogg | audio/ogg |
Wav | audio/wav |
video 视频标签
语法:
<video src="小猪佩奇.mp4" autoplay controls >video>
支持的格式
格式 | MIME-type |
---|---|
MP4 | video/mp4 |
WebM | video/webm |
Ogg | video/ogg |
video常用属性、方法、事件
属性 | 方法 | 事件 |
---|---|---|
duration 视频播放时长 | play 播放 | canplay 视频加载完毕 准备播放 |
currentTime 当前播放进度 | pause 暂停 | timeupdate 播放时-持续触发 |
volume 音量大小 |
source标签
可以通过在多媒体标签内加入source标签,用来指定多个播放路径,当第一个source标签的路径出错时,自动会切换到第二个source标签
<video >
<source src="1.mp4">
<source src="2.mp4">
<source src="3.mp4">
video>
object-fit属性
当video标签视频内容宽度没有铺满video标签时,可以在css写上 该属性即可
video {
/* 让视频内容铺满整个video标签 */
object-fit: fill;
}
公共属性
以下属性 是要直接写在标签上的 如 autoplay controls
<video src="小猪佩奇.mp4" autoplay controls >video>
属性 | 值 | 描述 |
---|---|---|
autoplay | autoplay | 如果出现该属性,则音频在就绪后马上播放。 |
controls | controls | 如果出现该属性,则向用户显示控件,比如播放按钮。 |
loop | loop | 如果出现该属性,则每当音频结束时重新开始播放。 |
muted | muted | 规定视频输出应该被静音。 |
preload | preload | 如果出现该属性,则音频在页面加载时进行加载,并预备播放。如果使用 “autoplay”,则忽略该属性。 |
src | url | 要播放的音频的 URL。 |
伪类选择符
结构伪类选择器
E:first-child —— 匹配父元素的第一个子元素
E:nth-child(n) E:nth-last-child(n)
匹配到父元素的第n个元素 或者 是倒数第n个元素(n也可以为公式、数字、关键字)
常见的关键词有even偶数、odd奇数
E:nth-of-type(n)
E:nth-child(n)
匹配父元素的第n个子元素E。E:nth-of-type(n)
匹配同类型中的第n个同级兄弟元素E。属性选择器
伪元素选择器
想要让伪元素有效,必须遵循以下注意事项
E ::before
这个写法是错误的content:""
;2d移动 translate
语法:div{
transform: translate(50px,50px);
}
translate:(50%,50%);
2d旋转 rotate
使用步骤:
transform
rotate(角度)
如 transform:rotate(30deg)
顺时针方向旋转30度div{
transform: rotate(0deg);
}
特点
转换中心 transform-origin
该属性可以修改元素旋转的时候的中心点
2d缩放 scale
transform
scale(宽的倍数,高的倍数)
如 宽变为两倍,高变为3倍 transform:scale(2,3)
div{
transform:scale(2,3);
}
小结
动画 animation
用@keyframes定义动画,类似定义类选择器
/* 1 声明动画函数 */
@keyframes ani_div {
0%{
width: 100px;
background-color: red;
}
50%{
width: 150px;
background-color: green;
}
100%{
width: 300px;
height: 300px;
background-color: yellow;
}
}
div {
width: 200px;
height: 200px;
background-color: aqua;
margin: 100px auto;
/* 2 调用动画 */
animation-name: ani_div;
/* 持续时间 */
animation-duration: 2s;
}
语法:
动画名
设置要使用的动画名 animation-name:xxx;
持续时间
设置动画播放的持续时间 animation-duration:3s
速度曲线
和设置过渡的速度曲线一样 animation-timing-function:linear;
延迟时间
animation-delay: 0s;
循环次数
设置动画播放的循环次数 animation-iteration-count: 2;
infinite 为无限循环
循环方向
animation-direction
如在动画中定义了 0%:红色 100%:黑色 那么 当属性值为
动画等待或者结束的状态
animation-fill-mode
设置动画在等待或者结束的时候的状态
暂停和播放
animation-play-state
控制 播放 还是 暂停
running
播放 paused
暂停
复合写法
animation: name duration timing-function delay iteration-count direction fill-mode;
animation:动画名称 持续性时间 运动曲线 合适开始 播放次数 是否反方向 起始或结束的标志
动画结束事件animationend
元素在动画结束之后,会自动触发的事件 animationend
var div = document.querySelector("div");
div.addEventListener("animationend", function () {
console.log("div的动画结束之后,触发");
})
css3兼容处理
css3涉及到较多的新属性,某些低版本(如ie8以及以下)的浏览器对css3的支持程度不够,因此需要做以下处理
添加对应的浏览器的前缀 常见前缀如下
如对 border-radius
进行兼容性处理
-webkit-border-radius: 30px 10px;
-moz-border-radius: 30px 10px;
-ms-border-radius: 30px 10px;
// border-radius 一定要放在最后
border-radius: 30px 10px;
如果发现添加前缀也解决不了兼容性问题,那么就不要使用该css3属性
3D转换
3d移动 translate3d
视距 perspertive
perspertive 就是用来设置 人 和 物体 的距离
写在被观察元素的父盒子里
左手准则
要判断某元素沿着x轴是怎么旋转的
3d旋转 rotate3d
语法:
transform:rotateX(45deg);
沿着x轴正方向旋转 45度transform:rotateY(45deg)
沿着y轴正方向旋转 45degtransform:rotateZ(45deg)
沿着Z轴正方向旋转 45degtransform:rotate3d(x,y,z,deg)
沿着自定义轴旋转 deg为角度 了解即可3D缩放 scale3d
语法:
transform: scale3d(1 ,1,2);
宽,高 缩放一倍,厚度放大两倍transform: scaleX(1)
只缩放宽transform: scaleY(1)
只缩放高transform: scaleZ(1)
只缩放厚视距原点 perspective-origin
视距原点 可以设置 人 站在x轴和y轴的位置
转换样式(3D呈现) transform-style
控制子元素是否开启3维立体环境
transform-style: flat;
平面模式 - 不开启3维立体环境transform-style: preserve-3d;
3维立体环境布局视口 layout viewport
移动设备的浏览器都默认设置了一个布局视口,用于解决早期的PC端页面在手机上显示的问题。
视觉视口 visual viewport
它是用户正在看到的网站的区域。注意:是网站的区域。
我们可以通过缩放去操作视觉视口,但不会影响布局视口,布局视口仍保持原来的宽度。
理想视口 ideal viewport
理想视口,对设备来讲,是最理想的视口尺寸
需要手动添写meta视口标签通知浏览器操作
meta视口标签的主要目的:布局视口的宽度应该与理想视口的宽度一致,简单理解就是设备有多宽,我们布局的视口就多宽
总结:我们开发最终会用理想视口,而理想视口就是将布局视口的宽度修改为视觉视口
meta标签
"viewport" content="width=device-width, initial-scale=1.0,maximum-scale=1.0, minimum-scale=1.0, user-scalable=no">
属性 | 解释 |
---|---|
width | 宽度设置的是viewport宽度,可以设置device-width特殊值 |
initial-scale | 初始缩放比,大于0的数字 |
maximum-scale | 最大缩放比,大于0的数字 |
minimum-scale | 最小缩放比,大于0的数字 |
user-scalable | 用户是否可以缩放,yes或no(1或0) |
最标准的viewport设置
二倍图
物理像素&物理像素比
物理像素点指的是屏幕显示的最小颗粒,是物理真实存在的。
物理像素比:一个px的能显示的物理像素点的个数,称为物理像素比或屏幕像素比
背景缩放background-size
background-size 属性规定背景图像的尺寸
background-size: 背景图片宽度 背景图片高度;
单位: 长度|百分比|cover|contain;
cover把背景图像扩展至足够大,以使背景图像完全覆盖背景区域。
contain把图像图像扩展至最大尺寸,以使其宽度和高度完全适应内容区域
CSS3盒子模型
传统模式宽度计算:盒子的宽度 = CSS中设置的width + border + padding
CSS3盒子模型: 盒子的宽度= CSS中设置的宽度width 里面包含了 border 和 padding
/*CSS3盒子模型(用这个)*/
box-sizing: border-box;
/*传统盒子模型*/
box-sizing: content-box;
移动端特殊样式
/*CSS3盒子模型*/
box-sizing: border-box;
-webkit-box-sizing: border-box;
/*点击高亮我们需要清除清除 设置为transparent 完成透明*/
-webkit-tap-highlight-color: transparent;
/*在移动端浏览器默认的外观在iOS上加上这个属性才能给按钮和输入框自定义样式*/
-webkit-appearance: none;
/*禁用长按页面时的弹出菜单*/
img,a { -webkit-touch-callout: none; }
流式布局方式
流式布局,就是百分比布局,也称非固定像素布局。
通过盒子的宽度设置成百分比来根据屏幕的宽度来进行伸缩,不受固定像素的限制,内容向两侧填充。
container),简称"容器"。它的所有子元素自动成为容器成员,称为 Flex 项目(flex
item),简称"项目"。
总结:就是通过给父盒子添加flex属性,来控制子盒子的位置和排列方式
父项常见属性
子属性 | 属性值 |
---|---|
row | 默认值从左到右 |
row-reverse | 从右到左 |
column | 从上到下 |
column-reverse | 从下到上 |
子属性 | 属性值 |
---|---|
flex-start | 默认值,从头部开始,如果主轴是X,则从左往右 |
flex-end | 从尾部开始排列 |
center | 在主轴居中对齐,如果主轴是X轴,水平居中 |
space-around | 平分剩余空间 |
space-bet | 先两边贴边再平分剩余空间 |
默认项目都排在一条线(又称”轴线”)上。
flex-wrap属性定义,flex布局中默认是不换行的
nowrap 不换行
wrap 换行
flex-start 从头部开始
flex-end 从尾部开始
center 居中显示
stretch 拉伸
只能用于子项出现 换行 的情况(多行),在单行下是没有效果的。
子属性 | 属性值 |
---|---|
flex-start | 默认值在侧轴的头部开始排列 |
flex-end | 从侧轴尾部开始排列 |
center | 在侧轴中间显示 |
space-around | 子项在侧轴平分剩余空间 |
space-bet | 子项在侧轴先两边贴边再平分剩余空间 |
stretch | 设置子项元素高度平分父元素高度 |
flex-flow:row wrap;
子项常见属性
flex 属性定义子项目分配剩余空间,用flex来表示占多少份数。
.item {
flex: ; /* 默认值 0 */
}
align-self 属性允许单个项目有与其他项目不一样的对齐方式,可覆盖 align-items 属性。
默认值为 auto,表示继承父元素的 align-items 属性,如果没有父元素,则等同于 stretch。
span:nth-child(2) {
/* 设置自己在侧轴上的排列方式 */
align-self: flex-end;
}
数值越小,排列越靠前,默认为0。
注意:和 z-index 不一样。
rem单位
rem (root em)是一个相对单位,类似于em,em是父元素字体大小。
不同的是rem的基准是相对于html元素的字体大小。
比如,根元素(html)设置font-size=12px; 非根元素设置width:2rem; 则换成px表示就是24px。
媒体查询
@media mediatype and|not|only (media feature) {
CSS-Code;
}
mediatype 查询类型
将不同的终端设备划分成不同的类型,称为媒体类型
all 用于所有设备
print 用于打印机和打印预览
scree 用于电脑屏幕,平板电脑,只能手机等
关键字
关键字将媒体类型或多个媒体特性连接到一起做为媒体查询的条件。
媒体特性
width 定义输出设备中页面可见区域的宽度
min-width 定义输出设备中页面最小可见区域宽度
max-width 定义输出设备中页面最大可见区域宽度
less 基础
Less安装
①安装nodejs,可选择版本(8.0),网址:http://nodejs.cn/download/
②检查是否安装成功,使用cmd命令(win10是window+r 打开运行输入cmd) —输入“node –v”查看版本即可
③基于nodejs在线安装Less,使用cmd命令“npm install -g less”即可
④检查是否安装成功,使用cmd命令“ lessc -v ”查看版本即可
Less 使用之变量
变量是指没有固定的值,可以改变的。因为我们CSS中的一些颜色和数值等经常使用。
@变量名:值;
@color: pink;
Less 编译 vocode Less 插件
Easy LESS 插件用来把less文件编译为css文件
安装完毕插件,重新加载下 vscode。
只要保存一下Less文件,会自动生成CSS文件。
Less 嵌套 :如果遇见 (交集|伪类|伪元素选择器) ,利用&进行连接
Less 运算
任何数字、颜色或者变量都可以参与运算。就是Less提供了加(+)、减(-)、乘(*)、除(/)算术运算。
使用媒体查询针对不同宽度的设备进行布局和样式的设置,从而适配不同设备的目的。
设备的划分情况:
父容器版心的尺寸划分
Bootstrap
Bootstrap 来自 Twitter(推特),是目前最受欢迎的前端框架。Bootstrap 是基于HTML、CSS 和 JAVASCRIPT 的,它简洁灵活,使得 Web 开发更加快捷。
bootstrap基本使用
创建文件夹结构
创建 html 骨架结构
引入相关样式文件
书写内容
bootstrap布局容器
.container
.container-fluid
bootstrap栅格系统
列偏移
使用 .col-md-offset-* 类可以将列向右侧偏移。这些类实际是通过使用 * 选择器为当前元素增加了左侧的边距(margin)。
1
2
列排序
通过使用 .col-md-push-* 和 .col-md-pull-* 类就可以很容易的改变列(column)的顺序。
往左侧推
往右侧推
响应式(隐藏)工具
类名 | 超小屏 | 小屏 | 中屏 | 大屏 |
---|---|---|---|---|
.hidden-xs | 隐藏 | 可见 | 可见 | 可见 |
.hidden-sm | 可见 | 隐藏 | 可见 | 可见 |
.hidden-md | 可见 | 可见 | 隐藏 | 可见 |
.hidden-lg | 可见 | 可见 | 可见 | 隐藏 |
语法: class="hidden-xs“
与之相反的是 visible-xs/sm/md/lg
JS组成
ECMAScript——JavaScript语法
DOM——页面文档对象模型
BOM——浏览器对象模型
数据存储单位
大小关系:bit < byte < kb < GB < TB<.....
输入输出语句
方法 | 说明 | 归属 |
---|---|---|
alert(msg) | 浏览器弹出警示框 | 浏览器 |
console.log(msg) | 浏览器控制台打印输出信息 | 浏览器 |
prompt(info) | 浏览器弹出输入框,用户可以输入 | 浏览器 |
alert() 主要用来显示消息给用户,console.log() 用来给程序员自己看运行时的消息。
声明变量
// 声明变量
var age; // 声明一个 名称为age 的变量
赋值
age = 10; // 给 age 这个变量赋值为 10
变量的初始化
var age = 18; // 声明变量同时赋值为 18
声明一个变量并赋值, 我们称之为变量的初始化。
数据类型简介
alert(Number.MAX_VALUE); // 1.7976931348623157e+308
alert(Number.MIN_VALUE); // 5e-324
alert(Infinity); // Infinity 无穷大
alert(-Infinity); // -Infinity 无穷小
alert(NaN); // NaN , Not a number,代表一个非数值
isNaN用来判断一个变量是否为非数字的类型,返回 true 或者 false
语法: var 变量名A = isNaN(变量名B)
String 字符串型
转义符 | 解释说明 |
---|---|
\n | 换行符,n 是 newline 的意思 |
\ \ | 斜杠 \ |
’ | ’ 单引号 |
" | ”双引号 |
\t | tab 缩进 |
\b | 空格 ,b 是 blank 的意思 |
字符串长度 —— 语法:语法: var 变量名A = 变量名B.length
字符串拼接
多个字符串之间可以使用 + 进行拼接,其拼接方式为 字符串 + 任何类型 = 拼接之后的新字符串
拼接前会把与字符串相加的任何类型转成字符串,再拼接成一个新的字符串
如果变量两侧都有字符串拼接,口诀“引引加加 ”,删掉数字,变量写加中间
获取变量数据类型
typeof 可用来获取检测变量的数据类型
var num = 18;
console.log(typeof num) // 结果 number
数据类型转换
转换为字符串
1.toString() 语法:alert(变量名.toString())
2.String()强制转换 语法:alert(String(变量名))
3.加号拼接字符串:和字符串拼接的结果都是字符串(隐式转换)
转换为数字型
1.parseInt(string)函数 语法:parseInt(’string‘)
2.parseFloat(string)函数 语法:parseInt(’string‘)
3.Number()强制转换 语法:Numer(‘string’)
4.js隐式转换:利用算术运算隐式转换为数值型 比如:‘12’-0
转换为布尔型
Boolean()函数 语法:Boolean(‘string’)
关键字
包括:break、case、catch、continue、default、delete、do、else、finally、for、function、if、in、instanceof、new、return、switch、this、throw、try、typeof、var、void、while、with 等。
递增运算符
++num 前置递增,就是自加1,类似于 num = num + 1,但是 ++num 写起来更简单。
使用口诀:先自加,后返回值
num++ 后置递增,就是自加1,类似于 num = num + 1 ,但是 num++ 写起来更简单。
使用口诀:先返回原值,后自加
比较运算符
< > <== >== == != === !==
逻辑运算符
与&& 或|| 非!
流程控制
if 语句
// 适合于检查多重条件。
if (条件表达式1) {
语句1;
} else if (条件表达式2) {
语句2;
} else if (条件表达式3) {
语句3;
....
} else {
// 上述条件都不成立执行此处代码
}
三元表达式
表达式1 ? 表达式2 : 表达式3;
switch分支流程控制
switch( 表达式 ){
case value1:
// 表达式 等于 value1 时要执行的代码
break;
case value2:
// 表达式 等于 value2 时要执行的代码
break;
default:
// 表达式 不等于任何一个 value 时要执行的代码
}
注意: 执行case 里面的语句时,如果没有break,则继续执行下一个case里面的语句。
for循环
for(初始化变量; 条件表达式; 操作表达式 ){
//循环体
}
while循环
while (条件表达式) {
// 循环体代码
}
do-while循环
do {
// 循环体代码 - 条件表达式为 true 时重复执行循环体代码
} while(条件表达式);
continue
continue 关键字用于立即跳出本次循环,继续下一次循环(本次循环体中 continue 之后的代码就会少执行一次)
break
立即跳出整个循环(循环结束)
创建数组
利用 new 创建数组
var 数组名 = new Array() ;
var arr = new Array(); // 创建一个新的空数组
注意 Array () ,A 要大写
利用数组字面量创建数组
//1. 使用数组字面量方式创建空的数组
var 数组名 = [];
//2. 使用数组字面量方式创建带初始值的数组
var 数组名 = ['小白','小黑','大黄','瑞奇'];
数组中新增元素
数组[ 数组.length ] = 新数据;
函数的使用
声明函数
// 声明函数
function 函数名() {
//函数体代码
}
调用函数
// 调用函数
函数名(); // 通过调用函数名来执行函数体代码
函数的参数
函数的返回值
return 语句
arguments的使用
当不确定有多少个参数传递的时候,可以用 arguments 来获取
arguments展示形式是一个伪数组,可以进行遍历
JavaScript(es6前)中的作用域有两种:
全局作用域 在函数内部没有声明直接赋值的变量属于全局变量
局部作用域(函数作用域)
预解析
预解析:在当前作用域下, JS 代码执行之前,浏览器会默认把带有 var 和 function 声明的变量在内存中进行提前声明或者定义。
代码执行: 从上到下执行JS语句。
预解析会把变量和函数的声明在代码执行之前执行完成。
对象
所有的事物都是对象,对象是由属性和方法组成的
创建对象的三种方式
1.利用字面量创建对象
var 对象名 = {
属性1:属性值1;
属性2:属性值2;
.......
sayHi : function(){
alert('大家好啊~');
}
};
调用对象——对象名.属性名 或 对象名[‘属性名’]
调用对象方法——对象名.方法名()
2.利用 new Object 创建对象
var 对象名 = new Obect();
通过内置构造函数Object创建对象,此时变量已经保存了创建出来的空对象
通过对象操作属性和方法的方式,来为对象增加属性和方法
比如——对象名1.属性1=’XXX‘;
3.利用构造函数创建对象
function 构造函数名(形参1,形参2,形参3) {
this.属性名1 = 参数1;
this.属性名2 = 参数2;
this.属性名3 = 参数3;
this.方法名 = 函数体;
}
构造函数的调用格式
var obj = new 构造函数名(实参1,实参2,实参3)
以上代码中,obj即接收到构造函数创建出来的对象
遍历对象
其语法如下:
for (var 变量 in 对象名字) {
// 在此执行代码
}
Math对象
属性、方法名 | 功能 |
---|---|
Math.PI | 圆周率 |
Math.floor() | 向下取整 |
Math.ceil() | 向上取整 |
Math.round() | 四舍五入版 就近取整 注意 -3.5 结果是 -3 |
Math.abs() | 绝对值 |
Math.max()/Math.min() | 求最大和最小值 |
Math.random() | 获取范围在[0,1)内的随机数 |
// Math随机数方法 包含两端的2个数字
function getRandom(min, max) {
return Math.floor(Math.random() * (max - min + 1)) + min;
}
console.log(getRandom(1, 10));
日期对象
var now = new Date();
var future = new Date('2019/5/1');//或者 ('2019-10-10 8:8:8')
// 返回当前年份
console.log(date.getFullYear());
// 返回当前月份 数值比实际月份小1 需要+1
console.log(date.getMonth() + 1);
// 返回当前日期是本月的多少日
console.log(date.getDate());
// 返回当前日期是周几 注意:返回当前是周几 周日返回值为0
console.log(date.getDay());
// 返回当前小时
console.log(date.getHours());
// 返回当前分钟
console.log(date.getMinutes());
// 返回当前秒钟
console.log(date.getSeconds());
基于1970年1月1日(世界标准时间)起的毫秒数
获取总毫秒数如下
// 实例化Date对象
var now = new Date();
// 1. 用于获取对象的原始值
console.log(date.valueOf())
console.log(date.getTime())
// 2. 简单写可以这么做
var now = + new Date();
// 3. HTML5中提供的方法,有兼容性问题
var now = Date.now();
数组对象
检测是否为数组
1.instanceof 可以判断一个对象是否是某个构造函数的实例 返回值为true或者false
语法:数组名 instanceof Array
比如:console.log(arr instanceof Array);
2**.Array.isArray(数组名)**用于判断一个对象是否为数组 返回值为true或者false 是 HTML5 中提供的方法
添加删除数组元素
方法名 | 说明 | 返回值 |
---|---|---|
push(参数1…) | 末尾添加一个或多个元素–数组名.push(要添加的) | 新的长度 |
pop() | 删除最后一个元素,数组长度减一 | 删除的元素值 |
unshift(参数1…) | 开头添加一个或多个元素 | 新的长度 |
shift() | 删除第一个元素,数组长度减一 | 第一个元素值 |
注意:push、unshift为增加元素方法;pop、shift为删除元素的方法
数组排序
方法名 | 说明 |
---|---|
reverse() | 颠倒数组中元素顺序 |
sort() | 对数组的元素进行排序 |
注意:sort方法需要传入参数来设置升序、降序排序
数组转换为字符串
1.toString() 把数组转换成字符串,逗号分隔每一项
2.join(‘分隔符’) 把数组中的所有元素转换为一个字符串
注意:二者均返回一个字符串,join方法如果不传入参数,则按照 “ , ”拼接元素
数组对象转换为字符串格式
JSON.stringify()
其他方法
数组连接 concat(‘连接内容’)
数组截取字符串 slice(截取的起始位置,截取的数量)
数组替换 replace(‘被替换的字符’,‘替换为的字符’) 只会替换第一个
数组根据索引号删除相关内容 splice(索引号,从索引号处开始要删除的数量 )
字符串对象
js 会把基本数据类型包装为复杂数据类型
字符串转换为数组对象
JSON.parse()
字符串操作方法
连接字符串 str.concat(‘连接内容’)
查找字符串 str.substr(start,length) 从start位置开始,length取的个数
截取字符串 slice(start,end) 从start位置开始,截取到end位置,end取不到
替换字符串 str.replace(‘被替换的字符’,‘替换为的字符’) 只会替换第一个
字符转换为数组 str.split(‘分隔符’)
API是给程序员提供的一种工具,以便能更轻松的实现想要完成的功能
获取元素
根据ID获取
语法:document.getElementById(id)
返回值:元素对象 或 null
根据标签名获取元素
语法:document.getElementsByTagName('标签名') 或者 element.getElementsByTagName('标签名')
返回值:元素对象集合(伪数组,数组元素是元素对象)
根据类名获取元素 (h5新增)
document.getElementsByClassName(‘类名’) //返回元素对象集合
根据选择器获取元素 (h5新增)
document.querySelector(‘选择器’) //返回第一个元素对象
document.querySelectorAll(‘选择器’) //根据指定选择器返回
获取body元素
document.body
获取html元素
document.documentElement
事件基础
事件三要素
执行事件的步骤
1.获取事件源
2.注册事件(绑定事件)
3.添加事件处理程序(采取函数赋值形式)
常见的鼠标事件
鼠标事件 | 触发条件 |
---|---|
onclick | 鼠标点击左键触发 |
onmouseover | 鼠标经过触发 |
onmouseout | 鼠标离开触发 |
onfocus | 获得鼠标焦点触发 |
onblur | 失去鼠标焦点触发 |
onmousemove | 鼠标移动触发 |
修改元素内容(获取或设置)
element.innerText 从起始到终止位置的内容,但不识别html标签,空格和换行也会去掉
element.innerHTML 从起始到终止位置的内容,但识别html标签,空格和换行也会保留
属性操作
获取属性的值: 元素对象.属性名
设置属性的值: 元素对象.属性名=值
样式属性操作
element.style 行内样式操作
element.className 类名样式操作
排他思想
如果有同一组元素,我们想要某一个元素实现某种样式, 需要用到循环的排他思想算法:
自定义属性操作
获取属性值
1.element.属性 //获取内置属性(元素本身自带的属性)
2.element.getAttribute(’属性值’) //主要获得自定义的属性,程序员自定义的属性
设置属性值
1.element.属性 = ‘值’ //设置内置属性值
2.element.setAttribute(’属性值’,‘值’) //主要设置自定义的属性
移出属性
element.removeAttribute(‘属性’);
H5自定义属性
H5规定自定义属性data-开头作为属性名并且赋值
比如:element.setAttribute('data-index',2)
获取H5自定义属性
element.dataset.属性名
element.dataset[’‘属性名’]
节点操作
元素节点 nodeType为1 //实际开发中的主要操作对象
属性节点 nodeType为2
文本节点 nodeType为3(包含文字、空格、换行等)
父级节点
node.parentNode //返回最近的一个父节点,没有则返回null
子节点
1.parentNode.childNodes //会返回所有节点
2.parentNode.children //只返回子元素节点,其余节点不返回,重点使用这个
第1个子节点:parentNode.firstElementChild
最后一个子节点:parentNode.lastElementChild
兄弟节点
node.nextElementSibling 返回下一个兄弟元素节点
node.previousElementSibling 返回上一个兄弟元素节点
创建节点
document.createElement(‘tagName’)
添加节点
node.appendChild(节点名) //将一个节点添加到指定父节点的子节点列表末尾,类似于css里的after伪元素
node.insertBefore(节点名,指定元素) //将一个节点添加到父节点指定的子节点前面,类似于css里的before伪元素
删除节点
node.removeChild(child)
说明:node.removeChild() 方法从 node节点中删除一个子节点,返回删除的节点。
复制(克隆)节点
node.cloneNode() ; // 括号为空或者里面是false 浅拷贝 只复制标签不复制里面的内容
node.cloneNode(true); //括号为true 深拷贝 复制标签复制里面的内容
document.write创建元素
语法:
区别:
方法事件监听addEventListener()
同一个元素同一个事件可以注册多个监听器(事件处理程序)
// 参数1:事件类型,它是字符串 必定加引号 而且不带on
// 参数2:事件处理程序
btns[1].addEventListener('click', function() {
alert(22);
})
btns[1].addEventListener('click', function() {
alert(33);
})
attachEvent()事件监听
eventTarget.attachEvent(eventNameWithOn, callback)
比如: btns[2].attachEvent('onclick', function() {
alert(11);
}) // attachEvent ie9以前的版本支持 这里的事件需要带on
删除事件(解绑事件)
1. eventTarget.removeEventListener(type, listener[, useCapture]);
//针对addEventListener()
2. eventTarget.detachEvent(eventNameWithOn, callback);
//针对attachEvent()
DOM 事件流
事件发生时会在元素节点之间按照特定的顺序传播,这个传播过程即 DOM 事件流。
注意:
事件对象
eventTarget.onclick = function(event) {
// 这个 event 就是事件对象,我们还喜欢的写成 e 或者 evt
}
eventTarget.addEventListener('click', function(event) {
// 这个 event 就是事件对象,我们还喜欢的写成 e 或者 evt
})
事件对象的属性和方法
事件对象属性方法 | 说明 |
---|---|
e.target | 返回触发事件的对象 标准 |
e.srcElement | 返回触发事件的对象 非标准 ie6-8使用 |
e.type | 返回事件的类型 比如click mouseover 不带on |
e.cancelBubble=true | 该属性阻止冒泡排序 非标准 ie6-8使用 |
e.returnValue=false | 阻止默认事件(默认行为) 非标准 ie6-8使用 比如不让链接跳转 |
e.preventDefault() | 阻止默认事件(默认行为) 标准 比如不让链接跳转 |
e.stopPropagation() | 阻止冒泡排序 |
e.target 和 this 的区别
阻止默认行为
<a href="http://www.baidu.com">百度</a>
<script>
// 2. 阻止默认行为 让链接不跳转
var a = document.querySelector('a');
a.addEventListener('click', function(e) {
e.preventDefault(); // dom 标准写法
});
// 3. 传统的注册方式
a.onclick = function(e) {
// 普通浏览器 e.preventDefault(); 方法
e.preventDefault();
// 低版本浏览器 ie678 returnValue 属性
e.returnValue = false;
// 我们可以利用return false 也能阻止默认行为 没有兼容性问题
return false;
}
</script>
阻止事件冒泡
var son = document.querySelector('.son');
// 给son注册单击事件
son.addEventListener('click', function(e) {
alert('son');
e.stopPropagation();
window.event.cancelBubble = true;
}, false);
if(e && e.stopPropagation){
e.stopPropagation();
}else{
window.event.cancelBubble = true;
}
事件委托
事件监听器设置在其父节点上,然后利用冒泡原理影响设置每个子节点。
禁止鼠标右键菜单
contextmenu事件:鼠标右键菜单事件。主要控制应该何时显示上下文菜单(右键菜单),主要用于程序员取消默认的上下文菜单
document.addEventListener('contextmenu', function(e) {
e.preventDefault();
})
禁止鼠标选中
selectstart 事件:鼠标选中事件,用于界面文字防止选中
document.addEventListener('selectstart', function(e) {
e.preventDefault();
})
鼠标事件对象
鼠标事件对象 | 说明 |
---|---|
e.clientX | 返回鼠标相对于浏览器窗口可视区的X坐标 |
e.clientY | 返回鼠标相对于浏览器窗口可视区的Y坐标 |
e.pageX | 返回鼠标相对于整个文档页面的X坐标 IE9+支持 |
e.pageY | 返回鼠标相对于整个文档页面的Y坐标 IE9+支持 |
e.screenX | 返回鼠标相对于电脑屏幕的X坐标 |
e.screenY | 返回鼠标相对于电脑屏幕的Y坐标 |
常用键盘事件
键盘事件 | 触发条件 |
---|---|
onkeyup | 某个键盘按键被松开时触发 |
onkeydown | 被按下时触发 |
onkeypress | 被按下时触发 但不识别功能键 比如ctrl shift 箭头等 |
onkeyCode | 返回该键的ASCII值 |
如果使用addEventListener 不需要加 on
三个事件的执行顺序是: keydown – keypress — keyup (按下–按住–抬起)
keyCode判断用户按下哪个键
<script>
// 键盘事件对象中的keyCode属性可以得到相应键的ASCII码值
document.addEventListener('keyup', function(e) {
console.log(e.keyCode);
// 我们可以利用keycode返回的ASCII码值来判断用户按下了那个键
if (e.keyCode === 65) {
alert('您按下的a键');
} else {
alert('您没有按下a键')
}
})
document.addEventListener('keypress', function(e) {
// console.log(e);
console.log(e.keyCode);
})
</script>
BOM(Browser Object Model)即浏览器对象模型,它提供了独立于内容而与浏览器窗口进行交互的对象,其核心对象是 window。
页面(窗口)加载事件
第一种——语法:
window.onload = function(){}
或者
window.addEventListener("load",function(){});
第二种——语法:
document.addEventListener('DOMContentLoaded',function(){})
DOMContentLoaded 事件触发时,仅当DOM加载完成,不包括样式表,图片,flash等等。
调整窗口大小事件
语法:
window.onresize = function(){}
window.addEventListener("resize",function(){});
window.onresize 是调整窗口大小加载事件, 当触发时就调用的处理函数。
window.innerWidth 当前屏幕的宽度
定时器
setTimeout()
window.setTimeout(回调函数, [延迟的毫秒数]);
清除定时器:
window.clearTimeout(定时器名字)
setInterval() 闹钟定时器
window.setInterval(回调函数, [间隔的毫秒数]);
和setTimeout用法类似
清除定时器:
window.clearInterval(intervalID);
this指向问题
location对象
获取或设置窗体的 URL,并且可以用于解析 URL
URL 的一般语法格式为:
protocol://host[:port]/path/[?query]#fragment
http://www.itcast.cn/index.html?name=andy&age=18#link
location 对象的属性
location 对象属性 | 返回值 |
---|---|
location.href | 获取或设置整个URL |
location.host | 返回主机(域名) |
location.port | 返回端口号 |
location.pathname | 返回路径 |
location.search | 返回参数 |
location.hash | 返回片段 #后面内容 常见于链接 锚点 |
location对象的常见方法
location对象方法 | 返回值 |
---|---|
location.assign() | 和href一样,可以跳转页面 |
location.replace() | 替换当前页面,因为不记录历史,所以不能后退 |
location.reload() | 重新加载页面,相当于刷新按钮或者F5 如果参数为true 强制刷新 |
navigator对象
navigator 对象包含有关浏览器的信息,它有很多属性,我们最常用的是 userAgent,该属性可以返回由客户机发送服务器的 user-agent 头部的值
下面前端代码可以判断用户那个终端打开页面,实现跳转
if((navigator.userAgent.match(/(phone|pad|pod|iPhone|iPod|ios|iPad|Android|Mobile|BlackBerry|IEMobile|MQQBrowser|JUC|Fennec|wOSBrowser|BrowserNG|WebOS|Symbian|Windows Phone)/i))) {
window.location.href = ""; //手机
} else {
window.location.href = ""; //电脑
}
history对象
与浏览器历史记录进行交互。该对象包含用户(在浏览器窗口中)访问过的URL
history对象方法 | 作用 |
---|---|
back() | 后退功能 |
forward() | 前进功能 |
go(参数) | 前进后退功能 参数是1则前进1个页面 参数是-1 后退1个页面 |
JS执行机制
同步:先做一件事情,然后再做另一件事情。他是单线程,一个人依次做多件事情
异步:是两件事情同时去做,他是多线程,多个人同时做多个事情
元素偏移量 offset
offset属性 | 作用 |
---|---|
element.offsetParent | 返回该元素带有定位的父元素 如果父级都没有定位则返回body |
element.offsetTop | 返回该元素相对带有定位父元素上方的偏移量 |
element.offsetLeft | 返回该元素相对带有定位父元素左边的偏移量 |
element.offsetWidth | 返回自身padding、边框、内容区的宽度 |
element.offsetHeight | 返回自身padding、边框、内容区的高度 |
注意:返回的数值都不带单位
offset 与 style 区别
offset:想要获取元素大小位置,用offset更合适
style:想要给元素更改值,则需要用style改变
获取鼠标在盒子内的坐标
var box = document.querySelector('.box');
box.addEventListener('mousemove', function(e) {
var x = e.pageX - this.offsetLeft;
var y = e.pageY - this.offsetTop;
this.innerHTML = 'x坐标是' + x + ' y坐标是' + y;
})
client
通过 client系列的相关属性可以动态的得到该元素的边框大小、元素大小等
client系列属性 | 作用 |
---|---|
element.clientTop | 返回元素上边框的大小 |
element.clientLeft | 返回元素左边框的大小 |
element.clientWidth | 返回自身包括padding、内容区的宽度,不含边框,返回数值不带单位 |
element.clientHeight | 返回自身包括padding、内容区的高度,不含边框,返回数值不带单位 |
立即执行函数
创建一个独立的作用域,避免了命名冲突问题
pageshow
元素滚动 scroll
scroll系列属性 | 作用 |
---|---|
element.scrollTop | 返回被卷去的上侧距离 |
element.scrollLeft | 返回被卷去的左侧距离 |
element.scrollWidth | 返回自身实际的宽度,不含边框 |
element.scrollHeight | 返回自身实际的高度,不含边框 |
返回数值均不带单位
页面被卷去的头部
可以通过window.pageYOffset 获得 如果是被卷去的左侧window.pageXOffset
注意,元素被卷去的头部是element.scrollTop , 如果是页面被卷去的头部 则是 window.pageYOffset
页面被卷去的头部兼容性解决方案
需要注意的是,获取页面被卷去的头部高度,有兼容性问题,因此通常有如下几种写法:
function getScroll() {
return {
left: window.pageXOffset || document.documentElement.scrollLeft || document.body.scrollLeft||0,
top: window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop || 0
};
}
//使用的时候 getScroll().left
mouseenter 和mouseover的区别
mouseover 鼠标经过自身盒子会触发,经过子盒子还会触发。mouseenter 只会经过自身盒子触发,因为mouseenter不会冒泡。
跟mouseenter搭配鼠标离开 mouseleave 同样不会冒泡
简单动画函数封装
function animate(obj目标对象, target目标位置){…}
给不同元素记录不同定时器
核心原理:利用 JS 是一门动态语言,可以很方便的给当前对象添加属性。
function animate(obj, target) {
// 当我们不断的点击按钮,这个元素的速度会越来越快,因为开启了太多的定时器
// 解决方案就是 让我们元素只有一个定时器执行
// 先清除以前的定时器,只保留当前的一个定时器执行
clearInterval(obj.timer);
obj.timer = setInterval(function() {
if (obj.offsetLeft >= target) {
// 停止动画 本质是停止定时器
clearInterval(obj.timer);
}
obj.style.left = obj.offsetLeft + 1 + 'px';
}, 30);
}
动画函数多个目标值之间移动
<script>
// 缓动动画函数封装obj目标对象 target 目标位置
// 思路:
// 1. 让盒子每次移动的距离慢慢变小, 速度就会慢慢落下来。
// 2. 核心算法:(目标值 - 现在的位置) / 10 做为每次移动的距离 步长
// 3. 停止的条件是: 让当前盒子位置等于目标位置就停止定时器
function animate(obj, target) {
// 先清除以前的定时器,只保留当前的一个定时器执行
clearInterval(obj.timer);
obj.timer = setInterval(function () {
// 步长值写到定时器的里面
// 把我们步长值改为整数 不要出现小数的问题
// var step = Math.ceil((target - obj.offsetLeft) / 10);
var step = (target - obj.offsetLeft) / 10;
step = step > 0 ? Math.ceil(step) : Math.floor(step);
if (obj.offsetLeft == target) {
// 停止动画 本质是停止定时器
clearInterval(obj.timer);
}
// 把每次加1 这个步长值改为一个慢慢变小的值 步长公式:(目标值 - 现在的位置) / 10
obj.style.left = obj.offsetLeft + step + 'px';
}, 15);
}
var span = document.querySelector('span');
var btn500 = document.querySelector('.btn500');
var btn800 = document.querySelector('.btn800');
btn500.addEventListener('click', function () {
// 调用函数
animate(span, 500);
})
btn800.addEventListener('click', function () {
// 调用函数
animate(span, 800);
})
// 匀速动画 就是 盒子是当前的位置 + 固定的值 10
// 缓动动画就是 盒子当前的位置 + 变化的值(目标值 - 现在的位置) / 10)
</script>
动画完整版代码
<script>
// 缓动动画函数封装obj目标对象 target 目标位置
// 思路:
// 1. 让盒子每次移动的距离慢慢变小, 速度就会慢慢落下来。
// 2. 核心算法:(目标值 - 现在的位置) / 10 做为每次移动的距离 步长
// 3. 停止的条件是: 让当前盒子位置等于目标位置就停止定时器
function animate(obj, target, callback) {
// console.log(callback); callback = function() {} 调用的时候 callback()
// 先清除以前的定时器,只保留当前的一个定时器执行
clearInterval(obj.timer);
obj.timer = setInterval(function () {
// 步长值写到定时器的里面
// 把我们步长值改为整数 不要出现小数的问题
// var step = Math.ceil((target - obj.offsetLeft) / 10);
var step = (target - obj.offsetLeft) / 10;
step = step > 0 ? Math.ceil(step) : Math.floor(step);
if (obj.offsetLeft == target) {
// 停止动画 本质是停止定时器
clearInterval(obj.timer);
// 回调函数写到定时器结束里面
if (callback) {
// 调用函数
callback();
}
}
// 把每次加1 这个步长值改为一个慢慢变小的值 步长公式:(目标值 - 现在的位置) / 10
obj.style.left = obj.offsetLeft + step + 'px';
}, 15);
}
var span = document.querySelector('span');
var btn500 = document.querySelector('.btn500');
var btn800 = document.querySelector('.btn800');
btn500.addEventListener('click', function () {
// 调用函数
animate(span, 500);
})
btn800.addEventListener('click', function () {
// 调用函数
animate(span, 800, function () {
// alert('你好吗');
span.style.backgroundColor = 'red';
});
})
// 匀速动画 就是 盒子是当前的位置 + 固定的值 10
// 缓动动画就是 盒子当前的位置 + 变化的值(目标值 - 现在的位置) / 10)
</script>
节流阀
当上一个函数动画内容执行完毕,再去执行下一个函数动画,让事件无法连续触发,利用回调函数,添加一个变量来控制,锁住函数和解锁函数
返回顶部
常见的触屏事件
触屏touch事件 | 说明 |
---|---|
touchstart | 手指触摸到一个DOM元素时触发 |
touchmove | 手指在一个DOM元素上滑动时触发 |
touchend | 手指从一个DOM元素上移开时触发 |
触摸事件对象(TouchEvent)
TouchEvent 是一类描述手指在触摸平面(触摸屏、触摸板等)的状态变化的事件。这类事件用于描述一个或多个触点,使开发者可以检测触点的移动,触点的增加和减少,等等
触摸列表 | 说明 |
---|---|
touches | 正在触摸屏幕的所有手指的一个列表 |
targetTouches | 正在触摸当前DOM元素上的手指的一个列表 |
changedTouches | 手指状态发生了改变的列表,从无到有,从有到无的变化 |
因为平时我们都是给元素注册触摸事件,所以重点记住 targetTocuhes
移动端拖动元素
<script>
// (1) 触摸元素 touchstart: 获取手指初始坐标,同时获得盒子原来的位置
// (2) 移动手指 touchmove: 计算手指的滑动距离,并且移动盒子
// (3) 离开手指 touchend:
var div = document.querySelector('div');
var startX = 0; //获取手指初始坐标
var startY = 0;
var x = 0; //获得盒子原来的位置
var y = 0;
div.addEventListener('touchstart', function(e) {
// 获取手指初始坐标
startX = e.targetTouches[0].pageX;
startY = e.targetTouches[0].pageY;
x = this.offsetLeft;
y = this.offsetTop;
});
div.addEventListener('touchmove', function(e) {
// 计算手指的移动距离: 手指移动之后的坐标减去手指初始的坐标
var moveX = e.targetTouches[0].pageX - startX;
var moveY = e.targetTouches[0].pageY - startY;
// 移动我们的盒子 盒子原来的位置 + 手指移动的距离
this.style.left = x + moveX + 'px';
this.style.top = y + moveY + 'px';
e.preventDefault(); // 阻止屏幕滚动的默认行为
//如果不阻止,当粉色盒子滚出界面之后会出现滚动条
});
</script>
注意: 手指移动也会触发滚动屏幕所以这里要阻止默认的屏幕滚动 e.preventDefault();
transitionend
监听过渡完成的事件对象
语法: element.addEventListener(‘transitionend’,函数);
classList 属性
返回元素的类名。但是ie10以上版本支持
添加类:
element.classList.add(’类名’);
focus.classList.add('current');
移除类:
element.classList.remove(’类名’);
focus.classList.remove('current');
例:ol.querySelector('.sty').classList.remove('sty');
切换类:
element.classList.toggle(’类名’); 有这个类名则移除,没有则添加
focus.classList.toggle('current');
注意:以上方法里面,所有类名都不带点
click 延时解决方案
移动端 click 事件会有 300ms 的延时,原因是移动端屏幕双击会缩放(double tap to zoom) 页面。
解决方案:
1. 禁用缩放: 浏览器禁用默认的双击缩放行为并且去掉300ms 的点击延迟。
<meta name="viewport" content="user-scalable=no">
2.利用touch事件自己封装这个事件解决300ms 延迟。
原理就是:
当我们手指触摸屏幕,记录当前触摸时间
当我们手指离开屏幕, 用离开的时间减去触摸的时间
如果时间小于150ms,并且没有滑动过屏幕, 那么我们就定义为点击
代码如下:
//封装tap,解决click 300ms 延时
function tap (obj, callback) {
var isMove = false;
var startTime = 0; // 记录触摸时候的时间变量
obj.addEventListener('touchstart', function (e) {
startTime = Date.now(); // 记录触摸时间
});
obj.addEventListener('touchmove', function (e) {
isMove = true; // 看看是否有滑动,有滑动算拖拽,不算点击
});
obj.addEventListener('touchend', function (e) {
if (!isMove && (Date.now() - startTime) < 150) { // 如果手指触摸和离开时间小于150ms 算点击
callback && callback(); // 执行回调函数
}
isMove = false; // 取反 重置
startTime = 0;
});
}
//调用
tap(div, function(){ // 执行代码 });
3.使用插件:fastclick 插件解决300ms 延迟
Swiper 插件
中文官网地址: https://www.swiper.com.cn/
其他移动端常见插件
lsuperslide: http://www.superslide2.com/
l iscroll: https://github.com/cubiq/iscroll
1.打开demo实例文件,查看需要引入的相关文件,并且引入
2.复制demo实例文件中的结构html,样式css以及js代码
移动端视频插件
zy.media.js
Bootstrap
Bootstrap JS插件使用步骤:
1.引入相关js 文件
2.复制HTML 结构
3.修改对应样式
4.修改相应JS 参数
本地存储
1、容量较大,sessionStorage约5M、localStorage约20M
2、只能存储字符串,可以将对象JSON.stringify() 编码后存储
window.sessionStorage (session:会话)
1、生命周期为关闭浏览器窗口
2、在同一个窗口(页面)下数据可以共享
3、以键值对的形式存储使用
存储数据:
sessionStorage.setItem('key', 存的内容)
获取数据:
sessionStorage.getItem('key')
删除数据:
sessionStorage.removeItem('key')
清空数据:(所有都清除掉)
sessionStorage.clear()
window.localStorage
1、声明周期永久生效,除非手动删除 否则关闭页面也会存在
2、可以多窗口(页面)共享(同一浏览器可以共享)
3、以键值对的形式存储使用
存储数据:
localStorage.setItem('key', value)
获取数据:
localStorage.getItem('key')
删除数据:
localStorage.removeItem('key')
清空数据:(所有都清除掉)
localStorage.clear()
change事件
当选框发生改变的时候可以使用change事件
jQuery 对象本质是: 利用$对DOM 对象包装后产生的对象(伪数组形式存储)
注意:
只有 jQuery 对象才能使用 jQuery 方法,DOM 对象则使用原生的 JavaScirpt 方法。
jQuery 的下载**
jQuery的官网地址: https://jquery.com/,官网即可下载最新版本。
各个版本的下载:https://code.jquery.com/
jQuery的入口函数
jQuery中常见的两种入口函数:
// 第一种: 简单易用。
$(function () {
... // 此处是页面 DOM 加载完成的入口
}) ;
// 第二种: 繁琐,但是也可以实现
$(document).ready(function(){
... // 此处是页面DOM加载完成的入口
});
相当于原生 js 中的 DOMContentLoaded
jQuery 对象和 DOM 对象转换
// 1.DOM对象转换成jQuery对象,方法只有一种
var box = document.getElementById('box'); // 获取DOM对象
var jQueryObject = $(box); // 把DOM对象转换为 jQuery 对象
// 2.jQuery 对象转换为 DOM 对象有两种方法:
// 2.1 jQuery对象[索引值]
var domObject1 = $('div')[0]
// 2.2 jQuery对象.get(索引值)
var domObject2 = $('div').get(0)
总结:实际开发比较常用的是把DOM对象转换为jQuery对象
jQuery 选择器
$("选择器") // 里面选择器直接写 CSS 选择器即可,但是要加引号 和CSS选择器写法一致
筛选选择器
语法 | 用法 | 描述 |
---|---|---|
:first | $(‘li:first’) | 获取第一个li元素 |
:last | $(‘li:last’) | 获取最后一个li元素 |
:eq(index) | $(‘li:eq(2)’) | 获取li元素中索引号为2的元素,index从0开始 |
:odd | $(‘li:odd’) | 获取li元素中索引号为奇数的元素 |
:even | $(‘li:even’) | 获取li元素中索引号为偶数的元素 |
筛选方法
语法 | 用法 | 说明 |
---|---|---|
parent() | $(‘li’).parent(); | 查找父级 |
children(‘选择器’) | $(“ul”).children(“li”); | 查找最近一级的亲儿子 相当于$(“ul>li”) |
find(‘选择器’) | $(“ul”).find(“li”); | 相当于$(“ul li”) 和后代选择器一样 |
siblings(‘选择器’) | $(".first").siblings(“li”); | 查找兄弟节点,不包括自身 |
nextAll([expr]) | $(".first").nextAll(); | 查找当前元素之后所有的兄弟元素 |
prevAll([expr]) | $(".first").prevAll(); | 查找当前元素之前所有的兄弟元素 |
hasClass(class) | $(“div”).hasClass("protected"0; | 检查当前的元素是否含有某个特定的类,如果有 返回true |
eq(index) | $(“li”).eq(2); | 相当于$(‘li:eq(2)’),index是从0开始的 |
jQuery样式操作
排他思想
// 想要多选一的效果,排他思想:当前元素设置样式,其余的兄弟元素清除样式。
$(this).css(“color”,”red”);
$(this).siblings().css(“color”,””);
隐式迭代
// 遍历内部 DOM 元素(伪数组形式存储)的过程就叫做隐式迭代。
// 简单理解:给匹配到的所有元素进行循环遍历,执行相应的方法,而不用我们再进行循环,简化我们的操作,方便我们调用。
$('div').hide(); // 页面中所有的div全部隐藏,不用循环操作
// 以前的js是不允许对于一组对象之间操作的,只能对一个元素对象进行操作
var divs = document.getElementsByTagName('div');
divs.style.backgroundColor = 'red'; // 错误
divs[0].style.backgroundColor = 'red'; // 正确
链式编程
// 链式编程是为了节省代码量,看起来更优雅。
//原代码
$(this).css('color', 'red');
$(this).sibling().css('color', '');
//链式编程的代码
$(this).css('color', 'red').sibling().css('color', '');
//jq的操作方法: css(),hide(),show()等等,会将调用者返回
//jq的筛选方法,会将筛选完的对象返回。 非筛选方法(操作方法),会将调用者(jq对象)返回
jQuery 得到当前元素索引号
$(this).index();
jQuery弹窗(类似alert)
var isC = confirm('您确定要退出吗')
//点击后返回布尔值
jQuery操作 css 方法
// 1.参数只写属性名,则是返回属性值
var strColor = $(this).css('color');
// 2. 参数是属性名,属性值,逗号分隔,是设置一组样式,属性必须加引号,值如果是数字可以不用跟单位和引号
$(this).css('color'', 'red');
// 3. 参数可以是对象形式,方便设置多组样式。属性名和属性值用冒号隔开, 属性可以不用加引号
$(this).css({ "color":"white","font-size":"20px"});
jQuery设置类样式
// 1.添加类
$("div").addClass("current"); // className,classList
// 2.删除类
$("div").removeClass("current");
// 3.切换类 没有就添上 有就移除
$("div").toggleClass("current");
原生 JS 中 className 会覆盖元素原先里面的类名,jQuery 里面类操作只是对指定类进行操作,不影响原先的类名
jQuery 效果
显示、隐藏、二者切换
显示
语法: show( [ speed ,[easing],[fn] ] ) 参数都可以省略
1.speed: 按照某种速度显示,默认normal,还有slow、fast,要带引号,也可直接设置毫秒数(不带单位)
2.easing: 用来指定切换效果,默认swing,还有linear,要带引号
3.fn: 回调函数,在动画完成时执行的函数,每个元素执行一次
隐藏
语法: hide( [ speed ,[easing],[fn] ] ) 参数都可以省略
1.speed: 按照某种速度显示,默认normal,还有slow、fast,要带引号,也可直接设置毫秒数(不带单位)
2.easing: 用来指定切换效果,默认swing,还有linear,要带引号
3.fn: 回调函数,在动画完成时执行的函数,每个元素执行一次
切换
语法: toggle( [ speed ,[easing],[fn] ] ) 参数都可以省略
1.speed: 按照某种速度显示,默认normal,还有slow、fast,要带引号,也可直接设置毫秒数(不带单位)
2.easing: 用来指定切换效果,默认swing,还有linear,要带引号
3.fn: 回调函数,在动画完成时执行的函数,每个元素执行一次
滑动
下拉滑动
语法: slideDown( [ speed ,[easing],[fn] ] ) 参数都可以省略
1.speed: 按照某种速度显示,默认normal,还有slow、fast,要带引号,也可直接设置毫秒数(不带单位)
2.easing: 用来指定切换效果,默认swing,还有linear,要带引号
3.fn: 回调函数,在动画完成时执行的函数,每个元素执行一次
上拉滑动
语法: slideUp( [ speed ,[easing],[fn] ] ) 参数都可以省略
1.speed: 按照某种速度显示,默认normal,还有slow、fast,要带引号,也可直接设置毫秒数(不带单位)
2.easing: 用来指定切换效果,默认swing,还有linear,要带引号
3.fn: 回调函数,在动画完成时执行的函数,每个元素执行一次
滑动切换
语法: slideToggle( [ speed ,[easing],[fn] ] ) 参数都可以省略
1.speed: 按照某种速度显示,默认normal,还有slow、fast,要带引号,也可直接设置毫秒数(不带单位)
2.easing: 用来指定切换效果,默认swing,还有linear,要带引号
3.fn: 回调函数,在动画完成时执行的函数,每个元素执行一次
淡入淡出 (透明度动画)
淡入
语法: fadeIn( [ speed ,[easing],[fn] ] ) 参数都可以省略
1.speed: 按照某种速度显示,默认normal,还有slow、fast,要带引号,也可直接设置毫秒数(不带单位)
2.easing: 用来指定切换效果,默认swing,还有linear,要带引号
3.fn: 回调函数,在动画完成时执行的函数,每个元素执行一次
淡出
语法: fadeOut( [ speed ,[easing],[fn] ] ) 参数都可以省略
1.speed: 按照某种速度显示,默认normal,还有slow、fast,要带引号,也可直接设置毫秒数(不带单位)
2.easing: 用来指定切换效果,默认swing,还有linear,要带引号
3.fn: 回调函数,在动画完成时执行的函数,每个元素执行一次
淡入淡出切换
语法: fadeToggle( [ speed ,[easing],[fn] ] ) 参数都可以省略
1.speed: 按照某种速度显示,默认normal,还有slow、fast,要带引号,也可直接设置毫秒数(不带单位)
2.easing: 用来指定切换效果,默认swing,还有linear,要带引号
3.fn: 回调函数,在动画完成时执行的函数,每个元素执行一次
修改透明度
语法: fadeTo( [ speed , opacity ,[easing],[fn] ] ) 参数都可以省略
<body>
<button>淡入效果</button>
<button>淡出效果</button>
<button>淡入淡出切换</button>
<button>修改透明度</button>
<div></div>
<script>
$(function() {
$("button").eq(0).click(function() {
// 淡入 fadeIn()
$("div").fadeIn(1000);
})
$("button").eq(1).click(function() {
// 淡出 fadeOut()
$("div").fadeOut(1000);
})
$("button").eq(2).click(function() {
// 淡入淡出切换 fadeToggle()
$("div").fadeToggle(1000);
});
$("button").eq(3).click(function() {
// 修改透明度 fadeTo() 这个速度和透明度要必须写
$("div").fadeTo(1000, 0.5);
});
});
</script>
</body>
自定义动画
语法:animate( params, [speed ] , [easing] , [fn] )
1.params:想要改变的样式属性,以对象形式传递,必须写
2.speed: 按照某种速度显示,默认normal,还有slow、fast,要带引号,也可直接设置毫秒数(不带单位)
3.easing: 用来指定切换效果,默认swing,还有linear,要带引号
4.fn: 回调函数,在动画完成时执行的函数,每个元素执行一次
<body>
<button>动起来</button>
<div></div>
<script>
$(function() {
$("button").click(function() {
$("div").animate({
left: 500,
top: 300,
opacity: .4,
width: 500
}, 500);
})
})
</script>
</body>
停止动画排队
动画或者效果一旦触发就会执行,如果多次触发,就造成多个动画或者效果排队执行
停止动画排队的方法为:stop() ;
总结: 每次使用动画之前,先调用 stop() ,在调用动画。
事件切换
hover([over,]out) // 其中over和out为两个函数
jQuery 属性操作
获取和设置元素固有属性值 prop()
1.获取元素固有属性: element.prop(‘属性名’);
2.设置元素固有属性: element.prop(‘属性名’,‘属性值’);
注意:prop() 除了普通属性操作,更适合操作表单属性:disabled / checked / selected 等。
获取和设置元素自定义属性值 attr()
1.获取元素自定义属性: element.attr(‘属性名’);
2.设置元素自定义属性: element.attr(‘属性名’,‘属性值’);
数据缓存 data()
1.获取数据缓存: element.date(‘数据名’);
2.设置数据缓存: element.date(‘数据名’,‘数据值’);
选择器 :checked
例:console.log($(".j-checkbox:checked").length);
jQuery 文本属性值
常见操作有三种:html() / text() / val() ; 分别对应JS中的 innerHTML 、innerText 和 value 属性
普通元素内容html()
1.html() //获取元素内容
2.html(‘内容’) //设置元素内容
普通元素文本内容text()
1.text() //获取元素的文本内容
2.text(‘内容’) //设置元素的文本内容
表单的值val()
1.val() //获取表单的值
2.val(‘内容’) //设置表单的值
注意:html() 可识别标签,text() 不识别标签
选择器parents
parents(‘选择器’) 可以返回指定祖先元素
保留几位小数
num.toFixed(位数)
jQuery 元素操作
遍历元素
注意:此方法用于遍历 jQuery 对象中的每一项,回调函数中元素为 DOM 对象,想要使用 jQuery 方法需要转换。
演示代码
<body>
<div>1</div>
<div>2</div>
<div>3</div>
<script>
$(function() {
// 如果针对于同一类元素做不同操作,需要用到遍历元素(类似for,但是比for强大)
var sum = 0;
var arr = ["red", "green", "blue"];
// 1. each() 方法遍历元素
$("div").each(function(i, domEle) {
// 回调函数第一个参数一定是索引号 可以自己指定索引号号名称
// console.log(i);
// 回调函数第二个参数一定是 dom 元素对象,也是自己命名
// console.log(domEle); // 使用jQuery方法需要转换 $(domEle)
$(domEle).css("color", arr[i]);
sum += parseInt($(domEle).text());
})
console.log(sum);
// 2. $.each() 方法遍历元素 主要用于遍历数据,处理数据
// $.each($("div"), function(i, ele) {
// console.log(i);
// console.log(ele);
// });
// $.each(arr, function(i, ele) {
// console.log(i);
// console.log(ele);
// })
$.each({
name: "andy",
age: 18
}, function(i, ele) {
console.log(i); // 输出的是 name age 属性名
console.log(ele); // 输出的是 andy 18 属性值
})
})
</script>
</body>
创建、添加、删除
1.创建
$(’
')2.内部添加
element.append(’ 内容 ') 把内容放入匹配元素内部最后面,类似于appendChild
element.prepend(’ 内容 ') 把内容放入匹配元素内部最前面,类似于
3.外部添加
element.after(’ 内容 ') //把内容放入目标元素后面
element.before(’ 内容 ') //把内容放入目标元素前面
4.删除
element.remove() //删除匹配的元素(自身)
element.empty() //删除匹配的元素集合中所有的子节点
element.html(’’) //清空匹配的元素内容
jQuery 尺寸、位置操作
尺寸操作
语法 | 用法 |
---|---|
width()/height() | 取得匹配元素宽度或高度,只算width/height |
innerWidth()/innerHeight() | 取得匹配元素宽度或高度,包含padding |
outWidth()/outHeight() | 取得匹配元素宽度或高度,包含paddin、border |
outWidth(true)/outHeight(true) | 取得匹配元素宽度或高度,包含paddin、border、margin |
如果参数为数字,则是修改相应值
jQuery 位置操作
jQuery的位置操作主要有三个: offset()、position()、scrollTop()/scrollLeft()
1.offset()设置或获取元素偏移
和父亲没有关系,是相对于文档的偏移坐标
该方法有2个属性left、top。offset().top/left 用于获取距离文档顶部/左侧的距离
可以设置元素的偏移: offset( { top:10,left:10 } )
2.position()获取元素偏移
和父亲有关系,是相对于父亲的偏移坐标,如果父亲都没有定位,则以文档为准
该方法有2个属性left、top。offset().top/left 用于获取距离文档顶部/左侧的距离
该方法只能获取数据,不可以进行设置
3.scrollTop()/scrollLeft()设置或获取元素被卷去的头部或左侧
不加参数是获取,加参数则是设置被卷去的头部,参数不带单位
代码演示
<body>
<div class="father">
<div class="son"></div>
</div>
<div class="back">返回顶部</div>
<div class="container"></div>
<script>
$(function() {
// 1. 获取设置距离文档的位置(偏移) offset
console.log($(".son").offset());
console.log($(".son").offset().top);
// $(".son").offset({
// top: 200,
// left: 200
// });
// 2. 获取距离带有定位父级位置(偏移) position 如果没有带有定位的父级,则以文档为准
// 这个方法只能获取不能设置偏移
console.log($(".son").position());
// $(".son").position({
// top: 200,
// left: 200
// });
// 3. 被卷去的头部
$(document).scrollTop(100);
// 被卷去的头部 scrollTop() / 被卷去的左侧 scrollLeft()
// 页面滚动事件
var boxTop = $(".container").offset().top;
$(window).scroll(function() {
// console.log(11);
console.log($(document).scrollTop());
if ($(document).scrollTop() >= boxTop) {
$(".back").fadeIn();
} else {
$(".back").fadeOut();
}
});
// 返回顶部
$(".back").click(function() {
// $(document).scrollTop(0);
$("body, html").stop().animate({
scrollTop: 0
});
// $(document).stop().animate({
// scrollTop: 0
// }); 不能是文档而是 html和body元素做动画
})
})
</script>
</body>
页面滚动事件
$(window).scroll( function () {…} )
jQuery 事件处理
on() 绑定事件
语法: element.on( ‘事件类型’, ’ 元素的子元素选择器 ’ , fn(){…} );
1.可绑定多个事件
例:
$(' 选择器').on( {
click : function () {},
mouseover: function () {},
....... });
2.可以进行事件委派操作,把需要加给子元素身上的事件绑定在父元素身上
$(' ul').on( 'click','li',function () { ...... } );
3.动态创建的元素,用click()这种没法绑定事件,on()可以给动态生成的元素绑定事件,通过事件委托绑定的事件,可以对未来元素生效
off() 解绑事件
off()方法可以移除通过on()方法添加的事件
1.$(’ p ').off() //解绑p元素所有事件
2.$(’ p ‘).off(’ click ') //解绑p元素上面的点击事件
3.$(’ ul ‘).off(’ click ‘,’ li’) //解绑事件委托
只触发一次的事件
element.one();
trigger() 自动触发事件
1.element.click()
2.element.trigger(‘事件类型’)
3.element.triggerHandler(‘事件类型’) //这一种不会触发元素的默认行为 而上面的会
jQuery 事件对象
element.on( ‘事件类型’, ’ 元素的子元素选择器 ’ , fn( e ){…} );
阻止默认行为:e.preventDefault()或者return false
阻止冒泡:e.stopPropagation()
jQuery 插件
jQuery 插件常用的网站:
插件的使用三点: 1. 引入css. 2.引入JS 3.引入html。 (有的简单插件只需引入html和js,甚至有的只需引入js)
对象
对象是由属性和方法组成的:是一个无序键值对的集合,指的是一个具体的事物
属性:事物的特征,在对象中用属性来表示(常用名词)
方法:事物的行为,在对象中用方法来表示(常用动词)
类
类抽象了对象的公共部分,它泛指某一大类(class)对象特指某一个, 通过类实例化一个具体的对象
创建类
语法:
class name{
constructor( ){ ..... }
.....
}
var 变量名 = new name();
constructor构造函数
可以接受传递过来的参数,同时返回实例对象 ,只要 new 生成实例时,就会自动调用这个函数, 如果我们不写这个 函数,类也会自动生成这个函数
类创建添加属性和方法
// 1. 创建类 class 创建一个 明星类
class Star {
// 类的共有属性放到 constructor 里面
constructor(uname, age) {
this.uname = uname;
this.age = age;
}
sing(song) {
// console.log('我唱歌');
console.log(this.uname + song);
}
}
// 2. 利用类创建对象 new
var ldh = new Star('刘德华', 18);
var zxy = new Star('张学友', 20);
console.log(ldh);
console.log(zxy);
// (1) 我们类里面所有的函数不需要写function
//(2) 多个函数方法之间不需要添加逗号分隔
ldh.sing('冰雨');
zxy.sing('李香兰')
类的继承
class son extends father { … }
// 1. 类的继承
// class Father {
// constructor() {
// }
// money() {
// console.log(100);
// }
// }
// class Son extends Father {
// }
// var son = new Son();
// son.money();
class Father {
constructor(x, y) {
this.x = x;
this.y = y;
}
sum() {
console.log(this.x + this.y);
}
}
class Son extends Father {
constructor(x, y) {
super(x, y); //调用了父类中的构造函数
}
}
var son = new Son(1, 2);
var son1 = new Son(11, 22);
son.sum();
son1.sum();
关键字super
用于访问和调用对象父类上的函数,必须在子类this之前调用
// super 关键字调用父类普通函数
class Father {
say() {
return '我是爸爸';
}
}
class Son extends Father {
say() {
// console.log('我是儿子');
console.log(super.say() + '的儿子');
// super.say() 就是调用父类中的普通函数 say()
}
}
var son = new Son();
son.say();
// 继承中的属性或者方法查找原则: 就近原则
// 1. 继承中,如果实例化子类输出一个方法,先看子类有没有这个方法,如果有就先执行子类的
// 2. 继承中,如果子类里面没有,就去查找父类有没有这个方法,如果有,就执行父类的这个方法(就近原则)
// 3.如果子类想要继承父类的方法,同时在自己内部扩展自己的方法,利用super 调用 父类的构造函数,super 必须在子类this之前调用
this的指向
insertAdjacentHTML( ‘position’ , text)
可以直接把字符串格式添加到父元素中,和element.append(‘内容’)和element.prepend(‘内容’)类似
position插入的位置:
1.beforebegin: 元素自身前面 2.afterend: 元素自身后面
3.afterbegin: 元素内部第一个子节点之前 4.beforeend: 元素内部最后一个子节点之后
text: 插入的内容
鼠标双击事件
element.ondblclick 但双击会默认选中文字 解决方法插入下面代码:
// 双击禁止选定文字
window.getSelection ? window.getSelection().removeAllRanges() : document.selection.empty();
双击文本框让文字内容处于选中状态
input.select();
构造函数和原型
静态成员和实例成员
实例成员 :构造函数内部通过this添加的成员
静态成员:在构造函数本身上添加的成员 比如:构造函数名.静态成员名 = ’ 内容 ';
,静态成员只能 通过构造函数来访问 比如:构造函数名.静态成员名
构造函数原型prototype
构造函数通过原型分配的函数是所有对象所共享的,每一个构造函数都有一个prototype 属性,指向另一个对象。这个 prototype就是一个对象,这个对象的所有属性和方法,都会被构造函数所拥有
可以把那些不变的方法,直接定义在 prototype 对象上,这样所有对象的实例就可 以共享这些方法
对象原型
对象都会有一个属性 _ _ proto _ _ 指向构造函数的 prototype 原型对象,之所以我们对象可以使用构造函数 prototype 原型对象的属性和方法,就是因为对象有 _ _ proto_ _ 原型的存在
_ _ proto_ _对象原型和原型对象 prototype 是等价的
_ _ proto_ _对象原型的意义就在于为对象的查找机制提供一个方向,或者说一条路线,但是 它是一个非标准属性,因此实际开发中,不可以使用这个属性,它只是内部指向原型对象 prototype
constructor构造函数
对象原型( _ _ proto_ _)和构造函数(prototype)原型对象里面都有一个属性 constructor 属性 ,constructor 我们称为构造函数,因为它指回构造函数本身。
constructor 主要用于记录该对象引用于哪个构造函数,它可以让原型对象重新指向原来 的构造函数。
一般情况下,对象的方法都在构造函数的原型对象中设置。如果有多个对象的方法,我们可 以给原型对象采取对象形式赋值,但是这样就会覆盖构造函数原型对象原来的内容,这样修 改后的原型对象 constructor 就不再指向当前构造函数了。此时,我们可以在修改后的 原型对象中,添加一个 constructor 指向原来的构造函数
原型链
①ldh 对象实例 ——(ldh._ _ proto_ _ )——>
②Str原型对象 prototype ——(prototype. _ _ proto_ _ )——>
③ object原型对象prototype ——(prototype. _ _ proto_ _ )——>
④null
构造函数实例和原型对象三角关系
①ldh 对象实例 ——(ldh._ _ proto_ _ )——>
②Str原型对象 prototype ——(star.prototype.constructor)——>
③构造函数 ——>①
③构造函数 ——( star.prototype )——> ② Str原型对象 prototype
原型对象中this指向
构造函数中的this和原型对象的this,都指向我们new出来的实例对象
继承
call()
语法:函数名.call( thisArg, arg1 , arg2…)
thisArg:当前调用函数this的指向对象
arg1 , arg2…:传递的其他参数
子构造函数继承父构造函数中的属性 和 借用原型对象继承方法
ES5新增方法
forEach遍历数组
arr.forEach(function(value, index, array) {
//参数一是:数组元素
//参数二是:数组元素的索引
//参数三是:当前的整个数组 })
//相当于数组遍历的 for循环 没有返回值
filter过滤数组
var arr = [1,2,3,4,5];
arr.filter(function(value, index, array) {
//参数一是:数组元素
//参数二是:数组元素的索引
//参数三是:当前的整个数组
return value <=2;
})
console.log(newArr);//[1,2] //返回值是一个新数组
some查找数组
some 查找数组中是否有满足条件的元素
var arr = [10, 30, 4];
var flag = arr.some(function(value,index,array) {
//参数一是:数组元素
//参数二是:数组元素的索引
//参数三是:当前的整个数组
return value < 3; });
console.log(flag);//false返回值是布尔值,只要查找到满足条件的一个元素就立马终止循环
some和forEach区别
1.如果查询数组中唯一的元素, 用some方法更合适,在some 里面 遇到 return true 就 是终止遍历 迭代效率更高
2.在forEach 里面 return 不会终止迭代
去除字符串两端的空格
str.trim()
获取对象的属性名
Object.keys(对象名) //获取到当前对象中的属性名 ,返回值是一个数组
Object.defineProperty设置或修改对象中的属性
Object.defineProperty(对象名,'修改或新增的属性名',{
value:修改或新增的属性的值,
writable:true/false,//如果值为false 不允许修改这个属性值 enumerable: false,//enumerable 如果值为false 则不允许遍历 configurable: false //configurable 如果为false 则不允许删除这个属性 属性是否可以被删除或是否可以再次修改特性 })
函数内部的this指向
调用方式 | this指向 |
---|---|
普通函数调用 | window |
构造函数调用 | 实例对象 原型对象里面的方法也指向实例对象 |
对象方法调用 | 该方法所属对象 |
事件绑定方法 | 绑定事件对象 |
window | |
window |
改变函数内部 this 指向
1.call()方法
语法:函数名.call( thisArg, arg1 , arg2…)
thisArg:当前调用函数this的指向对象
arg1 , arg2…:传递的其他参数
2.apply()方法
语法:fun.apply( thisArg, [argsArray] )
thisArg: 在fun函数运行时指定的this值
argsArray: 传递的值,为数组形式
3.bind()方法
语法:fun.bind( thisArg, arg1,arg2… ) //不会调用函数,但能改变函数内部this指向
thisArg: 在fun函数运行时指定的this值
arg1 , arg2…:传递的其他参数
返回由指定的this值和初始化参数改造的原函数拷贝
三者的异同
共同点 : 都可以改变this指向
不同点: 1.call 和 apply 会调用函数, 并且改变函数内部this指向;
开启严格模式
在所有语句或者函数内部最前面添加 ’ use strict ';
高阶函数
高阶函数是对其他函数进行操作的函数,它接收函数作为参数或将函数作为返回值输出。
闭包
闭包(closure)指有权访问另一个函数作用域中变量的函数。简单理解就是 ,一个作 域可以访问另外一个函数内部的局部变量。
代码示例:
递归
如果一个函数在内部可以调用其本身,那么这个函数就是递归函数。简单理解:函 数内部自己调用自己, 这个函数就是递归函数
代码示例:
正则表达式的创建
var rg = /123/;
正则表达式测试
var rg = /123/;
console.log(rg.test(123));//匹配字符中是否出现123 出现结果为true console.log(rg.test('abc'));//匹配字符中是否出现123 未出现结果为false
边界符
1.^:表示匹配行首的文本(以谁开始)
2.$:表示匹配行尾的文本(以谁结束)
如果 ^和 $ 在一起,表示必须是精确匹配。
var rg = /abc/; // 正则表达式里面不需要加引号 不管是数字型还是字符串型
// /abc/ 只要包含有abc这个字符串返回的都是true
console.log(rg.test('abc'));
console.log(rg.test('abcd'));
console.log(rg.test('aabcd'));
console.log('‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐');
var reg = /^abc/; console.log(reg.test('abc')); // true console.log(reg.test('abcd')); // true
console.log(reg.test('aabcd')); // false
console.log('‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐');
var reg1 = /^abc$/; // 精确匹配 要求必须是 abc字符串才符合规范 console.log(reg1.test('abc')); // true
console.log(reg1.test('abcd')); // false
console.log(reg1.test('aabcd')); // false
console.log(reg1.test('abcabc')); // false
字符类
字符类表示有一系列字符可供选择,只要匹配其中一个就可以了。所有可供选择的字符 都放在方括号内。
[ ]方括号
表示有一系列字符可供选择,只要匹配其中一个就可以了
var rg = /[abc]/; // 只要包含有a 或者 包含有b 或者包含有c 都返回为true console.log(rg.test('andy'));//true
console.log(rg.test('baby'));//true
console.log(rg.test('color'));//true
console.log(rg.test('red'));//false
var rg1 = /^[abc]$/; // 三选一 只有是a 或者是 b 或者是c 这三个字母才返回 true console.log(rg1.test('aa'));//false
console.log(rg1.test('a'));//true
console.log(rg1.test('b'));//true
console.log(rg1.test('c'));//true
console.log(rg1.test('abc'));//true ‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐var reg = /^[a‐z]$/ //26个英文字母任何一个字母返回 true ‐ 表示的是a 到z 的范 围 console.log(reg.test('a'));//true
console.log(reg.test('z'));//true
console.log(reg.test('A'));//false ‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐
//字符组合
var reg1 = /^[a‐zA‐Z0‐9]$/; // 26个英文字母(大写和小写都可以)任何一个字母返回 true ‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐
//取反 方括号内部加上 ^ 表示取反,只要包含方括号内的字符,都返回 false 。 var reg2 = /^[^a‐zA‐Z0‐9]$/;
console.log(reg2.test('a'));//false
console.log(reg2.test('B'));//false
console.log(reg2.test(8));//false
console.log(reg2.test('!'));//true
量词符
量词 | 说明 |
---|---|
* | 重复>=0次 |
+ | 重复>=1次 |
? | 重复0次或1次 |
{n} | 重复n次 |
{n,} | 重复>=n次 |
{n,m} | 重复n到m次 |
预定义类
预定类 | 说明 |
---|---|
\d | 匹配0-9之间任一数字,相当于[0-9] |
\D | 匹配所有0-9以外的字符,相当于[ ^0-9] |
\w | 匹配任意的字母、数字和下划线, 相当于[A-Za-z0-9] |
\W | 匹配所有字母、数字和下划线以外的字符, 相当于[ ^A-Za-z0-9] |
\s | 匹配空格(包括换行符、制表符、空格符等),相当于[\t\r\n\v\f] |
\S | 匹配非空格的字符,相当于[ ^\t\r\n\v\f] |
正则替换replace
replace() 方法可以实现替换字符串操作,用来替换的参数可以是一个字符串或是一个正 则表达式
stringObject.replace( / 表达式 / switch, replacement )
表达式 :被替换的字符串或正则表达式
switch:g–全局匹配; i–忽略大小写; gi–全局匹配+忽略大小写
replacement:替换为的字符串
返回值是一个替换完毕的新字符串
let
1.使用let关键字声明的变量才具有块级作用域,使用var声明的变量不具备块级作用 域特性
2.使用let关键字声明的变量没有变量提升,要先声明才能使用
const
用来声明常量,常量就是值(内存地址)不能变化的量
1.具有块级作用域 ,声明 const时候必须要给定值
2.如果是常量不能重新进行赋值,如果是基本数据类型,不能更改值,如果是复杂数据 类型,不能更改地址值
解构赋值
ES6中允许从数组中提取值,按照对应位置,对变量赋值,对象也可以实现解构
1.解构赋值就是把数据结构分解,然后给变量进行赋值
2.如果结构不成功,变量跟数值个数不匹配的时候,变量的值为undefined
3.数组解构用中括号包裹,多个变量用逗号隔开,对象解构用花括号包裹,多个变量用 逗号隔开
箭头函数
() => {} //():代表是函数; =>:必须要的符号,指向哪一个代码块;{}:函数体
const fn = () => {}//代表把一个函数赋值给fn
1.函数体中只有一句代码,且代码的执行结果就是返回值,可以省略大括号
2.如果形参只有一个,可以省略小括号
3.箭头函数不绑定this关键字,箭头函数中的this,指向的是函数定义位置的上下文this
剩余参数
function sum (first, ...args) {
console.log(first); // 10
console.log(args); // [20, 30]
}
sum(10, 20, 30);
Array 的扩展方法
扩展运算符 //扩展运算符可以将数组或者对象转为用逗号分隔的参数序列
let ary = [1, 2, 3];
...ary // 1, 2, 3
console.log(...ary); // 1 2 3,相当于下面的代码
console.log(1,2,3)
构造函数方法:Array.from()
将伪数组或可遍历对象转换为真正的数组
//定义一个集合
let arrayLike = {
'0': 'a',
'1': 'b',
'2': 'c',
length: 3
};
//转成数组
let arr2 = Array.from(arrayLike); // ['a', 'b', 'c']
该方法还可以接受第二个参数,作用类似于数组的map方法,用来对每个元素进行处理, 将处理后的值放入返回的数组
find()
用于找出第一个符合条件的数组成员,如果没有找到返回undefined
let ary = [{
id: 1,
name: '张三'
}, {
id: 2,
name: '李四'
}];
let target = ary.find((item, index) => item.id == 2);//找数组里面符合条件 的值,当数组中元素id等于2的查找出来,注意,只会匹配第一个
findIndex()
用于找出第一个符合条件的数组成员的位置,如果没有找到返回-1
let ary = [1, 5, 10, 15];
let index = ary.findIndex((value, index) => value > 9);
console.log(index); // 2
includes()
判断某个数组是否包含给定的值,返回布尔值。
[1, 2, 3].includes(2) // true
[1, 2, 3].includes(4) // false
String 的扩展方法
模板字符串 //用反引号
let name = '张三'; let sayHello = `hello,my name is ${name}`; // hello, my name is zhangsan模板字符串中可以解析变量、换行、调用函数
startsWith() 和 endsWith()
表示参数字符串是否在原字符串的头部/尾部,返回布尔值
repeat()
repeat方法表示将原字符串重复n次,返回一个新字符串
Set 数据结构
类似于数组,但是成员的值都是唯一的,没有重复的值。
const 常量名 = new Set();
包含的方法:
1.add(value):添加某个值,返回 Set 结构本身
2.delete(value):删除某个值,返回一个布尔值,表示删除是否成功
3.has(value):返回一个布尔值,表示该值是否为 Set 的成员
4.clear():清除所有成员,没有返回值
Node环境 中的 Javascript
node.js:Javascript的服务器端运行环境,可以让程序员使用Javacript来实现服务器端的编程,没有浏览器和HTML的概念,没有 BOM 和 DOM
Node中的js组成:ECMAScript核心 + 全局成员 +核心API模块
全局成员:console、setInterval、setTimeout…
核心API模块:Node平台提供的一些API,是Node独有的
node下载网站http://nodejs.cn/
REPL环境
打开任意终端,输入node并回车,就能进入
按两次ctrl + c 退出REPL环境
npm
全局包
npm install 包名 -g
即可;其中 -g
参数,表示 把包安装到全局目录中的意思;npm uninstall 包名 -g
即可;其中 uninstall
表示卸载的意思;本地包
npm init
或者npm init -y
命令,初始化一个package.json
的配置文件,否则包无法安装到本地项目中;npm i 包名 --save
即可安装本地包;都安装到了当前项目的 node_modules
目录下;
--save
命令,如果用的是 npm 3.x 的版本,则需要手动指定 --save
;package-lock.json
文件中记录了曾经装过的包的下载地址,方便下次直接下载包,能够加快装包的速度,提升装包的体验;npm uninstall/remove 包名 -S/-D
即可卸载指定的本地包;其它常用命令
--save
的缩写是 -S
--save-dev
的缩写是 -D
install
的缩写是 i
dependencies
节点,表示项目上线部署时候需要的依赖项;devDependencies
节点,表示项目在开发阶段需要的依赖项,但是当项目要部署上线了,devDependencies
节点中的包,就不再需要了!npm i
快速装包的时候,npm会检查package.json
文件中,所有的依赖项,然后都为我们安装到项目中--production
表示只安装 dependencies
节点下,记录的包,不安装devDependencies
节点下的包;当项目要上线了,才会使用--production
命令解决 npm 下载慢问题
cnpm
:运行 npm i cnpm -g
即可;cnpm
:在装包的时候,只需要把 npm
替换成 cnpm
即可,例如:
npm
安装 jquery
:运行 npm i jquery -S
cnpm
安装 jquery
: 运行 cnpm i jquery -S
安装node_modules里的插件
npm install --save
fs文件系统
const fs = require(‘fs’); //导入fs文件操作模块
文件读取
fs.readFile( __dirname + '/文件路径'[, '编码格式默认为null'] , function(err对象,data读取成功的结果 ){
if(err) return console.log(err.message); //如果err为null 就证明读取成功了 如果为true 则失败
console.log( data ); });
文件写入
fs.writeFile( __dirname + '/文件路径', 写入内容[, '编码格式默认为utf-8'] , function(err){
if(err) return console.log(err.message); //如果文件写入失败则报错
console.log( '文件写入成功' );
} ) //要写入的文件不存在则直接写入,如果已经存在则会覆盖之前的文件
文件内容追加
fs.appendFile(__dirname + '/文件路径', 追加内容[, '编码格式默认为utf-8'] , function(err){
if(err) return console.log(err.message); //如果文件内容追加失败则报错
console.log( '文件内容追加成功' );
})
如果要追加的文件路径不存在,则会先创建这个文件,再向创建的文件中追加内容
fs模块操作文件时路径问题
解决方案:使用node中提供的 __dirname 表示当前这个文件所处的磁盘目录
还有一种 __filename 表示当前这个文件的完整路径,包含了具体的文件名
读取文件信息
fs.stat(__dirname + '/文件路径', function(err, stats){
if(err) return console.log(err.message); //如果文件内容追加失败则报错
console.log( '文件内容读取成功' );
console.log( stats.size ); //文件大小
console.log( stats.birthtime ); //创建时间
console.log( stats.isFile ); //判断是否为文件
console.log( stats.isDirectory); //判断是否为目录
})
复制文件
fs.copyFile( '被拷贝的源文件路径,包含文件名称', '拷贝出的目标文件路径,包含名称'[,拷贝操作修饰符默认0],function(err){
if(err) return console.log(err.message); //如果拷贝失败则报错
console.log( '拷贝成功' );
} ) //如果要拷贝出的目标文件已经存在则会覆盖,如果不存在则会新建
路径操作
path.join([…paths])
const path = require('path')
path.join(__dirname, '相对路径')
其他:
const path = require('path')
// console.log(path.sep) // 路径分隔符
const str = 'c:/a/b/c/1.txt'
console.log(path.basename(str)) // 获取文件名称的
console.log(path.dirname(str)) // 获取文件所在的路径的
console.log(path.extname(str)) // 获取文件的扩展名
Javascript 的单线程和异步
Javascript 的解析和执行一直是单线程的,但是**宿主环境(浏览器或node)**是多线程的;
异步任务是由宿主环境开启子线程完成,并通过事件驱动、回调函数、队列,把完成的任务, 交给主线程执行;
Javascript解析引擎,一直在做一个工作,就是从任务队列里提取任务,放到主线程里执行。
CommonJS 规范
模块作用域 和 全局作用域
在Node.js中有两个作用域,分别是 全局作用域 和 模块作用域;
全局作用域使用 global
来访问,类似于浏览器中的window
;
每个 Javascript 文件,都是一个单独模块,每个模块都有自己独立的作用域,因此:模块中的成员,默认无法被其它模块访问。
如果在某个模块内部,想为 全局的 global 作用域挂载一些属性,需要显示的调用global.***
来挂载;
注意:在开发中,一般情况下,不推荐使用global
全局作用域来共享成员,会存在全局变量污染问题;
var b = 20
// console.log(global.b)
global.b = b
global.say = function () {
console.log('这是挂载到全局的 say 方法')
}
console.log(global.b)
global.say()
模块作用域
module(模块标识)
module 属性是 Common JS 规范中定义的,它是一个对象,表示当前这个具体的 js 模块;
require(引用模块)
每一个实现了 CommonJS 规范的模块,必须定义一个 require() 函数,使用这个 require 函数,就能够 很方便的导入其它 模块中的成员,供自己使用;
exports(暴露模块成员)
每一个模块中,如果想要把自己的一些私有成员,暴露给别人使用,那么,必须实现一个 exports 对象,通过exports对象,可以方便的把模块内私有的成员,暴露给外界使用;
module.exports 和 exports 的关系
module.exports
和 exports
默认引用了同一个空对象;module.exports
和 exports
作用一致,都可以向外暴露成员;module.exports
为准;module.exports = {}
模块成员的分类
模块成员,根据一些区别,又可以分为三大类: 核心模块、第三方模块、用户自定义模块
1.核心模块
fs
,path
等模块,都是由Node.js官方提供的核心模块;require('核心模块标识符')
2.第三方模块
什么是第三方模块:
NPM
的网站上搜索并下载才能使用;如何使用第三方模块:
先从 npm 官网上下载指定的第三方模块
使用 require('第三方模块的名称标识符')
来导入这个模块
根据 第三方模块的 官方文档,尝试使用
npm install package => 用npm命令安装(下载)第三方模块 (文件模块)
gulp
gulp的安装:
gulp的插件:
gulp语法:
1.gulp.task() 建立gulp任务
2.gulp.src() 获取任务要处理的文件
3.gulp.dest() 输出文件
4.gulp.watch() 监控文件的变化
如何卸载
npm unintall package => 用npm命令卸载包
3.用户自定义模块
require('路径标识符')
模块查找规则
package.json
项目描述文件,记录当前项目信息,例如项目名称、版本、作者、github地址、当前项目依赖了哪些第三方模块,目的是方便他人了解项目信息,下载项目依赖文件。
该文件一般被放置在项目的根目录下,使用npm init命令生成。
项目依赖
在项目的开发阶段和线上运营阶段,都需要依赖的第三方包,称为项目依赖。
使用npm install 包名
命令下载的文件会默认被添加到package.json文件的dependencies字段中。
开发依赖
在项目的开发阶段需要依赖,线上运营阶段不需要依赖的第三方包,称为开发依赖。
使用npm install 包名 --save-dev
命令将包添加到package.json文件的devDependencies字段中。
只安装项目运行依赖(dependencies)
npm install --production
为什么记录依赖项
当其他人获取到项目时,可以在项目根目录下执行npm install
命令,npm工具会自动去package.json文件中查找项目依赖文件并下载.
npm install --production
下载项目依赖,避免下载项目开发依赖。创建web服务器
// 引用系统模块
const http = require('http');
// 创建web服务器
const server = http.createServer();
// 当客户端发送请求的时候
server.on('request', (req, res) => {
// 设置响应头
res.writeHead(200, {
'Content-Type': 'text/html;charset=utf8'
});
// 设置响应体
res.write('哈哈哈
');
// 结束请求
res.end();
});
// 监听3000端口
server.listen(3000, error => {
if (!error) {
console.log('服务器已启动,监听3000端口,请访问 localhost:3000')
}
});
http协议
req.url //获取请求地址
req.headers //获取请求报文
req.method //获取请求方法
http状态码
内容类型
GET传参
参数被放置在地址栏中,格式为:name=zhangsan&age=20
// 处理get参数
const url = require('url');
let { query } = url.parse(req.url, true);
POST传参
参数被放置在请求体中,格式和GET参数相同。
// 处理post参数
// 由于post传递的参数数据量比较大,在网络中并不是一次性传递完成的,而是分成了多次传递
// 所以在接收的时候也需要分为多次接收
// 在NodeJs中接收post参数需要使用事件完成
const querystring = require('querystring');
router.post('/add', (req, res) => {
//接收post请求参数
let formData = '';
req.on('data', chunk => formData += chunk);//开始接受
req.on('end', async() => {//接受完
//querystring.parse(formData) 把字符串转换为对象
await Student.create(querystring.parse(formData))
res.writeHead(301, {
Location: '/list'
})
res.end()
})
})
路由
路由是指URL地址与程序的映射关系,更改URL地址可以改变程序的执行结果。简单说就是请求什么响应什么。
// 1.引入系统模块http
// 2.创建网站服务器
// 3.为网站服务器对象添加请求事件
// 4.实现路由功能
// 1.获取客户端的请求方式
// 2.获取客户端的请求地址
const http = require('http')
const url = require('url')
const app = http.createServer()
app.on('request', (req, res) => {
const method = req.method.toLowerCase()
const pathname = url.parse(req.url).pathname
//let { pathname, query } = url.parse(req.url, true) //返回值为对象
// 防止中文乱码
res.writeHeader(200, {
'Content-Type': 'text/html; charset=utf-8'
})
if (method === 'get') {
if (pathname === '/' || pathname === '/index') {
res.end('首页')
} else if (pathname === '/list') {
res.end('列表页')
} else {
res.end('无结果')
}
}
if (method === 'post') {
}
})
app.listen(3000)
console.log('to http://127.0.0.1:3000')
客户端请求方式
静态资源获取
服务器端不需要处理,可以直接响应给客户端的资源就是静态资源,例如CSS、JavaScript、image文件
const http = require('http');
const url = require('url');
const path = require('path');
const fs = require('fs');
const mime = require('mime');
const app = http.createServer();
app.on('request', function(req, res) {
//获取用户请求路径
let pathname = url.parse(req.url).pathname
pathname = pathname == '/' ? '/default.html' : pathname
let paths = path.join(__dirname, 'public' + pathname)
let type = mime.getType(paths)
fs.readFile(paths, (err, date) => {
if (err !== null) {
// 防止中文乱码
res.writeHeader(404, { //text/html能识别html标签;text/plain表示普通的文本字符串
'Content-Type': 'text/html; charset=utf-8'
})
res.writeHeader(200, {
'content-Type': type
})
return res.end('报错')
}
res.end(date)
})
})
app.listen(3000, '127.0.0.1', function() {
console.log('server running at http://127.0.0.1:3000');
})
promise
Promise出现的目的是解决Node.js异步编程中回调地狱的问题
//下面是用promise 读取静态资源文件
const promisify = require('util').promisify;
const fs = require('fs');
/* let promise = new Promise((dome1, dome2) => {
fs.readFile('./views/1.text', 'utf-8', (err, date) => {
if (err !== null) {
dome2(err)
} else {
dome1(date)
}
})
})
promise.then((date) => {
console.log(date);
})
.catch((err) => {
console.log(err);
}) */
function p1() {
return new Promise((dome1, dome2) => {
fs.readFile('./views/1.text', 'utf-8', (err, date) => {
if (err !== null) {
dome2(err)
} else {
dome1(date)
}
})
})
}
function p2() {
return new Promise((dome1, dome2) => {
fs.readFile('./views/2.text', 'utf-8', (err, date) => {
if (err !== null) {
dome2(err)
} else {
dome1(date)
}
})
})
}
p1().then((date) => {
console.log(date);
return p2()
})
.then((date) => {
console.log(date);
})
异步函数
异步函数是异步编程语法的终极解决方案,它可以让我们将异步代码写成同步的形式,让代码不再有回调函数嵌套,使代码变得清晰明了
const fn = async () => {};
async function fn () {}
async关键字
await关键字
promisify改造函数
//下面是异步函数读取文件代码示例:
const fs = require('fs');
// 改造现有异步函数api 让其返回promise对象 从而支持异步函数语法
const promisify = require('util').promisify;
// 调用promisify方法改造现有异步API 让其返回promise对象
const readFile = promisify(fs.readFile);
async function run() {
let n1 = await readFile('./views/1.text', 'utf-8')
let n2 = await readFile('./views/2.text', 'utf-8')
console.log(n1);
console.log(n2);
}
run()
异步函数示例代码如下:
// 1.在普通函数定义的前面加上async关键字 普通函数就变成了异步函数
// 2.异步函数默认的返回值是promise对象
// 3.在异步函数内部使用throw关键字进行错误的抛出
// await关键字
// 1.它只能出现在异步函数中
// 2.await promise 它可以暂停异步函数的执行 等待promise对象返回结果后再向下执行函数
// async function fn() {
// throw '发生了错误'
// return 123
// }
// fn().then((date) => {
// console.log(date);
// })
// .catch((err) => {
// console.log(err);
// })
async function p1() {
return 'p1'
}
async function p2() {
return 'p2'
}
async function p3() {
return 'p3'
}
async function run() {
console.log(await p1());
console.log(await p2());
console.log(await p3());
}
run()
MongoDB数据库安装
Node.js通常使用MongoDB作为其数据库,具有高性能,易使用,存储数据方便等特点,完全使用JavaScript语法即可操作。下载
MongoDB可视化软件
MongoDB可视化操作软件,使用图形界面操作数据库的一种方式。下载
Mongoose第三方包
使用Node.js操作MongoDB数据库需要依赖Node.js第三方包mongoose,使用npm install mongoose
命令下载
数据库连接
const mongoose = require('mongoose');
// 数据库连接 27017是mongodb数据库的默认端口
// mongoose.connect('mongodb://账号名:密码@localhost:27017/数据库名字', { useNewUrlParser: true })
mongoose.connect('mongodb://likai:550@localhost:27017/blog', { useNewUrlParser: true })
.then(() => console.log('数据库连接成功'))
.catch(() => console.log('数据库连接失败'));
创建集合
//连接数据库
const mongoose = require('mongoose')
mongoose.connect('mongodb://localhost/playground', { useNewUrlParser: true })
.then(() => {
console.log('数据库连接成功');
})
.catch((err) => {
console.log(err, '数据库连接失败');
})
//创建集合规则(类似于设计数据库表结构)
const courseSchema = new mongoose.Schema({
name: String,
author: String,
ispub: Boolean
})
//使用规则创建集合,第一个参数是集合名称(第一个字母要大写) 第二个参数是集合规则
const Course = mongoose.model('Course', courseSchema)
添加数据
//第一种插入数据方式
// const dome1 = new Course({
// name: 'kk',
// author: 'student',
// ispub: true
// })
// dome1.save()
//第二种插入数据方式
Course.create({
name: 'qiuqiu',
author: 'student',
ispub: true
})
.then(doc => {
console.log(doc);
})
.catch(err => {
console.log(err);
})
查找
//1.全部查询
// User.find().then(date => {
// console.log(date);
// })
User.find({
_id: '5c09f267aeb04b22f8460968'
}).then(date => {
console.log(date); //输出值是个数据
})
User.findOne({
// _id: '5c09f236aeb04b22f8460967'
}).then(date => {
console.log(date); //输出值是个集合,并且是集合中的第一条
})
//2.范围查询
User.find({
age: { $gt: 20, $lt: 50 }
}).then(date => {
console.log(date);
})
//3.包含查询
User.find({
hobbies: { $in: ['足球'] }
}).then(date => {
console.log(date);
console.log('-----------');
})
//4.字段查询,多个字段中间以空格隔开,前面加 - 表示不查询该字段
User.find().select('name age -_id').then(date => {
console.log(date); //返回值为数组包含数条集合
console.log('-----------');
})
//5.将查找的数据进行升序排序,若降序排列,在字段名前面加 - ,下面以年龄为示例
User.find().sort('age').then(date => {
console.log(date); //返回值为数组包含数条集合
})
//6.skip()跳过多少条数据, llimit()限制查询结果的数量
User.find().skip(2).limit(2).then(date => {
console.log(date); //返回值为数组包含数条集合
})
删除
// 查找到一条文档并且删除
// 返回删除的文档
// 如何查询条件匹配了多个文档 那么将会删除第一个匹配的文档
User.findOneAndDelete({ _id: '5c09f267aeb04b22f8460968' })
.then(date => {
console.log(date);
})
// 删除多条文档
//返回值为{ n:4, ok:1 } n为删除的数量,ok为1表示删除成功
// User.deleteMany({ _id: '5c09f267aeb04b22f8460968' })
// .then(date => {
// console.log(date);
// })
修改
//修改单个,返回值{ n: 1, nModified: 1, ok: 1 } n代表受影响的数据个数, nModifie表示修改的数据个数, ok为1表示成功
User.updateOne({ name: '赵六' }, { name: '赵云' })
.then(date => {
console.log(date);
})
//修改多个
User.updateMany({}, { age: 88 })
.then(date => {
console.log(date);
})
验证规则
// 创建集合规则,并添加规则验证
const pot = new mongoose.Schema({
title: {
type: String,
required: [true, '请传入文章标题'], //必选字段,第二参数为报错时提示信息
maxlength: 10, //传入字符串最大长度
minlength: 2, //传入字符串最小长度
trim: true //去除字符串两端的空格
},
age: {
type: Number,
min: 2, //数值最小值
max: 100 //数值最大值
},
publishDate: {
type: Date,
default: Date.now // 默认值
},
category: {
type: String,
// 枚举 列举出当前字段可以拥有的值
enum: {
values: ['html', 'css', 'javascript', 'node.js'],
message: '分类名称要在一定的范围内才可以'
}
},
author: {
type: String,
validate: {
validator: v => {
// 返回布尔值
// true 验证成功,false 验证失败
// v 要验证的值
return v && v.length > 4
},
message: '传入的值不符合验证规则' // 自定义错误信息
}
}
});
多集合联合查询(集合关联)
通常不同集合的数据之间是有关系的,例如文章信息和用户信息存储在不同集合中,但文章是某个用户发表的,要查询文章的所有信息包括发表用户,就需要用到集合关联。
// 用户集合
const User = mongoose.model('User', new mongoose.Schema({ name: { type: String } }));
// 文章集合
const Post = mongoose.model('Post', new mongoose.Schema({
title: { type: String },
// 使用ID将文章集合和作者集合进行关联
author: { type: mongoose.Schema.Types.ObjectId, ref: 'User' }
}));
//联合查询
Post.find()
.populate('author')
.then((err, result) => console.log(result));
在catch中获取错误信息
Post.create({title:'aa', age: 60, category: 'java', author: 'bd'})
.then(result => console.log(result))
.catch(error => {
// 获取错误信息对象
const err = error.errors;
// 循环错误信息对象
for (var attr in err) {
// 将错误信息打印到控制台中
console.log(err[attr]['message']);
}
})
数据库导入文档数据
mongoimport -d 数据库名称 -c 集合名称 --file '要导入的数据文件名(包含路径)'
mongoDB数据库添加账号
停止服务 net stop mongodb
mongod --remove
9.创建mongodb服务
mongod --logpath=“C:\Program
Files\MongoDB\Server\4.1\log\mongod.log” --dbpath=“C:\Program
Files\MongoDB\Server\4.1\data” --install –-auth
10.启动mongodb服务 net start mongodb
11.在项目中使用账号连接数据库
mongoose.connect(‘mongodb://likai:550@localhost:27017/blog’, { useNewUrlParser: true })
mongoose.connect(‘mongodb://账号名:密码@localhost:27017/数据库名字’, { useNewUrlParser: true })
创建项目数据库账号
1.mongo
2.use admin
3.db.auth(‘root’,‘root’)
4.use 项目使用的数据库名
5.db.createUser({user:‘likai’,pwd:‘550’,roles:[‘readWrite’]})
6.exit
art-template下载
高性能 JavaScript 模板引擎,使用npm install art-template
命令下载。
通过调用模板引擎提供的template函数,告知模板引擎将特定模板和特定数据进行拼接,最终返回拼接结果
//导入模板引擎
const template = require('art-template');
const path = require('path')
// 设置模板的根目录
template.defaults.root = path.join(__dirname, 'views');
// 配置模板的默认后缀
template.defaults.extname = '.html';
// template方法是用来拼接字符串的
// 参数1. 模板路径 绝对路径
// 参数2. 要在模板中显示的数据 对象类型
// 返回拼接好的字符串
const html = template('index.art'), {
name: '张三',
age: 20
})
console.log(html);
模板语法
标准语法: {{ 数据 }}
原始语法:<%= 数据 %>
原文输出
如果数据中携带HTML标签,默认不会解析标签,会将其转义后输出。使用以下方式可以解析标签。
标准语法: {{ @数据 }}
原始语法:<%- 数据 %>
条件判断
{{if 条件}} ... {{/if}}
{{if v1}} ... {{else if v2}} ... {{/if}}
<% if (value) { %> ... <% } %>
<% if (v1) { %> ... <% } else if (v2) { %> ... <% } %>
数据循环
<!-- 标准语法 -->
{{each 数据}}
{{$index}} {{$value}}
{{/each}}
<!-- 原始语法 -->
<% for(var i = 0; i < target.length; i++){ %>
<%= i %> <%= target[i] %> //带等号表示输出
<% } %>
子模板
使用子模板可以将网站公共区块(头部、底部)抽离到单独的文件中。
{{include '模板路径'}}
<% include('模板路径') %>
模板继承
使用模板继承可以将网站HTML骨架抽离到单独的文件中,其他页面模板可以继承骨架文件。
{{extend './layout.html'}}//要继承的html文件
{{block 'head'}} ... {{/block}} //内容填充
模板配置
下载: npm install dateformat
代码示例:
const dateformat = require('dateformat');
// 导入模板变量 用于处理日期格式的方法
template.defaults.imports.dateformat = dateformat;
//日期格式 {{dateformat($value.name名,'yyyy-mm-dd')}}
第三方模块 router
功能:实现路由
使用步骤:
获取路由对象
调用路由对象提供的方法创建路由
启用路由,使路由生效
const getRouter = require('router')
const router = getRouter();//创建路由
router.get('/list', async(req, res) => {
let student = await Student.find() //查询学生信息
let html = template('list.art', {
students: student
})
res.end(html)//最后要有一个返回值
})
app.on('request', (req, res) => {
router(req, res, () => {} )
})
实现静态资源访问
第三方模块serve-static
引入serve-static模块获取创建静态资源(比如css,js等)服务功能的方法
调用方法创建静态资源服务并指定静态资源服务目录
启用静态资源服务功能
const serveStatic = require('serve-static')
const serve = serveStatic('静态资源目录')
app.on('request', () => {
serve(req, res)
})
app.listen(3000)
Express
Express是一个基于Node平台的web应用开发框架,提供一系列强大特性,帮助你创建各种 Web应用。
使用npm install express
进行本地安装。
中间件
使用app.use()
方法定义中间件。
该方法可以传递一个函数作为参数,表示任何任何请求都会经过该中间件,都会执行该参数内部的代码。
app.use((req, res, next) => {
console.log(req.url);
next();
});
该方法的第一个参数也可以是请求路径,表示只有该请求路径才会经过该中间件。
app.use('/user', (req, res, next) => {
console.log(req.method);
next();
});
中间件错误处理
app.get('/index', (req, res, next) => {
// throw new Error('程序发生了未知错误')
fs.readFile('./01.js', 'utf8', (err, result) => {
if (err != null) {
next(err)
}else {
res.send(result)
}
})
})
// 下面是错误处理
app.use((err, req, res, next) => {
res.status(500).send(err.message);
})
异步函数错误捕捉
const express = require('express');
const fs = require('fs');
const promisify = require('util').promisify;
const readFile = promisify(fs.readFile);
app.get('/index', async (req, res, next) => {
try {
await readFile('./aaa.js')
}catch (ex) {
next(ex);
}
})
构建模块化路由
第一种:在同一个页面
const express = require('express')
// 创建路由对象
const home = express.Router();
// 将路由和请求路径进行匹配
app.use('/home', home);
// 在home路由下继续创建路由
home.get('/index', () => {
// /home/index
res.send('欢迎来到博客展示页面');
});
第二种:在多个页面
// home.js
const express = require('express')
// 创建路由对象
const home = express.Router();
home.get('/index', () => {
res.send('欢迎来到博客展示页面');
});
module.exports = home;
// admin.js
const express = require('express')
// 创建路由对象
const admin = express.Router();
admin.get('/index', () => {
res.send('欢迎来到博客管理页面');
});
module.exports = admin;
// app.js
const express = require('express');
// 创建网站服务器
const app = express();
const home = require('./route/home.js');
const admin = require('./route/admin.js');
app.use('/home', home);
app.use('/admin', admin);
// 端口监听
app.listen(3000);
console.log('to http://127.0.0.1:3000')
获取get请求参数
// 引入express框架
const express = require('express');
// 创建网站服务器
const app = express();
app.get('/index', (req, res) => {
// 获取get请求参数
res.send(req.query)
})
// 端口监听
app.listen(3000);
console.log('to http://127.0.0.1:3000')
获取post请求参数
Express中接收post请求参数需要借助第三方包 body-parser
// 引入express框架
const express = require('express');
const bodyParser = require('body-parser');
// 创建网站服务器
const app = express();
// 拦截所有请求
// extended: false 方法内部使用querystring模块处理请求参数的格式
// extended: true 方法内部使用第三方模块qs处理请求参数的格式
app.use(bodyParser.urlencoded({extended: false}))
app.post('/add', (req, res) => {
// 接收post请求参数
res.send(req.body)
})
// 端口监听
app.listen(3000);
console.log('to http://127.0.0.1:3000')
app.use方法
// 引入express框架
const express = require('express');
const bodyParser = require('body-parser');
// 创建网站服务器
const app = express();
app.use(fn({ a: 2 }))
function fn(obj) {
return function(req, res, next) {
if (obj.a == 1) {
console.log(req.url)
} else {
console.log(req.method)
}
next()
}
}
app.get('/', (req, res) => {
// 接收post请求参数
res.send('ok')
})
// 端口监听
app.listen(3000);
console.log('to http://127.0.0.1:3000')
路由参数
// 引入express框架
const express = require('express');
const bodyParser = require('body-parser');
// 创建网站服务器
const app = express();
app.get('/index/:id/:name/:age', (req, res) => {
// 客户端请求时地址栏应该写成这样
// http://localhost:3000/list/12/zhangsan /20
// 接收post请求参数
res.send(req.params)
})
// 端口监听
app.listen(3000);
console.log('to http://127.0.0.1:3000')
express静态资源
通过 Express 内置的 express.static
可以方便地托管静态文件,例如图片、CSS、JavaScript 文件等。
app.use(express.static('public'));
现在,public
目录下面的文件就可以访问了。
http://localhost:3000/images/kitten.jpg
http://localhost:3000/css/style.css
http://localhost:3000/js/app.js
http://localhost:3000/images/bg.png
http://localhost:3000/hello.html
express模板引擎
使用npm install art-template express-art-template
命令进行安装。
const express = require('express');
const path = require('path');
const app = express();
// 1.当渲染后缀为art的模板时 所使用的模板引擎是什么
// 参数1模板后缀,参数2使用的模板引擎
app.engine('art', require('express-art-template'))
// 2.告诉express框架模板存放的位置是什么
app.set('views', path.join(__dirname, 'views'))
// 3.告诉express框架模板的默认后缀是什么
app.set('view engine', 'art');
app.get('/index', (req, res) => {
// 1. 拼接模板路径
// 2. 拼接模板后缀
// 3. 哪一个模板和哪一个数据进行拼接
// 4. 将拼接结果响应给了客户端
// 第一个参数模板的路径(包含名字),第二个参数是一个对象
res.render('index', {
msg: 'message'
})
});
// 端口监听
app.listen(3000);
console.log('to http://127.0.0.1:3000')
app.locals
const express = require('express');
const path = require('path');
const app = express();
// 模板配置
app.engine('art', require('express-art-template'))
app.set('views', path.join(__dirname, 'views'))
app.set('view engine', 'art');
//将变量设置到app.locals对象中,这个数据在所有的模板中到可以获得到
app.locals.users = [{
name: 'zhangsan',
age: 20
}, {
name: '李四',
age: 30
}]
app.get('/index', (req, res) => {
res.render('index', {
msg: '首页'
})
});
// 端口监听
app.listen(3000);
console.log('to http://127.0.0.1:3000')
密码加密bcrypt
哈希斯加密是单程加密方式
在加密的密码中加入随机字符串可以增加密码被破解的难度
//导入bcrypt模板
const bcrypt = require('bcrypt')
//生成随机字符串 gen => generate生成 salt盐
let salt = await bcrypt.genSalt(10)
//使用随机字符串对密码进行加密
let pass = await bcrypt.hash('明文密码',salt)
//密码比对,返回布尔值
let isEqual = await bcrypt.compare('明文密码','加密密码')
bcrypt依赖的其他环境
1.python 2.x
2.node-gyp 安装命令:npm install -g node-gyp
3.windows-build-tools(window系统需要安装)
安装命令:npm install --global --production windows-build-tools
cookie与session
cookie:浏览器在电脑硬盘中开辟的一块空间,在客户端,主要供服务器端存储数据。
session:实际上就是一个对象,存储在服务器端的内存中,在session对象中也可以存储多条数据,每一条数据都有一个sessionid做为唯一标识。
在node中使用express-session模块实现session功能
const session = require('express-session');
app.use(session({ secret: 'secret key' }));
在app.js中引入模块
// 导入express-session模块
const session = require('express-session');
// 配置session
app.use(session({
secret: 'secret key',
saveUninitialized: false,
cookie: {
maxAge: 24 * 60 * 60 * 1000
}
}));
在用户页面从session中获取数据
// 创建用户列表路由
admin.get('/user',(req,res)=>{
res.render('admin/user',{
msg:req.session.username
})
})
实现退出功能
1.删除session
2.删除cookie
3.重定向到用户登录页面
module.exports = (req, res) => {
// 删除session
req.session.destroy(function () {
// 删除cookie
res.clearCookie('connect.sid');
// 重定向到用户登录页面
res.redirect('/admin/login');
});
}
express的页面重定向
res.redirect('/admin/user')
joi
JavaScript对象的规则描述语言和验证器
安装 npm install joi
const Joi = require('joi');
const schema = {//alphanum()字母字符串
username: Joi.string().alphanum().min(3).max(30).required().error(new Error(‘错误信息’)),
password: Joi.string().regex(/^[a-zA-Z0-9]{3,30}$/),
access_token: [Joi.string(), Joi.number()],//表示两种类型都可以
birthyear: Joi.number().integer().min(1900).max(2013),//integer()整数
email: Joi.string().email()//邮箱格式
//valid(0, 1)值必须为0或1
static: Joi.number().valid(0, 1).error(new Error('状态值非法'))
};
async function run () {
try {
// 实施验证
await Joi.validate({ username: 'abc', birthyear: 1994 }, schema);
}catch (ex) {
console.log(ex.message);
return;
}
console.log('验证通过')
formidable
作用:解析表单,支持get请求参数,post请求参数、文件上传
安装: npm install formidable
// 引入formidable模块
const formidable = require('formidable');
// 创建表单解析对象
const form = new formidable.IncomingForm();
// 设置文件上传路径
form.uploadDir = "/my/dir";
// 是否保留表单上传文件的扩展名
form.keepExtensions = true;
// 对表单进行解析
form.parse(req, (err, fields, files) => {
// fields 存储普通请求参数(普通表单数据)
// files 存储上传的文件信息
});
FileReader
//文件读取
var reader = new FileReader();
reader.readAsDataURL('文件');
reader.onload = function () {
console.log(reader.result);
}
数据分页 mongoose-sex-page
const pagination = require('mongoose-sex-page');
// page 指定当前页
// size 指定每页显示的数据条数
// display 指定客户端要显示的最多页码数
// exec 向数据库中发送查询请求
// 查询所有文章数据
pagination(集合构造函数).page(1) .size(20) .display(8) .exec();
config
作用:允许开发人员将不同运行环境下的应用配置信息抽离到单独的文件中,模块内部自动判断当前应用的运行环境,
并读取对应的配置信息,极大提供应用配置信息的维护成本,避免了当运行环境重复的多次切换时,手动到项目代码
中修改配置信息
使用步骤:
{
"db": {
"user": "itcast",
"host": "localhost",
"port": "27017",
"name": "blog"
}
}
mongoose.connect(`mongodb://${config.get('db.user')}:${config.get('db.pwd')}@${config.get('db.host')}:${config.get('db.port')}/${config.get('db.name')}`, {useNewUrlParser: true })
.then(() => console.log('数据库连接成功'))
.catch(() => console.log('数据库连接失败'))
将敏感配置信息存储在环境变量中
{
"db": {
"pwd": "APP_PWD"
}
}
它是浏览器提供的一套方法,可以实现页面无刷新更新数据,提高用户浏览网站应用的体验。
创建ajax对象
var xhr = new XMLHttpRequest();
告诉 Ajax 请求地址以及请求方式
xhr.open('get', 'http://www.example.com');
发送请求
xhr.send();
获取服务器端给与客户端的响应数据
xhr.onload = function () {
console.log(xhr.responseText);
}
服务端响应的数据格式
在真实的项目中,服务器端大多数情况下会以 JSON对象作为响应数据的格式。当客户端拿到响应数据时,要将 JSON 数据和 HTML 字符串进行拼接,然后将拼接的结果展示在页面中。
在 http 请求与响应的过程中,无论是请求参数还是响应内容,如果是对象类型,最终都会被转换为对象字符串进行传输。
JSON.parse() // 将 json 字符串转换为json对象
传递get请求参数
<script type="text/javascript">
// 获取按钮元素
var btn = document.getElementById('btn');
// 获取姓名文本框
var username = document.getElementById('username');
// 获取年龄文本框
var age = document.getElementById('age');
// 为按钮添加点击事件
btn.onclick = function() {
// 创建ajax对象
var xhr = new XMLHttpRequest();
// 获取用户在文本框中输入的值
var nameValue = username.value;
var ageValue = age.value;
// 拼接请求参数
var params = 'username=' + nameValue + '&age=' + ageValue;
// 配置ajax对象
//get请求是不能提交json对象数据格式的
xhr.open('get', 'http://localhost:3000/get?' + params);
// 发送请求
xhr.send();
// 获取服务器端响应的数据
xhr.onload = function() {
console.log(xhr.responseText)
}
}
</script>
传递post请求参数
<script type="text/javascript">
// 获取按钮元素
var btn = document.getElementById('btn');
// 获取姓名文本框
var username = document.getElementById('username');
// 获取年龄文本框
var age = document.getElementById('age');
// 为按钮添加点击事件
btn.onclick = function() {
// 创建ajax对象
var xhr = new XMLHttpRequest();
// 获取用户在文本框中输入的值
var nameValue = username.value;
var ageValue = age.value;
// 拼接请求参数
var params = 'username=' + nameValue + '&age=' + ageValue;
// 配置ajax对象
xhr.open('post', 'http://localhost:3000/post');
// 设置请求参数格式的类型(post请求必须要设置)
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
// 发送请求
xhr.send(params);
// 获取服务器端响应的数据
xhr.onload = function() {
console.log(xhr.responseText)
}
}
</script>
请求参数的格式
application/x-www-form-urlencoded
name=zhangsan&age=20&sex=男
application/json
{name: 'zhangsan', age: '20', sex: '男'}
Ajax 状态码
在创建ajax对象,配置ajax对象,发送请求,以及接收完服务器端响应数据,这个过程中的每一个步骤都会对应一个数值,这个数值就是ajax状态码。
<script type="text/javascript">
var xhr = new XMLHttpRequest();
//状态码
// 0 已经创建了ajax对象 但是还没有对ajax对象进行配置
console.log(xhr.readyState);
xhr.open('get', 'http://localhost:3000/readystate');
// 1 已经对ajax对象进行配置 但是还没有发送请求
console.log(xhr.readyState);
// onreadystatechange事件 当ajax状态码发生变化的时候触发
xhr.onreadystatechange = function() {
// 2 请求已经发送了
// 3 已经接收到服务器端的部分数据了
// 4 服务器端的响应数据已经接收完成
console.log(xhr.readyState);
// 对ajax状态码进行判断 如果状态码的值为4就代表数据已经接收完成了
if (xhr.readyState == 4) {
console.log(xhr.responseText);
}
}
xhr.send();
</script>
错误处理
可以判断服务器端返回的状态码,分别进行处理。xhr.status 获取http状态码
2.网络畅通,服务器端没有接收到请求,返回404状态码。
检查请求地址是否错误。
3.网络畅通,服务器端能接收到请求,服务器端返回500状态码。
服务器端错误,找后端程序员进行沟通。
4.网络中断,请求无法发送到服务器端。
会触发xhr对象下面的onerror事件,在onerror事件处理函数中对错误进行处理
低版本 IE 浏览器的缓存问题
**问题:**在低版本的 IE 浏览器中,Ajax 请求有严重的缓存问题,即在请求地址不发生变化的情况下,只有第一次请求会真正发送到服务器端,后续的请求都会从浏览器的缓存中获取结果。即使服务器端的数据更新了,客户端依然拿到的是缓存中的旧数据。
**解决方案:**在请求地址的后面加请求参数,保证每一次请求中的请求参数的值不相同。
xhr.open('get', 'http://www.example.com?t=' + Math.random());
Ajax封装
发送一次请求代码过多,发送多次请求代码冗余且重复
将请求代码封装到函数中,发请求时调用函数即可
<script>
function ajax(obj) {
//存储的是默认值
var defaults = {
type: 'get',
url: '',
date: {},
header: {
'Content-Type': 'application/x-www-form-urlencoded'
},
success: function() {},
error: function() {}
}
//使用obj对象中的属性覆盖defaults对象中的属性
Object.assign(defaults, obj);
//创建ajax对象
var xhr = new XMLHttpRequest()
//拼接请求参数的变量
var params = ''
//循环用户传递进来的对象格式参数
for (var attr in defaults.date) {
//将参数转换为字符串格式
params += attr + '=' + defaults.date[attr] + '&'
}
//将参数最后面的&截取掉,并重新赋值给params变量
params = params.substr(0, params.length - 1)
//判断请求方式
if (defaults.type == 'get') {
defaults.url = defaults.url + '?' + params
}
//配置ajax对象
xhr.open(defaults.type, defaults.url)
//如果请求方式是post
if (defaults.type == 'post') {
// 用户希望的向服务器端传递的请求参数的类型
var ContentType = defaults.header['Content-Type']
//设置请求参数格式的类型
xhr.setRequestHeader('Content-Type', ContentType)
// 判断用户希望的请求参数格式的类型
// 如果类型为json
if (ContentType == 'application/json') {
// 向服务器端传递json数据格式的参数
xhr.send(JSON.stringify(defaults.date))
} else {
// 向服务器端传递普通类型的请求参数
xhr.send(params)
}
} else {
xhr.send()
}
//监听xhr对象下面的onload事件
//当xhr对象接收完响应数据后触发
xhr.onload = function() {
// 获取响应头中的数据 xhr.getResponseHeader()
var contentType = xhr.getResponseHeader('Content-Type')
//服务器端返回的数据
var responseText = xhr.responseText
// 如果响应类型中包含applicaition/json
if (contentType.includes('application/json')) {
//将JSON字符串转换为JSON对象
responseText = JSON.parse(responseText)
}
// 当http状态码等于200的时候
if (xhr.status == 200) {
// 请求成功 调用处理成功情况的函数
defaults.success(responseText)
} else {
// 请求失败 调用处理失败情况的函数
defaults.error(responseText, xhr)
}
}
}
ajax({
//求情方式
type: 'get',
//请求地址
url: 'http://localhost:3000/responseData',
success: function(date) {
console.log('这里是success函数');
console.log(date);
},
error: function(date, xhr) {
console.log('这里是err函数' + date);
console.log(xhr);
}
})
/*
请求参数要考虑的问题
1.请求参数位置的问题
将请求参数传递到ajax函数内部, 在函数内部根据请求方式的不同将请求参数放置在不同的位置
get 放在请求地址的后面
post 放在send方法中
2.请求参数格式的问题
application/x-www-form-urlencoded
参数名称=参数值&参数名称=参数值
name=zhangsan&age=20
application/json
{name: 'zhangsan', age: 20}
1.传递对象数据类型对于函数的调用者更加友好
2.在函数内部对象数据类型转换为字符串数据类型更加方便
*/
</script>
模板引擎
作用:使用模板引擎提供的模板语法,可以将数据和 HTML 拼接起来。
官方地址:
https://aui.github.io/art-template/zh-cn/index.html
模板引擎使用步骤
<!-- 1. 将模板引擎的库文件引入到当前页面 -->
<script src="/js/template-web.js"></script>
<div id="container"></div>
<!-- 2.准备art-template模板 -->
<script type="text/html" id="tpl">
<h1>{{username}} {{age}}</h1>
</script>
<script type="text/javascript">
// 3.告诉模板引擎将那个数据和哪个模板进行拼接
// 1) 模板id 2)数据 对象类型
// 方法的返回值就是拼接好的html字符串
var html = template('tpl', {
username: 'zhangsan',
age: 30
});
document.getElementById('container').innerHTML = html;
</script>
FormData 对象的作用
FormData使用方法
<!-- 创建普通的html表单 -->
<form id="form">
<input type="text" name="username">
<input type="password" name="password">
<input type="button" id="btn" value="提交">
</form>
<script type="text/javascript">
// 获取按钮
var btn = document.getElementById('btn');
// 获取表单
var form = document.getElementById('form');
// 为按钮添加点击事件
btn.onclick = function() {
// 将普通的html表单转换为表单对象
var formData = new FormData(form);
// 创建ajax对象
var xhr = new XMLHttpRequest();
// 对ajax对象进行配置
xhr.open('post', 'http://localhost:3000/formData');
// 发送ajax请求
xhr.send(formData);
// 监听xhr对象下面的onload事件
xhr.onload = function() {
// 对象http状态码进行判断
if (xhr.status == 200) {
console.log(xhr.responseText);
}
}
}
</script>
//入口文件app.js
const formidable = require('formidable');
app.post('/formData', (req, res) => {
// 创建formidable表单解析对象
const form = new formidable.IncomingForm();
// 解析客户端传递过来的FormData对象
form.parse(req, (err, fields, files) => {
res.send(fields);
});
});
注意
formData 对象的实例方法
获取表单对象中属性的值
formData.get('key');
设置表单对象中属性的值
formData.set('key', 'value');
删除表单对象中属性的值
formData.delete('key');
向表单对象中追加属性值
formData.append('key', 'value');
注意:set 方法与 append 方法的区别是,在属性名已存在的情况下,set 会覆盖已有键名的值,append会保留两个值。
formData二进制文件上传
// 实现文件上传的路由
app.post('/upload', (req, res) => {
// 创建formidable表单解析对象
const form = new formidable.IncomingForm();
// 设置客户端上传文件的存储路径
form.uploadDir = path.join(__dirname, 'public', 'uploads');
// 保留上传文件的后缀名字
form.keepExtensions = true;
// 解析客户端传递过来的FormData对象
form.parse(req, (err, fields, files) => {
// 将客户端传递过来的文件地址响应到客户端
res.send({
path: files.attrName.path.split('public')[1]
});
});
});
<div class="container">
<div class="form-group">
<label>请选择文件</label>
<input type="file" id="file">
<div class="padding" id="box">
<!--<img src="" class="img-rounded img-responsive">-->
</div>
<div class="progress">
<div class="progress-bar" style="width: 0%;" id="bar">0%</div>
</div>
</div>
</div>
<script type="text/javascript">
// 获取文件选择控件
var file = document.getElementById('file');
// 获取进度条元素
var bar = document.getElementById('bar');
// 获取图片容器
var box = document.getElementById('box');
// 为文件选择控件添加onchanges事件
// 在用户选择文件时触发
file.onchange = function() {
// 创建空的formData表单对象
var formData = new FormData();
// 将用户选择的文件追加到formData表单对象中
formData.append('attrName', this.files[0]);
// 创建ajax对象
var xhr = new XMLHttpRequest();
// 对ajax对象进行配置
xhr.open('post', 'http://localhost:3000/upload');
// 在文件上传的过程中持续触发
xhr.upload.onprogress = function(ev) {
// ev.loaded 文件已经上传了多少
// ev.total 上传文件的总大小
var result = (ev.loaded / ev.total) * 100 + '%';
// 设置进度条的宽度
bar.style.width = result;
// 将百分比显示在进度条中
bar.innerHTML = result;
}
// 发送ajax请求
xhr.send(formData);
// 监听服务器端响应给客户端的数据
xhr.onload = function() {
// 如果服务器端返回的http状态码为200
// 说明请求是成功的
if (xhr.status == 200) {
// 将服务器端返回的数据显示在控制台中
var result = JSON.parse(xhr.responseText);
// 动态创建img标签
var img = document.createElement('img');
// 给图片标签设置src属性
img.src = result.path;
// 当图片加载完成以后
img.onload = function() {
// 将图片显示在页面中
box.appendChild(img);
}
}
}
}
</script>
同源
如果两个页面拥有相同的协议、域名和端口,那么这两个页面就属于同一个源,其中只要有一个不相同,就是不同源
同源政策是为了保证用户信息的安全,防止恶意的网站窃取数据。最初的同源政策是指
A 网站在客户端设置的 Cookie,B网站是不能访问的。
JSONP
jsonp 是 json with padding 的缩写,它不属于 Ajax 请求,但它可以模拟 Ajax 请求
//封装的JSONP方法
function jsonp(options) {
// 动态创建script标签
var script = document.createElement('script');
// 拼接字符串的变量
var params = '';
for (var attr in options.data) {
params += '&' + attr + '=' + options.data[attr];
}
// myJsonp0124741
var fnName = 'myJsonp' + Math.random().toString().replace('.', '');
// 它已经不是一个全局函数了
// 我们要想办法将它变成全局函数
window[fnName] = options.success;
// 为script标签添加src属性
script.src = options.url + '?callback=' + fnName + params;
// 将script标签追加到页面中
document.body.appendChild(script);
// 为script标签添加onload事件
script.onload = function() {
document.body.removeChild(script);
}
}
CORS 跨域资源共享
第三方插件cors 可实现跨域请求
const cors = require('cors')
app.use(cors())
CORS:全称为 Cross-originresource sharing,即跨域资源共享,它允许浏览器向跨域服务器发送 Ajax 请求,克服了 Ajax 只能同源使用的限制。
// 拦截所有请求
app.use((req, res, next) => {
// 1.允许哪些客户端访问我
// * 代表允许所有的客户端访问我
// 注意:如果跨域请求中涉及到cookie信息传递,值不可以为*号 比如是具体的域名信息
res.header('Access-Control-Allow-Origin', 'http://localhost:3000')
// 2.允许客户端使用哪些请求方法访问我
res.header('Access-Control-Allow-Methods', 'get,post')
// 允许客户端发送跨域请求时携带cookie信息
res.header('Access-Control-Allow-Credentials', true);
next();
});
withCredentials属性
在使用Ajax技术发送跨域请求时,默认情况下不会在请求中携带cookie信息。
withCredentials:指定在涉及到跨域请求时,是否携带cookie信息,默认值为false
Access-Control-Allow-Credentials:true 允许客户端发送请求时携带cookie
// 当发送跨域请求时,携带cookie信息
xhr.withCredentials = true;
第三方模块request
// 向其他服务器端请求数据的模块request
const request = require('request');
app.get('/server', (req, res) => {
request('http://localhost:3001/cross', (err, response, body) => {
res.send(body);
})
});
基本使用
<script src="/js/jquery.min.js"></script>
<script>
$('#btn').on('click', function() {
$.ajax({
// 请求方式
type: 'post',
// 请求地址
url: '/base',
// 请求成功以后函数被调用
success: function(response) {
// response为服务器端返回的数据
// 方法内部会自动将json字符串转换为json对象
console.log(response);
},
// 请求失败以后函数被调用
error: function(xhr) {
console.log(xhr)
}
})
});
</script>
传递请求参数
//在 $.ajax({})中
data: JSON.stringify(params),
// 指定参数的格式类型
contentType: 'application/json',
beforeSend方法
//在 $.ajax({})中
// 在请求发送之前调用
beforeSend: function() {
alert('请求不会被发送')
// 请求不会被发送
return false;
}
serialize方法
作用:将表单中的数据自动拼接成字符串类型的参数
var params = $('#form').serialize();
// name=zhangsan&age=30
// 将表单中用户输入的内容转换为对象类型
function serializeObject(obj) {
// 处理结果对象
var result = {};
// [{name: 'username', value: '用户输入的内容'}, {name: 'password', value: '123456'}]
var params = obj.serializeArray();
// 循环数组 将数组转换为对象类型
$.each(params, function(index, value) {
result[value.name] = value.value;
})
// 将处理的结果返回到函数外部
return result;
}
发送jsonp请求
$.ajax({
url: 'http://www.example.com',
// 指定当前发送jsonp请求
dataType: 'jsonp',
// 修改callback参数名称
jsonp: 'cb',
// 指定函数名称
jsonCallback: 'fnName',
success: function (response) {}
})
$.get
作用: 用于发送get请求
$.get('http://www.example.com', {name: 'zhangsan', age: 30}, function (response) {})
$.post
作用: 用于发送post请求
$.post('http://www.example.com', {name: 'lisi', age: 22}, function (response) {})
全局事件
// 当页面中有ajax请求发送时触发
$(document).on('ajaxStart', function() {
NProgress.start()
})
// 当页面中有ajax请求完成时触发
$(document).on('ajaxComplete', function() {
NProgress.done()
})
RESTful 风格的API
GET | POST | PUT | DELETE |
---|---|---|---|
获取数据 | 添加数据 | 更新数据 | 删除数据 |
XML基础
XML是什么?
XML 的全称是 extensible markup language,代表可扩展标记语言,它的作用是传输和存储数据。
XML DOM
XML DOM 即 XML 文档对象模型,是 w3c 组织定义的一套操作 XML 文档对象的API。浏览器会将 XML 文档解析成文档对象模型
<button id="btn">发送请求</button>
<div id="container"></div>
<script type="text/javascript">
var btn = document.getElementById('btn');
var container = document.getElementById('container');
btn.onclick = function() {
var xhr = new XMLHttpRequest();
xhr.open('get', '/xml');
xhr.send();
xhr.onload = function() {
// xhr.responseXML 获取服务器端返回的xml数据
var xmlDocument = xhr.responseXML;
var title = xmlDocument.getElementsByTagName('title')[0].innerHTML;
container.innerHTML = title;
}
}
</script>
Git是一个分布式版本管理控制系统(缩写VCS),它可以在任何时间点,将文档的状态作为更新记录保存起来,也可以在任何时间点,将更新记录恢复回来。
git
菜单,选中 Git Bash Here
,弹出命令窗口git --version
查看git
版本git使用前配置
git config --global user.name 提交人姓名
git config --global user.email 提交人邮箱
git config --list
git使用
git status
查看文件状态git add 文件列表
追踪文件git commit -m 提交信息
向仓库中提交代码git log
查看提交记录git checkout 文件
撤销,用暂存区中的文件覆盖工作目录中的文件git rm --cached 文件名
将文件从暂存区中删除git reset --hard 提交ID
恢复git仓库中指定版本的项目git分支
git branch
查看分支git branch 分支名称
创建分支
git checkout 分支名称
切换分支
git merge 要合并进来的分名
合并分支
git branch -d 分支名称
删除分支(分支被合并后才允许删除)(-D 强制删除)
git暂时保存更改
在git中,可以暂时提取分支上所有的改动并存储,让开发人员得到一个干净的工作副本,临时转向其他工作。
Github
访问github首页,点击 Sign up 连接。(注册)
git remote add 远程仓库地址别名 远程仓库地址
git push -u 远程仓库地址或别名 本地分支名称:
-u 记住推送地址及分支,下次推送只需要输入git push即可
多人协作开发
因为A已经创建了远程的仓库,所以程序员B就不需要创建仓库,直接把远程的仓库克隆一份到本地即可
git clone 远程仓库地址
A将远程仓库中的最新内容拉取到本地
拉取利用pull命令,拉取是读操作,不需要校验身份
git pull origin master
git忽略清单
将不需要被git
管理的文件名字添加到此文件中,在执行git
命令的时候,git
就会忽略这些文件
git
忽略清单文件名称叫: .gitignore
仓库的详细说明
在仓库根目录添加一个 readme.md
文件即可,在里面写上内容,push到服务器后,默认在github
里面就能看到仓库的详细说明了
git相关命令整理
git config --global user.name //配置姓名
git config --global user.email //配置邮箱
git config --list //查看配置信息
git init //初始化本地仓库
git status //查看文件状态
git add 文件名 //添加某个文件到暂存区,如果写 . 代表当前文件夹下所有的文件、
git commit -m 日志说明 //提交到本地仓库
git log //查看提交记录
git checkout 文件名 //撤销,让暂存区文件覆盖工作区间文件
git rm --cached 文件名 //在暂存区移除相应文件
git reset --hard 提交ID //恢复到指定版本
git branch //查看分支
git branch develop //创建分支
git checkout 分支名 //切换分支
git merge 要合并的分支名//合并分支
git branch -d 分支名称 //删除分支
git clone 地址 //克隆远程仓库
git push 地址 分支名 //往服务器推送
git pull 地址 //将服务器代码拉取到本地
git remote add 名称 地址 //给地址取别名
git push -u origin 分支名 //把该分支推送到云端仓库
ssh-keygen //生成一对密钥
v-cloak
防止页面加载时出现闪烁问题
<script type="text/css">
[v - cloak] { display: none; }
</script>
<div id="app" v-cloak>
</div>
v-text
<div v-text='msg'></div>
<div v-text>{{msg}}</div>
v-html
v-html
,永不用在用户提交的内容上 <div v-html='msg1'></div>
v-pre
<div v-pre>{{msg}}</div>
v-once
执行一次性的插值【当数据改变时,插值处的内容不会继续更新】
<!-- 即使data里面定义了msg 后期我们修改了 仍然显示的是第一次data里面存储的数据即 Hello Vue.js -->
<span v-once>{{ msg}}</span>
<script>
new Vue({
el: '#app',
data: {
msg: 'Hello Vue.js'
}
});
</script>
v-model
双向数据绑定
v-model是一个指令,限制在 、
中使用
<div id="app">
<div>{{msg}}</div>
<div>
当输入框中内容改变的时候, 页面上的msg 会自动更新
<input type="text" v-model='msg'>
</div>
</div>
mvvm
v-on
<div>{{num}}</div>
<button v-on:click='num++'>点击</button>
<button @click='num++'>点击</button>
<!-- 如果事件直接绑定函数名称,那么默认会传递事件对象作为事件函数的第一个参数 -->
<!-- 2、如果事件绑定函数调用,那么事件对象必须作为最后一个参数显示传递,
并且事件对象的名称必须是$event -->
<button @click='handle(123,456,$event)'>点击1</button>
事件修饰符
<!-- 阻止单击事件继续传播 -->
<a v-on:click.stop="doThis"></a>
<!-- 提交事件不再重载页面 -->
<form v-on:submit.prevent="onSubmit"></form>
<!-- 修饰符可以串联 即阻止冒泡也阻止默认事件 -->
<a v-on:click.stop.prevent="doThat"></a>
<!-- 只当在 event.target 是当前元素自身时触发处理函数 -->
<!-- 即事件不是从内部元素触发的 -->
<div v-on:click.self="doThat">...</div>
按键修饰符
在做项目中有时会用到键盘事件,在监听键盘事件时,我们经常需要检查详细的按键。Vue 允许为 v-on
在监听键盘事件时添加按键修饰符
<!-- 只有在 `keyCode` 是 13 时调用 `vm.submit()` -->
<input v-on:keyup.13="submit">
<!-- -当点击enter 时调用 `vm.submit()` -->
<input v-on:keyup.enter="submit">
<!--当点击enter或者space时 时调用 `vm.alertMe()` -->
<input type="text" v-on:keyup.enter.space="alertMe" >
常用的按键修饰符
.enter => enter键
.tab => tab键
.delete (捕获“删除”和“退格”按键) => 删除键
.esc => 取消键
.space => 空格键
.up => 上
.down => 下
.left => 左
.right => 右
<script>
var vm = new Vue({
el:"#app",
methods: {
submit:function(){},
alertMe:function(){},
}
})
</script>
自定义修饰符别名
在Vue中可以通过config.keyCodes
自定义按键修饰符别名
<div id="app">
预先定义了keycode 116(即F5)的别名为f5,因此在文字输入框中按下F5,会触发prompt方法
<input type="text" v-on:keydown.f5="prompt()">
</div>
<script>
Vue.config.keyCodes.f5 = 116;
let app = new Vue({
el: '#app',
methods: {
prompt: function() {
alert('我是 F5!');
}
}
});
</script>
v-bind 属性绑定
<!-- 绑定一个属性 -->
<img v-bind:src="imageSrc">
<!-- 缩写 -->
<img :src="imageSrc">
分支结构 v-if
<div id="app">
<div v-if='score>90'>优秀</div>
<div v-else-if='score>60'>良好</div>
<div v-else>不及格</div>
<br>
<!-- v-show控制显示与隐藏 -->
<div v-show='false'>v-show测试</div>
</div>
<script src="./js/vue.js"></script>
<script>
var lk = new Vue({
//el:元素挂载位置 data:模型数据(值是一个对象)
el: '#app',
data: {
score: 55
},
//函数要定义在methods中
methods: {
handle: function() {
this.url = 'https://cn.vuejs.org/v2/api/#v-on'
}
}
})
</script>
v-show 和 v-if的区别
循环结构 v-for
<div id="app">
<div>水果列表</div>
<ul>
<li v-for='item in fruits'>{{item}}</li>
</ul>
<ul>
//:k的作用:帮助Vue区分不同的元素 从而提高性能
<li :key='index' v-for='(item,index) in fruits'>{{item+'----'+index}}</li>
</ul>
</div>
<script src="./js/vue.js"></script>
<script>
var lk = new Vue({
//el:元素挂载位置 data:模型数据(值是一个对象)
el: '#app',
data: {
fruits: ['apple', 'orange', 'banana']
},
//函数要定义在methods中
methods: {
}
})
</script>
v-if
和 v-for
v-if
与 v-for
一起使用时,v-for
具有比 v-if
更高的优先级。key 的作用
表单
v-model
1.单选
<div>
<span>性别:</span>
<span>
<input type="radio" id="male" value="1" v-model='gender'>
<label for="male">男</label>
<input type="radio" id="female" value="2" v-model='gender'>
<label for="female">女</label>
</span>
</div>
2.多选 – hobby 要定义成数组 否则无法实现多选
<div>
<span>爱好:</span>
<input type="checkbox" id="ball" value="1" v-model='hobby'>
<label for="ball">篮球</label>
<input type="checkbox" id="sing" value="2" v-model='hobby'>
<label for="sing">唱歌</label>
<input type="checkbox" id="code" value="3" v-model='hobby'>
<label for="code">写代码</label>
</div>
3.下拉框和文本
<div>
<span>职业:</span>
<select v-model='occupation' multiple>
<option value="0">请选择职业...</option>
<option value="1">教师</option>
<option value="2">软件工程师</option>
<option value="3">律师</option>
</select>
</div>
<div>
<span>个人简介:</span>
<textarea v-model='desc'></textarea>
</div>
表单修饰符
<input v-model.number="age" type="number">
<input v-model.trim="msg">
<input v-model.lazy="msg" >
自定义指令
Vue.directive('focus', {
inserted: function(el) {
// el表示指令所绑定的元素
el.focus();
}
});
自定义局部指令
//自定义局部指定
directives: {
color: {
bind: function(el, binding) {
el.style.backgroundColor = binding.value.color
}
}
}
计算属性 computed
//计算属性,需要有返回值
computed: {
方法名: function() {
return 返回值
}
}
//使用时直接写方法名 不需要跟括号
侦听属性 watch
//侦听
watch: {
firstName: function(val) {
this.fullName = val + ' ' + this.lastName;
},
lastName: function(val) {
this.fullName = this.firstName + ' ' + val;
}
}
});
过滤器 filter
过滤器三种使用方式
<div>{{msg | upper}}</div>
<div>{{msg | upper | lower}}</div>
<div :abc='msg | upper'>测试数据</div>
局部过滤器filters
//过滤器
filters: {
upper: function(val) {
return val.charAt(0).toUpperCase() + val.slice(1);
}
}
自定义过滤器filter
Vue.filter(‘过滤器名称’,函数)
Vue.filter('upper', function(val) {
return val.charAt(0).toUpperCase() + val.slice(1);
});
data
,而只是改变渲染的结果,并返回过滤后的版本生命周期
常用的 钩子函数
beforeCreate | 在实例初始化之后,数据观测和事件配置之前被调用 此时data 和 methods 以及页面的DOM结构都没有初始化 什么都做不了 |
---|---|
created | 在实例创建完成后被立即调用此时data 和 methods已经可以使用 但是页面还没有渲染出来 |
beforeMount | 在挂载开始之前被调用 此时页面上还看不到真实数据 只是一个模板页面而已 |
mounted | el被新创建的vm.$el替换,并挂载到实例上去之后调用该钩子。 数据已经真实渲染到页面上 在这个钩子函数里面我们可以使用一些第三方的插件 |
beforeUpdate | 数据更新时调用,发生在虚拟DOM打补丁之前。 页面上数据还是旧的 |
updated | 由于数据更改导致的虚拟DOM重新渲染和打补丁,在这之后会调用该钩子。 页面上数据已经替换成最新的 |
beforeDestroy | 实例销毁之前调用 |
destroyed | 实例销毁后调用 |
数组变异方法
push() |
往数组最后面添加一个元素,成功返回当前数组的长度 |
---|---|
pop() |
删除数组的最后一个元素,成功返回删除元素的值 |
shift() |
删除数组的第一个元素,成功返回删除元素的值 |
unshift() |
往数组最前面添加一个元素,成功返回当前数组的长度 |
splice() |
有三个参数,第一个是想要删除的元素的下标(必选),第二个是想要删除的个数(必选),第三个是删除 后想要在原位置替换的值 |
sort() |
sort() 使数组按照字符编码默认从小到大排序,成功返回排序后的数组 |
reverse() |
reverse() 将数组倒序,成功返回倒序后的数组 |
替换数组
filter | filter() 方法创建一个新的数组,新数组中的元素是通过检查指定数组中符合条件的所有元素。 |
---|---|
concat | concat() 方法用于连接两个或多个数组。该方法不会改变现有的数组 |
slice | slice() 方法可从已有的数组中返回选定的元素。该方法并不会修改数组,而是返回一个子数组 |
动态数组响应式数据
// Vue.set(vm.list, 2, 'lemon');
vm.$set(vm.list, 1, 'lemon');
// vm.info.gender = 'male';
vm.$set(vm.info, 'gender', 'female');
组件注册
1.全局注册
//注册组件
//如果使用驼峰式命名组件,那么在使用组件的时候,只能在字符串模板中用驼峰的方式使用组件,但是
//在普通的标签模板中, 必须使用短横线的方式使用组件
Vue.component('button-counter', {
//data必须是一个函数
data() {
return {
count: 0
}
},
//组件模板内容必须是单个跟元素
template: `
`,
methods: {
handle: function() {
this.count += 2
}
}
})
2.局部注册
var vm = new Vue({
el: '#app',
data: {
},
//局部组件,局部组件只能在注册他的父组件中使用
components: {
'hello-world': {
data: function() {
return {
msg: 'HelloWorld'
}
},
template: '{{msg}}'
};
}
});
组件传值
<div id="app">
<div :style='{fontSize: fontSize + "px"}'>{{pmsg}}div>
<menu-item :title='dome' content='hellow' @enlarge-text='handle($event)'>menu-item>
div>
<script type="text/javascript" src="js/vue.js">script>
<script type="text/javascript">
Vue.component('menu-item', {
//props接收传递过来的值
props: ['title', 'content'],
data() {
return {
msg: '子组件'
}
},
template: `
{{msg+'----'+title+'----'+content}}
`
})
var vm = new Vue({
el: '#app',
data: {
pmsg: '父组件',
dome: '父组件传值',
fontSize: 10
},
methods: {
handle: function(val) {
// 扩大字体大小
this.fontSize += val;
}
}
});
script>
数据交互
<div id="app">
<div>父组件div>
<div>
<button @click='handle'>销毁事件button>
div>
<test-tom>test-tom>
<test-jerry>test-jerry>
div>
<script type="text/javascript" src="js/vue.js">script>
<script type="text/javascript">
//提供事件中心
var hub = new Vue()
Vue.component('test-tom', {
data() {
return {
num: 0
}
},
template: `
TOM:{{num}}
点击
`,
methods: {
handle: function() {
//触发兄弟组件的事件
hub.$emit('jerry-event', 2)
}
},
mounted: function() {
// 监听事件
hub.$on('tom-event', (val) => {
this.num += val;
});
}
})
Vue.component('test-jerry', {
data() {
return {
num: 0
}
},
template: `
JERRY:{{num}}
点击
`,
methods: {
handle: function() {
//触发兄弟组件的事件
hub.$emit('tom-event', 1)
}
},
mounted() {
//监听事件
hub.$on('jerry-event', (val) => {
this.num += val;
});
}
})
var vm = new Vue({
el: '#app',
data: {
},
methods: {
handle: function() {
//销毁事件
hub.$off('tom-event')
hub.$off('jerry-event')
}
}
});
script>
插槽
<div id="app">
<div>
<alert-box>bugalert-box>
<alert-box>abcalert-box>
<alert-box>alert-box>
<base-layout>
<p slot='header'>标题信息p>
<template slot='header'>
<p>标题信息1p>
template>
<p>主要内容1p>
<template slot='footer'>
<p>底部信息信息1p>
template>
base-layout>
div>
div>
<script type="text/javascript" src="js/vue.js">script>
<script type="text/javascript">
Vue.component('alert-box', {
//通过slot设置插槽
template: `
ERROR:
默认内容
`
})
//具名插槽
Vue.component('base-layout', {
template: `
`
});
var vm = new Vue({
el: '#app',
data: {
},
methods: {
}
});
script>
作用域插槽
<div id="app">
<fruit-list :list='list'>
<template slot-scope='slotProps'>
<strong v-if='slotProps.info.id==2' class="current">{{slotProps.info.name}}strong>
<span v-else >{{slotProps.info.name}}span>
template>
fruit-list>
div>
<script type="text/javascript" src="js/vue.js">script>
<script type="text/javascript">
Vue.component('fruit-list', {
props: ['list'],
template: `
{{item.name}}
`
})
var vm = new Vue({
el: '#app',
data: {
list: [{
id: 1,
name: 'apple'
}, {
id: 2,
name: 'orange'
}, {
id: 3,
name: 'banana'
}]
},
methods: {
}
});
script>
Promise
<script type="text/javascript">
/*
1. Promise基本使用
我们使用new来构建一个Promise Promise的构造函数接收一个参数,是函数,并且传入两个参数: resolve,reject, 分别表示异步操作执行成功后的回调函数和异步操作执行失败后的回调函数
*/
var p = new Promise(function(resolve, reject){
//2. 这里用于实现异步任务 setTimeout
setTimeout(function(){
var flag = false;
if(flag) {
//3. 正常情况
resolve('hello');
}else{
//4. 异常情况
reject('出错了');
}
}, 100);
});
// 5 Promise实例生成以后,可以用then方法指定resolved状态和reject状态的回调函数
// 在then方法中,你也可以直接return数据而不是Promise对象,在后面的then中就可以接收到数据了
p.then(function(data){
console.log(data)
},function(info){
console.log(info)
});
script>
基于Promise发送Ajax请求
<script type="text/javascript">
/*
基于Promise发送Ajax请求
*/
function queryData(url) {
# 1.1 创建一个Promise实例
var p = new Promise(function(resolve, reject){
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function(){
if(xhr.readyState != 4) return;
if(xhr.readyState == 4 && xhr.status == 200) {
# 1.2 处理正常的情况
resolve(xhr.responseText);
}else{
# 1.3 处理异常情况
reject('服务器错误');
}
};
xhr.open('get', url);
xhr.send(null);
});
return p;
}
# 注意: 这里需要开启一个服务
# 在then方法中,你也可以直接return数据而不是Promise对象,在后面的then中就可以接收到数据了
queryData('http://localhost:3000/data')
.then(function(data){
console.log(data)
# 1.4 想要继续链式编程下去 需要 return
return queryData('http://localhost:3000/data1');
})
.then(function(data){
console.log(data);
return queryData('http://localhost:3000/data2');
})
.then(function(data){
console.log(data)
});
script>
Promise 基本AP
.then()
.catch()
.finally()
<script type="text/javascript">
function foo() {
return new Promise(function(resolve, reject) {
setTimeout(function() {
// resolve(123);
reject('error');
}, 100);
})
}
// foo()
// .then(function(data){
// console.log(data)
// })
// .catch(function(data){
// console.log(data)
// })
// .finally(function(){
// console.log('finished')
// });
// --------------------------
// 两种写法是等效的
foo()
.then(function(data) {
console.log(data)
}, function(data) {
console.log(data)
})
//.finally()成功与否都会执行(尚且不是正式标准)
.finally(function() {
console.log('finished')
});
script>
Promise 静态方法
//Promise.all()并发处理多个异步任务,所有任务都执行完成才能得到结果
Promise.all([p1, p2, p3]).then(function(result) {
console.log(result)
})
//Promise.race()并发处理多个异步任务,只要有一个任务完成就能得到结果
Promise.race([p1, p2, p3]).then(function(result) {
console.log(result)
})
fetch
fetch('http://localhost:3000/books', {
method: 'post',
body: JSON.stringify({
uname: '张三',
pwd: '456'
}),
headers: {
'Content-Type': 'application/json'
}
})
.then(function(data) {
//text()方法属于fetchAPI的一部分,它返回一个Promise实例对象,用于获取后台返回的数据
return data.text()
})
.then(function(data) {
console.log(data);
})
fetchAPI 中 响应格式
JSON
,BLOB
或者TEXT
等等 /*
Fetch响应结果的数据格式
*/
fetch('http://localhost:3000/json').then(function(data){
// return data.json(); // 将获取到的数据使用 json 转换对象
return data.text(); // // 将获取到的数据 转换成字符串
}).then(function(data){
// console.log(data.uname)
// console.log(typeof data)
var obj = JSON.parse(data);
console.log(obj.uname,obj.age,obj.gender)
})
axios
// axios put 请求传参
axios.put('http://localhost:3000/axios/123', {
uname: 'lisi',
pwd: 123
}).then(function(ret) {
console.log(ret.data)
})
axios 全局配置
// 配置请求的基准URL地址
axios.defaults.baseURL = 'http://localhost:3000/';
// 配置请求头信息
axios.defaults.headers['mytoken'] = 'hello';
axios.get('axios-json').then(ret => {
console.log(ret.data.uname)
})
axios 拦截器
//请求拦截器
axios.interceptors.request.use(function(config) {
console.log(config.url)
config.headers.mytoken = 'nihao';
return config;
}, function(err) {
console.log(err)
})
//响应拦截器
axios.interceptors.response.use(function(res) {
// console.log(res)
var data = res.data;
return data;
}, function(err) {
console.log(err)
})
async 和 await
async
函数都会隐式返回一个promise
await
关键字只能在使用async
定义的函数中使用
# 1. async 基础用法
# 1.1 async作为一个关键字放到函数前面
async function queryData() {
# 1.2 await关键字只能在使用async定义的函数中使用 await后面可以直接跟一个 Promise实例对象
var ret = await new Promise(function(resolve, reject){
setTimeout(function(){
resolve('nihao')
},1000);
})
// console.log(ret.data)
return ret;
}
# 1.3 任何一个async函数都会隐式返回一个promise 我们可以使用then 进行链式编程
queryData().then(function(data){
console.log(data)
})
#2. async 函数处理多个异步函数
axios.defaults.baseURL = 'http://localhost:3000';
async function queryData() {
# 2.1 添加await之后 当前的await 返回结果之后才会执行后面的代码
var info = await axios.get('async1');
#2.2 让异步代码看起来、表现起来更像同步代码
var ret = await axios.get('async2?info=' + info.data);
return ret.data;
}
queryData().then(function(data){
console.log(data)
})
**v-router ** --包含嵌套路由
1.引入相关的库文件
2.添加路由链接
3.添加路由占位符(填充位)
4.创建路由组件
5.配置路由规则并创建路由实例
6.挂载路由实例对象
<script src="./lib/vue_2.5.22.js">script>
<script src="./lib/vue-router_3.0.2.js">script>
<div id="app">
<router-link to="/user">Userrouter-link>
<router-link to="/register">Registerrouter-link>
<router-view>router-view>
div>
<script>
// 4.创建路由组件
const User = {
template: 'User 组件
'
}
//嵌套路由模板
const Register = {
template: `
Register 组件
tab1
tab2
`
}
const Tab1 = {
template: 'tab1 子组件
'
}
const Tab2 = {
template: 'tab2 子组件
'
}
// 5.配置路由规则并创建路由实例
const router = new VueRouter({
// routes 是路由规则数组
routes: [{
//每个路由规则都是一个配置对象,其中至少包含 path 和 component 两个属性
path: '/user',
component: User
}, {
path: '/register',
component: Register,
//嵌套路由--通过chrldren 属性,为 /register 添加子路由规则
children: [{
path: '/register/tab1',
component: Tab1
}, {
path: '/register/tab2',
component: Tab2
}]
}, {
//redirect 表示将要被重定向的新地址
path: '/',
redirect: '/user'
}]
})
const vm = new new Vue({
el: '#app',
data: {},
// 6.挂载路由实例对象
// router: router
router
})
script>
动态路由
<router-link to="/user/1">User1</router-link>
const User = {
props: ['id', 'uname', 'age'], //使用proos接收路由参数
template: ' 用户id为:{{id}}--姓名为:{{uname}}--年龄为:{{age}}'
}
// 创建路由实例对象
const router = new VueRouter({
// 所有的路由规则
routes: [{
path: '/',
redirect: '/user/1'
}, {
path: '/user/:id',
component: User,
//如果 props 被设置为true, route.params 将会被设置为组件属性
// props: true
// props: { uname: 'lisi',age: 20}
//如果要传递id值 props的值应为函数类型
props: route => ({
uname: 'lisi',
age: 20,
id: route.params.id
})
}]
})
命名路由
在配置路由规则并创建路由实例时,添加 name 属性来进行命名
<!-- 使用命名路由 -->
<router-link :to="{ name: 'user', params: {id: 3} }">User3</router-link>
// 创建路由实例对象
const router = new VueRouter({
// 所有的路由规则
routes: [{
// 命名路由
name: 'user',
path: '/user/:id',
component: User,
props: route => ({
uname: 'zs',
age: 20,
id: route.params.id
})
}]
})
编程式导航
//跳转
this.$router.push('/register')
//后退
this.$router.go(-1)
webpack
1.基本使用步骤
①新建项目空白目录,并运行npm init -y
命令,初始化包管理配置文件package.json
②新建 src 源代码目录
③新建 src-> index.html 首页
④初始化首页基本的结构
⑤运行 npminstall jquery -S
命令,安装jQuery
2.在项目中安装和配置webpack
①运行 npminstall webpack webpack-cli -D
命令,安装webpack 相关的包
②在项目根目录中,创建名为webpack.config.js 的 webpack 配置文件
③在 webpack 的配置文件中,初始化如下基本配置:
module.exports = {
//编译模式
mode: 'development' //两种模式 development production
}
④ 在 package.json 配置文件中的scripts节点下,新增dev脚本如下:
"scripts": {
"dev": "webpack" // script 节点下的脚本,可以通过 npm run 名字 执行
}
⑤ 在终端中运行npm run dev
命令,启动webpack 进行项目打包。
打包的入口文件为 src -> index.js
打包的输出文件为 dist-> main.js
3.配置打包的入口与出口
如果要修改打包的入口与出口,可以在 webpack.config.js 中新增如下配置信息:
const path = require('path')
module.exports = {
entry: path.join(__dirname, './src/index.js'), //打包入口文件的路径
output: {
path: path.join(__dirname, './dist'), // 输出文件的存放路径
filename: 'bundle.js' // 输出文件的名称
}
}
4.配置 webpack 的自动打包功能
1.运行 npm install webpack-dev-server -D
命令,安装支持项目自动打包的工具
2.修改 package.json -> scripts 中的 dev 命令如下:
"scripts": {
"dev": "webpack-dev-server" // script 节点下的脚本,可以通过 npm run 名字 执行
}
3.将 src -> index.html 中, script 脚本的引用路径, 修改为 “/buldle.js”
4.运行 npm run dev
命令, 重新进行打包
5.在浏览器中访问 http://localhost:8080 地址, 查看自动打包效果
注意:
webpack-dev-server会启动一个实时打包的http服务器
webpack-dev-server打包生成的输出文件,默认放到了项目根目录中,而且是虚拟的、看不见的
5.配置 html-webpack-plugin 生成预览页面
1.运行 npm install html-webpack-plugin -D
命令, 安装生成预览页面的插件
2.修改 webpack.config.js 文件头部区域, 添加如下配置信息:
//导入生成预览页面的插件,得到一个构造函数
const HtmlWebpackPlugin = require('html-webpack-plugin')
const htmlPlguin = new HtmlWebpackPlugin({ //创建插件的实例对象
template: './src/index.html', //指定要用到的模板文件
filename: 'index.html' //指定生成的文件的名称,该文件存在于内存中,在目录中不显示
})
3.修改 webpack.config.js 文件向外暴露的配置对象, 新增如下配置节点:
module.exports = {
plugins: [htmlPlguin], //plugins数组是 webpack 打包期间会用到的一些插件列表
}
6.配置自动打包相关参数
//package.json中的配置
// --open 打包完成后自动打开浏览器
// -- host 配置IP地址
// --port 配置端口
"scripts": {
"dev": "webpack-dev-server --open --host 127.0.0.1 --port 8888" // script 节点下的脚本,可以通过 npm run 名字 执行
}
webpack加载器 --通过loader打包非js模块
1.打包处理css文件
1.运行 npm install style-loader css-loader -D
安装处理css文件的loader
2.在 webpack.config.js 的module -> rules 数组中, 添加 loader 规则如下:
module: {
rules: [
//test 表示匹配的文件类型, use 表示对应要调用的loader,并且use数组中loader顺序是固定的
{ test: /\.css$/, use: ['style-loader', 'css-loader'} ]
}
2.打包处理less文件
1.运行 npm install less-loader less -D
2.在 webpack.config.js 的module -> rules 数组中, 添加 loader 规则如下:
module: {
rules: [
//test 表示匹配的文件类型, use 表示对应要调用的loader,并且use数组中loader顺序是固定的
{ test: /\.less$/, use: ['style-loader', 'css-loader', 'less-loader'] } ]
}
3.打包处理scss文件
1.运行 npm install sass-loader node-sass -D
2.在 webpack.config.js 的module -> rules 数组中, 添加 loader 规则如下:
module: {
rules: [
//test 表示匹配的文件类型, use 表示对应要调用的loader,并且use数组中loader顺序是固定的
{ test: /\.scss$/, use: ['style-loader', 'css-loader', 'sass-loader'] } ]
}
4.配置postCss自动添加css的兼容前缀
1.运行 npm install postcss-loader autoprefixer -D
2.在项目根目录中创建 postcss 的配置文件, postcss.config.js, 并初始化如下配置:
const autoprefixer = require('autoprefixer')
module.exports = {
plugins: [autoprefixer] //挂载插件
}
3.在 webpack.config.js 的module -> rules 数组中, 修改css的 loader 规则如下:
module: {
rules: [
//test 表示匹配的文件类型, use 表示对应要调用的loader,并且use数组中loader顺序是固定的
{ test: /\.css$/, use: ['style-loader', 'css-loader', 'postcss-loader'] } ]
}
5.打包样式表中的图片和字体文件
1.运行 npm install url-loader file-loader -D
2.在 webpack.config.js 的module -> rules 数组中, 添加 loader 规则如下:
module: {
rules: [
//test 表示匹配的文件类型, use 表示对应要调用的loader,并且use数组中loader顺序是固定的
{ test: /\.jpg|png|gif|bmp|ttf|eot|svg|woff|woff2$/, use: 'url-loader?limit=16941' } ]
}
其中 ? 之后的是 loader的参数项
limit用来指定图片的大小,单位是字节(byte),只有小于 limit大小的图片,才会被转为base64图片
6.打包处理js文件中的高级语法
1.安装babel转换器相关的包: npm install babel-loader @babel/core @babel/runtime -D
2.安装babel语法插件相关的包: npm install @babel/preset-env @babel/plugin-transform-runtime @babel/plugin-proposal-class-properties -D
3.在项目根目录中, 创建 babel 配置文件 babel.config.js 并初始化基本配置如下:
module.exports = {
presets: ['@babel/preset-env'],
plugins: ['@babel/plugin-transform-runtime', '@babel/plugin-proposal-class-properties']
}
4.在 webpack.config.js 的module -> rules 数组中, 添加 loader 规则如下:
module: {
rules: [
//exclude为排除项,表示 babel-loader 不需要处理的js文件
{ test: /\.js$/, use: 'babel-loader', exclude: /node_modules/ } ]
}
7.配置vue组件加载器
1.运行 npm install vue-loader vue-template-compiler -D
2.在 webpack.config.js 的module -> rules 数组中, 添加 vue-loader 的配置如下:
const VueLoaderPlugin = require('vue-loader/lib/plugin')
module.exports = {
//plugins数组是 webpack 打包期间会用到的一些插件列表
plugins: [htmlPlguin, new VueLoaderPlugin()],
module: {
rules: [
//test 表示匹配的文件类型, use 表示对应要调用的loader,并且use数组中loader顺序是固定的
{ test: /\.vue$/, use: 'vue-loader' }
]
}
}
8.在webpack项目中使用vue
1.运行 npm install vue -S
安装vue
2.在 src -> index.js 入口文件中, 通过 import Vue from ‘vue’ 来导入 vue 构造函数
3.创建 vue 的实例对象, 并指定要控制的 el 区域
4.通过 render 函数渲染App 根组件
// 1.导入 Vue 构造函数
import Vue from 'vue'
// 2.导入单App根组件
import App from './components/App.vue'
const vm = new Vue({
// 3.指定 vm 实例要控制的页面区域
el: '#app',
// 4.通过 render 函数, 把指定的组件渲染到 el 区域中
render: h => h(App)
})
9.webpack 打包发布
上线之前需要通过webpack将应用进行整体打包,可以通过 package.json 文件配置打包命令:
//在package.json文件中配置 webpack 打包命令
//该命令默认加载项目根目录中的 webpack.config.js 配置文件
"scripts": {
//用于开发调试的命令
"dev": "webpack-dev-server --open --host 127.0.0.1 --port 8888",
//用于打包的命令
"build": "webpack -p"
}
Vue 脚手架用于快速生成 Vue 项目基础架构,其官网地址为:https://cli.vuejs.org/zh/
安装3.x版本的Vue脚手架: npm install -g @vue/cli
基于3.x版本的脚手架创建vue项目
//1.基于 交互命令行 的方式,创建新版vue项目
vue create 项目名(自定义)
//2.基于 图形化界面 的方式,创建新版vue项目
vue ui
//3.基于 2.x 的旧模板,创建旧版vue项目
npm install -g @vue/cli-init
vue init webpack my-project
Vue脚手架自定义配置
1.在项目的根目录创建文件 vue.config.js
2.在该文件中进行相关配置,从而覆盖默认配置
//vue.config.js
module.exports = {
devServer: {
// 自动打开浏览器
open: true,
//配置默认端口号
port: 8878
}
}
Element-UI
官网为: https://element.eleme.cn/#/zh-CN --桌面端组件库
1.基于命令行方式手动安装
1.安装依赖包 npm install element-ui -S
2.导入 Element-UI 相关资源
//手动配置 element-ui
//导入组件库
import ElementUI from 'element-ui'
//导入组件相关样式
import 'element-ui/lib/theme-chalk/index.css'
//配置 Vue 插件
Vue.use(ElementUI)
2.基于图形化界面自动安装
1.运行 vue ui
打开图形化界面
2.通过Vue项目管理器,进入具体的项目配置面板
3.点击 插件 -> 添加插件,进入插件查询面板
4.搜索 vue-cli-plugin-element 并安装
5.配置插件,实现按需导入,从而减少打包后项目的体积
树形表格插件 --vue-table-with-tree-grid
//在main.js中
import TreeTable from 'vue-table-with-tree-grid'
Vue.component('tree-table', TreeTable)
富文本编辑器插件 --vue-quill-editor
//在main.js中
//导入富文本编辑器
import VueQuillEditor from 'vue-quill-editor'
//导入富文本编辑器对应的样式
import 'quill/dist/quill.core.css'
import 'quill/dist/quill.snow.css'
import 'quill/dist/quill.bubble.css'
//将富文本编辑器注册为全局可用组件
Vue.use(VueQuillEditor)
统计图插件 --echarts
//1.导入 echarts
import echarts from 'echarts'
<!-- 2.为ECharts准备一个具备大小(宽高)的Dom -->
<div id="main" style="width: 700px;height:400px;"></div>
// 3.基于准备好的dom,初始化echarts实例
var myChart = echarts.init(document.getElementById('main'));
// 4.指定图表的配置项和数据
const result = _.merge(res.data, this.options)
//5.展示数据
myChart.setOption(result)
深拷贝插件 --lodash
import _ from 'lodash'
_.merge(res.data, this.options)
进度条插件 --nprogerss
//在main.js中
//导入进度条对应的js和css
import NProgress from 'nprogress'
import 'nprogress/nprogress.css'
//在request拦截器中,展示进度条 NProgress.start()
axios.interceptors.request.use(config => {
NProgress.start()
config.headers.Authorization = window.sessionStorage.getItem('token')
// 在最后必须 return config
return config
})
//在response拦截器中,隐藏进度条 NProgress.done()
axios.interceptors.response.use(config => {
NProgress.done()
return config
})
去除console插件 --balel-plugin-transform-remove-console
//在babel.config.js文件里的中
//这是项目发布阶段需要用到的babel插件
const prodPlugins = []
if (process.NODE_ENV === 'production') {
prodPlugins.push('transform-remove-console')
}
//"plugins"数组中,插入
...prodPlugins
修改webpack的默认配置
默认情况下,vue-cli 3.0生成的项目,隐藏了webpack配置项,如果我们需要配置webpack
需要通过vue.config.js来配置。
在项目根目录中创建vue.config.js文件,
module.exports = {
chainWebpack:config=>{
//发布模式
config.when(process.env.NODE_ENV === 'production',config=>{
//entry找到默认的打包入口,调用clear则是删除默认的打包入口
//add添加新的打包入口
config.entry('app').clear().add('./src/main-prod.js')
})
//开发模式
config.when(process.env.NODE_ENV === 'development',config=>{
config.entry('app').clear().add('./src/main-dev.js')
})
}
}
补充:
chainWebpack可以通过链式编程的形式,修改webpack配置
configureWebpack可以通过操作对象的形式,修改webpack配置
通过externals加载外部CND资源
//在vue.config.js文件中,放在chainWebpack开发者模式中
config.set('externals', {
vue: 'Vue',
'vue-router': 'VueRouter',
axios: 'axios',
lodash: '_',
echarts: 'echarts',
nprogress: 'NProgress',
'vue-quill-editor': 'VueQuillEditor'
})
})
//然后在index.html的头部区域中,通过CDN加载js和css样式
<% if(htmlWebpackPlugin.options.isProd){ %>
<link rel="stylesheet" href="https://cdn.staticfile.org/nprogress/0.2.0/nprogress.min.css" />
<link rel="stylesheet" href="https://cdn.staticfile.org/quill/1.3.4/quill.core.min.css" />
<link rel="stylesheet" href="https://cdn.staticfile.org/quill/1.3.4/quill.snow.min.css" />
<link rel="stylesheet" href="https://cdn.staticfile.org/quill/1.3.4/quill.bubble.min.css" />
<script src="https://cdn.staticfile.org/vue/2.5.22/vue.min.js">script>
<script src="https://cdn.staticfile.org/vue-router/3.0.1/vue-router.min.js">script>
<script src="https://cdn.staticfile.org/axios/0.18.0/axios.min.js">script>
<script src="https://cdn.staticfile.org/lodash.js/4.17.11/lodash.min.js">script>
<script src="https://cdn.staticfile.org/echarts/4.1.0/echarts.min.js">script>
<script src="https://cdn.staticfile.org/nprogress/0.2.0/nprogress.min.js">script>
<script src="https://cdn.staticfile.org/quill/1.3.4/quill.min.js">script>
<script src="https://cdn.jsdelivr.net/npm/vue-quill-editor@3.0.4/dist/vue-quill-editor.js">script>
<% } %>
通过CDN优化ElementUI的打包
1.在main-prod.js中,注释掉element-ui按需加载的代码
2.在index.html的头部区域中,通过CDN加载element-ui的js和css样式
<link rel="stylesheet" href="https://cdn.staticfile.org/element-ui/2.8.2/theme-chalk/index.css" />
<script src="https://cdn.staticfile.org/element-ui/2.8.2/index.js">script>
路由懒加载
1.安装 @babel/plugin-syntax-dynamic-import
2.在babel.config.js配置文件中声明该插件
//在"plugins"数组中
'@babel/plugin-syntax-dynamic-import'
3.将路由改为按需加载的形式
//注:webpackChunkName后面为分组名字,最后面是该组件路径
// import Cate from './components/goods/Cate.vue'
const Cate = () => import(/* webpackChunkName: "Cate_Params" */ './components/goods/Cate.vue')
// import Params from './components/goods/Params.vue'
const Params = () => import(/* webpackChunkName: "Cate_Params" */ './components/goods/Params.vue')
项目上线配置
1.创建一个新文件夹 运行 npm init -y
初始化
2.运行 npm install express
3.把build的dist文件夹复制到该文件夹内
4.创建app.js入口文件, 配置如下: 然后用node服务器运行该入口文件
const express = require('express')
const app = express()
app.use(express.static('./dist'))
app.listen(80, () => {
console.log('server running at http://127.0.0.1');
})
5.开启gzip配置运行 npm install compression -D
//在app.js中
//网络传输压缩
const compression = require('compression')
//这行代码一定要写到静态资源托管之前
app.use(compression())
6.使用pm2管理应用,安装 npm install pm2 -g
使用pm2启动项目,在终端中输入命令:pm2 start app.js --name 自定义名称
查看项目列表命令:pm2 ls
重启项目:pm2 restart 自定义名称
停止项目:pm2 stop 自定义名称
删除项目:pm2 delete 自定义名称
Vuex是实现组件全局状态(数据)管理的一种机制,可以方便的实现组件之间的数据共享
使用Vuex管理数据的好处:
A.能够在vuex中集中管理共享的数据,便于开发和后期进行维护
B.能够高效的实现组件之间的数据共享,提高开发效率
C.存储在vuex中的数据是响应式的,当数据发生改变时,页面中的数据也会同步更新
Vuex是实现组件全局状态(数据)管理的一种机制,可以方便的实现组件之间的数据共享
使用Vuex管理数据的好处:
A.能够在vuex中集中管理共享的数据,便于开发和后期进行维护
B.能够高效的实现组件之间的数据共享,提高开发效率
C.存储在vuex中的数据是响应式的,当数据发生改变时,页面中的数据也会同步更新
Vuex基本使用
1.安装 npm install vuex --save
2.导入vuex包
//在store文件夹或者store.js中
import Vuex from 'vuex'
Vue.use(Vuex)
3.创建store对象
//在store文件夹或者store.js中
const store = new Vuex.Store({
//state 中存放的就是全局共享的数据
state: { count:0 }
})
4.将store对象挂载到vue实例中
new Vue({
el:'#app',
render:h => h(app),
router,
//将创建的共享数据对象,挂载到Vue实例中
//所有的组件,就可以直接从store 中获取全局的数据了
store
})
组件访问State数据
State提供唯一的公共数据源,所有共享的数据都要统一放到Store中的State中存储
方法一: this.$store.state.数据名
--在< template >中可省略 this.
方法二:
<h3>当前最新的count值为:{{count}}</h3>
<script>
import { mapState } from 'vuex'
export default {
computed: {
...mapState(['count'])
}
}
</script>
Mutation
Mutation用于修改变更$store中的数据,并且只能通过mutation变更Store数据,不可以直接操作Store中的数据
使用方法一:
//在store.js
mutations: {
add(state,step){
//第一个形参永远都是state也就是$state对象
//第二个形参是调用add时传递的参数
state.count+=step;
}
}
//在调用的文件中
methods:{
Add(){
//使用commit函数调用mutations中的对应函数,
//第一个参数就是我们要调用的mutations中的函数名
//第二个参数就是传递给add函数的参数
this.$store.commit('add',10)
}
}
使用方法二:
<button @click='sub(10)'>-1</button>
<script>
import { mapState, mapMutations } from 'vuex'
export default {
computed: {
...mapState(['count'])
},
methods: {
//获得mapMutations映射的sub函数
...mapMutations(['sub'])
}
}
</script>
Action
在mutations中不能编写异步的代码,会导致vue调试器的显示出错。
在vuex中我们可以使用Action来执行异步操作。
方法一:
//在store.js中
mutations: {
jia (state) {
//变更状态
state.count += 1
}
},
actions: {
//来执行异步操作,不能直接修改state中的数据
addAsync (context) {//若传递有参数 (context, nn)
setTimeout(() => {
context.commit('jia')
}, 1000)
}
//在要使用的文件的methods方法中定义,然后调用dome1函数即可
dome1() {
this.$store.dispatch('addAsync')//若传递有参数 ('addAsync',5)
}
方法二:
//在store.js中同上
<button @click='调用的函数名'>-1</button>
//在要使用的文件的methods方法中
import {mapActions} from 'vuex'
methods:{
...mapActions(['调用的函数名'])
}
Getter
Getter用于对Store中的数据进行加工处理形成新的数据
它只会包装Store中保存的数据,并不会修改Store中保存的数据,当Store中的数据发生变化时,Getter生成的内容也会随之变化
使用方法一: this.$store.getters.名称
使用方法二:
import { mapGetters } from 'vuex'
computed:{
...mapGetters(['调用名称'])
}
下载微信开发者工具 https://developers.weixin.qq.com/miniprogram/dev/devtools/download.html
text文本
属性名 | 类型 | 默认值 | 说明 |
---|---|---|---|
selectable | Boolean | false | 文本是否可选,除了text组件外,其他组件都无法长按选中 |
space | String | false | 显示连续空格,可选值:ensp、emsp、nbsp |
decode | Boolean | false | 是否解码,可解析: 、<、>、&、&apos、&ensp、&emsp |
view视图容器
属性名 | 类型 | 默认值 | 说明 |
---|---|---|---|
hover-class | String | none | 指定按下去的样式类,当值为none时,没有点击效果 |
hover-stop-propagation | Boolean | false | 指定是否阻止本节点的父节点出现点击态 |
hover-start-time | Number | 50 | 按住后多久出现点击状态,单位毫秒 |
hover-stay-time | Number | 40 | 手指松开后点击态保留时间,单位毫秒 |
button按钮
属性名 | 类型 | 默认值 | 说明 |
---|---|---|---|
size | String | default | 按钮大小 |
type | String | default | 按钮的样式类型: primary, warn |
plain | Boolean | false | 按钮是否镂空,背景透明色 |
disabled | Boolean | false | 是否禁用 |
loading | Boolean | false | 名称前是否带loading图标 |
input输入框
属性名 | 类型 | 默认值 | 说明 |
---|---|---|---|
value | String | 输入框的初始内容 | |
type | String | ‘text’ | input的类型:text,number,idcard(身份证),digit(带小数点的数字) |
password | Boolean | false | 是否是密码类型 |
placeholder | String | 输入框为空时的占位符 | |
disabled | Boolean | false | 是否禁用 |
maxlength | Number | 140 | 最大输入长度,值为-1时不限制最大长度 |
image图片
1.scr:支持本地和网络上的图片
2.mode:指定图片裁剪、缩放的模式,image组件默认宽300px、高225px
WXSS
WXSS(WeiXin Style Sheets)是一套样式语言,用来决定 WXML 的组件应该怎么显示
rpx
rpx(responsive pixel):是微信小程序独有的、解决屏幕自适应的尺寸单位
1.可以根据屏幕宽度进行自适应。不论大小屏幕,规定屏幕宽为750rpx。
2.通过rpx设置元素和字体的大小,小程序在不同尺寸的屏幕上,可以实现自动适配
@import 样式导入
使用@import 可以导入外联样式表
语法: @import ‘wxss样式表的相对路径’;
app.json配置文件的作用
小程序根目录下的 app.json 文件用来对微信小程序进行全局配置,它决定了页面文件的路径、窗口表现、设置网络超时时间、设置多 tab 等
page 数组:配置小程序的页面路径
window 对象:用于设置小程序的状态栏、导航条、标题、窗口背景颜色
tabBar 对象:配置小程序的tab栏效果,只能配置最少2个,最多5个tab标签,当渲染顶部tabBar时,不显示icon,只显示文本
window节点常用的配置项
属性名 | 类型 | 默认值 | 说明 |
---|---|---|---|
navigationBarTitleTex | String | 字符串 | 导航栏标题文字内容 |
navigationBarBackgroundColo | HexColor | #000000 | 导航栏背景颜色,只接收16进制 |
navigationBarTextStyle | String | white | 导航栏标题颜色,仅支持black/white |
backgroundColor | HexColor | #ffffff | 下拉时窗口的背景颜色,只接收16进制 |
backgroundTextStyle | String | dark | 下拉loading的样式,仅支持dark/light |
enablePullDownRefresh | Boolean | false | 是否全局开启下拉刷新 |
onReachBottomDistance | Number | 50 | 页面上拉触底时间触发时距页面底部距离,单位px |
tabBar 的组成部分
background:导航条背景色
selectedlconPath:选中时的图片路径
borderStyle:tabBar上边框的颜色
iconPath:未选中时的图片
属性 | 类型 | 必填 | 默认值 | 描述 |
---|---|---|---|---|
color | HexColor | 否 | tab上的文字默认颜色 | |
selectedColor | HexColor | 否 | tab上的文字选中时的颜色 | |
backgroundColor | HexColor | 否 | tab的背景 | |
borderStyle | String | 否 | black | tabBar上边框的颜色 |
list | Array | 是 | tab的列表,最少2个、最多5个 | |
position | Array | 否 | bottom | babBar的位置,仅支持bottom/top |
list的配置项如下:
属性 | 类型 | 必填 | 描述 |
---|---|---|---|
pagePath | String | 是 | 页面路径,必须在 pages 中先定义 |
text | String | 是 | tab 上按钮文字 |
iconPath | String | 否 | 图片路径,icon 大小限制为 40kb,建议尺寸为 81px * 81px,不支持网络图片。当 position 为 top 时,不显示 icon |
selectedIconPath | String | 否 | 选中时的图片路径,icon 大小限制为 40kb,建议尺寸为 81px * 81px,不支持网络图片。当 position 为 top 时,不显示 icon |
page.json配置列表
属性 | 类型 | 默认值 | 描述 |
---|---|---|---|
navigationBarBackgroundColor | HexColor | #000000 | 导航栏背景颜色,如 #000000 |
navigationBarTextStyle | String | white | 导航栏标题颜色,仅支持 black / white |
navigationBarTitleText | String | 导航栏标题文字内 | |
backgroundColor | HexColor | 窗口的背景色 | |
backgroundTextStyle | String | #ffffff | 下拉 loading 的样式,仅支持 dark / light |
enablePullDownRefresh | Boolean | false | 是否开启当前页面下拉刷新 |
onReachBottomDistance | Number | 50 | 页面上拉触底事件触发时距页面底部距离,单位为px |
disableScroll | Boolean | false | 设置为 true 则页面整体不能上下滚动。只在页面配置中有效,无法在 app.json 中设置 |
生命周期
1.应用生命周期:特指小程序从启动 -> 运行 -> 销毁的过程
2.页面生命周期:特指小程序中,每个页面的加载 -> 渲染 -> 销毁的过程
其中,页面的生命周期范围较小,应用程序的生命周期范围较大
应用生命周期函数
app.js是小程序执行的入口文件,在app.js中必须调用App()函数,且只能调用一次。其中,App()函数是用来注册并执行小程序的。
App(Object)函数接收一个Object参数,可以通过这个Object参数,指定小程序的生命周期函数。
例如:
App({
// 小程序初始化完成时,执行此函数,可以做一些初始化的工作。
onLaunch: function(options) {},
// 小程序显示到屏幕上的时候,执行此函数。
onShow : function(options) {},
// 小程序被最小化的时候,执行此函数。
onHide : function() {}
})
页面生命周期函数
每个小程序页面,必须拥有自己的.js文件,且必须调用 Page() 函数,否则报错。其中Page()函数用来注册小程序页面。
Page(Object) 函数接收一个Object参数,可以通过这个Object参数,指定页面的生命周期函数。
例如:
Page({
onLoad : function(options) {}, // 监听页面加载
onShow : function() {}, // 监听页面显示
onReady : function() {}, // 监听页面初次渲染完成
onHide : function() {}, // 监听页面隐藏
onUnload: function() {} // 监听页面卸载
})
数据绑定
小程序中每个页面,由4部分组成,其中 .js 文件内可以定义页面的数据、生命周期函数、其它业务逻辑;
如果要在.js文件内定义页面的数据,只需把数据定义到 data 节点下即可;
示例代码如下:
Page({
data: {
info: 'init data', // 字符串类型的数据
array: [{msg: '1'}, {msg: '2'}] // 数组类型的数据
}
})
Mustache语法
把data中的数据绑定到页面中渲染,使用Mustache 语法(双大括号)将变量包起来即可;
语法格式为:
绑定属性
页面结构:
页面数据:
Page({
data: {
id: 0
}
})
bindtap绑定触摸事件
1.通过 bindtap,可以为组件绑定触摸事件,语法如下:
<view bindtap=“tapName”> Click me! <view>
2.在相应的Page定义中写上相应的事件处理函数,事件参数是event
Page({
inputName: function(event) {
console.log(event)
}
})
bindinput绑定文本框输入事件
1.通过 bindinput,可以为文本框绑定输入事件,语法如下
<input bindinput=“inputName”><input>
2.在相应的Page定义中写上相应的事件处理函数,事件参数是event
Page({
inputName: function(event) {
console.log(event)
}
})
data与文本框直接数据同步
通过 this.setData(dataObject) 方法,可以给页面中的data数据重新赋值
inputName: function (event) {
this.setData({
msg: event.detail.value // 为 data 中的 msg 重新赋值
})
}
事件传参
1.不能在绑定事件的同时传递参数
2.通过 data-*自定义属性传参,如下:
//其中,info 会被当作参数名,数值 123 会被当作参数值。
<button bindtap='btnHandler’ data-info=“{{123}}”>事件传参</button>
3.通过事件参数 event.target.dataset.参数名,能够获取data-*自定义属性传递到事件处理函数中的参数
btnHandler: function(event){
console.log(event.target.dataset.info)
}
wxs脚本
wxs(WeiXin Script)是小程序的一套脚本语言,结合WXML,可以构建出页面的结构
1.没有兼容性:wxs不依赖于运行时的基础库版本,可以在所有版本的小程序中运行
2与 javascript 不同:wxs与javascript是不同的语言,有自己的语法,并不和javascript一致
3.隔离性:wxs的运行环境和其他javascript代码是隔离的,wxs中不能调用其他javascript文件中定义的函数,也不能调用小程序提供的API
4.不能作为事件回调:wxs 函数不能作为组件的事件回调
5.iOS设备上比 javascript 运行快:由于运行环境的差异,在iOS设备上小程序内的wxs会比javascript代码快2~ 20 倍。在android设备上二者运行效率无差异
6.wxml 文件中的每个
标签,必须提供一个 module 属性,用来指定当前
标签的模块名。在单个wxml文件内,建议其值唯一
wxs 遵循 CommonJS模块化规范
在wxs中,可以使用CommonJS中规定的如下成员:
1.module 对象:每个wxs都是独立的模块,每个模块均有一个内置的module对象,每个模块都有自己独立的作用域。
2.module.exports:由于 wxs拥有独立作用域,所以在一个模块里面定义的变量与函数,默认为私有的,对其他模块不可见,通过module.exports 属性,可以对外共享本模块的私有变量与函数。
3.require函数:在.wxs模块中引用其他 wxs 文件模块,可以使用require函数。
wx:if
在小程序中,使用 wx:if="{{condition}}" 来判断是否需要渲染该代码块
<view wx:if="{{length > 5}}"> 1 </view>
<view wx:elif="{{length > 2}}"> 2 </view>
<view wx:else> 3 </view>
block wx:if --block wx:for用法和这个类似
因为 wx:if是一个控制属性,需要将它添加到一个标签上。如果要一次性判断多个组件标签,可以使用一个
标签将多个组件包装起来,并在上边使用wx:if控制属性
<block wx:if="{{true}}">
<view> view1 </view>
<view> view2 </view>
</block>
注意:
并不是一个组件,它仅仅是一个包装元素,不会在页面中做任何渲染,只接受控制属性
hidden
在小程序中,直接使用 hidden="{{condition}}" 也能控制元素的显示与隐藏
<view hidden="{{condition}}"> 条件为 true 隐藏,条件为 false 显示 </view>
wx:for
在组件上使用 wx:for 控制属性绑定一个数组,即可使用数组中各项的数据重复渲染该组件。
默认数组的当前项的下标变量名默认为 index,数组当前项的变量名默认为 item。
使用 wx:for-item 可以指定数组当前元素的变量名
使用 wx:for-index 可以指定数组当前下标的变量名
<view wx:for="{{array}}" wx:key="index" wx:for-index="idx" wx:for-item="itemName">
索引是:{{idx}} 当前项是:{{itemName}}
</view>
key 值的注意点
①key 值必须具有唯一性,且不能动态改变
②key 的值必须是数字或字符串
③保留关键字 *this 代表在 for 循环中的 item 本身,它也可以充当 key 值,但是有以下限制:需要 item 本身是一个唯一的字符串或者数字。
④如不提供 wx:key,会报一个warning,如果明确知道该列表是静态,或者不必关注其顺序,可以选择忽略。
下拉刷新
下拉刷新是移动端更新列表数据的交互行为,用户通过手指在屏幕上自上而下的滑动,可以触发页面的下拉刷新,更新列表数据
启用下拉刷新两种方式:
①需要在 app.json 的window 选项中或页面配置中开启enablePullDownRefresh。但是,一般情况下,推荐在页面配置中为需要的页面单独开启下拉刷新行为。
②可以通过 wx.startPullDownRefresh() 触发下拉刷新,调用后触发下拉刷新动画,效果与用户手动下拉刷新一致。当处理完下拉刷新后,下拉刷新的 loading效果会一直显示,不会主动消失,所以需要手动隐藏下拉刷新的loading效果。此时,调用 wx.stopPullDownRefresh() 可以停止当前页面的下拉刷新。
下拉刷新窗口的样式配置
需要在 app.json 的 window 选项中或页面配置中修改backgroundColor 和 backgroundTextStyle 选项。
lbackgroundColor用来配置下拉刷新窗口的背景颜色,仅支持16进制颜色值
lbackgroundTextStyle用来配置下拉刷新 loading 的样式,仅支持 dark 和 light
上拉加载更多
在移动端,随着手指不断向上滑动,当内容将要到达屏幕底部的时候,页面会随之不断的加载后续内容,直到没有新内容为止,我们称之为上拉加载更多。上拉加载更多的本质就是数据的分页加载
onPageScroll(obj) 监听用户滑动页面事件
属性 | 类型 | 说明 |
---|---|---|
scrollTop | Number | 页面在垂直方向已滚动的距离,单位px |
onShareAppMessage(obj)
监听用户点击页面内转发按钮(组件open-type=“share”)或右上角菜单“转发”按钮的行为,并自定义转发内容。其中Object参数说明如下:
参数 | 类型 | 说明 |
---|---|---|
from | String | 转发事件来源;button:页面内转发按钮;menu:右上角转发菜单 |
target | Object | 如果 from 值是 button,则 target 是触发这次转发事件的 button,否则为 undefined |
webViewUrl | String | 页面中包含 组件时,返回当前 的url |
同时,此转发事件需要 return 一个 Object,用于自定义转发内容,返回内容如下
参数 | 说明 | 默认值 |
---|---|---|
title | 转发标题 | 当前小程序的名称 |
path | 转发路径 | 当前页面path,必须是以/开头的完整路径 |
imageUrl | 自定义图片路径,支持PNG和JPG | 使用默认截图 |
onTabItemTap(Object)
点击 tab 时触发,其中 Object参数说明如下:
参数 | 类型 | 说明 |
---|---|---|
index | String | 被点击tabItem的序号,从0开始 |
pagePath | String | 被点击tabItem的页面路径 |
text | String | 被点击tabItem的按钮文字 |
页面导航
页面导航就是页面之间的跳转,小程序中页面之间的导航有两种方式:
① 声明式导航:通过点击navigator 组件实现页面跳转的方式;
② 编程式导航:通过调用小程序的API接口实现跳转的方式;
声明式导航
1.导航到非 tabBar 页面:非 tabBar页面指的是没有被当作 tabBar进行切换的页面。
<navigator url='/pages/info/info'>去info页面</navigator>
上述代码使用 url 属性指定要跳转到的页面路径;其中,页面路径应该以 / 开头,且路径必须提前在app.json的 pages节点下声明,才能实现正常的跳转。
2.导航到 tabBar 页面:如果 navigator 组件单纯使用 url 属性,无法导航到 tabBar 页面,需要结合 open-type 属性进行导航
<navigator url='/pages/home/home' open-type='switchTab'>
导航到home页面
</navigator>
3.后退导航:需要把 open-type 设置为 navigateBack,同时使用 delta属性指定后退的层数
<navigator open-type='navigateBack' delta='1'>
返回上一页
</navigator>
编程式导航
1.导航到非 tabBar 页面:通过 wx.navigateTo(Object object) 方法,可以跳转到应用内的某个页面。但是不能跳到 tabbar页面
属性 | 类型 | 是否必填 | 说明 |
---|---|---|---|
url | String | 是 | 需要跳转的应用内非 tabBar 的页面的路径, 路径后可以带参数。参数与路径之间使用 ?分隔,参数键与参数值用 = 相连,不同参数用 & 分隔;如 ‘path?key=value&key2=value2’ |
success | function | 否 | 接口调用成功的回调函数 |
fail | function | 否 | 接口调用失败的回调函数 |
complete | function | 否 | 接口调用结束的回调函数(调用成功、失败都会执行) |
2.导航到 tabBar 页面:通过 wx.switchTab(Object object) 方法,可以跳转到 tabBar页面,并关闭其他所有非 tabBar页面
属性 | 类型 | 是否必填 | 说明 |
---|---|---|---|
url | String | 是 | 需要跳转的 tabBar 页面的路径(需在app.json的tabBar字段定义的页面),路径后不能带参数 |
success | function | 否 | 接口调用成功的回调函数 |
fail | function | 否 | 接口调用失败的回调函数 |
complete | function | 否 | 接口调用结束的回调函数(调用成功、失败都会执行) |
3.后退导航:通过 wx.navigateBack(Object object) 方法,关闭当前页面,返回上一页面或多级页面
属性 | 类型 | 是否必填 | 说明 |
---|---|---|---|
delta | number | 是 | 返回的页面数,如果delta大于现有页面,则返回到首页 |
success | function | 否 | 接口调用成功的回调函数 |
fail | function | 否 | 接口调用失败的回调函数 |
complete | function | 否 | 接口调用结束的回调函数(调用成功、失败都会执行) |
导航传参
1.声明式导航传参:navigator 组件的 url属性用来指定导航到的页面路径,同时路径后面还可以携带参数,参数与路径之间使用 ?分隔,参数键与参数值用 = 相连,不同参数用 & 分隔。
<navigator url='/pages/logs/logs?name=zs&age=20'>去logs页面</navigator>
2.编程式导航传参:wx.navigateTo(Object object) 方法的 object 参数中,url 属性用来指定需要跳转的应用内非 tabBar 的页面的路径, 路径后可以带参数。参数与路径之间使用 ? 分隔,参数键与参数值用 = 相连,不同参数用 & 分隔
wx.navigateTo({
url: '/pages/logs/logs?name=zs&age=20',
})
3.接收传参:最终导航到的页面可以在 onLoad 生命周期函数中接收传递过来的参数
//生命周期函数--监听页面加载
onLoad: function(options) {
console.log(options) // options 就是导航传递过来的参数
}
4.自定义编译模式快速传参
小程序每次修改代码并编译后,会默认从首页进入,但是在开发阶段,我们经常会针对特定的页面进行开发,为了方便编译后直接进入对应的页面,可以配置自定义编译模式,步骤如下:
①单击工具栏上的“普通编译”下拉菜单;
②单击下拉菜单中的“添加编译模式”选项;
③在弹出的“自定义编译条件窗口”,按需添加模式名称、启用页面、启动参数、进入场景等。
网络数据请求
配置服务器域名
每个微信小程序需要事先设置一个通讯域名,小程序只可以跟指定的域名进行网络通信。
服务器域名请在 「小程序后台-开发-开发设置-服务器域名」中进行配置,配置时需要注意:
1.域名只支持 https(request、uploadFile、downloadFile)和wss(connectSocket) 协议
2.域名不能使用 IP地址或localhost
3.域名必须经过 ICP备案
4.服务器域名一个月内可申请5次修改
发起 get请求
调用 wx.request(Object object) 方法发起 get请求
wx.request({// 请求的URL地址,必须基于 HTTPS 协议
url: 'https://www.liulongbin.top:8082/api/get',
// 发送到服务器的数据
data: { name: 'zs', age: 20 },
// 成功之后的回调函数
success: function(result) {
console.log(result)
}
})
发起post请求
调用 wx.request(Object object) 方法发起 post请求
wx.request({
url: 'https://www.liulongbin.top:8082/api/post',
method: 'POST', // 设置请求类型,如果不设置,默认发起 GET 请求
data: { name: 'ls', gender: '男' }, // 发送到服务器的数据
success: function(result) {
console.log(result)
}
})
引用组件
①在需要引用组件的页面中,找到页面的.json 配置文件,新增 usingComponents节点
②在 usingComponents中,通过键值对的形式,注册组件;键为注册的组件名称,值为组件的相对引用路径
③在页面的 .wxml 文件中,把注册的组件名称,以标签形式在页面上使用,即可把组件展示到页面上
使用样式美化组件
组件对应 wxss 文件的样式,只对组件 wxml内的节点生效。编写组件样式时,需要注意以下几点:
①组件和引用组件的页面不能使用id选择器(#a)、属性选择器([a])和标签名选择器,请改用class选择器。
②组件和引用组件的页面中使用后代选择器(.a .b)在一些极端情况下会有非预期的表现,如遇,请避免使用。
③子元素选择器(.a>.b)只能用于 view 组件与其子节点之间,用于其他组件可能导致非预期的情况。
④继承样式,如 font 、 color ,会从组件外继承到组件内。
⑤除继承样式外, app.wxss 中的样式、组件所在页面的样式对自定义组件无效。
为组件传递properties的值
<!-- 引用组件的页面模板 -->
<view>
<component-tag-name prop-a="{{dataFieldA}}" prop-b="{{dataFieldB}}">
</component-tag-name>
</view>
组件的属性 propA 和 propB 将收到页面传递的数据。页面可以通过 setData来改变绑定的数据字段
注意:在定义 properties时,属性名采用驼峰写法(propertyName);在 wxml 中,指定属性值时,则对应使用连字符写法(property-name=“alue”),应用于数据绑定时,采用驼峰写法(attr="{{propertyName}}"
数据监听
数据监听器可以用于监听和响应任何属性和数据字段的变化,从而执行特定的操作。作用类似于vue 中的 watch。数据监听器从小程序基础库版本2.6.1 开始支持。
Component({
observers: {
'字段A, 字段B': function(字段A的新值,字段B的新值) {
// do something
}
}
})
监听子数据字段的变化
Component({
observers: {
'some.subfield': function (subfield) {
// 使用 setData 设置 this.data.some.subfield 时触发
// (除此以外,使用 setData 设置 this.data.some 也会触发)
},
'arr[12]': function (arr12) {
// 使用 setData 设置 this.data.arr[12] 时触发
// (除此以外,使用 setData 设置 this.data.arr 也会触发)
}
}
})
组件的主要生命周期
1.组件实例刚刚被创建好时, created生命周期被触发。此时还不能调用 setData 。通常情况下,这个生命周期只应该用于给组件 this 添加一些自定义属性字段。
2.在组件完全初始化完毕、进入页面节点树后, attached生命周期被触发。此时, this.data 已被初始化完毕。这个生命周期很有用,绝大多数初始化工作可以在这个时机进行。
3.在组件离开页面节点树后, detached生命周期被触发。退出一个页面时,如果组件还在页面节点树中,则detached 会被触发。
Component({
lifetimes: {
attached() {}, // 在组件实例进入页面节点树时执行
detached() {}, // 在组件实例被从页面节点树移除时执行
},
// 以下是旧式的定义方式,可以保持对 <2.2.3 版本基础库的兼容
attached() {}, // 在组件实例进入页面节点树时执行
detached() {}, // 在组件实例被从页面节点树移除时执行
// ...
})
组件所在的页面的生命周期
Component({
pageLifetimes: {
show() { // 页面被展示
},
hide() { // 页面被隐藏
},
resize(size) { // 页面尺寸变化
}
}
})
默认插槽
<!-- 组件模板 -->
<view class="wrapper">
<view>这里是组件的内部节点</view>
<slot></slot>
</view>
<!-- 引用组件的页面模板 -->
<view>
<component-tag-name>
<!-- 这部分内容将被放置在组件 <slot> 的位置上 -->
<view>这里是插入到组件slot中的内容</view>
</component-tag-name>
</view>
启用多个插槽
Component({
options: {
multipleSlots: true // 在组件定义时的选项中启用多slot支持
},
properties: { /* ... */ },
methods: { /* ... */ }
})
可以在组件的 wxml 中使用多个 slot 标签,以不同的 name 来区分不同的插槽,使用时,用 slot 属性来将节点插入到不同的 slot 中
<!-- 引用组件的页面模板 -->
<view>
<component-tag-name>
<!-- 这部分内容将被放置在组件 <slot name="before"> 的位置上 -->
<view slot="before">这里是插入到组件slot name="before"中的内容</view>
<!-- 这部分内容将被放置在组件 <slot name="after"> 的位置上 -->
<view slot="after">这里是插入到组件slot name="after"中的内容</view>
</component-tag-name>
</view>
组件之间的基本通信方式
①WXML 数据绑定:用于父组件向子组件的指定属性传递数据,仅能设置 JSON 兼容数据(自基础库版本 2.0.9 开始,还可以在数据中包含函数)。
②事件:用于子组件向父组件传递数据,可以传递任意数据。
如果以上两种方式不足以满足需要,父组件还可以通过 this.selectComponent 方法获取子组件实例对象,这样就可以直接访问组件的任意数据和方法
通过事件监听实现子向父传值
①在父组件的 js 中,定义一个函数,这个函数即将通过自定义事件的形式,传递给子组件
②在父组件的 wxml 中,通过自定义事件的形式,将步骤一中定义的函数引用,传递给子组件
③在子组件的 js 中,通过调用 this.triggerEvent(‘自定义事件名称’, { /* 参数对象 */ }) ,将数据发送到父组件
④在父组件的 js 中,通过 e.detail 获取到子组件传递过来的数据
WePY框架
WePY 是腾讯官方出品的一个小程序快速开发框架,对原生小程序的开发模式进行了再次封装,更贴近于MVVM 架构模式,并支持ES6/7的一些新特性,同时语法风格更接近于Vue.js,使用 WePY 框架能够提高小程序的开发效率。
注意:WePY 只是小程序的快速开发框架之一,市面上还有如 mpvue 之类的小程序开发框架也比较流行
安装WePY框架
npm install wepy-cli -g
初始化WePY项目
wepy init standard myproject
其中,”wepy init” 是固定写法,代表要初始化 wepy 项目;”standard” 代表模板类型为标准模板,可以运行”wepy list” 命令查看所有可用的项目模板; ”myproject” 为自定义的项目名称。
注意:创建项目的时候,要勾选 ESLint 选项!
使用 wepy init 命令初始化项目后,只是得到了一个模板项目,如果想开启实时编译,得到小程序项目,步骤如下:
①运行 cd myproject 切换至 WePY 项目根目录
②运行 npm install 安装 WePY 项目依赖项
③运行 wepy build --watch 开启实时编译
注意:wepy build --watch 命令,会循环监听 WePY 项目中源代码的变化,自动编译生成小程序项目,生成的小程序项目默认被存放于dist 目录中。
创建 .wpy 页面注意事项
①每个页面的 script 标签中,必须导入 wepy 模块,并创建继承自 wepy.page 的页面类;否则会报错。
②每个页面的路径,必须记录到 app.wpy 的 config ->pages 数组中。
页面路径记录完毕之后,必须再回到页面文件中,摁下 Ctrl + S 快捷键重新编译生成页面,否则会报错
事件传参优化写法
如果 @ 符号绑定的事件处理函数需要传参,可以采用优化的写法,示例如下:
原 bindtap="clickHandler"data-index={{index}}
替换为@tap="click({{index}})"
使用wxs脚本
①将 wxs 脚本定义为外联文件,并且后缀名为.wxs
②在 标签内,通过 import 导入相对路径的 wxs 模块
import testWXS from '../wxs/test.wxs'
③在当前页面的 class 类中,通过 wxs = { } 注册刚才导入的 wxs 模块
wxs = {
test: testWXS
}
注意:被注册的 wxs 模块,只能在当前页面的 template 中使用,不能在script中使用
配置 promisify 启用 async 和 await
需要手动开启,在src -> app.wpy ,找到constructor() 构造函数,添加this.use('promisify')
constructor() {
super()
this.use('requestfix')
this.use('promisify') // 添加此行代码,即可启用 async 和 await
}
使用 WePY 发起get请求
//通过 wepy.request() 发起get请求
methods = {
async getInfo() {
const res = await wepy.request('https://www.liulongbin.top:8082/api/get')
console.log(res)
}
}
使用 WePY 发起post请求
methods = {
async postInfo() {
const res = await wepy.request({
url: 'https://www.liulongbin.top:8082/api/post',
method: 'post',
data: { name: 'zs', age: 20 }
})
console.log(res)
}
}
异步更新数据
在异步函数中更新数据的时候,页面检测不到数据的变化,必须手动调用 this.$apply 方法, 强制页面重新渲染
methods = {
async getInfo() { // 被 async 修饰的函数叫做异步函数
const res = await wepy.request('https://www.liulongbin.top:8081/api/get’)
this.getMsg = res.data
//需要重新渲染页面数据才能更新
this.$apply()
}
}