javaWeb学习笔记

网页主要由三部分组成:

结构:HTML

表现:CSS

行为:JavaScript

HTML

Chrome浏览器调试工具:右键点“检查”,或按F12

常用标签

标题标签 : < h1 > ~ < h6 >

段落标签:< p > < /p > (两段之间会插入一定的间距)

换行标签:< br >

水平分割线:< hr >

文本格式化标签:

  • 加粗:< strong >< /strong >或者 < b >< /b >
  • 倾斜:< em >< /em > 或者 < i >< /i >
  • 删除线:< del >< /del > 或者 < s >< /s >
  • 下划线:< ins >< /ins > 或者 < u >< /u >

分区标签:

  • < div > < /div > :一行只能放一个 < div > ,是大分区;
  • < span > < /span > :一行可以放多个 < span >,是小分区;

其他布局标签:(用于手机网页制作)

标签名 语义
header 网页头部
nav 网页导航
footer 网页底部
aside 网页侧边栏
section 网页区块
article 网页文章

javaWeb学习笔记_第1张图片

图像标签:

  • < img src=“图像URL” / >

  • < img src=“图像URL” alt=“替换的文字” title=“图像提示文字”/ >

    图像标签的属性:

    属性之间不分先后顺序,但必须用空格分开

    属性采用键值对的格式:key=“value”

    属性 属性值 说明
    src 图片路径 必须属性
    alt 文本 替换文本,图像不能显示时出现的文字
    title 文本 提示文本,鼠标放到图像上会浮现的文字
    width 像素 设置图像的宽度
    height 像素 设置图像的高度
    border 像素 设置图像的边框粗细

相对路径: / 指下一级路径, …/ 指上一级路径

绝对路径:\


<base href="http://localhost:8080/07_servlet/a/b/">

base标签:可以设置当前页面中所有路径工作时,参照哪个路径来进行跳转。

超链接:< a > 具体为:< a href=“跳转目标” target=“目标窗口的弹出方式” > 文本、图像、音频等(点击样式) < /a>

属性 作用
href 用于指定链接目标的url地址(必须属性)
target 用于指定链接页面的打开方式,_self为默认值, _blank为在新窗口打开

如:< a href=“http://www.qq.com” target=“_blank”> 腾讯< /a >

内部链接:则href 后可以直接写相对路径。即两者在同一文件夹。

空链接:href 后写个 # ,即 < a href=“#”> ** < /a >

下载链接:href后写压缩文件的路径

锚点链接:在href属性中,设为 #名字 的形式,如 < a href=“#ZZC”> 哈哈 < /a >,然后在目标处,添加一个id属性=设定的名字,如 < h4 id=“ZZC” >


注释: < !-- 注释语句 – > ,快捷键 :ctrl + /

特殊字符:(只记空格符就行,所有字符后都要带个分号 ; )

特殊字符 描述 字符的代码
空格符  
< 小于号 <
> 大于号 >
& 和号 &
人民币 ¥
© 版权 ©
® 注册商标 ®
° 摄氏度 °
± 正负号 ±
× 乘号 ×
÷ 除号 ÷
² 平方2 ²
³ 立方3 ³


表格标签

< table>< /table>:是用于定于表格的标签

< tr >< /tr >:用于定义表格中的行,必须在< table >中

< td >< /td >:用于单元格,必须嵌套在< tr >中

< th >< /th >:表示表头单元格(文本内容居中加粗)

表格结构标签:< thead >指表格的头部区域,指表格 的主体区域。

合并单元格(属性):跨行合并——rowspan=”合并个数“,跨列合并——colspan=“合并个数”(也可说是占了若干个单元格)

合并步骤:找到目标单元格,写上合并方式,如:< td colspan=“2” >< /td >,然后再删除多余的单元格。

表格属性:

属性 属性值 描述
align legt,center,right 规定表格相对周围元素的对齐方式
border 1或 ” “ 是否有边框,默认为” “,即无边框
cellpadding 像素值 规定单元边沿与内容之间的空白,默认1像素
cellspacing 像素值 规定单元格之间的空白,默认1像素
width 像素值或百分比 规定表格的宽度

如:

<table align="center" border="1" cellpadding="0">
	<tr>
    	< th>表头单元格的内容th>
		< td>单元格中的内容td>
	tr>
table>


列表

无序列表:< ul > ,列表项:< li >

有序列表:< ol >

自定义列表:< dl > ,表项头< dt >,表项:< dd >

< ul >和< ol >里只能放< li >, < li >里面可以放任意标签,< dl >里只能放< dt >和< dd >。


表单

表单域(区域):< form >

<form action="url地址" method="提交方式" name="名称">

表单域属性:

属性 属性值 作用
action url地址 指定接收该表的服务器程序的url地址
method GET/POST 设置表单数据的提交方式
name 名称 指定表单名称

表单元素:

  • 输入元素:< input type=“属性值” / >

    input属性:

    属性 属性值 描述
    name 自定义 定义input元素的名称
    value 自定义 规定input元素的值
    checked checked 规定此input首次加载时被选中
    maxlength 正整数 规定输入字符的最大长度

    注:name和value是每个表单元素都有的属性值,主要给后台人员使用;要求单选按钮和复选框要有相同的name值

    type属性值:

    属性 描述
    button 定义可点击按钮(多数情况下,用于通过 Javascript启动脚本)
    checkbox 定义复选框。
    file 定义输入字段和“浏览"按钮,供文件上传。和 multiple 搭配可以上传多个文件
    hidden 定义隐藏的输入字段。
    image 定义图像形式的提交按钮
    password 定义密码字段。该字段中的字符被掩码。
    radio 定义单选按钮
    reset 定义重置按钮。重置按钮会清除表单中的所有数据
    submit 定义提交按钮。提交按钮会把表单数据发送到服务器。
    text 定义单行的输入字段,用户可在其中输入文本。默认宽度为20个字符。
    placeholder 占位符,作提示,常用于需要输入的文本框

    < label > :用于绑定一个表单元素,当单击此标签内的文本时,会自动选择对应的表单元素,以增加用户体验。

    格式:< label >里的for属性 应该与相关元素的 id属性相同。如:

    <label for="zzc"> 文本label> 
    <input type=" " id="zzc"/>
    
  • 下拉元素:< select > :定义下拉列表

    在< option >中添加selected=”selected”时,为默认选中项

    <select>
        <option> 选项 option>
    select>
    
  • 文本域元素:< textarea >:定义多行文本输入控件

<textarea>
	文本内容
textarea>

CSS

CSS:层叠样式表

CSS书写顺序:

  1. 浮动 / display
  2. 盒子模型:margin border padding 宽度高度背景色
  3. 文字样式

导入方式

  1. 内联样式:在标签内使用style属性(耦合较高,较少使用)

    <div style="color: red"> HELLO CSS div>
    
  2. 内部样式:定义 < style > 标签,在标签内定义css样式;

    (一般写在head标签里,title标签下面)

    <style>
    /*选择器 { 样式 } */
    /*给谁改样式 { 改什么样式 } */
    p {
        color: red;		/*键值对用:分开,每行用;结尾*/
        fon-size: 12px;
    }
    style>
    
  3. 外部样式:定义link标签,引入外部的css文件

    <link rel="stylesheet" href="demo.css">
    
    /*demo.css*/
    div{
    	color: red;
    }
    

规范:

选择器、属性名、属性值统一小写;

选择器(标签)和大括号中间带空格;

冒号后带空格



选择器

  • 标签选择器:元素名称{color: red;}

    div{color: red}
    
  • id选择器:#id属性值{color: red;}

    注意:id是唯一的,一般与js配合制作动态效果

    #name{color: red;}
    
    "name">hello css
  • 类选择器:.class属性值{color: red;}

    .cls{color: red;}
    
    "cls">helle css
  • 通配符选择器:*{ color: red;}

    作用:为页面的所有标签 设置样式。

    *{
    	margin: 0;
        padding: 0; /*去除默认的外边距*/
    }
    


更多用法:

  • 后代选择器:选择器1 选择器2 { css }

    作用:根据嵌套关系,选择父元素的 后代中满足条件的元素。

    注:后代包括 儿子、孙子…

    div p{
        ....
    }   /* 选择div下的p标签 */
    
  • 子代选择器: 选择器1 > 选择器2{css}

    作用:选择父元素的子代元素。

    注:子代只包含儿子

  • 并集选择器: 选择器1,选择器2{css}

    作用:用逗号隔开,同时选择多组标签,设置相同的样式。

    注:一般写法是 每个选择器写一行,提高代码的可读性。

  • 交集选择器:选择器1选择器2 { css }

    作用:选中页面中同时满足多个选择器的标签

    注:选择器连着写,且标签选择器优先写在前面。

  • hover伪类选择器:选择器:hover {css}

    作用:在鼠标悬停在元素上时 会出现的状态样式

字体和文本样式

字体样式

  • 字体大小:font-size

    取值:数字+px

    谷歌浏览器默认文字大小是16px

    p{
        font-size: 30px
    }
    
  • 粗细:font-weight

    取值:normal,bold;(指正常和加粗)

    或取100到900的整百数,正常是400,加粗是700

  • 样式:font-style (是否倾斜)

    取值:normal,italic(正常和倾斜)

  • 类型系列:font-family

    取值:微软雅黑,黑体…等等,最后应该加sans-serif(无衬线字体)(从设置的第一种字体开始选,没有就选择下一个电脑有的字体)

  • 字体font连写:

    取值:font:style weight size family(可以省略前两个值,为默认值)

    复合属性:一个属性后面写多个值的写法

    font: italic 700 66px 宋体
    

文本样式

  • 文本缩进:text-indent

    取值:数字+px 或 数字+em(1em=当前标签的大小,推荐)

    p{
        text-indent: 2em  /*缩进两字符*/
    }
    
  • 文本水平对齐方式:text-align

    属性值:left,center,right;分别是左对齐,居中,右对齐

    注:text-align 其实是内容对齐,不仅仅用于文本, 能用于 文本、span标签、a标签、input标签、img标签 。不过需要在以上元素的父元素设置,如。

  • 文本修饰:text-decoration

    取值:underline,line-through,overline,none;分别是下划线(常用),删除线,上划线,无装饰线(常用)。


line-height行高

作用:控制一行的上下行间距

取值:数字+px 或 倍数(当前标签font-size的倍数)

注意:

如果同时设置了行高和font连写,注意覆盖问题
font:style weight size/line-height family

font:ita1ic 700 66px/2 宋体;

标签水平居中: margin:0 auto

margin:0 auto 一般用于有固定宽度的盒子,如果没有宽度,会默认占满父元素的宽度。


背景

背景色:background-color:

背景图:background-image: url(‘…’)

背景平铺:background-repeat:

取值 效果
repeat 默认,水平和垂直方向平铺
no-repeat 不平铺
repeat-x 沿水平方向平铺
repeat-y 沿垂直方向平铺

背景位置:background-position:x值 y值;

方向名词

  • 水平:left,center,right
  • 垂直:top,center,bottom

数字+px(坐标)

背景相关属性连写

顺序无要求,推荐顺序:background:color image repeat position


元素显示模式

< >可以叫标签,标记,元素。

  • 块级元素

    独占一行,宽度默认是父元素的宽度,高度由内容撑开,可以设置宽高

    如:div,p,h系列,ul,li,dl,dt,dd,form,header

  • 行内元素

    一行可以显示多个,宽度和高度默认由内容撑开,不可以设置宽高

    如:a,apar,b,u,i,s,strong,ins,em,del

  • 行内块元素

    一行可以显示多个,可以设置宽高

    如:image,input,textarea,button,select

元素显示模式转换:

作用:改变元素默认的显示特点,让元素符合布局要求

语法:

属性 效果
display: block 转成块级元素
display: inline-block 转成行内块元素
display: inline 转成行内元素

元素的嵌套规范

  • 块级元素一般作为大容器,可以嵌套:文本、块级元素、行内元素、行内块元素等等…

    但是:p标签中不要嵌套div、p、h等块级元素

  • a 标签内部可以嵌套任意元素

    但是:a标签不能嵌套a标签

CSS特性

  • 继承性:子元素默认继承父元素的样式特点

    控制文字属性的都可以继承,如:

    color,font- ,text- ,line-height 。。。。

    但有例外:a标签的color有自己的蓝色,h系列的font-size有自己的字体大小,都会继承失效。

  • 层叠性:覆盖,后面的覆盖前面的

  • 优先级:

    继承 < 通配符选择器 < 标签选择器 < 类选择器 < id选择器 < 行内样式 < !important

    !important可以提升选择器的优先级到最高,写在属性值的后面,分号的前面。

    注:继承的优先级不能用 !important提高,它的优先级最低。

盒子模型

页面中的每一个标签,都可看做是一个“盒子”,通过盒子的视角更方便的进行布局。

盒子构成

  • 内容区域 content

  • 内边距区域 padding

    取值:可以四个,三个,两个,一个值

    padding: 10px 20px 30px 40px (对应上 右 下 左,即逆时针开始数)

    padding: 10px 20px 30px (对应上 左右 下,也是逆时针)

    padding: 10px 20px(对应上下 左右,也是逆时针)

  • 边框区域 border

    如:border:10px solid red ——>10像素,直线,红色(粗细,线段样式,颜色)

    如果只需要一边的边框线,则border-方向即可,如:border-left/ right/ top/ bottom

    线段:直线solid,dashed虚线,dotted点线(其他的线用不着,需要的用图片)

    快捷键:bd

  • 外边距区域 margin

自动内减

box-sizing:border-box

给盒子设置border或paddingl时,盒子会被撑大,需要再次设置参数,手动计算麻烦,所以有了自动内减,浏览器会自动计算,在内容中减去相应大小。

清除默认的内外边距

margin:0;

padding:0;

淘宝网的:

blockquote,body,button,dd,dl,dt,fieldset,form,h1,h2,h3,h4,h5,h6,hr,input,legend,li,ol,p,pre,td,textarea,th,ul{
	margin:0;
	padding:0;
}

京东的:

*{
   	margin: 0;
   	padding: 0;
}

一些问题

  • 塌陷现象:

    场景:相互嵌套的块级元素,子元素设置了margin-top,会同样作用在父元素上。致使父元素一起往下移动。

    解决:

    • 给父元素设置border-top或者padding-top(分隔父子元素的margin-top)
    • 给父元素设置 overflow: hidden
    • 转换成行内块元素
    • 设置浮动

浮动

结构伪类选择器

根据元素在HTML的结构关系查找元素。常用于查找某父级选择器的子元素。

优势:减少对HTML中类的依赖,有利于保持代码的整洁。

选择器 说明
E:first-child{} 匹配父元素中第一个子元素,且是E元素
E:last-child{} 匹配父元素中最后一个子元素,且是E元素
E:nth-child(n){} 匹配父元素中第n个子元素,且是E元素
E:nth-last-child(n){} 匹配父元素中倒数第n个子元素,且是E元素

n可以写成公式,如4n+1,则会选中第5个,第9个…

伪元素

一般在页面的非主体内容可以使用伪元素。

伪元素 作用
::before 在父元素内容的最前添加一个伪元素
::after 在父元素内容的最后添加一个伪元素

注:必须设置content属性才能生效,伪元素默认是行内元素

例:

   
	


    
    
"father">爱

浮动特点

  • 浮动元素会脱离标准流(简称:脱标),在标准流中不占位置

    标准流:又称文档流 ,指浏览器在渲染网页时默认采用的一套排版规则。

  • 浮动元素比标准流高半个级别,可以覆盖标准流中的元素

  • 浮动找浮动,下一个浮动元素会在上一个浮动元素后面左右浮动

  • 浮动元素有特殊的显示效果

    • 一行可以显示多个
    • 可以设置宽高

注:浮动的元素不能使用text-align: center或者margin: 0 auto 设置

清除浮动

浮动带来的问题:如果子元素浮动了,此时子元素不占位置,不能撑开标准流的块级父元素。

解决:

  1. 直接设置父元素的高度

    优点:简单

    缺点:有些布局中不能固定父元素高度

  2. 额外标签法

    在父元素内容的最后添加一个块级元素,并对其设置 clear: both。

    缺点:添加了额外标签,会使HTML结构变复杂

  3. 单伪元素清除法

    用伪元素替代了额外标签。

    /*基本写法*/
    .clearfix::after{	/*clearfix常用作需要清除浮动的元素的类名*/
    	content: '';
    	display: block;
    	clear: both;
    }
    /*补充写法*/
    .clearfix::after{
        content: '';
    	display: block;
    	clear: both;
        /*补充的部分是为了在网页中看不见伪元素*/
        height: 0;
        visibility: hidden;
    }
    
  4. 双伪元素清除法

    .clearfix::before,
    .clearfix::after{
    	content: '';
    	display: table;
    }
    .clearfix::after{
    	clear: both;
    }
    

    优点:可以在项目中直接使用,直接给标签加类clearfix即可清除浮动。

  5. 设置overflow:hidden

    直接给父元素设置overflow:hidden即可。

    优点:方便

定位

可以让元素自由的摆放在网页的任意位置,一般用于盒子之间的层叠情况

应用:定位之后的元素层级最高,可以层叠在其他盒子上面,也可以让盒子始终固定在屏幕中的某个位置。

定位种类

属性名:position:

属性值:

定位方式 属性值
静态定位 static(加不加效果一样)
相对定位 relative
绝对定位 absolute
固定定位 fixed
粘性定位 sticky

偏移值:水平和垂直方向各选一个即可(都写的话以left和top为准)

方向 属性名 属性值 含义
水平 left 数字px 距离左边的距离
水平 right 数字px 距离右边的距离
垂直 top 数字px 距离上边的距离
垂直 bottom 数字px 距离下边的距离

属性值 也可以用 % 来设置,这样就是以参照物来看,如 50%就是左边界在参照物的中间。

  • 相对定位——position: relative

    相对于非静态定位的父元素进行移动。

    .box{
        position: relative;
        left: 100px;
        top: 200px;
    }
    
    • 原位置仍在页面 中占位置(没有脱标)
  • 绝对定位——position: absolute

    就近找已经定位的父级为参照进行定位,没有定位的父级,则默认相对于浏览器可视区域(即)进行移动。(子绝父相)

    • 原位置在页面中不占位置(已经脱标)

    • 绝对定位的盒子模式具备行内块特点

    例题:让元素的位置处于浏览器或参照物正中间。

    .box{
    	position: absolute;
        left: 50%;
        margin-left: -150px;/*宽的一半*/
        
        top: 20%;
        margin-top: -200px;/*高的一半*/
        /*transform:translate(-50%,-50%); 上面的margin位移也可以写成这个,位移自己的一半*/
        
        width: 300px;
        heght: 400px
    	background-color: pink;
    }
    
  • 固定定位——position: fixed

    特点:

    • 脱标,不占位置;

    • 参照浏览器窗口改变位置;

    • 具备行内块特点

  • 粘性定位——position: sticky

    可看作是相对定位和固定定位的混合,允许被定位的元素表现的像相对定位一样,直到滚动至某个阈值点为止,之后变为固定。(如:顶部导航栏最多滚动至顶部起10px,之后固定)

    必须指定 top, right, bottom, left 四个阈值其中之⼀,粘性定位才生效。

    .xxx {
        position: sticky;
        top: 30px;
        left: 30px;
    }
    

层级关系

不同布局:标准流 < 浮动 < 定位

而相对,绝对,固定三种定位方式层级相同,谁写在下就覆盖其他的。

一些应用

  • 元素居中:

    1. 先设定width或height;
    2. 将left,right 或 top,bottom 距离设置为0;
    3. 将left,right 或 top,bottom 的margin设置为auto

    绝对定位和固定定位中,margin为auto时,会自动吸收剩余空间。

  • 元素的重叠:

    设置元素的堆叠顺序: z-index

  • 绝对定位、固定定位的补充:

    • 如果没有指定宽高,默认大小是内容的大小;
    • 一定是块盒;
    • 一定不会浮动;
    • 不会发生外边距合并;
    • 会盖住下面常规流的所有内容(浮动元素只会盖住盒子,不会盖住里面的文字图片,因为浮动元素最初是做文字环绕效果的)

装饰

浏览器解析 行内 和 行内块 时当作文字,会根据基线对齐,所以导致常常图片或按钮之类的与文本框或背景对不齐。

垂直对齐

属性名:vertical-align

属性值:

属性值 效果
baseline 默认,基线对齐
top 顶部对齐
middle 中间对齐
bottom 底部对齐

光标类型

设置鼠标光标在元素上时显示的样式。

属性名:cursor

属性值:

属性值 效果
default 默认值,通常是箭头
pointer 小手,提示可以点击
text 工字型,提示可以选择文字
move 十字光标,提示可以移动

边框圆角

场景:让盒子四个角变得圆润,增加页面细节。

属性名:border-radius

常见取值:数字+px、百分比(指圆角半径)

赋值规则:从左上角开始,顺时针赋值,没有赋值的看对角

画一个正圆:

盒子为正方形,设置圆角为盒子宽高的一半,即 border-radius: 50%

按钮胶囊:

盒子为长方形,设置圆角为盒子 高度 的一半,即 border-radius: 50%

也可以使用clip-path属性:

clip-path: circle(45%)

溢出部分显示

溢出部分:指盒子内容部分所超出盒子范围的区域。

overflow用于控制内容溢出部分的显示效果,如:显示/隐藏滚动条。

属性名:overflow

属性值:

属性值 效果
visible 默认值,溢出部分可见
hidden 溢出部分隐藏
scroll 无论是否溢出,都显示滚动条
auto 根据是否溢出,自动显示或隐藏滚动条

元素本身隐藏

让某元素本身在屏幕中不可见,如:鼠标hover之后元素隐藏,用于隐藏/显示子菜单之类的场景

属性:

  • visibility: hidden

    占位置的隐藏效果,用的不多

  • display: none

    脱标的隐藏效果(不占位置)

    display:black 显示元素

元素整体透明

让某元素(包括内容)一起变透明。

属性名:opacity

属性值:0~1之间的数字——0为完全透明

弹性盒子display:flex

flex用于 按行或按列布局元素(一维布局)。

设置容器为flex后,其子元素的 float 、 clear 、 vertical-align 属性将失效。

flex容器的属性:

  • flex-direction :主轴反向

    .box {
        flex-direction: row; /* 默认值,横向从左⾄右排列 */
        flex-direction: row-reverse; /* 横向从右⾄左排列 */
        flex-direction: column; /* 纵向从上到下排列 */
        flex-direction: column-reverse; /* 纵向从下到上排列 */
    }
    
  • flex-wrap: 超出父容器的子容器的排列方式

    flex容器 {
        flex-wrap: wrap; /* ⾥⾯的flex项溢出时会⾃动换⾏ ,第⼀⾏在上⽅*/
        flex-wrap: wrap-reverse; /* ⾥⾯的flex项溢出时会⾃动换⾏ ,第⼀⾏在下⽅*/
    }
    flex项 {
        flex: 200px
    }
    
  • flex-flow:上两者的合并写法

    {
        flex-flow: row wrap;
    }
    /* 等价于 */
    {
        flex-direction: row;
        flew-wrap: wrap;
    }
    
  • justify-content:子容器在主轴的排列方向和空间分配

    flex容器 {
        display: flex;
        justify-content: stretch; /* ⾃动⼤⼩(auto-sized)的flex项会拉伸 */
        justify-content: flex-start; /* 默认值,flex项从flex容器起始线开始排列 */
        justify-content: flex-end; /* flex项从flex容器终⽌线开始排列 */
        justify-content: center; /* flex项在flex容器中间排列 */
        justify-content: space-around; /* 每个flex项左右空间相等 */
        justify-content: space-between; /* flex项间的间隔相等,第⼀个和最后⼀个flex项靠在左右两端 */
    }
    
  • align-items:子容器在交叉轴的排列方向

    flex容器 {
        display: flex;
        align-items: stretch; /* 默认值,flex项会拉伸⾄填满flex容器交叉轴 */
        align-items: flex-start; /* flex项依flex容器的顶部对⻬ */
        align-items: flex-end; /* flex项依flex容器的底部对⻬ */
        align-items: center; /* flex项在交叉轴居中对⻬ */
    }
    
  • align-content:多主轴情况下⼦容器在交叉轴上的对齐和空间分配

    flex-item {
        align-content: stretch; /* 默认值,flex项拉伸占满整个交叉轴 */
        align-content: flex-start; /* flex项依flex容器的顶部对⻬ */
        align-content: flex-end; /* flex项依flex容器的底部对⻬ */
        align-content: center; /* flex项在交叉轴居中对⻬ */
        align-content: space-between; /* 在交叉轴两端对⻬,轴线之间的间隔平均分配 */
        align-content: space-around; /* 轴线间的间隔⽐轴线与边框的间隔⼤⼀倍 */
    }
    

flex项的属性:

  • flex-grow:flex项在可用空间中的拉伸比例(沿主轴方向增长尺寸)

  • flex-shrink:flex项超出主轴时的压缩比例

  • flex-basis:flex项在不伸缩情况下的原始尺寸(默认auto,采用元素内容的尺寸)

  • flex:flex-grow, flex-shrink, flex-basis 的简写属性

    flex项 {
        flex: initial; /* 默认值,相当于 flex: 0 1 auto; 即不可拉伸,可以收缩 */
        flex: auto; /* 相当于 flex: 1 1 auto; 即可以拉伸也可以收缩 */
        flex: none; /* 相当于 flex: 0 0 auto; 即不可拉伸也不可收缩 */
        flex: 正整数; /* 相当于 flex: 1 1 0; 即可以在 flex-basis==0的基础上伸缩
    }
    
    /* 每个flex项占用空间相等, 最小值是200px */
    flex项 {
        flex: 1 200px;
    }
    /* 第二个flex项是其他的2倍 */
    flex项:nth-of-type(2) {
        flex: 2 200px;
    }
    
  • order:flex项的排列顺序, 默认为0,值越小越靠前

    /* 第一个按钮移到主轴的末尾 */
    button:first-child {
        order: 1;
    }
    /* 第二个按钮移动到主轴的最前面 */
    button:last-child {
        order: -1;
    }
    
  • align-self:可使自己覆盖flex容器上设置的 align-items 值

    flex-item {
        align-self: auto; /* 默认值,继承flex容器的align-items值 */
        align-self: flex-start / flex-end / center / stretch; /* 与align-items值的含义类似 */
    }
    

网格布局display:grid

grid布局是二维布局,能把内容按照行与列的格式排版。

基本概念:

  • 网格容器:采用网格布局的区域;
  • 网格项:容器内的子元素;
  • 网格线:网格的水平和垂直的分界线;
  • 网格轨道:相邻两条网格线之间的空间,即行、列。
  • 网格单元格:被网格线围起来的最小单元格。
  • 网格区域:任意四条网格线组成的空间,包含若干单元格。

使用:

  • 定义:默认创建一列或一行的网格

    .container {
        display: grid; /* 设置⽹格布局,一列 */
        display: inline-grid; /* 设置⽹格布局,一行 */
    }
    
  • 设置行列:

    .container {
        display: grid;
        grid-template-columns: 200px 200px 200px;/*设置3个列,宽度各为200px*/
        grid-template-rows: 200px 200px 200px;/*设置3个行,行高各为200px*/
    }
    
    .container {
        display: grid;
        grid-template-columns: 2fr 1fr 1fr /*设置3个列,宽度比为2:1:1*/
    }
    

    可以混搭:

    container {
        display: grid;
        grid-template-columns: 100px auto 2fr;
    }
    
  • 重复构建行列:repeat()

    .container {
        display: grid;
        grid-template-columns: repeat(3, 2fr 1fr); /*相当于2fr 1fr 2fr 1fr */
    }
    
  • 自动多列填充: auto-fill

    container {
        display: grid;
        grid-template-columns: repeat(auto-fill, 100px); /*包含多个100px列宽的网格,将容器填满*/
    }
    
  • 行列最小尺寸: minmax()

    container {
        display: grid;
        grid-template-columns: 1fr 1fr minmax(200px, 1fr); /*列宽不小于200px,不大于1fr*/
    }
    
  • 网格间隙:gap

    container {
        display: grid;
        grid-template-columns: 2fr 1fr
        gap: 20px 50px; /*行间距20px,列间距50px*/
    
  • 网格区域: grid-template-areas

    • 需要填满网格的每个格子
    • 对于某个横跨多个格子的元素,重复写上那个元素grid-area属性定义的区域名字
    • 所有名字只能出现在⼀个连续的区域,不能在不同的位置出现
    • ⼀个连续的区域必须是⼀个矩形
    • 使用 . 符号,让⼀个格子留空
    .container {
        display: grid;
        grid-template-areas: /* 3⾏2列 */
        "header header"
        "sidebar content"
        "footer footer";
        grid-template-columns: 1fr 3fr;
        grid-gap:20px;
    }
        
    header {
        grid-area: header; /* 指定
    元素的位置 */ } article { grid-area: content; /* 指定
    元素的位置 */ } aside { grid-area: sidebar; } footer { grid-area: footer; }
  • 内容对齐:

    • 设置整个内容区在容器的对齐方式(在容器中设):
      • justify-content 属性是整个内容区域在容器里面的水平位置(左中右),
      • align-content 属性是整个内容 区域的垂直位置(上中下)。
      • place-content 属性是 align-content 属性和 justify-content 属性的合并简写 形式。
    • 设置所有网格项在单元格中的对齐方式(在容器中设):
      • justify-items 属性设置单元格内容的水平位置(左中右),
      • align-items 属性设置单元格内容的垂直位置 (上中下)。
      • place-items 属性是 align-items 属性和 justify-items 属性的合并简写形式。
    • 设置某个网格项在单元格中的对齐方式(在网格项中设)
      • justify-self 属性设置单元格内容的水平位置(左中右),
      • align-self 属性设置单元格内容的垂直位置(上 中下)。
      • place-self 属性是 align-self 属性和 justify-self 属性的合并简写形式。

居中方法总结

水平居中

  • 行盒:

    text-align: center;
    
  • 块盒:

    子元素宽度固定:

    • 方法1: margin: 0 auto

      .inner {
          width: 200px; /* 宽度固定 */
          margin: 0 auto; /* ⽔平居中 */
      }
      
    • 用绝对定位:

      .container {
          width: 500px;
          height: 500px;
          position: relative;
      }
      
      .inner {
          width: 200px; /* 宽度固定 */
          height: 100px;
          position: absolute;
          left: 50%;	/*定位到中线*/
          margin-left: -100px /*外边距设为宽度的一半*/
      }
      

      或者:设定元素的宽度 width ,然后设置左右两边的定位坐标为0(即: left: 0; right: 0 ),并将左右 margin 设 置为 auto 。

      div { /* 假定 div 为 p 的⽗元素 */
          position: relative;
      }
      p {
          width: 200px;
          position: absolute;
          left: 0;
          right: 0;
          margin: 0 auto;
      

    子元素宽度未知:

    • 将子元素设置为行内块元素,然后⽗元素设置 text-align: center 。

      .container {
          width: 500px;
          height: 500px;
          text-align: center; /* 内容居中 */
      }
      .inner{
          display: inline-block; /* 设置为⾏块盒 */
      }
      
  • 多个块盒元素:

    • 方法一: 使⽤ display: inline-block 和 text-align: center

      .container {
          width: 500px;
          height: 500px;
          text-align: center; /* 内容居中 */
      }
      .inner{
          display: inline-block; /* 设置为⾏块盒 */
          width: 100px;
          height: 150px;
      }
      
    • 使用flex布局:

      弹性盒⼦中的 Flex items的⽔平居中可使⽤ justify-content 属性设置,使其中的 Flex items沿主轴对⻬。

      .container {
          width: 500px;
          height: 500px;
          display: flex; 
          justify-content: center /* 在主轴上居中 */
      }
      .inner{
          width: 100px;
          height: 150px;
      }
      

垂直居中

  • 单行行内元素:

    将子元素的行高( line-height )等于高度( height )就可以了。

    .container {
        width: 500px;
        height: 500px;
    }
    .inner{
        display: inline-block; 
        height: 150px;
        line-height: 200px;
    }
    
  • 多行元素:

    • 使用绝对定位:

      .container {
          width: 500px;
          height: 500px;
          position: relative;
      }
      .inner{
          width: 100px;
          height: 100px; /*高度固定*/
          position: absolute;
          top: 50%;	/*定到中线*/
          margin-top: -100px; /*外边距设为高度的一半*/
      }
      

      或设定元素的高度 heigh ,然后设置上下两边的定位坐标为0(即: top: 0; bottom: 0 ),并将上下 margin 设置为 auto 。

      div { /* 假定 div 为 p 的⽗元素 */
          position: relative;
      }
      
      p {
          height: 50px;
          position: absolute;
          top: 0;
          bottom: 0;
          margin-top: auto 0;
      }
      
    • 使用flex布局:

      .container {
          width: 500px;
          height: 500px;
          display: flex;
          align-items: center;
      }
      .inner{
          width: 100px;
          height: 100px;
      }
      
  • 图片文字并排:

    • 使用flex布局:(与上一段代码一致)

    • 给图片设置 vertical-align: middle ,文字盒子设置为 display: inline-block

      * {
      	margin: 0;
          padding: 0;
      }
      
      .container {
          width: 500px;
          height: 500px;
          line-height: 500px;
      }
      .container img {
          display: inline-block;
          vertical-align: middle;
      }
      
      .container p {
          display: inline-block;
      }
      

CSS响应式设计

一些应用

  • a标签去除下划线:

    a {
        text-decoration: none;
    }
    

JavaScript

跨平台、面向对象的脚本语言,用来控制网页行为,网页交互。

js引擎运行

分两步:预解析,再执行代码

  • 预解析:js引擎会把js里面的所有var还有function提升到当前作用域的最前面;
    • 变量预解析(变量提升):把所有的变量声明提升到当前作用域最前面,但不提升赋值操作。
    • 函数预解析(函数提升):把所有的函数声明提升到当前作用域最前面,不会调用函数。
  • 代码执行:按照代码书写顺序从上往下执行。

引入方式

内部脚本:定义在HTML页面中

<script>
	...
</script>

JS代码必须在< script >< /script >之间,可以放置在任何地方,任意数量。一般放在< body >的底部,可改善显示速度,因为脚本执行会拖慢显示。

外部脚本:作为外部JS文件引入

<script src="文件路径"></script>

外部脚本不能包含< script >标签,< script >不能自闭合


基础语法

与java相似,不过语句末的分号;可有可无。

输出语句

window.alert(" ... ")  //写入警告框
document.write(" ... ")  //写入HTML输出
console.log(" ... ")   //写入浏览器控制台
console.dir(object)  //打印元素对象,查看属性,方法
prompt(info) //弹出输入框,用户可以输入

变量

使用 var 关键字来声明变量。(variable)

  • 作用域:全局变量;
  • 变量可以重复声明;
var test = 20;
test = "张三";

JS是弱类型语言,变量可以存放不同类型的值

ES6新增 let 关键字来定义变量,其变量只在let所在的代码块内有效,且不允许重复声明。

ES6新增 const 关键字来声明一个只读的常量。

  • 全局变量 在浏览器关闭时销毁;
  • 局部变量 在程序运行完毕后就销毁;

常量

使用const声量,必须初始化,不能被修改。

const birthday = '11.22.1922'

数据类型

  • 原始类型:

    • number:数字(整数,小数,NaN(Not a Number))

      .toFixed(x) —— 格式化一个数字,x是要保留的小数点后位数。

    • string:字符,字符串,单双引号皆可

    • boolean:布尔类型

    • null:空

    • undefined:变量未初始化时的默认值

    使用typeof运算符可以获取数据类型

    typedef 变量名
    
  • 引用类型

类型转换

  • 其他类型转为number:
    • string:按字符的字面值转为数字,如果字面值不是数字,则转为NaN。一般使用正负号 或 parseInt 进行转化。
    • boolean:true 转为 1, false 转为 0.
  • 其他类型转为boolean:
    • number:0和NaN转为 false,其他转为 true
    • string:空字符串转为 false,其他转为true
    • null:转为false
    • nudefined:转为false

运算符

关系运算符

  • == :先判断类型是否一致,不一致会进行类型转换再比较两个值;
  • === :(全等于)如果类型不一致,会直接返回false,类型一致时才会比较两个值。

函数

函数通过function关键字进行定义。

function functionName(参数列表){
	......
}
//形式参数不需要类型,返回值也不需要定义类型,因为JavaScreipt是弱类型语言
function add(a,b){
    return a + b;
}
    
//定义方式二
var functionName = function(参数列表){...}
var add = function(a,b){
    return a + b;
}
//调用,JS函数调用函数,可以传递任意个参数个数
let result = add(1,2,3);
let result = add(1);
                                  
//立即执行函数,作用:立即执行,同时也独立创建了一个作用域,里面所有变量都是局部变量,避免命名冲突;
(function(){})();
(function(){}());                               //如: 
(function(a,b){
    console(a + b);
})(2,3);
(function(a,b){
    console.log(a + b);
}(2,3));

arguments

是当前函数的内置对象,存储了传递的所有实参。其展示形式是一个伪数组,可以遍历,有lenght属性,有索引,没有push,pop等方法。

内部函数可以访问外部函数的变量:采用链式查找的方式来决定取哪个值,即找最近的——作用域链。

匿名函数:没有名字的函数,通常与事件处理程序一起使用。

const myButton = document.querySelector('button');

myButton.onclick = function() { // 匿名函数
    alert('hello');
}

const textBox = document.querySelector('#text-box');

textBox.addEventListener('keydown', function(event) {
	console.log(`You pressed "${event.key}".`);
});

箭头函数: 尽量使用箭头函数(更简洁)

// 前面的匿名函数也可以写成如下的箭头函数的形式
textBox.addEventListener('keydown', (event) => {
    console.log(`You pressed "${event.key}".`);
});

// 如果函数体只有一条语句,还可以省略花括号
textBox.addEventListener('keydown', (event) => console.log(`You pressed
"${event.key}".`));

// 如果函数只有一个参数,还可以省略参数的括号
textBox.addEventListener('keydown', event => console.log(`You pressed
"${event.key}".`));

// 如果只有一个返回值,且函数体只有一条语句,可省略掉return语句
const originals = [1, 2, 3];
const doubled = originals.map((item) => item * 2);	// 将原始数组的每个元素乘以2得到新的数组

let sum = (a, b) => a + b;
alert(sum(1,3));  // 3

常用对象

Array对象

Array用于定义数组

  • 创建方法:

    • 一、var 变量名 = new Array(元素列表);
    var arr = new Array(1,2,3);
    
    • 二、var 变量名 = [元素列表];
    var arr = [1,2,3]
    
  • 属性:

    length:数组中元素的个数

    push:末尾添加一个元素; unshift:开头添加一个元素

    var arrs = [1,2,3];
    arrs.push(10);
    

    pop:末尾删除一个元素;shift:开头删除一个元素

    indexof:查找元素

    splice:删除多个元素

    arrs.splice(0,2); //参数:从0号位开始删,删2个
    
  • 遍历数组:

    const array = [1,2,3];
    for(const e of array){
        console.log(e);
    }
    
  • 字符串和数组的转化:

    const data = 'aa,bb,cc,dd';
    
    const array = data.split(',');
    
    const string = array.join(',');
    cosnt string2 = array.toString();
    

String对象

  • 创建方法:

    • var 变量名 = new String(s);

    • var 变量名 = s;

      var str = new String("hello");
      
  • 属性:

    length:字符串的长度

  • 方法:

    string[0]:查看指定下标位置的字符

    .chaAt():返回在指定位置的字符

    .indexOf():检索指定字符串

    .trim():去除字符串前后的空格

    .concat(str1,str2…):链接多个字符串,等效+,+更常用

    .substr(start,lenght):从start开始,取lenght个字符

    .splice(a,b):提取下标a到b-1的字符串,只有a下标的话,取下标a之后剩下的字符串。

    .replace(a,b):将a替换成b

    .includes(string):是否包含某字符串

    .startswith(string):是否以某字符串开头

    .endswith(string):是否以某字符串结束

Date对象

和Math不同,Date对象需要实例化后才能使用。

Date() ——(没有参数)返回系统的当前时间

使用 .valueOf() 或 getTime() 来获得总的毫秒数(时间戳),从1970年1月1日到现在。

有更常用的写法:将 +new Date() 实例化,也可获得总的毫秒数。

H5新增的获取方法: Date.now()

方法名 说明
getFullYear() 获取当年
getMonth() 获取当月(0~11)
getDate() 获取当天日期
getDay() 获取星期几(周期0 到 周六6)
getHours() 当前小时
getMinutes() 当前分钟
getSeconds() 当前秒

自定义对象

格式:

  • var 对象名 = {属性名 : 属性值,… 函数名 : function(参数){} … };

  • 或者使用:var 对象名 = new Object(); 来创造一个空的对象,再利用追加属性的方法,往里面添加数据。

  • 使用构造函数来创建对象:

    function 构造函数名(参数值){ this.属性 = 值; this.方法 = function(){} }————调用时,用“new 构造方法名” 赋值给变量。

    注:构造函数名字首字母要大写

var person = {
	name:"zhangsan",
	age:23,
	eat:function(){
		alert("干饭");
	}
};

var obj = new Object();
obj.name = "zhangsan"

function People(name,age,sex){
    this.name = name;
    this.age = age;
    this.sex = sex;
    this.sing = function(sang){
        sonsole.log(sang);
    }
}
var zhangsan = new People('刘德华'19'男');

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

调用方法:对象名.方法名

遍历对象属性:for…in可以对数组或对象进行遍历。

for(var k in obj){	
    console.log(k);	//k变量输出得到的是属性名
    console.log(obj[k]); //obj[k]得到的是属性值
}

JS执行机制

JS是单线程的,即同一时间只能做一件事,这意味着所有任务需要排队,如果JS执行时间过长,会导致页面渲染不流畅。

于是,HTML5提出Web Worker标准,允许JS脚本创建多个线程。于是就有了同步和异步。

  • 同步

    程序之间的执行顺序与排列顺序一致,即同步。

  • 异步

    执行某程序的同时可以执行另一个程序,即异步。

  • 同步任务

    同步任务都在主线程执行,形成一个执行栈

  • 异步任务

    JS的异步是通过回调函数实现的,一般而言,异步任务有三种:

    • 普通事件:如click,resize
    • 资源加载:如load,error
    • 定时器:如setInterval,setTimeout

    异步任务相关的回调函数会添加到任务队列(消息队列)中。

执行机制:

  1. 先执行执行栈中的同步任务;

  2. 遇到异步任务,将其回调函数放入任务队列中;

    异步任务会先交给异步进程处理,只有异步任务的事件发生,或如click点击了,setInterval的时间到了,才会把相关的回调函数放入任务队列。

  3. 等执行栈中的所有同步任务执行完毕后,系统会按次序读取任务队列中的异步任务,使其进入执行栈,开始执行。

    事件循环:主线程不断的重复获取任务,执行任务,再获取任务,反复循环。

BOM对象

Browser Object Model 浏览器对象模型,JS将浏览器的各个组成部分封装成对象:Window,Navigator,Screen,History,Location。

  • Window对象:浏览器窗口对象

    • 获取:直接使用window,其中window. 可以省略。

      window.alert();
      
    • 属性:获取其他四个BOM对象

    • 方法:

      • alert() 显示带有一段消息和一个确认的警告框
      • confirm() 显示带有一段消息和确认和取消的对话框,点确定会返回ture,点取消会返回false
      • setInterval() 按照指定的周期(毫秒计)来调用函数或计算表达式(定时器,循环执行)
      • setTimeout() 在指定的毫秒后调用函数或计算表达式(定时器,只执行一次)
  • Navigator:浏览器对象

    常用:userAgent 返回由客服端发送给服务器的user-agent头部的值。

    使用下面代码尅判断用户在那个终端打开页面,以实现跳转:

    if ((navigator.userAgent.match(/(phone|pad| pod|iPhone|iPod|ios|iPad|Android|Mobile|BlackBerry|IEMobile|MOOBrowser|JUC|Fennec|wosBrowser|BrowserNG|Webos|Symbian|Windows Phone)/i))){
    	window.location.href =""	//手机
    }else{
    	window.location.href =""	//电脑
    }
    
  • Screen:屏幕对象

  • History:历史记录对象

    • 获取:使用window.history获取,其中window. 可以省略。

      window.history.方法();
      history.方法();
      
    • 方法:

      • back() 后退,加载history列表的前一个url
      • forward() 前进,加载history列表的下一个url
      • go(参数) 参数为n,前进n个页面,参数为-n,后退n个页面
  • Location:地址栏对象

    • 获取:使用window.location获取,其中window. 可以省略。

      window.location.方法();
      location.方法();
      

      URL:同一资源定位符 Uniform Resource Locator

      是互联网上标准资源的地址,互联网的每个文件都有唯一的url,它包含的信息指出文件的位置,以及浏览器应该怎么处理它。

      格式:

      protocol://host[:port]/path/[?query]#fragment
      如:http:/www.baidu.cn/index.html?name=andy&age=18#link
      
      组成 说明
      protocol 通信协议常用的http, ftp, maito 等
      host 主机(域名)
      port 端口号,可选,省略时使用方案的默认端口如http的默认端口为80
      path 路径,由零或多个 ‘/’ 符号隔开的字符串,一般用来表示主机上的一个目录或文件地址
      query 参数,以键值对的形式,通过&符号分隔开来
      fragment 片段,#后面内容,常见于链接、锚点
    • 属性:

      location.href 设置或返回完整的url

      location.host 返回主机/域名

      location.port 返回端口号,如果未写则返回空字符串

      location.pathname 返回路径

      location.search 返回参数

      location.hash 返回片段

      案例:第一页面,使用提交表单,url里的参数会携带表单的数据到另一个页面。

      
      <form action="index.html"
            用户名:  type="text" name="uname">
      	  <input type="submit" value="登录">
      form>
      
      
      
      var arr = location.search.substr(1).split('=');  
          
          
          <div id="root">
              <h1>hello {{name}}h1>
          div>
      body>
      
      <script>
          Vue.config.productionTip = false //阻止vue在启动时生产提示(本地url地址时没接网络可能报一些错,但不影响运行)
      
          //创建Vue实例
          new Vue({
              el: '#root',    //el用于指定当前Vue示例为哪个容器服务
              data: {         //data中用于存储数据,数据供el指定的容器所使用
                  name: 'valcanoZz'
              },
          })
      script>
      
    • 基本使用

      模板语法

      • 插值语法 —— 用于解析标签体内容。
        • 写法:{{xxx}},xxx是js表达式,且可以直接读取到data中的所有属性。
      • 指令语法:—— 用于解析标签(包括:标签属性、标签体内容、绑定事件…)
        • 举例:v-bind: href=“xxx” 或 简写为 :href=“xxx”,xxx同样要写js表达式,
          且可以直接读取到data中的所有属性。
        • 注:Vue中有很多的指令,且形式都是:v-???,此处只是拿v-bind举个例子。
      <body>
          <div id="app">
              
              <h1>插值语法 --> {{name}}h1>
              
              <a v-bind:href="url">指令语法a>
              <a :href="url">指令语法 v-bind:的简写a>
          div>
      body>
      
      <script>
          Vue.config.productionTip = false
          new Vue({
              el: '#app',
              data: {
                  name: 'zzc',
                  url: 'http://www.baidu.com'
              }
          })
      script>
      

      数据绑定

      • 单向数据绑定(v-bind)—— 数据只能从data流向页面;
      • 双向数据绑定(v-model)—— 数据不仅能从data流向页面,还可以从页面流向data;

      v-model 只能用于表单类元素,因为只有表单类元素才有需求更改数据。

      <body>
          <div id="app">
              单向数据绑定:<input type="text" :value="name"><br />
              
              
              双向数据绑定:<input type="text" v-model:value="name"><br>
              
              双向数据绑定简写:<input type="text" v-model="name">
              
          div>
      body>
      
      <script>
          Vue.config.productionTip = false
          new Vue({
              el: '#app',
              data: {
                  name: 'zzc',
              }
          })
      script>
      

      el与data的写法

      一个重要的原则:

      Vue管理的函数,一定不要写箭头函数,一旦写了箭头函数,就不再是Vue实例了。

      <body>
          <div id="app">
              <h1>你好,{{name}}h1>
          div>
      body>
      
      <script>
          Vue.config.productionTip = false
          const vm = new Vue({
              el: '#app',         //el第一种写法
              data: {                 //data第一种写法:对象式
                  name: 'zzc',
              }
          })
      
          //el第二种写法
          vm.$mount('#app')  //更灵活, 比如可以等1秒后再让Vue挂载容器
          
          //data的第二写法:函数式 —————— 组件必须采用函数式
          //注意:data不要写箭头函数,否侧Vue实例调用不到,调用者往外为window
          new Vue({
              el: '#app',
              data() {
                  console.log('@@@',this) //此处的this是Vue实例对象
                  return {
                      name:'zzc'
                  }
              },
          })
      script>
      

      事件处理

      事件绑定 —— v-on

      可简写为 @ ;加上小括号也可以传参进去,如果需要接受event对象,要加上$event进行占位;

      事件修饰符

      • prevent:阻止默认事件(常用)
      • stop:阻止事件冒泡(常用)
      • once:事件只触发一次(常用)
      • capture:使用事件的捕获模式
      • self:只有event,target是当前操作的元素时才触发事件
      • passive事件的默认行为立即执行,无需等待事件回调执行完毕
      <body>
          <div id="app">
              <h1>你好,{{name}}h1>
              <button v-on:click="showInfo1">事件绑定: v-onbutton>
              <button @click="showInfo1">事件绑定的简写: 换成@button>
              <button @click="showInfo2(66,$event)">事件绑定: 传参进去,$event作为占位符给event对象button>
              
              
              <div id="app">
              <a href="http://wwww.baidu.com" @click.prevent="showInfo">事件绑定,加".prevent"可阻止默认事件a>
          div>
          div>
      body>
      
      <script>
          new Vue({
              el: '#app',
              data: {             
                  name: 'zzc',
              },
              methods: {                  //在methods中配置函数
                  showInfo1(event) {
                      console.log(event.target);  //event.target是触发事件的对象,即button标签
                      console.log(this);  //这里this是v,即vue实例
                  },
                  showInfo2(a, b) {
                      console.log(a, b);
                  }
              },
          })
      script>
      

      键盘事件

      使用 @keydown.按键别名@keydown.按键别名 来使用键盘事件。

      Vue中常用的按键别名:

      • 回车 => enter
      • 删除 => delete (捕获“删除”和“退格”键)
      • 退出 => esc
      • 空格 => space
      • 换行 => tab (特殊,必须配合keydown去使用)
      • 上 => up
      • 下 => down
      • 左 => left
      • 右 => right
      1. Vue 未提供别名的按键,可以使用按键原始的key值去绑定,但注意要转为kebab-case(短横线命名)

      2. 系统修饰键(用法特殊):ctrl、alt、shift、meta

        • 配合keyup使用:按下修饰键的同时,再按下其他键,随后释放其他键,事件才被触发。
        • 配合keydown使用:正常触发事件。
      3. 也可以使用keyCode去指定具体的按键(不推荐)

      4. Vue.config.keyCodes.自定义键名 = 键码,可以去定制按键别名

      <body>
      	<div id="root">
              <h2>欢迎来到{{name}}学习h2>
              <input type="text" placeholder="按下回车提示输入" @keydown.huiche="showInfo">
          div>
      body>
      
      <script type="text/javascript">
          Vue.config.keyCodes.huiche = 13 //定义了一个别名按键
      
          new Vue({
              el:'#root',
              data:{
                  name:'zzc'
              },
              methods: {
                  showInfo(e){
                      // console.log(e.key,e.keyCode)
                      console.log(e.target.value)
                  }
              },
          })
      script>
      

      计算属性computed

      定义:要用的属性不存在,要通过已有属性计算得来。

      原理:底层借助了Objcet.defineproperty方法提供的getter和setter。

      get函数什么时候执行?

      • 初次读取时会执行一次。
      • 当依赖的数据发生改变时会被再次调用。

      优势:与methods实现相比,内部有缓存机制(复用),效率更高,调试方便。

      注:

      计算属性最终会出现在 Vue实例上,直接读取使用即可。

      如果计算属性要被修改,那必须写set函数去响应修改,且set中要引起计算时依赖的数据发生改变。

      <body>
          <div id="root">
              姓:<input type="text" v-model="firstName"> <br /><br />
              名:<input type="text" v-model="lastName"> <br /><br />
              全名:<span>{{firstName}}-{{lastName}}span><br /><br /> 
              全名:<span>{{fullName1()}}span><br /><br /> 
              全名:<span>{{fullName2}}span><br /><br /> 
              全名:<input type="text" v-model="fullName2"> <br /><br />
          div>
      body>
      
      <script type="text/javascript">
          new Vue({
              el: '#root',
              data: {
                  firstName: '张',
                  lastName: '三'
              },
              methods: {
                  fullName1() {           //没有缓存, 每调用一次就执行一次; 而计算属性有缓存,只在初次读和数据变化时才执行
                      return this.firstName + '-' + this.lastName
                  }
              },
              computed: {
                  fullName2: {
                      //get有什么作用?当有人读取fullName时,get就会被调用,且返回值就作为fullName的值
                      //get什么时候调用?1.初次读取fullName时。2.所依赖的数据发生变化时。
                      get() {
                          // console.log('get被调用了')
                          // console.log(this) //此处的this是vm
                          return this.firstName + '-' + this.lastName
                      },
                      //set什么时候调用? 当fullName被修改时。
                      set(value) {
                          // console.log('set', value)
                          const arr = value.split('-')
                          this.firstName = arr[0]
                          this.lastName = arr[1]
                      }
                  },
                  
                  //计算属性时,如果确定只使用get(), 可以简写, 但注意不要和methods混淆了
                  fullName3(){
                      return this.firstName + '-' + this.lastName
                  }
              }
          })
      script>
      

      监视属性watch

      监视属性 —— watch

      • 当被监视的属性变化时, 回调函数自动调用, 进行相关操作
      • 监视的属性必须存在,才能进行监视!!
      • 监视的两种写法:
        1. new Vue时传入watch配置
        2. 通过vm.$watch监视

      深度监视 ——

      • Vue中的watch默认不监测对象内部值的改变(只管理一层)。

      • 配置deep:true可以监测对象内部值改变(多层)。

        注:
        Vue自身可以监测对象内部值的改变,但Vue提供的watch默认不可以!
        使用watch时根据数据的具体结构,决定是否采用深度监视。

      <body>
          <div id="app">
              <h2>今天天气很 {{info}} h2>
              <button @click="isHot = !isHot">切换button>
      
              <h3>a的值是:{{numbers.a}}h3>
              <button @click="numbers.a++">点我让a+1button>
      
              <h3>b的值是:{{numbers.b}}h3>
              <button @click="numbers.b++">点我让b+1button>
          div>
      
      body>
      <script type="text/javascript">
          const vm = new Vue({
              el: '#app',
              data: {
                  isHot: true,
                  numbers: {
                      a: 1,
                      b: 1,
                  }
              },
              computed: {
                  info() {
                      return this.isHot ? '炎热' : '凉爽'
                  }
              },
              watch: {
                  isHot: {
                      immediate: true,// immediate:true, //初始化时让handler调用一下
      				//handler什么时候调用?当isHot发生改变时。
                      handler(newValue, oldValue) {
                          console.log("isHot被修改了", newValue, oldValue)
                      }
                  },
                  // 当只有handler时,可以简写:
                  isHot(newValue, oldValue){
                      console.log("isHot被修改了", newValue, oldValue)
                  },
      
                  //监视多级结构中某个属性的变化, 要重新加上引号
                  'numbers.a': {
                      handler() {
                          console.log('a被改变了')
                      }
                  },
                  //监视多级结构中所有属性的变化, 修改属性deep为true
                  numbers: {
                      deep: true,
                      handler() {
                          console.log('numbers改变了')
                      }
                  }
              },
          })
      
          //监视功能 还可以在实例外定义使用
          vm.$watch('isHot', {
              immediate: true,
              handler(newValue, oldValue) {
                  console.log("isHot被修改了", newValue, oldValue)
              },
          })
      script>
      

      computed和watch区别

      • computed能完成的功能,watch都可以完成。

      • watch能完成的功能,computed不一定能完成,例如:watch可以进行异步操作。

      • 两个重要的小原则:

        • 被Vue管理的函数,最好写成普通函数,这样this的指向才是vm 或 组件实例对象。
        • 所有不被Vue所管理的函数(定时器的回调函数、ajax的回调函数等、Promise的回调函数),最好写成箭头函数,这样this的指向才是vm或组件实例对象。

        如:在vue里使用定时器回调函数,要用箭头函数,否则this会指向管理者window;

        <script type="text/javascript">
        	new Vue({
                el:'#root',
                data:{
                    firstName:'张',
                    lastName:'三',
                    fullName:'张-三'
                },
                watch:{
                    //修改firstName后,经过1秒再修改fullName
                    firstName(val){
                        setTimeout(()=>{
                            console.log(this)
                            this.fullName = val + '-' + this.lastName
                        },1000);
                    },
                    lastName(val){
                        this.fullName = this.firstName + '-' + val
                    }
                }
            })
        script>
        

      监视数据

      Vue监视数据的原理:

      1. vue会监视data中所有层次的数据。

      2. 如何监测对象中的数据?

        通过setter实现监视,且要在new Vue时就传入要监测的数据。

        • 对象中后追加的属性,Vue默认不做响应式处理;
        • 如需给后添加的属性做响应式,请使用如下API:
          • Vue.set (target,propertyName/index,value) 或 vm.$set (target,propertyName/index,value)
      3. 如何监测数组中的数据?

        通过包裹数组更新元素的方法实现,本质就是做了两件事:

        1. 调用原生对应的方法对数组进行更新。
        2. 重新解析模板,进而更新页面。
      4. 在Vue修改数组中的某个元素一定要用如下方法:

        • 使用这些API: push()、pop()、shift()、unshift()、splice()、sort()、reverse()

          push() 向数组的末尾添加一个或者多个元素,并返回新的长度

          pop() 删除并返回数组的最后一个元素

          shift() 删除并返回数组的第一个元素

          unshift() 向数组的开头添加一个或多个元素,并返回新的长度

          splice() 删除元素,并向数组添加新元素

          sort() 对数组的元素进行排序

          reverse() 颠倒数组中元素的顺序

        • Vue.set() 或 vm.$set()

      特别注意:Vue.set() 和 vm.$set() 不能给 vm 或 vm 的根数据对象 添加属性!!!即不能增加data中的第一层数据。

      <body>
          <div id="root">
              <h2>学生信息h2>
      
              <button @click="student.age++">年龄+1button><br>
              <button @click="addSex">添加性别,默认为男button><br>
              <button @click="addFriends">在列表首位添加一个朋友button><br>
              <button @click="updateFriendName">修改第一个朋友的名字: 张三button><br>
              <button @click="addHobby">添加一个爱好button><br>
              <button @click="updateHobby">修改第一爱好button><br>
      
              <h3>姓名: {{student.name}}h3>
              <h3>年龄:{{student.age}} h3>
              <h3>性别:{{student.sex}} h3>
              <h3>爱好: h3>
              <ul>
                  <li v-for="(h, index) in student.hobby" :key="index">
                      {{h}}
                  li>
              ul>
              <h3>朋友们: h3>
              <ul>
                  <li v-for="(f, index) in student.friends" :key="index">
                      {{f.name}} - {{f.age}}
                  li>
              ul>
          div>
      body>
      <script type="text/javascript">
          const vm = new Vue({
              el: '#root',
              data: {
                  student: {
                      name: 'tom',
                      age: 18,
                      hobby: ['书法', '弹琴', '看书'],
                      friends: [
                          { name: 'amy', age: 35 },
                          { name: 'tony', age: 36 }
                      ]
                  }
              },
              methods: {
                  addSex(){
                      Vue.set(this.student,'sex','男')
                  },
                  addFriends(){
                      this.student.friends.unshift({name:'aaa',age:40})
                  },
                  updateFriendName(){
                      this.student.friends[0].name = '张三'   //fridends[0]没有生成get和set方法,但里面的属性name和age,都有对应的get和set方法; 只要Vue有生成对应的get和set方法,都可以直接修改(会响应至页面)
                  },
                  addHobby(){
                      this.student.hobby.push('新加的爱好')	//不能直接改hobby[0],因为hobby[0]没有对应的get和set,修改数据后页面并不会响应
                  },
                  updateHobby(){
                      this.student.hobby.splice(0,1,'修改的爱好')     //删掉第0个,添加一个
                      Vue.set(this.student.hobby, 1, '另一种修改')
                  }
      
              },
          })
      script>
      

      绑定样式

      • class样式

        写法:class=“xxx” xxx可以是字符串、对象、数组。

        • 字符串写法适用于:类名不确定,要动态获取。
        • 对象写法适用于:要绑定多个样式,个数不确定,名字也不确定。
        • 数组写法适用于:要绑定多个样式,个数确定,名字也确定,但不确定用不用。
      • style样式(用的少)

        • :style=“{fontSize: xxx}” 其中xxx是动态值。
        • :style=“[a,b]” 其中a、b是样式对象。
      DOCTYPE html>
      <html lang="en">
      
      <head>
          <meta charset="UTF-8">
          <meta http-equiv="X-UA-Compatible" content="IE=edge">
          <meta name="viewport" content="width=device-width, initial-scale=1.0">
          <title>Documenttitle>
          <script type="text/javascript" src="../js/vue.js">script>
          <style>
              .basic {
                  width: 400px;
                  height: 100px;
                  border: 1px solid black;
              }
      
              .happy {
                  border: 4px solid red;
                  ;
                  background-color: rgba(255, 255, 0, 0.644);
                  background: linear-gradient(30deg, yellow, pink, orange, yellow);
              }
      
              .sad {
                  border: 4px dashed rgb(2, 197, 2);
                  background-color: gray;
              }
      
              .normal {
                  background-color: skyblue;
              }
      
              .sty1 {
                  background-color: yellowgreen;
              }
      
              .sty2 {
                  font-size: 30px;
                  text-shadow: 2px 2px 10px red;
              }
      
              .sty3 {
                  border-radius: 20px;
              }
          style>
      head>
      
      <body>
          
          <div id="root">
              
              <div class="basic" :class="mood" @click="changeMood">{{name}}div> <br/><br/>
      
              
              <div class="basic" :class="classArr">{{name}}div> <br/><br/>
      
              
              <div class="basic" :class="classObj">{{name}}div> <br/><br/>
      
              
              <div class="basic" :style="styleObj">{{name}}div> <br/><br/>
              
              <div class="basic" :style="styleArr">{{name}}div>
          div>
      body>
      
      <script type="text/javascript">
          new Vue({
              el:'#root',
              data:{
                  name:'zzc',
                  mood:'normal',
                  classArr:['sty1','sty2','sty3'],    //class样式 —— 数组写法
                  classObj:{                  //对象写法
                      sty1:false,
                      sty2:false,
                  },
      			//style样式 —— 对象写法
                  styleObj:{                  
                      fontSize: '40px',
                      color:'red',
                  },
                  styleObj2:{
                      backgroundColor:'orange'
                  },
                  //数组写法
                  styleArr:[
                      {
                          fontSize: '40px',
                          color:'blue',
                      },
                      {
                          backgroundColor:'gray'
                      }
                  ]
              },
              methods: {
                  changeMood(){
                      //随机使用三种样式之一
                      const arr = ['happy','sad','normal']	
                      const index = Math.floor(Math.random()*3)
                      this.mood = arr[index]
                  }
              },
          })
      script>
      
      html>
      

      条件渲染

      • v-if
        写法:

        • v-if=“表达式”
        • v-else-if=“表达式”
        • v-else=“表达式”

        适用于:切换频率较低的场景。
        特点:不展示的DOM元素直接被移除。
        注意:v-if可以和:v-else-if、v-else一起使用,但要求结构不能被“打断”。

      • v-show
        写法:v-show=“表达式”

        适用于:切换频率较高的场景。
        特点:不展示的DOM元素未被移除,仅仅是使用样式隐藏掉

      注:使用v-if的时,元素如果被移除了就无法获取到,而使用v-show一定可以获取到。

      <body>
          
          <div id="root">
              <h2>当前的n值是:{{n}}h2>
              <button @click="n++">点我n+1button>
              
              
              <h2 v-show="false">欢迎来到{{name}}h2>
              <h2 v-show="1 === 1">欢迎来到{{name}}h2>
      
              
              <h2 v-if="false">欢迎来到{{name}}h2>
              <h2 v-if="1 === 1">欢迎来到{{name}}h2>
      
              
              <div v-if="n === 1">Angulardiv>
              <div v-else-if="n === 2">Reactdiv>
              <div v-else-if="n === 3">Vuediv>
              <div v-else>哈哈div>
      
              
              <template v-if="n === 1">
                  <h2>你好h2>
                  <h2>zzch2>
                  <h2>广东h2>
              template>
      
          div>
      body>
      
      <script type="text/javascript">
          const vm = new Vue({
              el: '#root',
              data: {
                  name: 'zzc',
                  n: 0
              }
          })
      script>
      

      列表渲染

      基本列表

      使用v-for指令展示列表数据:v-for="(item, index) in items" :key="index"

      注:key的选用,最好使用每条数据的唯一标识作为key, 比如id、手机号、身份证号、学号等唯一值。如果不存在对数据的逆序添加、逆序删除等破坏顺序操作,仅用于渲染列表用于展示,使用index作为key也没有问题。

      由于操作DOM较耗性能,所以会向模拟出虚拟DOM,与旧的虚拟DOM比较,然后才更新视图;

      key的作用:

      • key是虚拟DOM对象的标识,当数据发生变化时,Vue会根据【新数据】生成【新的虚拟DOM】, 随后Vue进行【新虚拟DOM】与【旧虚拟DOM】的差异比较,比较规则如下:

        • 旧虚拟DOM中找到了与新虚拟DOM相同的key:

          ​ ①.若虚拟DOM中内容没变, 直接使用之前的真实DOM!

          ​ ②.若虚拟DOM中内容变了, 则生成新的真实DOM,随后替换掉页面中之前的真实DOM。

        • 旧虚拟DOM中未找到与新虚拟DOM相同的key,则创建新的真实DOM,随后渲染到到页面。

      注:直接用index作为key可能引发一些问题:

      • 若对数据进行:逆序添加、逆序删除等破坏顺序操作,会产生没有必要的真实DOM更新 ==> 界面效果没问题, 但效率低。
      • 如果结构中还包含输入类的DOM,则会产生错误DOM更新 ==> 界面有问题。
      <body>
          <div id="root">
              
              <h2>人员列表 (遍历数组)h2>
              <ul>
                  <li v-for="(p,index) in persons" :key="index">
                      {{p.name}}-{{p.age}}
                  li>
              ul>
      
              <h2>汽车信息(遍历对象)h2>
              <ul>
                  <li v-for="(value, k) in car" :key="k">
                      {{value}}-{{k}}
                  li>
              ul>
      
              <h2>遍历字符串h2>
              <ul>
                  <li v-for="(char,index) in str" :key="index">
                      {{char}}-{{index}}
                  li>
              ul>
      
              <h2>遍历指定次数 h2>
              <ul>
                  <li v-for="(number,index) in 5" :key="index">
                      {{number}}-{{index}}
                  li>
              ul>
          div>
      body>
      <script type="text/javascript">
          new Vue({
              el: '#root',
              data: {
                  persons: [
                      { id: '001', name: '张三', age: 18 },
                      { id: '002', name: '李四', age: 19 },
                      { id: '003', name: '王五', age: 20 },
                  ],
                  car: {
                      name: 'zz',
                      price: '70万',
                      color: 'red'
                  },
                  str: 'hello'
              },
          })
      script>
      
      列表过滤

      使用watch和computed都可以

      <body>
          <div id="root">
              <h2>人员列表h2>
              <input type="text" placeholder="请输入名字" v-model="keyWord">
              <ul>
                  <li v-for="(p,index) of filPerons" :key="index">
                      {{p.name}}-{{p.age}}-{{p.sex}}
                  li>
              ul>
          div>
      body>
      <script type="text/javascript">
          //#region  使用#region和#endregion可以实现代码折叠
          new Vue({
              el: '#root',
              data: {
                  keyWord: '',
                  persons: [
                      { id: '001', name: '马冬梅', age: 19, sex: '女' },
                      { id: '002', name: '周冬雨', age: 20, sex: '女' },
                      { id: '003', name: '周杰伦', age: 21, sex: '男' },
                      { id: '004', name: '温兆伦', age: 22, sex: '男' }
                  ],
                  filPerons: []       //筛选后存放数据的数组,如果用原数组的话,数据会丢失
              },
              watch: {
                  keyWord: {
                      immediate: true,    
                      handler(val) {
                          this.filPerons = this.persons.filter((p) => {
                              return p.name.indexOf(val) !== -1       
                          })
                      }
                  }
              }
          })
          //#endregion
      
          //用computed实现
          new Vue({
              el: '#root',
              data: {
                  keyWord: '',
                  persons: [
                      { id: '001', name: '马冬梅', age: 19, sex: '女' },
                      { id: '002', name: '周冬雨', age: 20, sex: '女' },
                      { id: '003', name: '周杰伦', age: 21, sex: '男' },
                      { id: '004', name: '温兆伦', age: 22, sex: '男' }
                  ]
              },
              computed: {
                  filPerons() {
                      return this.persons.filter((p) => {
                          return p.name.indexOf(this.keyWord) !== -1
                      })
                  }
              }
          }) 
      script>
      

      收集表单数据

      注意事项:

      • 若:,则 v-model收集的是value值,用户输入的就是value值。
      • 若:,则v-model收集的是value值,且要给标签配置value值。
      • 若:
        • 没有配置input的value属性,那么收集的就是checked(勾选 or 未勾选,是布尔值true,false)
        • 配置input的value属性:
          • v-model的初始值是非数组,那么收集的就是checked(勾选 or 未勾选,是布尔值)
          • v-model的初始值是数组,那么收集的的就是value组成的数组

      v-model的三个修饰符:

      • lazy:失去焦点再收集数据
      • number:输入字符串转为有效的数字
      • trim:输入首尾空格过滤
      <body>
          <div id="root">
              <form @submit.prevent="demo">
                  <label for="demo">账号: label>
                  <input type="text" id="demo" v-model="userInfo.ccount"><br><br>
                  <label for="pass">密码: label>
                  <input type="password" id="pass" v-model="userInfo.password"><br><br>
                  
                  年龄: <input type="number" v-model.number="userInfo.age"><br><br>
                  性别:
                  男<input type="radio" name="sex" v-model="userInfo.sex" value="male"><input type="radio" name="sex" v-model="userInfo.sex" value="female"><br><br>
                  爱好:
                  书法<input type="checkbox" v-model="userInfo.hobby" value="书法">
                  学习<input type="checkbox" v-model="userInfo.hobby" value="学习">
                  弹琴<input type="checkbox" v-model="userInfo.hobby" value="弹琴"><br><br>
                  所属校区:
                  <select v-model="userInfo.city">
                      <option value="">请选择校区option>
                      <option value="beijin">北京option>
                      <option value="shanghai">上海option>
                      <option value="shenzhen">深圳4option>
                  select><br><br>
                  其他信息:<br> 
                  <textarea cols="30" rows="10" v-model.lazy="userInfo.other">textarea><br><br>
                  <input type="checkbox" v-model="userInfo.agree"> 阅读并接受<a href="www. baidu.com">《用户协议》a><br><br>
                  <button>提交button>
              form>
          div>
      body>
      <script type="text/javascript">
          new Vue({
              el: '#root',
              data: {
                  userInfo: {
                      account: '',
                      password: '',
                      sex: 'male',
                      age: '',
                      hobby: [],
                      city: 'beijin',
                      other: '',
                      agree: ''
                  }
              },
              methods: {
                  demo() {
                      console.log(JSON.stringify(this._data))
                  }
              },
          })
      script>
      
      

      过滤器

      定义:对要显示的数据进行特定格式化后再显示(适用于一些简单逻辑的处理)。

      语法:

      1. 注册过滤器:Vue.filter(name,callback) 或 new Vue{filters:{}}
      2. 使用过滤器:{{ xxx | 过滤器名}} 或 v-bind:属性 = “xxx | 过滤器名”

      备注:

      • 过滤器也可以接收额外参数、多个过滤器也可以串联
      • 过滤器并没有改变原本的数据, 而是产生新的对应的数据
      <body>
          <div id="root">
              
              <h2>格式化时间: {{fmTime}} h2>
              
              <h2>格式化时间: {{getFmTime()}} h2>
              
              <h2>格式化时间: {{time | timeFormater}} h2>
              
              <h2>格式化时间: {{time | timeFormater('YYYY-MM-DD') | mySlice}} h2>
          div>
      body>
      <script>
          //全局过滤器
          Vue.filter('mySlice', function (value) {
              return value.slice(0, 4)
          })
      
          new Vue({
              el: '#root',
              data: {
                  time: 1621561377603
              },
              computed: {
                  fmTime() {
                      return dayjs(this.time).format('YYYY-MM-DD HH:mm:ss')
                  }
              },
              methods: {
                  getFmTime() {
                      return dayjs().format('YYYY-MM-DD HH:mm:ss')
                  }
              },
              //局部过滤器
              filters: {
                  timeFormater(value, str = 'YYYY年MM月DD日 HH:mm:ss') {
                      return dayjs(value).format(str)
                  },
              }
          })
      script>
      

      内置指令/自定义指令

      常见指令:

      • v-bind —— 单向绑定解析表达式, 可简写为 :xxx

      • v-model —— 双向数据绑定

      • v-for —— 遍历数组/对象/字符串

      • v-on —— 绑定事件监听, 可简写为@

      • v-if —— 条件渲染(动态控制节点是否存存在)

      • v-else —— 条件渲染(动态控制节点是否存存在)

      • v-show —— 条件渲染 (动态控制节点是否展示)

      • v-once —— v-once所在节点在初次动态渲染后,就视为静态内容了。以后数据的改变不会引起v-once所在结构的更新,可以用于优化性能。

      • v-text —— 向其所在的节点中渲染文本内容。
        (与插值语法的区别:v-text会替换掉节点中的内容,{{xx}}则不会。)

      • v-html —— 向指定节点中渲染包含html结构的内容。
        (与插值语法的区别:v-html会替换掉节点中所有的内容,{{xx}}则不会。且v-html可以识别html结构。)

        v-html有安全性问题!!!!
        (1).在网站上动态渲染任意HTML是非常危险的,容易导致XSS攻击。
        (2).一定要在可信的内容上使用v-html,永不要用在用户提交的内容上!

      • v-cloak指令(没有值)—— 本质是一个特殊属性,Vue实例创建完毕并接管容器后,会删掉v-cloak属性。

        使用css的内容不显示 配合v-cloak可以解决网速慢时页面展示出{{xxx}}的问题。

      • v-pre —— 跳过其所在节点的编译过程。可利用它跳过:没有使用指令语法、没有使用插值语法的节点,会加快编译。


      自定义指令:

      定义语法:

      • 局部指令:

        • new Vue({
          	directives:{
          		//配置对象
          		指令名:{
          			bind(element, binding){},
          			inserted(element, binding){},
          			update(element, binding){},
          		}
          	} 
          })
          
        • new Vue({
          	directives:{
          		//回调函数
          		指令名(){}
          	}
          })	
          
      • 全局指令:

        Vue.directive(指令名,配置对象) 或   Vue.directive(指令名,回调函数)
        

      配置对象中常用的3个回调:

      • bind:指令与元素成功绑定时调用。
      • inserted:指令所在元素被插入页面时调用。
      • update:指令所在模板结构被重新解析时调用。

      注:

      指令定义时不加v-,但使用时要加v-;
      指令名如果是多个单词,要使用kebab-case命名方式,不要用camelCase命名。

      <body>
          
          <div id="root">
              <h2>放大后的n的值: <span v-big="n">span> {{n}} h2>
              <input type="text" v-f-Bind:value="n"> <br><br>
              <button @click="n++">n+1button>
          div>
      body>
      <script>
          new Vue({
              el: '#root',
              data: {
                  n : 4,
              },
              directives:{
                  //big函数何时会被调用?
                  //  1.指令与元素成功绑定时(一上来)。
                  //  2.指令所在的模板被重新解析时。
                  big(element, binding){
                      console.log('指令被调用')
                      element.innerText = binding.value * 10
                  },
                  'f-bind':{
                      //指令与元素成功绑定时(一上来)调用
                      bind(element, binding){
                          element.value = binding.value
                      },
                      //指令所在元素被插入页面时调用
                      inserted(element, binding){
                          element.focus()
                      },
                      //指令所在的模板被重新解析时调用
                      update(element, binding){
                          element.value = binding.value
                      },
                  }
              }
          })
      script>
      

      nextTick

      1. 语法:this.$nextTick(回调函数)
      2. 作用:在下一次 DOM 更新结束后执行其指定的回调。
      3. 什么时候用:当改变数据后,要基于更新后的新DOM进行某些操作时,要在nextTick所指定的回调函数中执行。

      如:

      method: {
      	medo(){
      		...
      		this.$nextTick(function(){
      			this.$refs.xxx.focus()
      		})
      	}
      }
      

      Vue实例生命周期

      生命周期,又叫生命周期回调函数、生命周期函数、生命周期钩子。

      本质:是Vue在关键时刻调用的一些特殊名称的函数。

      常用的生命周期钩子:

      1. mounted: 发送ajax请求、启动定时器、绑定自定义事件、订阅消息等【初始化操作】。

      2. beforeDestroy: 清除定时器、解绑自定义事件、取消订阅消息等【收尾工作】。

      关于销毁Vue实例:

      1. 销毁后借助Vue开发者工具看不到任何信息。

      2. 销毁后自定义事件会失效,但原生DOM事件依然有效。

      3. 一般不会在beforeDestroy操作数据,因为即便操作数据,也不会再触发更新流程了。

      javaWeb学习笔记_第3张图片

      <body>
          <div id="root">
              <h2 :style="{opacity}">欢迎学习Vueh2>
              <button @click="opacity = 1">透明度设置为1button>
              <button @click="stop">点我停止变换button>
          div>
      body>
      <script type="text/javascript">
          new Vue({
              el: '#root',
              data: {
                  opacity: 1
              },
              methods: {
                  stop() {
                      //自己调用销毁方法,一般不会这么做
                      this.$destroy()
                  }
              },
              beforeCreate() {
                  console.log('beforeCreate')
              },
              created() {
                  console.log('created')
              },
              beforeMount() {
                  console.log('beforeMount')
              },
              //Vue完成模板的解析并把初始的真实DOM元素放入页面后(挂载完毕)调用mounted
              mounted() {
                  console.log('mounted', this)
                  this.timer = setInterval(() => {
                      console.log('setInterval')
                      this.opacity -= 0.01
                      if (this.opacity <= 0) this.opacity = 1
                  }, 16)
              },
              beforeUpdate() {
                  console.log('beforeUpdate')
              },
              updated() {
                  console.log('updated')
              },
              beforeDestroy() {
                  clearInterval(this.timer)
                  console.log('beforeDestroy')
              },
              destroyed() {
                  console.log('destroyed')
              },
          }) 
      script>
      

      常用事件

      @blur —— 是当元素失去焦点时所触发的事件

      <input type="text" placeholder="请输入内容" @blur="blur"/>
      

      Vue组件化编程

      模块与组件

      模块:向外提供特定功能的js程序,作用是便于复用js,简化js编写,提高js运行效率;(因为js文件多而杂)

      模块化:应用中的js都以模块来编写;

      组件:用来实现局部功能效果的代码合集(html/css/js/图片音频等),作用:便于复用代码,简化项目编码,提高运行效率;(因为界面的功能很复杂)

      组件化:应用中的功能以多组件的方式编写;

      组件

      组件是可复用的 Vue 实例,且带有一个名字。分为:

      • 非单文件组件:一个文件中包含有n个组件
      • 单文件组件:一个文件中只包含一个组件,文件后缀为 “.vue” (常用)

      因为组件是可复用的 Vue 实例,所以它们与 new Vue 接收相同的选项,例如 datacomputedwatchmethods 以及生命周期钩子等。仅有的例外是像 el 这样根实例特有的选项。

      注:: 组件中的data必须为一个函数,不然,这个的组件的一个实例发生改变,其他实例也会发生相同的改变。

      data() {
          return {
              name: 'Tom'
          }
      }
      

      Vue中使用组件的步骤:

      1. 定义组件(创建组件);
        • 使用Vue.extend(options)创建,其中options和new Vue(options) 时传入的options几乎一样,但也有点区别:
          • 不能写el,因为最终所有的组件都要经过一个vm的管理,由vm中的el决定服务哪个容器。
          • data必须写成函数,这是为了 避免组件被复用时,数据存在引用关系。
      2. 注册组件;
        • 局部注册:靠new Vue的时候传入components选项
        • 全局注册:靠Vue.component(‘组件名’,组件)
      3. 使用组件:即编写组件标签

      关于组件的命名规范:

      • 一个单词组成:
        • 首字母小写:school
        • 首字母大写:School (推荐)
      • 多个单词组成:
        • kebab-case命名:my-school
        • CamelCase命名:MySchool(需要Vue脚手架支持)(推荐)

      注:组件中可以使用name配置项 该组件在开发者工具中呈现的名字。

      定义组件的简写方式:

      • const school = Vue.extend(options) 可简写为:const school = options

      VueComponent

      组件本质是一个名为VueComponent的构造函数,且不是程序员定义的,是Vue.extend生成的。

      只需要写上组件标签,Vue解析时会帮我们创建该组件的实例对象,即Vue帮我们执行的:new VueComponent(options)。 —— 每次调用Vue.extend,返回的都是一个全新的VueComponent。

      关于this的指向:

      • 组件配置中——

        data函数、methods中的函数、watch中的函数、computed中的函数 它们的 this 均是【VueComponent实例对象】。

      • new Vue(options)配置中——

        data函数、methods中的函数、watch中的函数、computed中的函数 它们的this均是【Vue实例对象】。

      一个重要的内置关系:VueComponent.prototype._proto_ === Vue.prototype

      这个关系让 组件实例对象(vc)可以访问到 Vue原型上的属性、方法。

      javaWeb学习笔记_第4张图片

      非单文件组件

      <body>
          <div id="root">
              
              <hello>hello>
              <hr>
              <school>school>
          div>
      body>
      <script>
          //第一步:创建student组件
          const student = Vue.extend({
              template: `
      				

      学生姓名:{{studentName}}

      学生年龄:{{age}}

      `
      , data() { return { studentName: 'zzc', age: 18 } } }) //第一步:创建school组件 const school = Vue.extend({ template: `

      学校名称:{{schoolName}}

      学校地址:{{address}}



      `
      , //组件嵌套 components: { student, student_1: student }, data() { return { schoolName: 'zzc', address: '广东广州', } }, methods: { showName() { alert(this.schoolName) } }, }) //第一步:创建hello组件 const hello = Vue.extend({ template: `

      你好啊!{{name}}

      `
      , data() { return { name: 'Tom' } } }) //第二步:全局注册组件 Vue.component('hello', hello) new Vue({ el: '#root', //第二步:注册组件(局部注册) components: { school, }, data: { msg: 'Vue' } })
      script>

      单文件组件

      一般将不同的页面功能 写成多个 .vue文件,由一个App.vue 进行汇总,然后让 main.js 引入 App.vue;

      组件结构快捷模板: 输入

      代码格式:

      App.vue文件:

      
      
      
      
      
      

      main.js:

      import App from './App.vue'
      
      new Vue({
          el: '#root',
          components:{
              App
          }
      })
      

      使用Vue脚手架

      Vue脚手架(Vue CLI,command line interface)是 Vue官方提供的标准化开发工具(开发平台)

      初始化脚手架

      初始化步骤 ——————

      1. 仅第一次执行时,全局安装@vue/cli, 在命令行窗口输入 “npm install -g @vue/cli”
      2. 切换到要创建项目的目录,输入命令 “vue create 项目名”
      3. 进入到项目中,启动项目 “npm run serve”

      如出现下载缓慢可以 配置 npm 淘宝镜像:npm config set registry https://registry.npm.taobao.org

      目录结构 ——————

      • node_modules
      • public
        • index.html 主页面
      • src
        • assets 存放静态资源
        • components 存放组件
        • App.vue 用于汇总所有组件
        • main.js 入口文件
      • .gitignore git版本管理忽略配置
      • **babel.config.js ** babel的配置文件
      • package.json 应用包配置文件
      • README.md 应用描述文件
      • package-lock.json 包版本控制文件

      render函数 ——————

      在main.js中用到了render函数,作用是将App组件放入容器,因为在main.js中引入了精简的vue,其中不包含vue的模板解析器,所以render的作用就是代替模板解析器,节省掉这部分代码。

      vue.js与vue.runtime.xxx.js的区别:
      (1).vue.js是完整版的Vue,包含:核心功能+模板解析器。
      (2).vue.runtime.xxx.js是运行版的Vue,只包含:核心功能;没有模板解析器。

      因为vue.runtime.xxx.js没有模板解析器,所以不能使用template配置项,需要使用render函数接收到的createElement函数去指定具体内容。

      render: h => h(App),
      //上面是简写
      render(h){
      	return h(App),
      }
      

      vue.config.js 配置文件 ——————

      • 使用命令 vue inspect > output.js 可以将Vue脚手架的默认配置输出到output.js文件中查看;
      • 使用vue.config.js 配置文件可以对脚手架进行个性化定制,详情见 配置参考 | Vue CLI

      如:

      module.exports = {
          pages:{
              index: {
                  //入口文件
                  entry: 'src/main.js',
              },
          },
        	lintOnSave: false //关闭语法检查
      }
      

      ref与props

      ref属性:

      1. 被用来给元素或子组件注册引用信息(id的替代者)
      2. 应用在html标签上获取的是真实DOM元素,应用在组件标签上是组件实例对象(vc)
      3. 使用方式:
        1. 打标识:

          .....

        2. 获取:this.$refs.xxx

      props配置项:

      1. 功能:让组件接收外部传过来的数据,父组件==>子组件

      2. 传递数据:<组件名 name="xxx"/>

      3. 接收数据:

        1. 第一种方式(只接收):props:['name']

        2. 第二种方式(限制类型):props:{name:String}

        3. 第三种方式(限制类型、限制必要性、指定默认值):

          props:{
          	name:{
          	type:String, //类型
          	required:true, //必要性
          	default:'老王' //默认值
          	}
          }
          

        备注:props是只读的,Vue底层会监测对props的修改,如果进行了修改,就会发出警告;
        若业务需求确实需要修改,那么请复制props的内容到data中一份,然后去修改data中的数据。

        (props的内容会比data先准备好)

        //data中的'myName'的值是 props中的'name', 使用'name'不能修改,而'myName'就可以进行修改
        data(){
        	return{
        		myName: this.name
        	}
        }
        props:['name','age']
        

      混入mixin

      功能:可以把多个组件共用的配置提取成一个混入对象

      使用方式:

      1. 第一步定义混合:定义 .js文件,写下混入的内容

        export const mixin1 = {
            methods: {
                showName() {
                    alert(this.name)
                }
            },
        }
        export const mixin2 = {
            data() {
                return {
                    x: 100,
                    y: 200
                }
            }
        }
        
      2. 第二步使用混入:

        ​ 全局混入:Vue.mixin(xxx) ,在main.js中引入,全局有效
        ​ 局部混入:mixins:['xxx'] ,在组件中各自引入

        <script>
            //局部引入
            import {mixin1} from "../mixin"
        
            export default {
              name: "MySchool",
           	  //配置项mixins: 配置多个混入
              mixins: [mixin1]
            };
        script>
        
        //在main.js中 全局引入及配置
        import {mixin1} from "./mixin"
        Vue.mixin(mixin1)
        

      插件

      功能:用于增强Vue

      本质:包含install方法的一个对象,install的第一个参数是Vue,第二个以后的参数是插件使用者传递的数据。

      1. 定义插件:

        //创建一个plugins.js文件,定义插件
        对象.install = function (Vue, options) {
            // 1. 添加全局过滤器
            Vue.filter(....)
        
            // 2. 添加全局指令
            Vue.directive(....)
        
            // 3. 配置全局混入(合)
            Vue.mixin(....)
        
            // 4. 添加实例方法
            Vue.prototype.$myMethod = function () {...}
            Vue.prototype.$myProperty = xxxx
        }
        
        //只有一个对象
        export default{
            install(Vue){
                Vue.directive(....)
                Vue.mixin(....)
                ....
            }
        }
        
      2. 使用插件:

        import plugins from './plugins'
        Vue.use(plugins)
        

        Vue.use()

      scoped样式

      1. 作用:让样式在局部生效,防止冲突。
      2. 写法: