当前位置: 首页 > article >正文

Web三件套学习笔记

<!-- HTML -->

HTML是超文本标记语言

1、html常用标签

块级标签

  • 独占一行

  • 可以设置宽度,高度,margin,padding

  • 宽度默认所在容器的宽度

标签作用
table定义表格
h1 ~ h6定义标题
hr定义一条水平线
p定义段落
li标签定义列表项目
ul定义无序列表
ol定义有序列表
div定义文档中的分区或节
form创建 HTML 表单

table标签

<table  border="1" cellpadding="0" cellspacing="0"  width="500" height="249">
    <thead >
    <tr>
        <th>序号</th>
        <th>name</th>
    </tr>
    </thead>
    <tbody>
    <tr>
        <td>1</td>
        <td>枫枫</td>
    </tr>
    <tr>
        <td>2</td>
        <td>张三</td>
    </tr>
    </tbody>
</table>
<!--align属性名,属性值为left center right,规定表格相对周围元素的对齐方式-->
<!--border属性名,属性值1或"",规定表格是否有边框,默认为"",表示没有边框-->
<!--cellpadding属性名,属性值像素值,单元格内容和边框之间的空白,默认为1-->
<!--cellspacing属性名,属性值像素值,单元格和单元格之间的距离,默认为2-->
<!--width属性名,属性值像素值或百分比,规定表格的宽度-->
<!--height属性名,属性值像素值或百分比,规定表格的高度-->

列表标签

有缩进 有序标签可以通过type属性设置

<!-- 可以选择:i A 1 a I -->
<ol type="I"><li>有序</li><li>标签</li></ol>

form标签

<form action="/xxx" method="get" name="form1">
    <!-- action提交地址 method提交方式-->
    <input name="name">
    <input value="提交" type="submit"/>
    <input type="submit">提交</form>
    <input value="重置" type="reset"/>
</form>
属性描述
accept-charset规定在被提交表单中使用的字符集(默认:页面字符集)
action规定向何处提交表单的地址(URL)(提交页面)
autocomplete规定浏览器应该自动完成表单(默认:开启)
enctype规定被提交数据的编码(默认:url-encoded
method规定在提交表单时所用的 HTTP 方法(默认:GET)
name规定识别表单的名称(对于 DOM 使用:document.forms.name
novalidate规定浏览器不验证表单
target规定 action 属性中地址的目标(默认:_self)

行内标签

  • 与其他行内元素并排

  • 设置宽高无效

  • 默认的宽度就是文本内容的宽度

  • 水平方向的 padding 和 margin 属性可以使用。

  • 只能容纳文本级元素和内联元素

标签作用
a标签定义超链接
span组合文档中的行内元素
br定义换行
b定义字体缩写
label标签
表单标签input textarea select
img图片

a标签

<a href="" target="_blank">新标签页打开</a>
<a href="" download>下载</a>
<a href="" download="a1.png">会用a1.png作为名字进行下载</a>

target

  • _blank 表示在新标签页中打开目标网页

  • _self 表示在当前标签页中打开目标网页

download:用于下载

input标签

type属性值表现形式对应代码
text单行输入文本<input type=text" />
password密码输入框 
date日期输入框 
checkbox复选框<input type="checkbox" name="sg1" value="pg">苹果
radio单选框<input type="radio" name="sg" value="pg">苹果
submit提交按钮 
reset重置按钮 
button普通按钮 
hidden隐藏输入框 
file文本选择框 

属性说明:

  • name:表单提交时的 键,注意和id的区别

  • value:表单提交时对应项的值

    • type="button", "reset", "submit"时,为按钮上显示的文本内容

    • type="text","password","hidden"时,为输入框的初始值

    • type="checkbox", "radio", "file",为输入相关联的值

  • checkedradiocheckbox默认被选中的项

  • readonlytext和password设置只读

  • disabled:禁用,所有input均适用

label标签中的for属性会和input中的id关联

<label for="user">用户名</label>
<input type="text" placeholder="请输入" value="zard" name="name">
<input placeholder="请输入用户名" id="user">
<input type="password">

<label for="file">选择文件</label>
<input id="file" style="dispaly: none" type="file">

select(下拉)标签

<select name="user">
    <option value="1">枫枫</option>
    <option value="2">张三</option>
    <option value="3">王五</option>
</select>

可设置 multiple 表示可多选

img标签

<img src="图片的路径" alt="图片未加载成功时的提示" title="鼠标悬浮时提示信息" width="宽" height="高(宽高两个属性只用一个会自动等比缩放)">

span和div

span是行内标签中的默认标签

div是块级标签中的默认标签

方便去通过css设置样式

2、相对路径与绝对路径

文件的相对路径和绝对路径

相对路径
<img src="./avatar.png" alt="">
<img src="avatar.png" alt="">

绝对路径
<img src="G:\IT\前端项目\qianduan_study\html\avatar.png" alt="">

web中相对路径和绝对路径

相对路径
<form action="xxx">
    <input type="submit" value="提交">
</form>

绝对路径
<form action="/xxx">
    <input type="submit" value="提交">
</form>
// 相对路径
http://localhost:63342/qianduan_study/html/4.%E7%9B%B8%E5%AF%B9%E8%B7%AF%E5%BE%84%E5%92%8C%E7%BB%9D%E5%AF%B9%E8%B7%AF%E5%BE%84.html
提交 地址 变成了
http://localhost:63342/qianduan_study/html/xxx?
// 绝对路径
http://localhost:63342/qianduan_study/html/4.%E7%9B%B8%E5%AF%B9%E8%B7%AF%E5%BE%84%E5%92%8C%E7%BB%9D%E5%AF%B9%E8%B7%AF%E5%BE%84.html
提交 地址 变成了
http://localhost:63342/xxx?

<!-- css -->

css引入方式

  • 外部引入

    • <link rel="stylesheet" href="index.css">
  • 内部样式

  • 行内样式

层叠样式表

  • 优先级(权重最重要)

  • 同级后面的会覆盖前面的

1、css选择器

id选择器

特点:id是唯一的,不能重复

<div id="box"></div>
#box{}

类选择器

<div class="box"></div>
.box{}

标签选择器

<div id="box"></div>
div{}

属性选择器 []

<div id="box" ></div>
<a href="https://www.baidu.com"></a>
div[id="box"]{}
a[href]{}
a[href="https://www.baidu.com"]{}

通用选择器

给网页元素做一些通用的样式,margin:0padding:0用来清除自带网页的内外间距。

*{
    margin: 0;
    padding: 0;
}

并集选择器 ,

#box,#xxx{}

交集选择器

<div id="box" class="xxx"></div>
#box.xxx{}

后代选择器

<div id="box">
    <div class="sub">
        <div class="s1">
        </div>
    </div>
</div>
.box .s1 {}

子选择器

<div id="box">
    <div class="sub">
        <div class="s1">
        </div>
    </div>
</div>
.box>.sub>.s1{}

相邻兄弟选择器 -

兄弟只能从上往下选

<div class="s1"></div>
<div class="s2"></div>
<div class="s3"></div>
.s1+.s2{}

普通兄弟选择器 ~

<div class="s1"></div>
<div class="s2"></div>
<div class="s3"></div>
.s1~.s3{}

伪类选择器

  • hover

  • nth-child()

    • <style>
          ul li:nth-child(2){
              color: red;
          }
          /* 参数edd是奇数行,even是偶数行
          还可以写表达式2n+1 */
      </style>
      <ul>
          <li>1</li>
          <li>2</li>
      </ul> 
  • first-child

  • last-child

否定伪类选择器

  • :not()

    • <style>
          .not>div:not(.n){
              font-size:30px;
          }
      </style>
      <div class="not">
          <div class="n">123</div>
          <div>123</div>
      </div>

伪元素选择器

  • before

  • after

    • <!-- 加的伪元素不能被选中 -->
      <style>
          .mys::after{
              content: "";
              width: 20px;
              height: 20px;
              background: blue;
              display: block;  /*inline-block*/
          }
          .mys::before{
              content: "之前";
          }
      </style>
      <div class="mys">
          这是微元素
      </div>

优先级

!important > 内联选择器 > ID选择器 > 类选择器 > 属性选择器 > 伪类 > 元素选择器 > 通配符选择器 > 继承选择器

/* !important  可以更改内联样式 */
.li{
    color: green!important;
}

2、css盒模型

*盒子宽度模式

*{
    box-sizing: border-box;  /* 盒子的宽度模式content-box */
}

*display

  • none:不显示

  • block:块盒,上下的margin会合并

  • inline:行盒,设置之后width、height变成无效

  • inline-block:行内块,设置后和inline一样不过可设置宽高

  • flex布局

  • grid布局

padding

padding-left: 20px;
padding-top: 10px;
padding-right: 20px;
padding-bottom: 10px;
/*四个就是 上 右 下 左;三个就是 上 左右 下;两个就是 上下 左右 */
padding: 20 10 30 40;

margin

基本设置同padding类似

但是margin有auto属性 学flex的时候再说

块盒,上下的margin会合并

border

border-width
border-style  
/* solid实线;dashed虚线;dotted点线;double双实线 */
border-color
border-left-color: blue;

border: 10px solid red;
border-radius: 5px;  /* 圆角上右下左 */
border-radius: 50%;  /* 圆形 */

设置三角形

只需要给盒子的宽度设置为零,然后设置某一个边的宽度和颜色即可

.box{
    width: 0;
    height: 0;
    border-width: 20px;
    border-style: solid;
    border-bottom-color: aqua;
    border-right-color: aquamarine;
    border-top-color: antiquewhite;
    border-left-color: blueviolet;  
    /* 需要什么样的三角形,就让其他的三角形颜色是透明的 transparent; 透明色 */
}

 

outline 设置

轮廓线,属性和border类似

  • 不占用盒子的宽度

  • 只能设置整个的,没有单个方向的

3、css定位

描述
absolute生成绝对定位的元素,相对于 static 定位以外的第一个父元素进行定位。元素的位置通过 left, top, right 以及 bottom 属性进行规定
fixed生成固定定位的元素,相对于浏览器窗口进行定位。元素的位置通过 left, top, right以及 bottom属性进行规定
relative生成相对定位的元素,相对于其正常位置进行定位。因此,left:20 会向元素的 LEFT 位置添加 20 像素
static默认值。没有定位,元素出现在正常的流中(忽略 top, bottom, left, right 或者 z-index 声明)
sticky粘性定位。根据用户的滚动位置进行定位

相对定位 relative

  • 相对元素之前的位置

  • 之前的位置还在文档流中

<style>
    .box{
        display: inline-block;
        width: 100px;
        height: 100px;
        background: aquamarine;
        position: relative;
        left: 100px;
        top: 100px;
    }
    .sub{
        width: 40px;
        height: 40px;
        background: red;
        position: relative;
        left: 70px;
        top: 60px;
    }
</style>
<body>
    相对定位相对定位 
    <div class="box">
    <div class="sub"></div>
    </div> 
    相对定位相对定位相对定位
</body>

绝对定位 absolute

  • 脱离文档流

  • 找父级非static的元素进行偏移,找不到就层层往上,直到body

<style>
    .box{
        display: inline-block;
        width: 100px;
        height: 100px;
        background: aquamarine;
        position: absolute;
        right: 100px;
        top: 100px;
    }
    .sub{
        width: 40px;
        height: 40px;
        background: red;
        position: absolute;
        left: 70px;
        top: 60px;
    }
</style>
<body>
    相对定位相对定位 
    <div class="box">
    <div class="sub"></div>
        1234
    </div> 
    相对定位相对定位相对定位
</body>

固定定位 fixed

  • 脱离文档流

  • 以浏览器为参照

<style>
    .box{
        display: inline-block;
        width: 100%;
        height: 60px;
        background: rgba(0,0,0, 0.5);
        position: fixed;
        top: 0;
        left: 0;
    }
    body{
        height: 2000px;
    }
</style>
<body>
    相对定位相对定位 
    <div class="box"></div>
    相对定位相对定位相对定位
</body>

粘性定位 sticky

粘性定位的元素是依赖于用户的滚动,它的行为就像 position:relative; 而当页面滚动超出目标区域时,它的表现就像 position:fixed;,它会固定在目标位置,元素定位表现为在跨越特定阈值前为相对定位,之后为固定定位

  • 占据原来的位置

  • 以浏览器为参考

<style>
    .d1{
        height: 40px;
        width: 40px;
        background: #b81cc9;
        position: sticky;
        top: 100px;
    }
</style>
<body>
    <div class="d1"></div>
</body>

z-index

图层概念

  • 只能在定位元素上生效

  • 父子关系z-index不生效

.c1{
    position: relative;
    width: 100px;
    height: 100px;
    background-color: blueviolet;
    top: 50px;
    z-index: 1;
}
.c2{
    position: relative;
    width: 100px;
    height: 100px;
    background-color: #2be274;
    left: 50px;
}

4、css背景设置

背景图片

.bg {
    width: 100%;
    height: 200px;
    background-image: url("https://profile-avatar.csdnimg.cn/392dc034291241239877635a77987f39_m0_65534674.jpg!1");
    background-size: 50px;    /* cover占满、contain保证图片一定在盒子里面 */
}

背景尺寸

background-size: contain;		/* 保证图片一定在盒子里面 */
background-size: cover;			/* 占满 */
background-size: 100% 50%;		/* 背景图像宽度为元素宽度,高度为元素高度的一半 */
background-size: 300px auto;	/* 背景图像宽度固定为300px,高度自动调整 */

背景平铺

background-repeat: no-repeat /*不平铺*/
background-repeat: repeat-x /*横向平铺*/
background-repeat: repeat-y /*纵向平铺*/
background-repeat: repeat 	/*双向平铺,默认*/

图片位置

background-position: left bottom;  /* 左上,右上,右下,中心 */
background-position: 10px  20px;  /* 从左上角开始算 */

雪碧图

把多个小图片合到一个大图片里面,然后通过css图片定位方式,把图片显示出来 哔哩哔哩

.bg {
    width: 40px;
    height: 40px;
    background-image: url("https://image.fengfengzhidao.com/rj_0731/20240618113057.png");
    background-position: -10px -266px;
    background-repeat: no-repeat;
}

渐变

好看的渐变色网站

线性渐变

body{
    width: 100%;
    height: 100hv;
    margin: 0;
    background-image: linear-gradient(to top, #a18cd1 0%, #fbc2eb 100%);
}

表示方位

to top  /* 从下往上进行渐变 */
to bottom /* 从上往下进行渐变 */
to right /* 从左往右进行渐变 */
to left /* 从右往左进行渐变 */
to top left /* 从右下向左上进行渐变(top和left可以交换位置,下同) */
to top right /* 从左下向右上进行渐变 */
to bottom left /* 从右上向左下进行渐变 */
to bottom right /* 从左上向右下进行渐变 */
60peg  /* 使用角度表示, 90deg等同于to right */

径向渐变

.radial{
    width: 300px;
    height: 300px;
    background-image: radial-gradient(#a18cd1 0%, #fbc2eb 100%);
}
/* 圆形 */
background-image: radial-gradient(circle, red, blue); 
/* 椭圆形 */
background-image: radial-gradient(ellipse, red, blue); 
/* 重复 */
background-image: repeating-radial-gradient(red, yellow 10%, green 20%);

 

边框渐变

.border{
    width: 300px;
    height: 300px;
    border: 20px solid;
    border-image: linear-gradient(to bottom right, yellow, green) 1 1 1 1;  /* 内向偏移量 上右下左1110>左边没边框 */
}

文字渐变

display: inline-block;  /* 宽度变成文字宽度 */ 
font-size: 30px;
background-image: linear-gradient(to top, #fbc2eb 0%, #a6c1ee 100%);
background-clip: text;
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;

5、css文字设置

字体样式

font-style 可继承

font-style: italic  /* 显示一个斜体的字体样式 */
font-style: oblique  /* 显示一个倾斜的字体样式 */
font-style: normal  /* 默认值, 正常字体 */

text-decoration 文本的划线 可继承

text-decoration: none  /* 不画线,并删除任何现有的装饰 */
text-decoration: underline  /* 下划线 */
text-decoration: line-through  /* 中划线 */
text-decoration: overline  /* 上划线 */
/* 也可以设置宽度和颜色 */
text-decoration: underline 10px coral;

font-weight 可继承

font-weight:bold;

text-indent 文本缩进 可继承

/* 首行缩进2字符 */
text-indent: 2rem;

text-transform 大小写控制 可继承

text-transform: capitalize /* 首字母大写 */
text-transform: uppercase  /* 大写 */
text-transform: lowercase  /* 小写 */
text-transform: none       /* 正常 */

间距

line-height 行间距 可继承

/*1.5倍行距*/
line-height: 1.5rem;

letter-spacing 字符间距 可继承

letter-spacing: 2rem;

word-spacing 单词间距 可继承

word-spacing: 1rem;

空白处理

white-space 可继承

white-space: nowrap;  /* 强制在一行中显示  会出现横向滚动条 */
white-space: pre     /* 换行和空格保留 */
white-space: normal  /* 自动换行 */

超出显示省略号

单行超出显示省略号

/*不换行*/
white-space: nowrap;
/*溢出隐藏*/
overflow: hidden;
/*显示省略号*/
text-overflow: ellipsis;

多行超出显示省略号

/*溢出隐藏*/
overflow: hidden;
/*显示省略号*/
text-overflow: ellipsis;
display: -webkit-box;
-webkit-box-orient: vertical;
/*设置显示文本的行数*/
-webkit-line-clamp: 4;

文本对齐

text-align 水平对齐 可继承 对行内元素无效,行内块需要设置宽度

text-align: left  /* 左对齐 */
text-align: center  /* 居中对齐 */
text-align: right  /* 右对齐 */

vertical-align 垂直对齐 对行内元素或者行内块元素有效

vertical-align: bottom
/* sub设置文本为下标,super设置文本为上标 , top与顶端对齐 ,text-bottom与低端对齐 */

经常用于设置图片或者表单(行内块元素)和文字垂直对齐

<div class="line">
 <span>这是文字</span>
 <img width="100" src="https://img0.baidu.com/it/u=2426072799,1960439289&fm=253&app=120&size=w931&n=0&f=JPEG&fmt=auto?sec=1718816400&t=94b5bbee4836daa4206bfecc6c0baf4b" alt="">
 <span>这是文字</span>
</div>

 

vertical-align: bottom;

 

字体设置

font-family 可继承

/* 可以设置多个字体,第一个没有就找后面的 */
font-family: "宋体", "方正舒体";

导入字体

用 @font-face 导入

@font-face {
    src: url("./ZiXiaoHunLiLiangCuHeiTi(ShangYongXuShouQuan)-2.ttf");
    font-family: "xxx";
}
.line {
    font-family: "xxx";
}

6、css变换与动画

变换 transform

使用变换之后,这个原来的位置还在文档流里

只作用于块和行内块,可以多个属性共存

平移 translate

transform: translate(x, y);

旋转 rotate

transform: rotate(60deg);

缩放 scale

transform: scale(1.2);
/* 缩放,可以破除浏览器12px最小字体大小的限制 */

锚点

主要这对于缩放和旋转

transform-origin: left top;

过渡

transition属性包括以下几个子属性:

  • transition-property:指定要过渡的CSS属性名称,可以使用通配符 all 表示所有属性都要过渡

  • transition-duration:指定过渡的持续时间,单位可以是秒(s)或毫秒(ms)

  • transition-timing-function:指定过渡的时间函数,用于控制过渡的速度曲线,常见的值有 easelinearease-inease-outease-in-out

  • transition-delay:指定过渡的延迟时间,即过渡开始前等待的时间,单位可以是秒(s)或毫秒(ms)

.line{
    display: inline-block;
    transition: transform 1s;  /* all 1s; */
    transform-origin: right top;
}
.line:hover{
    transform: scale(1.2);
}

动画

创建动画序列,需要使用 animation 属性或其子属性,该属性允许配置动画时间、时长以及其他动画细节,但该属性不能配置动画的实际表现,动画的实际表现是由 @keyframes 规则实现

属性描述
animation-name指定由 @keyframes 描述的关键帧名称
animation-duration设置动画一个周期的时长
animation-delay设置延时
animation-direction设置动画在每次运行完后是反向运行还是重新回到开始位置重复运行
animation-iteration-count设置动画重复次数, 可以指定 infinite 无限次重复动画
animation-play-state允许暂停和恢复动画
animation-timing-function设置动画速度, 即通过建立加速度曲线,设置动画在关键帧之间是如何变化
animation-fill-mode规定元素在不播放动画时的样式(在开始前、结束后,或两者同时)

 

/* 
<div class="tags">
    <div class="box"></div>
</div>
*/
.tags {
    position: relative;
    width: 400px;
    height: 400px;
    background: rosybrown;
}
.box {
    position: absolute;
    width: 20px;
    height: 20px;
    background: blue;
    animation-name: move_box; /* 指定由@keyframes描述的关键帧名称 */
    animation-duration: 5s;  /* 执行一次动画的时长 */
    animation-iteration-count: infinite; /* 循环播放 */
}
.tags:hover .box{
    animation-play-state: paused;  /* 允许暂停和恢复动画 */
}
@keyframes move_box {
    0% {
        left: 0;
        top: 0;
    }
    25% {
        left: calc(100% - 20px);
        top: 0;
    }
    50% {
        left: calc(100% - 20px);
        top: calc(100% - 20px);
    }
    75% {
        left: 0;
        top: calc(100% - 20px);
    }
    100% {
        left: 0;
        top: 0;
    }
}
/* <div class="box"></div> */
@keyframes box_move {
    0% {
        transfrom: translate(0, 0);
    }
    100% {
        transfrom: translate(1000px, 0);
    }
}
.box{
    width: 40px;
    height: 40px;
    background-color: #800e0e;
    animation-name: move_box; /* 指定由@keyframes描述的关键帧名称 */
    animation-duration: 5s;  /* 执行一次动画的时长 */
    animation-iteration-count: infinite; /* 循环播放 */
}

7、css中的flex布局

Flexbox 布局也叫 Flex 布局,弹性盒子布局

它决定了元素如何在页面上排列,使它们能在不同的屏幕尺寸和设备下可预测地展现出来,更简便、完整、响应式地实现各种页面布局

它的主要思想是使父元素能够调整子元素的宽度、高度、排列方式,从而更好的适应可用的布局空间

采用 Flex 布局的元素,称为 Flex 容器(flex container),简称"容器"

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

容器属性

flex-direction 主轴方向

决定主轴的方向(即项目的排列方向)

属性值含义
row默认值,主轴为水平方向(水平布局),起点在左端,从左向右排列
row-reverse主轴为水平方向(水平布局),起点在右端,从右向左排列
column主轴为垂直方向(垂直布局),起点在上沿,从上往下排列
column-reverse主轴为垂直方向(垂直布局),起点在下沿,从下往上排列

justify-content 对齐方式

定义了项目在主轴上的对齐方式

属性值含义
flex-start默认值,左对齐
flex-end右对齐
center居中
space-between两端对齐,项目之间的间隔都相等
space-around每个项目两侧的间隔相等。所以,项目之间的间隔比项目与边框的间隔大一倍
space-evenly均匀排列每个元素

align-items 交叉轴对齐方式

定义项目在交叉轴的对齐方式

属性值含义
flex-start交叉轴的起点对齐
flex-end交叉轴的终点对齐
center交叉轴的中点对齐
baseline项目的第一行文字的基线对齐
stretch(默认值) 如果项目未设置高度或设为auto,将占满整个容器的高度

flex-wrap 换行

默认情况下,项目都排在一条线(又称"轴线")上。flex-wrap属性定义,如果一条轴线排不下,如何换行

属性值含义
nowrap默认值,表示不换行
wrap换行
wrap-reverse换行,第一行在下方

flex-flow

flex-flow 属性是 flex-direction 和 flex-wrap 主轴方向和换行的复合属性

flex-flow: row wrap;

align-content

属性和align-items交叉轴对齐方式一样,但是多了space-的设置

align-content适用于多行情况

项目属性

order 排序

order属性用来定义项目的排列顺序。数值越小,排列越靠前,默认为 0

<style>
    .flex1{
        margin-top: 20px;
        width: 400px;
        background-color: #f6bcbe;
        display: flex;
    }
    .flex1 .item{
        order: 10;
    }
</style>
<div class="flex1">
	<div class="item">1</div>
	<div class="item">2</div>
	<div class="item">3</div>
	<div class="item" style="order: 1">4</div>
</div>

flex-grow 放大比例

flex-grow属性定义项目的放大比例,默认为 0 ,即如果存在剩余空间,也不放大

<style>
    .flex1{
        margin-top: 20px;
        width: 400px;
        background-color: #f6bcbe;
        display: flex;
    }
    .flex1 .item{
        margin: 1px;
    }
</style>
<div class="flex1">
	<div class="item">1</div>
	<div class="item">2</div>
	<div class="item">3</div>
	<div class="item" style="flex-grow: 2">4</div>
    <!-- 按剩余空间大小侵占 -->
</div>

flex-shrink

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

<style>
    .flex1{
        margin-top: 20px;
        background-color: #f6bcbe;
        display: flex;
    }
    .flex1 .item{
        width: 100px;
        margin: 1px;
    }
</style>
<div class="flex1">
	<div class="item" style="flex-shrink: 0">1</div>  
    <!-- 缩小到一定程度就不缩小了 -->
	<div class="item">2</div>
	<div class="item">3</div>
	<div class="item" style="flex-grow: 2">4</div>
    <!-- 按剩余空间大小侵占 -->
</div>

flex-basis 设置宽

如果 flex-basis 的值不是 auto,width 属性会被忽略

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

它的初始值是 auto,此时浏览器会检查元素是否设置了 width 属性值

如果有,则使用 width 的值作为 flex-basis 的值;

如果没有,则用元素内容自身的大小

如果 flex-basis 的值不是 auto,width 属性会被忽略

flex

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

.item {
  flex:0 1 auto;
}
.item {
  flex-grow: 0;
  flex-shrink: 1;
  flex-basis: auto;
}

align-self

align-self属性允许单个项目有与其他项目不一样的对齐方式,可覆盖align-items属性。默认值为auto,表示继承父元素的align-items属性,如果没有父元素,则等同于stretch

<style>
    .flex1{
        margin-top: 20px;
        background-color: #f6bcbe;
        display: flex;
    }
    .flex1 .item{
        width: 100px;
        margin: 1px;
    }
</style>
<div class="flex1">
	<div class="item" style="flex-shrink: 0">1</div>  
    <!-- 缩小到一定程度就不缩小了 -->
	<div class="item" style="align-self: center">2</div>
	<div class="item">3</div>
	<div class="item" style="flex-grow: 2">4</div>
    <!-- 按剩余空间大小侵占 -->
</div>

flex与margin auto

之前埋了一个关子,在学习margin的时候。它有一个auto属性需要到flex才能用到

<style>
    .flex1{
        margin-top: 20px;
        width: 400px;
        background-color: #f6bcbe;
        display: flex;
        /* justify-content: space-between; */
    }
    .flex1 .item:nth-child(2){
        margin: 0 auto;
    }
</style>
<div class="flex1">
	<div class="item">1</div>  
	<div class="item">2</div>
	<div class="item">3</div>
</div>

8、css中的grid布局

Flex 布局是轴线布局,只能指定“项目”针对轴线的位置,可以看作是一维布局

Grid 布局则是将容器划分成“行”和“列”,产生单元格,然后指定"项目所在"的单元格,可以看作是二维布局。Grid 布局远比 Flex 布局强大

一般情况下,在处理某一行的元素的布局时使用flex布局;在处理多行的元素布局时使用grid布局

grid解决

 

如果使用flex要实现类似这样的布局,是很麻烦的

需要去算盒子的宽度和中间的间隔

<style>
    body {
        margin: 0;
    }
    .flex {
        background-color: #f0eeee;
        width: 600px;
        display: flex;
        flex-wrap: wrap;
        /* justify-content: space-between; */
    }
    .flex .item{
        width: 135px;
        height: 40px;
        background-color: #3be598;
        margin-bottom: 20px;
    }
    .flex .item:nth-child(4n+1),
    .flex .item:nth-child(4n+2),
    .flex .item:nth-child(4n+3){
        margin-right: 20px;
        /* margin-right: auto; */
    }
</style>
</head>
<body>
    <div class="flex">
        <div class="item"></div>
        <div class="item"></div>
        <div class="item"></div>
        <div class="item"></div>
        <div class="item"></div>
        <div class="item"></div>
        <div class="item"></div>
        <div class="item"></div>
    </div>
</body>

如果不用flex会更复杂,但是也是可以实现的

注意空白折叠!

<style>
    body {
        margin: 0;
    }
    .box {
        background-color: #f0eeee;
        width: 600px;
        margin-top: 20px;
    }
    .box .item{
        width: 135px;
        height: 40px;
        background-color: #3be598;
        display: inline-block;
        margin-bottom: 20px;
    }
    .box .item:nth-child(4n+1),
    .box .item:nth-child(4n+2),
    .box .item:nth-child(4n+3){
        margin-right: 15.2px;
        /* margin-right: calc((100%-1200px)/3); */
    }
</style>
</head>
<body>
    <div class="box">
        <div class="item"></div>
        <div class="item"></div>
        <div class="item"></div>
        <div class="item"></div>
        <div class="item"></div>
        <div class="item"></div>
        <div class="item"></div>
        <div class="item"></div>
    </div>
</body>

但是,如果使用grid,将会超级简单

<style>
    body {
        margin: 0;
    }
    .grid {
        background-color: #f0eeee;
        width: 600px;
        margin-top: 20px;
        display: grid;
        grid-template-columns: repeat(4, 1fr);
        /* grid-row-gap: 20px; */
        row-gap: 20px;
        column-gap: 20px;
    }
    .grid .item{
        width: 100%;
        height: 40px;
        background-color: #3be598;
    }
</style>
</head>
<body>
    <div class="grid">
        <div class="item"></div>
        <div class="item"></div>
        <div class="item"></div>
        <div class="item"></div>
        <div class="item"></div>
        <div class="item"></div>
        <div class="item"></div>
        <div class="item"></div>
    </div>
</body>

grid容器属性

grid-template-columns 划分列数

固定宽度

grid-template-columns: 40px 40px;

百分比

grid-template-columns: 40% 60%;

比例

grid-template-columns: 1fr 2fr;

重复

grid-template-columns: repeat(5, 1fr);  /*5列,每列等宽*/

自动计算列

grid-template-columns: repeat(auto-fill, 600px); /*每列固定600px,自动算多少列*/
grid-template-columns: repeat(auto-fit, 600px); /*每列固定600px,自动算多少列*/

auto

grid-template-columns: 100px auto 100px;

grid-template-rows 划分行数

行列间距

grid-template-columns: repeat(3,1fr);
/*grid-template-rows: repeat(3,1fr);*/
row-gap: 20px;
column-gap: 20px;

 

gap是row-gap和column-gap是简写

容器对齐方式

justify-content 水平对齐方式

justify-content: center;    /* 属性和之前一样 */

align-content 垂直对齐方式

align-content: center;

place-content 是align-content属性和justify-content属性的合并简写形式

place-content: end end;

单元格对齐方式

justify-items

align-items

place-items

align-items属性和justify-items属性的合并简写形式。

justify-items: end;
align-items: end;

 

项目内单元格对齐方式

用法和justify-items类似,但是是在项目属性上写的

<div class="item" style="place-self: end end">1</div>

 

grid项目属性

合并单元格

.item-8{
    grid-column-start: 2;
    grid-column-end: 4;
}

 

.item-5{
  grid-column-start: 2;
  grid-column-end: 4;
  grid-row-start: 2;
  grid-row-end: 4;
}

可简写为

grid-row: 2/4;
grid-column: 2/4;

 

9、css栅格化

css栅格化

UI组件库的基石,整个css布局的核心知识

.row {
    display: flex;
    height: 100px;
}
.col {
    height: 100%;
}
.col-1 {
    flex: 0 0 10%;
}
.col-2 {
    flex: 0 0 20%;
}
.col-3 {
    flex: 0 0 30%;
}
.col-4 {
    flex: 0 0 40%;
}
.col-5 {
    flex: 0 0 50%;
}
.col-6 {
    flex: 0 0 60%;
}
.col-7 {
    flex: 0 0 70%;
}
.col-8 {
    flex: 0 0 80%;
}
.col-9 {
    flex: 0 0 90%;
}
.col-10 {
    flex: 0 0 100%;
}

Bootstrap

  1. 比较早使用css栅格化的ui组件库

  2. 它可以单独使用,不挑前端框架

官方文档

<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4.6.2/dist/css/bootstrap.min.css" integrity="sha384-xOolHFLEh07PJGoPkLv1IbcEPTNtaed2xpHsD9ESMhqIYd0nLMwNLD69Npy4HI+N" crossorigin="anonymous">
<!-- 建议下载下来 -->
https://cdn.jsdelivr.net/npm/bootstrap@4.6.2/dist/css/bootstrap.min.css

10、css实战布局

枫枫博客后台布局

 

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <title>博客后台框架</title>
    <style>
        * {
            box-sizing: border-box;
        }
        body {
            margin: 0;
        }
        .admin {
            display: flex;
        }
        .admin > aside {
            width: 240px;
            height: 100vh;
            background-color: white;
            border-right: 1px solid #f0eeee;
        }
        .admin > aside > .logo {
            height: 90px;
            border-bottom: 1px solid #f0eeee;
        }
        .admin > main {
            width: calc(100% - 240px);
            height: 100vh;
            background-color: white;
        }
        .admin > main > .head {
            height: 60px;
        }
        .admin > main > .tabs {
            height: 30px;
            border-top: 1px solid #f0eeee;
            border-bottom: 1px solid #f0eeee; 
            /* 下划边框线 */
        }
        .admin > main > .container {
            height: calc(100vh - 90px);
            overflow-y: auto; /* 控制滚动条出现的样式 */
            background-color: #f0eeee;
            padding: 20px;
        }
        .default_main {
            width: 100%;
            height: 100%;
            background-color: white;
            border-radius: 5px;
        }
    </style>
</head>
<body>
<div class="admin">
    <aside>
        <div class="logo">
        </div>
        <div class="menu">
        </div>
    </aside>
    <main>
        <div class="head">
        </div>
        <div class="tabs">
        </div>
        <div class="container">
            <div class="default_main">
            </div>
        </div>
    </main>
</div>
</body>
</html>

枫枫博客前台布局

 

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <title>博客前台</title>
    <style>
        body {
            margin: 0;
        }
        * {
            box-sizing: border-box;
        }
        a {
            color: #333;
            text-decoration: none;
        }
        .blog {
        }
        .blog .nav {
            width: 100%;
            height: 60px;
            background-color: rgba(255, 255, 255, 0.8);
            position: fixed;
            top: 0;
            display: flex;
            justify-content: center;
            z-index: 100;
        }
        .blog .nav .container {
            align-items: center;
        }
        .blog .nav .left {
            width: 10%;
        }
        .blog .nav .left div:nth-child(1) {
            font-size: 22px;
        }
        .blog .nav .left div:nth-child(2) {
            font-size: 12px;
        }
        .blog .nav .center {
            width: 70%;
        }
        .blog .nav .center a {
            margin-left: 20px;
        }
        .blog .nav .right {
            width: 20%;
            text-align: right;
        }
        .blog .banner {
            height: 600px;
            position: relative;
        }
        .blog .banner img {
            width: 100%;
            height: 100%;
            object-fit: cover;  /* 自适应 */
        }
        .blog .banner .slogan {
            position: absolute;
            left: 50%;
            top: 50%;
            color: white;
            transform: translate(-50%, -50%);  /* 偏移50% */
        }
        .blog .banner .slogan div {
            text-align: center;
        }
        .blog .banner .slogan div:nth-child(1) {
            font-size: 26px;
        }
        .blog .banner .slogan div:nth-child(2) {
            font-size: 18px;
            margin-top: 10px;
        }
        .container {
            width: 1200px;
            display: flex;
        }
        .blog main {
            background-color: #f0eeee;
            display: flex;
            justify-content: center;
            padding: 20px 0;
        }
        .blog main .container > .left {
            width: calc(100% - 300px - 20px);
            margin-right: 20px;
        }
        .blog main .container > .right {
            width: 300px;
        }
        .blog main .news {
            margin-bottom: 20px;
        }
        .blog main .tags {
            margin-bottom: 20px;
        }
        .blog .footer{
            height: 50px;
            background-color: white;
            justify-content: center;
            align-items: center;
            display: flex;
        }
        .card {
            background-color: white;
            border-radius: 5px;
        }

        .card .head {
            padding: 20px 20px 10px 20px;
            border-bottom: 1px solid #f0eeee;
        }

        .card .head .title {
            font-size: 18px;
            font-weight: 600;
        }
        .card .body{
            padding: 10px 20px 20px 20px;
        }
    </style>
</head>
<body>
<div class="blog">
    <div class="nav">
        <div class="container">
            <div class="left">
                <div>枫枫知道</div>
                <div>FFENGZHIDAO</div>
            </div>
            <div class="center">
                <a href="">首页</a>
                <a href="">搜索</a>
                <a href="">聊天室</a>
            </div>
            <div class="right">
                <a href="">登录</a>
            </div>
        </div>
    </div>
    <div class="banner">
        <img src="http://image.fengfengzhidao.com/gvb_1009/20231123092743__1123-e.png" alt="">
        <div class="slogan">
            <div>枫枫知道个人博客九代</div>
            <div>我的九代博客</div>
        </div>
    </div>
    <main>
        <div class="container">
            <div class="left">
                <div class="card news">
                    <div class="head">
                        <div class="title">今日热搜</div>
                    </div>
                    <div class="body">
                    </div>
                </div>
                <div class="card article">
                    <div class="head">
                        <div class="title">文章列表</div>
                    </div>
                    <div class="body">

                    </div>
                </div>
            </div>
            <div class="right">
                <div class="card tags">
                    <div class="head">
                        <div class="title">标签云</div>
                    </div>
                    <div class="body">
                    </div>
                </div>
                <div class="card user_info">
                    <div class="head">
                        <div class="title">个人信息</div>
                    </div>
                    <div class="body">
                    </div>
                </div>
            </div>
        </div>
    </main>
    <div class="footer">
        建站日期:2023-02-15网站已运行: 493天15时32分45秒
    </div>
</div>
</body>
</html>

<!-- JavaScript -->

  • 前端所使用的编程语言

  • 弱类型动态语言

1、使用js的三种方式

  • 行内

    <button οnclick="alert('你点到我了')">点我</button>
  • 外部引入

    <script src="index.js"></script>
  • 内嵌 可以在任何地方引入

    <!DOCTYPE html>
    <html lang="zh-CN">
        <head>
            <meta charset="UTF-8">
            <title>引入js</title>
            <script>
                console.log("hello world head里面")
            </script>
        </head>
        <body>
            <script>
                console.log("hello world body里面")
            </script>
        </body>
        <script>
            console.log("hello world body外面")
        </script>
    </html>
    <script>
        console.log("hello world html的外面")
    </script>

2、变量与基本数据类型

变量声明

var

  1. 函数作用域

  2. 作用域提升

    console.log(name)
    {
        var name = "xiaojin" 
    }
  3. 全局变量可以被挂载到window上

let

  1. 块级作用域

  2. 暂时性死区

const

  1. 常量,声明就需要初始化

  2. 通常用于声明数组和对象

==和===

==是值判断,不会去判断类型

===是值和类型一起判断

console.log(12 == "12") // true
console.log(12 === "12") // false

基本数据类型

八种基本数据类型

Number、String、Boolean、Null、undefined、object、symbol、bigInt

number

const a = 123
const a1 = Number(123)
console.log(a, typeof a)
console.log(a1, typeof a1)
const a2 = 0b110 //  6
console.log(a2)
const a3 = 0o11 // 9
console.log(a3)
// 0 1 2 3 4 5 6 7 8 9 a b c d e f
const a4 = 0xa1 // 10 * 16 + 1 = 161
console.log(a4)  // 最终打印都是十进制

保留小数 toFixed

const a5 = 3.14159265354
console.log(a5)
console.log(a5.toFixed(2)) // 3.14
console.log(a5.toFixed(0)) // 3

转整数 Number.parseInt()

console.log(Number.parseInt(3.14)) // 3
console.log(Number.parseInt("5")) // 5
console.log(Number.parseInt("5.256")) // 5

是否为整数Number.isInteger()

console.log(Number.isInteger(1)) // true
console.log(Number.isInteger(1.2)) // false
console.log(Number.isInteger("1.2")) // false
console.log(Number.isInteger("1")) // false
console.log(Number.isInteger(-3)) // true

取整

console.log(Math.round(3.5)) // 四舍五入 4
console.log(Math.round(3.4)) // 四舍五入 3
console.log(Math.ceil(1.0000001)) // 向上取整 2
console.log(Math.ceil(1.9)) // 向上取整 2
console.log(Math.floor(1.9)) // 向下取整 1
console.log(Math.floor(1.001)) // 向下取整 1

string

字符串

const s1 = "ffzd"
console.log(s1, typeof s1)
const s2 = String("枫枫")
console.log(s2, typeof s2)

console.log(s1[0]) // f
console.log(s1[2]) // z

indexOf() 根据字符找编号

const s1 = "ffzd"
console.log(s1.indexOf('z')) // 2
console.log(s1.indexOf('1')) // -1
// 如果有多个字符匹配,返回最开始那个字符的编号
console.log(s1.indexOf('zd')) // 2  

split() 按照特点的分隔符切割字符串

const s3 = "枫枫,zhangsan,lisi"
const a = s3.split(",")
console.log(a[0], a[1])

slice() 切片,返回值也是一个字符串

const s4 = "枫枫,zhangsan,lisi"
console.log(s4.slice(3, 11)) // 前闭后开 zhangsan

includes() 包含,判断是否有子串包含

const s5 = "枫枫,zhangsan,lisi"
console.log(s5.includes("lisi")) // true
console.log(s5.indexOf("lisi") !== -1) // true

trim() 去空格

const s6 = "   我的名字是枫枫   "
console.log(s6)
console.log(s6.trim())

boolean

  • false、0、""、null、undefined、NaN 转为 布尔值 为 false

  • 其他所有值 转为布尔值 为 true

const b1 = true
const b2 = false
console.log(Boolean(0))
console.log(Boolean('')) // 空字符串 false
console.log(Boolean(' ')) // 空格字符串 true
console.log(Boolean(null))
console.log(Boolean(undefined))
console.log(Boolean(false))
console.log(Boolean(NaN))

object

增删改查

const lyf = {
    "name": "lyf",
    "age": 18
}
const lyf1 = {
    name: "lyf",
    age: 18
}
console.log(lyf, typeof lyf)
console.log(lyf1, typeof lyf1)

console.log(lyf.name)
console.log(lyf["name"])

lyf.addr = "湖南"
lyf["xxx"] = "yyy"
console.log(lyf)

lyf.age = 19
console.log(lyf)

delete lyf.addr
delete  lyf["xxx"]
console.log(lyf)


const name = "fengfeng"
const obj = {
    [name]: ""
}
console.log(obj)

null

null表示一个空值或没有对象值。它是一个表示空对象指针的特殊关键字

null的用法:

  1. 作为函数的参数,表示该函数的参数不是对象

  2. 作为对象原型链的终点

undefined

undefined的用法

  1. 变量被声明了,但没有赋值时,就等于undefined

  2. 调用函数时,应该提供的参数没有提供,该参数等于undefined

  3. 对象没有赋值的属性,该属性的值为undefined

  4. 函数没有返回值时,默认返回undefined

为啥要用null和undefined

symbol 唯一值

js对象属性名都是字符串,这容易造成属性名冲突的问题

const name = Symbol("name")
const age = Symbol("age")
const symObj = {
    [name]: "张三",
    [age]: "14",
}
symObj["name"] = "枫枫" // 不会替换那个name
console.log(symObj)
console.log(symObj[name])

bigInt

可以安全地存储和操作大整数,即使这个数已经超出了Number类型能够表示的安全整数范围。

在 JavaScript 中,普通的数字(Number 类型)只能安全地表示 -9007199254740991(即 -(2^53 - 1))到 9007199254740991(即 2^53 - 1)之间的整数。超出这个范围的整数在表示时可能会失去精度。因此,BigInt解决了之前Number整数溢出的问题。

const b1 = BigInt(123)
console.log(typeof b1, b1)
console.log(b1 + BigInt(10086)) // 必须都是bigint才行
const b2 = 12345678910n  // bigint类型
console.log(typeof b2, b2)

3、数组与数组方法

数组

数组创建

const a1 = ["fengfeng", "zhangsan", "lisi"]
console.log(a1[0]) // 获取数组的第一个元素
console.log(a1.length) // 获取数组的长度=数组中元素的个数
console.log(a1[a1.length - 1]) // 获取数组的最后一个元素
const a2 = Array("fengfeng", "zhangsan", "lisi")
console.log(a2)

遍历数组

for i

for (let i = 0; i < a1.length; i++) {
    console.log(i, a1[i])
}

for of

遍历数组最常用方法

for (const value of a2) {
    console.log(value)
}

判断一个对象是不是数组

typeof(数组) 得到的结果是object。因为数组本质就是对象

Array.isArray()

console.log(Array.isArray(a1)) // true
console.log(Array.isArray(1)) // false

instanceof

console.log(a1 instanceof Array) // true

数组方法

push()、pop()方法

push() 数组末端添加一个或多个元素,返回添加之后数组的长度

const a1 = ["fengfeng", "zhangsan", "lisi"]
a1.push("王五")
const l = a1.push("z1", "z2")
console.log(l, a1)

pop() 移除数组末端的元素,并返回

const a2 = ["fengfeng", "zhangsan", "lisi"]
const item = a2.pop()
console.log(item, a2)

shift()、unshift()方法

shift() 从数组最左端移出元素,并返回移出的元素

const a3 = ["fengfeng", "zhangsan", "lisi"]
const fi = a3.shift()
console.log(fi, a3)

unshift() 在数组的开头插入新元素,并返回数组的新长度

const a4 = ["fengfeng", "zhangsan", "lisi"]
const l1 = a4.unshift("小红")
console.log(l1, a4)

join()方法

将数组内所有元素按join()内的参数为分割添加到字符串中

const a5 = ["fengfeng", "zhangsan", "lisi"]

const s = a5.join(",")
console.log(s) // fengfeng,zhangsan,lisi
console.log(a5.join()) // 默认就是,
console.log(a5.join("|")) // fengfeng|zhangsan|lisi

sort()方法 默认升序

const a6 = [4, 2, 1, 5]
console.log(a6.sort()) // 升序

可以通过reverse()反转得到降序

const a6 = [4, 2, 1, 5]
console.log(a6.sort()) // 升序
console.log(a6.reverse()) // 反转

高级用法 (后一个元素,当前元素)

return 正值和0不变 return 负值就交换

const a6 = [0, 2, 1, 5]

a6.sort(function (a, b){
    console.log(a, b)
    return b-a
})
console.log(a6)

a-b 升序后一个比当前元素大 b-a 降序 当前元素比后一个大

splice()方法

用于删除数组中的元素,并且返回被删除的数组

const a7 = ["fengfeng", "zhangsan", "lisi"]
const a8 = a7.splice(1, 1)  // (索引, 要删除的个数)
console.log(a8) // 被删除的数组  ["zhangsan"]  
console.log(a7) // 原位删除 ["fengfeng","lisi"]

以下是ES6新增的数组方法

forEach() 循环

  • 中途不能退出

const a1 = ["fengfeng", "zhangsan", "lisi"]
a1.forEach(function (value, index, array){
    console.log(value, index, array)
})

map() 迭代

迭代每一个元素,去进行操作

const a2 = a1.map(function (value, index, array){
    return value + "@qq.com"
})
console.log(a2) // ['fengfeng@qq.com', 'zhangsan@qq.com', 'lisi@qq.com'] 不会原位修改

filter() 过滤

const a3 = a1.filter(function (value, index, array){
    if (value === "zhangsan"){
        return true
    }
})
console.log(a3) // ['zhangsan']

every()方法、some()方法

every:判断数组中是不是 每一个 都满足条件

some:判断数组中 其中一个 满足条件

const a4 = [5, 1, 0, -1, 2]
console.log(a4.every(function (value){
    if (value >= 0){
        return true
    }
}))  // false

console.log(a4.some(function (value){
    if (value >= 0){
        return true
    }
})) // true

find()方法

获取数组中满足条件的数据,如果有 就是满足条件的第一个数据;如果没有就是undefined

const a5 = [5, 1, 0, -1, 2]
const item = a5.find(function (value, index, obj){
    if (value >= 5){
        return true
    }
})
console.log(item) // 5 找不到就是undefined
const index = a5.findIndex(function (value, index, obj){
    if (value >= 5){
        return true
    }
})
console.log(index) // 0 找不到就是-1

4、流程控制

逻辑运算符

流程控制的关键,掌管进退的神

一般用于编写复合逻辑

与 &&

const name = "fengfeng"
const age = 12
console.log(age >= 18 && name.startsWith("f"))

或 &&

const name = "fengfeng"
const age = 12
console.log(age >= 18 || name.startsWith("f"))

非 !

console.log(!(age >= 18) )

逻辑短路

&&: 如果前面的条件是false,那就不会去判断后面的条件了

||:如果前端的条件是true,那就不会去判断后面的条件了

如何验证

function t(){
    console.log("t")
    return true
}

console.log(-1>0 && t()) // 不会执行t
console.log(1>0 || t()) //  不会执行t

判断语句

if语句

单分支

const name = "fengfeng"
if (name === "fengfeng") {
    console.log("去度假")
}

// 如果代码语句只有一行,可以省略{}
if (name === "fengfeng")
    console.log("去度假")
console.log("不管什么我都会执行")

双分支

if (name === "fengfeng"){
    console.log("fengfeng去度假")
}else {
    console.log("fengfeng继续搬砖")
}

多分支

const scope = 90
if (scope >= 90) {
    console.log("A")
} else if (scope >= 80) {
    console.log("B")
} else if (scope >= 60) {
    console.log("C")
} else {
    console.log("D")
}

分支嵌套

if (scope >= 80){
    if (scope >= 90){
        console.log("A")
    }else {
        console.log("B")
    }
}else {
    if (scope >= 60){
        console.log("C")
    }else {
        console.log("D")
    }
}

分支优化

function get_scope(scope){
    if (scope >= 90){
        console.log("A")
        return;
    }
    if (scope >= 80){
        console.log("B")
        return;
    }
    if (scope >= 60){
        console.log("C")
        return;
    }
    console.log("D")
    
}

switch语句

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

const day = 7

switch (day) {
    case 1:
        console.log("周一")
        break
    case 2:
        console.log("周二")
        break
    case 3:
        console.log("周三")
        break
    case 4:
        console.log("周四")
        break
    case 5:
        console.log("周五")
        break
    case 6:
        console.log("周六")
        break
    case 7:
        console.log("周天")
        break
    default:
        console.log("错误")
}

循环语句

传统for循环

let sum = 0
for (let i = 1; i <= 100; i++) {
    sum += i
}
console.log(sum)

for in循环 遍历对象

for...in循环可以用来遍历对象的可枚举属性列表(包括原型链上的属性)

const obj = {
    name:"枫枫",
    age: 21
}
for (const objKey in obj) {
    console.log(objKey)
}

for of循环 遍历数组

用于遍历数组

const array = ["枫枫", "张三"]
for (const item of array) {
    console.log(item)
}

while循环

let i = 1
let r = 0
while (i <= 100){
    // 循环体
    r += i
    i ++
}
console.log(r)

do while循环

先执行一次循环体,再进行条件判断

let o = 1
let r = 0
do {
    r += o
    o ++
}while (o <= 100)
console.log(r)

continue

例如,吃5个包子,吃到第3个发现里面有半个虫子,这个包子就不吃了,继续吃下一个。

for (let j = 1; j <= 10; j++) {
    if (j === 3){
        console.log(`吃到第${j}个包子,发现虫子,这个包子我不吃了`)
        continue
    }
    console.log(`吃到第${j}个包子`)
}

break

跳出整个循环

例如,吃5个包子,吃到第3个发现里面有半个虫子,这盘都不吃了。

for (let j = 1; j <= 10; j++) {
    if (j === 3){
        console.log(`吃到第${j}个包子,发现虫子,我都不吃了`)
        break
    }
    console.log(`吃到第${j}个包子`)
}

5、js函数

函数是一种可重复使用的代码块

函数是一种非常重要和常用的语言特性,可以用于封装代码、抽象功能、提高代码的可读性和可维护性等

例如经常使用的 console.log函数,它的功能就是将变量打印到控制台上,我们只需要调用这个函数即可,而log函数考虑的就很多了

函数声明和调用

  • function声明

function hello() {
    console.log("hello")
}
hello()
  • 匿名函数

const say = function (){
    console.log("say")
}
say()
  • 箭头函数

const eat = ()=>{
    console.log("eat")
}
eat()
  • 立即执行函数

(function (){
    console.log("立即执行")
})()

函数参数

声明是形参,调用是实参

function add(a, b){  // a,b是形参
    return a + b
}
console.log(add(1,2))  // 1,2是实参

默认参数

如果对应的参数没有被赋值,那么对应的参数就是undefined

function getName(name="feng"){
    // if (name === undefined){
    //     return "feng"
    // }
    // name = name || "feng"
    return name
}

参数列表

形参和实参的传递是一一对应的,剩余的被参数列表接收

// function sum(a, ...list) {}
function sum(...list) {
    let res = 0
    for (const item of list) {
        res += item
    }
    return res
}
console.log(sum(2, 3))
console.log(sum(2, 3, 2, 3, 45))

arguments

完整的参数列表,是一个类数组

function sum1() {
    let res = 0
    for (const item of arguments) {
        res += item
    }
    return res
}
console.log(sum1(2, 3))
console.log(sum1(2, 3, 2, 3, 45))

函数返回值

  • 没有显式return等于return undefined

function set(){
}
console.log(set()) // undefined

函数作为变量

函数自身也可以作为参数,放入对象、数组中

function getName(){
    return "fengfeng"
}

const lis = [1,"sss", getName]
console.log(lis[2]())

如果函数在对象中,此时它就叫方法

const obj = {
    name: "fengfeng",
    eat: function (){
        return `${this.name}在吃饭`
    },
    say: ()=>{
        // 箭头函数中不能用this
        console.log("在说话")
    },
    study(){
        console.log(`${this.name}在学习`)
    }
}
console.log(obj.name)
console.log(obj.eat())
obj.say()
obj.study()

递归函数

在函数中调用自身

一定要设置退出条件

示例:展开所有的数组,变成一维数组

const list = [
        "你好", "吃饭了吗",
        [
            "好",
            [
                [
                    "abc"
                ]
            ]
        ]
    ]

写法1

const a1 = []
function oneArray(array){
    for (const arrayElement of array) {
        if (arrayElement instanceof Array){
            oneArray(arrayElement)
            continue
        }
        a1.push(arrayElement)
    }
}
oneArray(list)
console.log(a1)

写法2

function oneArray1(array){
    const a2 = []
    function oneArray(array){
        for (const arrayElement of array) {
            if (arrayElement instanceof Array){
                oneArray(arrayElement)
                continue
            }
            a2.push(arrayElement)
        }
    }
    oneArray(array)
    return a2
}
console.log(oneArray1(list))

有非常多的方法

function oneArray2(array){
    const a3 = []
    for (const arrayElement of array) {
        if (arrayElement instanceof Array){
            a3.push(...oneArray2(arrayElement))
            continue
        }
        a3.push(arrayElement)
    }
    return a3
}

console.log(oneArray2(list))

this问题

this指向

  • 函数外:window

  • 函数内:函数中的this指向谁,取决于这个函数是怎么调用的

  • 箭头函数没有this或者this是window

this指向修改

function.call()

function.call(this指向谁, 函数参数1,参数2...)
// 调用函数,并修改函数中的this指向;

function.apply()

function.apply(this指向谁, [参数1, 参数2...])
// 调用函数,并修改函数中的this指向

function.bind()

function.bind(指向,参数1,参数2,...)
// 绑定this指向

箭头函数的this不能修改

function get() {
    console.log("get", this, arguments)
}
const set = ()=>{
    console.log("set", this)
}
const obj = {
    name: "fengfeng",
    get: get,
    set: set,
}
get()
obj.get()
set()
obj.set()
// 改变this
get.call(obj, 1,2,3)
get.apply(obj, [1,2,3])
get.bind(obj, 1,2,3)(4,5,6)
// 箭头函数的this指向不能修改

6、js的对象

创建对象

字面量

const obj = {
    name: "枫枫"
}

new一个对象

const o2 = new Object({})

原型对象

function People(name, age){
    this.name = name
    this.age = age
}
People.prototype.eat = function (){
    console.log(`${this.name}在吃饭`)
}
const o2 = new People("枫枫", 21)
console.log(o2)
o2.eat()

create方法

继承

// 其中的name和age属性 是在原型上
const o3 = Object.create({name: "枫枫", age: 21})
console.log(o3)
console.log(o3.name)
o3.name = "lisi"
// 给自己加了一个name属性
console.log(o3.name)
// 如果自己有这个属性,就用自己的,没有就去原型上去找

属性操作

查询,通过点或者方括号获取

console.log(o3.name)
console.log(o3["name"])

删除属性 delete,只能删除自身的,继承来的不能删

delete  o3.name // 只能删自己身上的属性
delete  o3.age
// 原型上的name和age还在

检测属性

"属性名" in object, 可以自己+检测继承来的属性

const o3 = Object.create({name: "枫枫", age: 21, eat: function (){}})
o3.addr = "长沙市"
console.log("age" in o3) // true
console.log("addr" in o3) // true
console.log("eat" in o3) // true  方法就是特殊的属性

object.hasOwnPreperty("属性名") 检测自身的属性

const o3 = Object.create({name: "枫枫", age: 21, eat: function (){}})
o3.addr = "长沙市"
console.log(o3.hasOwnProperty("addr")) // true
console.log(o3.hasOwnProperty("age")) // false

属性枚举

for-in,继承+自身的属性

const o3 = Object.create({name: "枫枫", age: 21, eat: function (){}})
o3.addr = "长沙市"
for (const o3Key in o3) {
    console.log(o3Key)
}

Object.keys() 自己的属性

const o3 = Object.create({name: "枫枫", age: 21, eat: function (){}})
o3.addr = "长沙市"
console.log(Object.keys(o3)) // ["addr"]

Object常用的API

Object.assign() 浅拷贝

Object.assign(target, ...sources)
// 参数:target 目标参数,sources源对象 返回值:目标对象
  • 如果目标对象中的属性具有相同的键,则属性将被源对象中的属性覆盖

    Object.assign 方法只会拷贝源对象自身的并且可枚举的属性到目标对象

  • assign其实是浅拷贝而不是深拷贝。也就是说,如果源对象某个属性的值是对象,那么目标对象拷贝得到的是这个对象的引用。同名属性会替换

const obj = {name: "王五", addr: "长沙"}
const source = {
    name: "枫枫",
    info: {
        age: 21
    },
    likes: []
}
Object.assign(obj, source)
source.info.age = 22 // 最终会影响到 obj里面的age
source.name = "zhangsan" // 外层的不会影响
source.likes.push("篮球") // 最终会影响到 obj里面的likes
console.log(obj)

Object.keys()

一个表示给定对象的所有可枚举属性的字符串数组

const o3 = Object.create({name: "枫枫", age: 21, eat: function (){}})
o3.addr = "长沙市"
console.log(Object.keys(o3)) // ["addr"]

Object.defineProperty()定义对象属性

Object.defineProperty(obj, "name", {
  value: 101, // 属性的值
  writable: true, // 是否允许修改
  enumerable: true, // 是否允许枚举
  configurable: true, // 是否允许删除
});

Object.getOwnPropertyNames()

Object.getOwnPropertyNames() 返回一个数组,该数组对元素是对象自身拥有的枚举或不可枚举属性名称字符串。

const o1 = {name: "枫枫"}

Object.defineProperty(o1, "age", {
    value: 21,
    writable: true, // 是否可修改
    enumerable: false, // 是否可枚举
    configurable: true, // 是否可删除
})
console.log("Object.keys", Object.keys(o1)) // 获取可枚举的属性列表
console.log("Object.getOwnPropertyNames", Object.getOwnPropertyNames(o1)) // 获取属性列表
// delete o1.age

原型与原型链

原型在JavaScript是一个很重要的概念,它是面向对象可以继承的基础

原型链是原型的查找机制,是一条寻址链。其实原型上的方法或属性查找,都是按照一定的顺序沿着原型链进行查找的。如果查找到最后仍然没有找到这个原型和方法,那么就真的没有了

原型链的尽头是null

给构造函数添加原型

// Object.prototype.字段名
const obj = {}
console.log(obj)
const o1 = new Object({})
Object.prototype.name = "枫枫"
console.log(o1)

修改现有对象的原型

找这个现有对象的父级的构造函数

比如{}的原型是Object的实例

const obj = {}
Object.prototype.toString = function (){
    return "这是对象的toString方法"
}
console.log(obj + "")
console.log(obj.toString())

Object.create()设置原型方法

const o2 = Object.create({
    eat(){
        console.log("吃饭")
    }
})
console.log(o2)

使用proto属性

可以通过设置对象的 __proto__ 属性来改变其原型

const o2 = Object.create({
    eat(){
        console.log("吃饭")
    }
})
o2.__proto__.study = function (){
    console.log("在学习")
}
console.log(o2)

new的过程

  1. 创建一个新的对象

  2. 把该对象的__proto__属性设置为构造函数的prototype属性,即完成原型链

  3. 执行构造函数中的代码,构造函数中的this指向该对象(obj)

  4. 返回该对象obj

function People(name){
    this.name = name
}

function _new(fn, ...args){
    // 1. 创建一个新的对象
    const o = {}
    // 2. 把该对象的__proto__属性设置为构造函数的prototype属性,即完成原型链
    o.__proto__ = fn.prototype
    // 3. 执行构造函数中的代码,构造函数中的this指向该对象(obj)
    fn.apply(o, args)
    // 4. 返回对象
    return o
}
const o3 = new People("枫枫")
console.log(o3)
const o4 = _new(People, "枫枫")
console.log(o4)

7、js时间库

在JavaScript中,时间戳(timestamp)是一种表示特定时刻距离某个固定时间点的毫秒数。通常这个固定时间点是指 1970年1月1日00:00:00(UTC) ,即Unix纪元

时间戳

获取当前时间戳

console.log(new Date().getTime()) // 获取毫秒级时间戳 13位

将时间戳转换为时间对象

console.log(new Date(1719414979389))

日期对象

格式化日期对象

const date = new Date()
console.log(date.getFullYear())
console.log(date.getMonth() + 1) // 月是从0开始的
console.log(date.getDate())
console.log(date.getHours())
console.log(date.getMinutes())
console.log(date.getSeconds())

把时间变成 2024-06-26 15:04:05这样的格式

可以使用字符串的padStart() 方法,把格式变成两位不够的用第二个参数补

function parseDate(dateString){
    let date
    if (dateString){
        date = new Date(dateString)
    }else {
        date = new Date()
    }
    const y = date.getFullYear().toString()
    const M = (date.getMonth() + 1).toString().padStart(2, "0")
    const d = date.getDate().toString().padStart(2, "0")
    const h = date.getHours().toString().padStart(2, "0")
    const m = date.getMinutes().toString().padStart(2, "0")
    const s = date.getSeconds().toString().padStart(2, "0")
    return `${y}-${M}-${d} ${h}:${m}:${s}`
}

console.log(parseDate("2022-12-12 15:04:05"))
console.log(parseDate())

字符串转换为时间对象

new Date("2022-12-12 15:04:05")

日期计算

在一个日期上加减一个时间

调用setXXX方法,重新设置一个时间

const d1 = new Date()
console.log(parseDate(d1))
// 七天前
d1.setDate(d1.getDate() - 7)
// 5小时后
d1.setHours(d1.getHours() + 5)
console.log(parseDate(d1))

一个未来的时间距离现在还剩多久 时间戳相减

得到一个毫秒的时间,然后算出秒数、分钟、小时、天

function timeUntil(timeStr) {
  const now = new Date();
  const then = new Date(timeStr);
  const diff = then - now;
  // 如果给定时间已经过去,返回过去的时间 
  if (diff < 0) {
    return '时间已经过去';
  }
  // 将毫秒转换为秒
  const seconds = Math.floor(diff / 1000);  // 向下取整
  const minutes = Math.floor(seconds / 60);
  const hours = Math.floor(minutes / 60);
  const days = Math.floor(hours / 24);
  if (days > 0) {
    return `${days} 天 ${hours % 24} 小时 ${minutes % 60} 分钟 ${seconds % 60} 秒`;
  } else if (hours > 0) {
    return `${hours} 小时 ${minutes % 60} 分钟 ${seconds % 60} 秒`;
  } else if (minutes > 0) {
    return `${minutes} 分钟 ${seconds % 60} 秒`;
  } else {
    return `${seconds} 秒`;
  }
}

一个过去的时间距离现在过了多久

也是算时间的差值,直接除以大的年,大于0就直接返回,以此类推

function getDateDiff(dateTimeStamp) {
    // 时间字符串转时间戳
    const timestamp = new Date(dateTimeStamp).getTime();

    const minute = 1000 * 60;
    const hour = minute * 60;
    const day = hour * 24;
    const month = day * 30;
    const year = day * 365;
    const now = new Date().getTime();
    const diffValue = now - timestamp;
    let result;
    if (diffValue < 0) {
        return;
    }
    const yearC = diffValue / year;
    const monthC = diffValue / month;
    const weekC = diffValue / (7 * day);
    const dayC = diffValue / day;
    const hourC = diffValue / hour;
    const minC = diffValue / minute;
    if (yearC >= 1) {
        result = "" + parseInt(yearC) + "年前";
    } else if (monthC >= 1) {
        result = "" + parseInt(monthC) + "月前";
    } else if (weekC >= 1) {
        result = "" + parseInt(weekC) + "周前";
    } else if (dayC >= 1) {
        result = "" + parseInt(dayC) + "天前";
    } else if (hourC >= 1) {
        result = "" + parseInt(hourC) + "小时前";
    } else if (minC >= 1) {
        result = "" + parseInt(minC) + "分钟前";
    } else
        result = "刚刚";
    return result;
}

8、正则表达式

正则表达式(Regular Expression,在代码中常简写为regexregexp或RE)使用单个字符串来描述、匹配一系列符合某个句法规则的字符串搜索模式。搜索模式可用于文本搜索和文本替换

各个编程语言中都支持正则表达式

正则表达式的用途有很多,比如:

  1. 表单输入验证

  2. 搜索和替换

  3. 过滤大量文本文件(如日志)中的信息

  4. 读取配置文件

  5. 网页抓取

  6. 处理具有一致语法的文本文件,例如 CSV

在线正则表达式

/[ab012]/g

字符集合

使用“[]” 里面属于||的关系

/[az012]/g    // []中是||的关系

 

 

 

字符范围

使用“-”

/[a-z]/g
/[\u4e00-\u9fa5]/g  // 匹配中文

 

数量字符

{m,n}

最少匹配m个,最多匹配n个

/[\u4e00-\u9fa5]{2,3}/g  // 匹配中文
/* {m,n} 最少匹配m个,最多匹配n个 */

 

+:匹配前面一个表达式一次或者多次,相当于{1,}。

/a[bc]+a/g  // 相当于{1,}

 

*:匹配前面一个表达式0次或者多次,相当于{0,}。

/a[bc]*a/g  // 相当于{0,}

 

?:单独使用匹配前面一个表达式零次或者一次,相当于{0,1},

/https?:\/\//g  // 相当于{0,1}

 

贪婪模式

正则会尽可能的匹配多的字符

/a[ab]*a/g  // 贪婪模式,正则会尽可能的匹配多的字符

 

非贪婪模式

尽可能匹配少的

/a[ab]?a/g  // 非贪婪模式,尽可能匹配少的

元字符

元字符说明
\d匹配数字 [0-9]
\D匹配非数字
\w匹配数字、字母、下划线
\W匹配非数字、字母、下划线
\s匹配任意的空白字符
\S匹配任意的非空白符
.匹配除换行符之外的任意字符

特殊字符

特殊字符说明
.匹配除了换行符之外的任何单个字符
\转义字符
|逻辑或操作符
[^]取非,匹配未包含的任意字符 [^0-9]

位置匹配

位置字符说明
\b匹配一个单词边界,也就是指单词和空格间的位置 \s空格也可
\B匹配非单词边界
^匹配开头,在多行匹配中匹配行开头
$匹配结尾,在多行匹配中匹配行结尾

 

 

分组

使用小括号

捕获分组

/\d{4}-(\d{2})-d{2}-(\d{2}):\d{2}:\d{2}/g
月:$1 小时:$2

 

无捕获分组

有些时候,使用小括号只是希望把它当做一个整体,不希望分组

/(\d+\.){3}\d+/g
$1
/?:(\d+\.){3}\d+/g
$1

 

 

修饰符

修饰符说明
g表示全局匹配,即在整个字符串中搜索所有匹配项,而不仅仅是第一个匹配项 //g
i表示在匹配时忽略大小写 //gi
m表示多行模式,在这种模式下,正则表达式可以同时匹配每一行的内容,而不仅仅是整个字符串 /^python/gim
u表示在匹配时进行完全递归,这样可以处理一些较为复杂和嵌套的情况
s在默认情况下,.元字符匹配除了换行符之外的任意字符。但是在设置了s修饰符后,.元字符也会匹配换行符 /<a.*?>(.*?)<\/a>/gims

m模式

主要影响^和$符合的行为

 

 

s模式

点号可以匹配换行

 

js中的正则表达式

定义正则表达式

const re = /1\d{10}/g
const re1 = new RegExp("1\d{10}", "g")

字符串的正则方法

通过字符串调用的方法

search() 被匹配的最开始索引

没有匹配到就返回-1

const re = /1\d{10}/g
const s = "我的手机号是 15254586535"
console.log(s.search(re)) // 7最开始匹配到的索引

match() 正则匹配

console.log(s.match(re))

replace()正则替换

console.log("大傻春,你要干什么!你是大傻叉吗".replace("傻", "*"))
console.log("大傻春,你要干什么!你是大傻叉吗".replaceAll("傻", "*"))
console.log("大傻春,你要干什么!你是大傻叉吗".replace(/[傻叉]/g, "*"))

使用分组替换

const r = /(1\d{10}).*?([\w-]+@\w+\.\w+)/g
const str = "my phone is : 15252523256, my email is: 525416@qq.com"
concole.log(str.replace(r, "我的手机号, $1, 邮箱: $2"))

正则表达式函数

const r = /(1\d{10}).*?([\w-]+@\w+\.\w+)/g
const str = "my phone is : 15252523256, my email is: 525416@qq.com"
concole.log(str.replace(r, function(data, g1, g2){
    // (data, ...args)     console.log(data, args)
    console.log(data, args)
    return `我的手机号, ${g1}, 邮箱: ${g2}`
})
concole.log(str.replace(r, function(data, g1, g2){
    const tel = Number(g1)+1
    return `我的手机号, ${tel.toString()}, 邮箱: ${g2}`
})

正则方法

通过正则对象调用的方法

test() 是否匹配

console.log(/abc/.test("abcd")) // true
console.log(/abc/.test("abd")) // false

execl() 方法

可以使用分组,第一个参数就是正则表达式匹配的内容

后面的参数就是分组匹配的内容

const r = /'(1\d{10})'/g
console.log(r.exec("my phone is: '15252523256'"))
console.log(res[1])  // 第一个分组

具名分组

const r = /(?<phone>1\d{10}).*?(?<email>[\w-]+@\w+\.\w+)/g
res = r.exec("my phone is : 15252523256, my email is: 525416@qq.com"))
console.log(res.groups.phone)

9、class

在过去,JavaScript 是一门基于原型的面向对象编程语言,没有 Class 和模块化的概念。这导致了代码的组织结构混乱,难以维护和扩展

类和对象

我们生活中有很多的车,小车,汽车,自行车,火车,摩托车,电动车

他们都是属于“车”这么一类

具体的一辆你在2024年买的一辆四个轮子的小车,这就叫对象

class定义

class Animal{
    name
    age
    class1
    constructor(name, age) {  // 传参
        this.name = name
        this.age = age
        class1 = "碳基生物"
    }
    eat(){
        console.log(`${this.name}在吃饭`)
    }
}
const cat = new Animal("加菲猫", 5)
console.log(cat)
cat.eat()

其中的constructor属于构造方法,name、age属于对象属性,eat属于对象方法

其中的eat方法是在原型上的

*继承

使用class之后就能很方便的使用继承功能

使用 extends 继承父类,super() 用于实例化继承的类

class Animal{
    name
    constructor(name) {
        this.name = name
    }
    eat(){
        console.log(`${this.name}在吃饭`)
    }
}
// 猫继承动物的属性或方法
class Cat extends Animal{
    color
    constructor(name, color) {
        super(name);
        this.color = color
    }
    running(){
        console.log("猫在行走")
    }
}
const cat = new Cat("加菲猫", "白色")
console.log(cat)

静态属性和方法

只能由类去调用

// 只能由类去调用
class Animal{
    static name = "动物"
    static eat(){
        console.log(`在吃饭`)
    }
}

Animal.eat()
console.log(Animal.name)

10、js模块化

模块化是指将一个复杂的程序依据一定的规则(规范)封装成几个块(文件),并进行组合在一起

最早我们开发将所有的代码写在一个js文件中,随着需求越来越复杂,代码量越来越大,如果仍然把所有代码写在一个js文件中,那么代码耦合度过高不方便后期维护,也不方便程序员找到某一个功能点的代码

模块化将一个复杂的js文件按共同或类似的逻辑拆分成多个js文件,拆封的文件内部数据是私有的,只是向外部暴露一些接口(方法)与其他模块通信,不仅方便找到某一块功能点的代码,也可以达到复用的效果

ES6实现模块化

重点是引入js的地方,必须要有一个 type="module"

<script src="module/index.js" type="module"></script>

然后子模块可以使用 export 将成员抛出

父模块使用 import 将子模块的成员导入

导入的时候,把js文件的后缀写完

export 具体成员

// ./module/m1.js
export function add(x, y){
    return x+y
}
export const name = "枫枫"
export const obj = {
    name: "fengfeng"
}
<script type="module">
	import {add, name, obj} from "./module/m1.js";
</script>

export default

export default {
    obj: {
        name: "张三"
    },
    add,  // add: add,
}
<script type="module">
	import m1 from "./module/m1.js";
    import {add, name, obj} from "./module/m1.js";
</script>

立即执行函数实现模块化

除了可以用使用对象进行成员隔离

还可以使用立即执行函数创造一个封闭的代码空间

const m1 = (function (){
    function add(a, b){
        return a+b
    }
    return {
        add: add,
    }
}())

const m2 = (function (){
    function add(){
        return "this is m2 add"
    }
    return {
        add: add,
    }
}())


console.log(m1.add(1,2))
console.log(m2.add())

模块化实现

  • IIFE,就是匿名函数自执行的方式(闭包)

<!-- 向window对象上添加全局属性,也有的把这种方法叫做添加命名空间 -->
<!-- 目的就是向外暴露方法(接口),方法很好,但是多个模块之间有相互依赖关系就不好办了 -->
<script type="text/javascript">
    (function(win){
     function aFn(){
	// ...
    }
    function bFn(){
	// ...
    }
    // 向外暴露方法,es6的写法
    win.myMethod = {aFn, bFn}
    })(window)
</script>
  • IIFE,模式增强:向入口中传入依赖的模块

<!-- 假设依赖jq,这种方式引入的js文件、模块,必须有一定的先后顺序,否则报错undefined -->
<script type="text/javascript">
    (function(win){
     function aFn(){
         $(body).css(...)
    }
    function bFn(){
             // ...
    }
    // 向外暴露方法,es6的写法
    win.myMethod = {aFn, bFn}
    })(window,jQuery);
</script>

模块化的好处

<!-- 在面试时背下来就好 -->

  • 避免命名冲突(减少命名空间污染)

  • 更好的分离,按需加载

  • 更高的复用性、高可维护性

引入多个script后会出现的问题

引入多个script之后,会不可避免的出现请求的交叉

  • 请求过多

  • 依赖会乱掉,依赖模糊

  • 难以维护,各种调用交织在一起

这也就促使真正上的模块化的出现,就是后来的common.js,AMD,es6,CMD


// sum.js
function sum(a,b){
return a+b
}
<scrtpt src="./sum.js"></scrtpt>  <!-- 全局污染 -->
<scrtpt src="./sum.js" type="module"></scrtpt>

导出

// sum.js
function sum(a,b){
return a+b
}
export default sum;    /* 不会污染全局 */
// main.js
import sum from './sum.js';
console.log(sum);
<scrtpt src="./main.js" type="module"></scrtpt>

官方包管理 npmdd

社区包管理 yarn pnpm cnpm

npm i jquery
npm i jquery@1  // 安装版本1
npm uninstall jquery

11、BOM浏览器对象模型

BOM(Browser Object Model):浏览器对象模型

  • BOM的核心就是window对象

  • window是浏览器内置的一个对象,里面包含着操作浏览器的方法

History 浏览器记录

history.back(上一页)相当于浏览器上的返回按钮

history.forword(下一页)相当于浏览器上的前进按钮

history.go(n) n为正时向前n页,n为负时后退n页

<button οnclick="forword()">前进</button>
<button οnclick="back()">后退</button>
<button οnclick="go(1)">前进1页</button>
<button οnclick="go(-1)">后退1页</button>
<script>
    function forword(){
        history.forward()
    }
    function back(){
        history.back()
    }
    function go(n){
        history.go(n)
    }
</script>

Location 浏览器地址

以http://do.com:3000/xx/yy?name=ff为例,除了源地址其他属性可以重新赋值

属性说明
location.portocolhttp:页面使用的协议,通常是http:https:
location.hostnamedo.com服务器域名
location.port3000请求的端口号
location.hostdo.com:3000服务器名及端口号
location.originhttp://do.com:3000url的源地址,只读
location.href完整的url地址等价于window.location
location.pathname/(这里指的是3000后面的/)url中的路径和文件名,不会返回hash和search后面的内容,只有当打开的页面是一个文件时才会生效
location.search?name=ff查询参数

location.reload() 刷新页面

location.replace() 替换页面

  • 不会保留当前页面的历史记录,因此用户无法通过浏览器的后退按钮返回到之前的页面

对话框

alert 提示框

console.log(alert("这是一个提示信息"))

confirm 询问框

console.log(confirm("确定要删除吗?"))  // 阻塞代码

可以获取到用户点击的确定和取消的操作,确定就是true,取消就是false

prompt 输入框

console.log(prompt("今天晚上吃什么?", "西北风"))  // 阻塞代码

定时器

setTimeout

  • 倒计时多少时间以后执行函数

  • 语法:setTimeout(要执行的函数,多少时间以后执行)

  • 单位是毫秒,返回值是当前这个定时器是页面中的第几个定时器

  • 可以使用clearTimeout关闭定时器

function handler(){
    console.log("handler")
}
setTimeout(handler, 3000)
const timer = setTimeout(handler, 3000) // 页面中的第几个定时器
console.log(timer)
clearTimeout(timer) // 关闭定时器

setInterval

  • 每隔多少时间执行一次函数

  • 语法:setInterval(要执行的函数,间隔多少时间)

  • 只要不关闭,会一直执行

  • 可以使用clearInterval关闭定时器

let count = 0;
const timer1 = setInterval(()=>{
    if (count === 3){
        clearInterval(timer1)
        return
    }
    console.log(new Date().toLocaleString())
    count ++
}, 1000)  // 间隔执行,第一个参数是函数,第二个是间隔时间
console.log(timer1)

防抖和节流

用户点击按钮的时候,点太快了点了两下,那么这个函数就会被执行两次

debouncethrottle

防抖

在事件被触发n秒后执行回调,如果在这n秒内事件又被触发,则重新计时

类似于回城,被打断就要重新开始(重新计时)

<button οnclick="newHandler('hello')">1</button>
<script>
    function handler(name){
        console.log("被点击了", name)
    }
    function debounce(fn, delay) {  // 函数,防抖时间
        let timer = null;
        return function() {
            clearTimeout(timer);  // 之前如果有计时器要清除
            timer = setTimeout(() => {
                fn.apply(this, arguments);
            }, delay);
        }
    }
</script>
const newHandler = debounce(handler, 300)

节流

在规定的单位时间内,只能有一次触发事件的回调函数执行,如果在同一时间内被触发多次,只会生效一次

类似于技能CD,CD没好,你用不了技能

节流的逻辑要稍微复杂一点,首先事件触发之后是要立即执行的,后续再触发时间则要看看是不是在设定的时间阈值内,在的话就不执行,不在就立即执行

<button οnclick="throttleHandler('hello')">1</button>
<script>
function throttle(fn, delay) {
    let timer = null;
    let startTime = Date.now();  // new Date().getTime()
    return function () {
        // 判断现在的时间
        const curTime = Date.now();
        // 节流时间-两个时间的时间戳
        const remaining = delay - (curTime - startTime);
        // 清除定时器
        clearTimeout(timer);
        // 已经超过时间差了,直接执行
        if (remaining <= 0) {
            fn.apply(this, arguments);
            startTime = Date.now();
        } else {
            // 还没到时间差,设置一个定时器去执行
            timer = setTimeout(() => {
                fn.apply(this, arguments);
                startTime = Date.now();
            }, remaining);
        }
    };
}
</script>
const throttleHandler = throttle(handler, 300)

window界面属性

屏幕,窗口,视口

console.log("视口", window.innerWidth, window.innerHeight)
console.log("窗口", window.outerWidth, window.outerHeight)
console.log("屏幕", window.screen.width, window.screen.height)

 

滚动相关

文档向右或者向下滚动的距离

scrollX scrollY

只针对body的滚动条才有效

定位:scrollTo(绝对)scrollBy(相对)

// 滚动到页面左上角
window.scrollTo(0,0)
// 滚动到页面左边100像素和顶部200像素的位置
window.scrollTo(100,200)

// 当前视口向下滚动100像素
window.scrollBy(0,100)
// 当前视口向右滚动40像素
window.scrollBy(40,0)

平滑滚动

// 平滑滚动
window.scrollTo({top: 1200, behavior: "smooth"})

Navigator(浏览器信息)

属性描述
navigator.userAgent获取浏览器的整体信息
navigator.appName获取浏览器名称
navigator.appVersion获取浏览器的版本号
navigator.platform获取当前计算机的操作系统

12、DOM文档对象模型

DOM是“Document Object Model”的首字母缩写,即文档对象模型。用来描绘一个层次化的节点树,允许开发人员获取、添加、移除和修改页面的某一部分元素

获取元素

通过id获取

const dom = document.getElementById("box1")
console.log(dom)

通过css选择器获取

// console.log(document.getElementsByClassName("name"))用的很少
console.log(document.querySelector(".name"))
console.log(document.querySelector("#name"))
console.log(document.querySelectorAll(".name"))

Element元素对象

元素tag 标签名

dom.tagName		// 获取标签名

属性

// 属性操作
const a = document.getElementById("a")
// 获取属性
console.log(a.getAttribute("href"))
// 设置、修改属性
a.setAttribute("href", "https://www.fengfengzhidao.com")
// 删除属性
a.removeAttribute("xxx")

dataset 标签属性

可以以对象的形式获取、设置标签属性

<div id="box" data-name="枫枫">  <!-- 必须带上data- -->
    这是一个盒子
</div>
<script>
    const dom = document.getElementById("box")
    
    // 获取
    console.log(dom.dataset.name)
    console.log(dom.dataset["name"])
    console.log(dom.dataset)
    
    // 设置
    dom.dataset.addr = "长沙市"
    
    // 删除
    delete dom.dataset.name
    
    // 可以使用自定义属性的方式
    console.log(dom.getAttribute("data-addr"))
</script>

classList class名

以数组的形式获取、操作标签的class

<div class="box"> </div>
<script>
    const box = document.querySelector(".box")
    console.log(box.classList)
    // 添加标签类名
    box.classList.add("head")

    // 是否包含
    console.log(box.classList.contains("head"))

    // 有就删除,没有就创建
    box.classList.toggle("footer")
    box.classList.toggle("footer")

    // 删除
    box.classList.remove("head")

    // 替换
    box.classList.replace("box", "box1")
</script>

outerHTMLinnerHTMLinnerText

<div id="box">
    <a href="htt://www.fengfengzhidao.com">点我</a>
    <span>你好</span>
</div>
<script>
    const box = document.getElementById("box")
    console.log(box.innerText)
    console.log(box.innerHTML)
    console.log(box.outerHTML)
//     box.innerText = "<a>xxx</a>"
//     box.innerHTML = `<div><span>234</span></div>`
//     box.outerHTML = "<a>xxx</a>"
</script>

style 样式

设置或读取css样式

如果通过 style 属性去获取样式,则只能获取行内样式,不能获取其他地方的样式

对于 - 相连的css属性名,要么使用 [] 来调用属性,要么转换成小驼峰命名的方式

<div class="name" style="font-size: 20px; background-color: #800e0e; color: white">枫枫知道</div>
<script>
    const dom = document.querySelector(".name")
    // 获取样式
    console.log(dom.style.fontSize)
    console.log(dom.style.backgroundColor)
    console.log(dom.style.color)
    console.log(dom.style.textAlign) // 只能获取行内的,其他地方的获取不到
    // 设置样式
    dom.style.fontSize = "30px"
    dom.style.padding = "30px"
</script>

可以通过 getComputedStyle 可以获取到的元素的计算之后的样式信息

console.log(getComputedStyle(dom).textAlign) // 获取计算后的style样式

节点操作

节点的操作主要就是增删改查

创建节点

document.createElement

// 创建节点
const dom = document.createElement("a")
dom.setAttribute("href", "https://www.fengfengzhidao.com")
dom.innerText = "枫枫知道"

插入子节点

给一个已知的节点去插入一个新的节点

appendChild,在父节点的最后一个子节点后插入一个节点

append,在父节点的最后一个子节点后插入多个不同的节点

insertBefore,在父节点的子节点之前插入节点,第二个参数为null就是append

// 插入子节点
const box = document.getElementById("box")
// box.appendChild(dom)
// box.append(dom)

// 在任意位置之前插入
// box.insertBefore(dom, null)  // 在末尾插入
// box.insertBefore(dom, box.children[1])  // 在第二个元素前插入
// box.insertBefore(dom, document.querySelector(".d2"))

添加兄弟节点

after 在后面插入

before 在前面插入

const d1 = document.querySelector(".d1")
// d1.before(dom) // 在d1的前面插入
d1.after(dom) // 在d1的后面插入

删除节点

node.removeChild() 从DOM中删除一个子节点。返回删除的节点

node.remove() 删除自身,没有返回值

const d2 = document.querySelector(".d2")
console.log(d2.removeChild(d2.querySelector(".dd2"))) // 删除子节点,并返回被删除的子节点

d2.remove() // 删除自己

父子节点

const d2 = document.querySelector(".d2")
console.log(d2.children) // 获取它的子节点列表
console.log(d2.parentNode) // 获取它的父亲节点

事件

JS事件,就是用户或浏览器本身的某种行为,一般是用户对页面的一些动作引起的

例如,单击某个链接或按钮、在文本框中输入文本、按下键盘上的某个按键、移动鼠标等等

当事件发生时,您可以使用 JavaScript 中的事件处理程序(也可称为事件监听器)来检测并执行某些特定的程序。

一般情况下事件的名称都是以单词on开头的,例如点击事件 onclick、页面加载事件 onload

事件有三种绑定方式,分别是:

在标签上绑定事件

<input placeholder="用户名" οninput="input(event)">
<button>点我</button>
<script>
    function input(e){
        console.log(e.target.value)
    }
</script>

在dom中绑定事件

const btn = document.querySelector(".btn")
btn.onclick = function (e){
    console.log(e.target) // 获取被点击的dom对象
}

添加事件监听

function click(e){
    console.log(e.target)
}
btn.addEventListener("click", click)

// btn.addEventListener("click", function (e){
//     console.log(2, e.target)
// })

// 移除事件
const removeEvent = document.querySelector(".remove_event")
removeEvent.onclick = function (){
    btn.removeEventListener("click", click)
}

需要记住的一些事件

load    加载完成
resize   窗口大小变化
scroll   滚动事件

blur    失去焦点
focus   获得焦点

click     用户单击鼠标左键或按下回车键触发
dbclick   用户双击鼠标左键触发。
mousedown   在用户按下了任意鼠标按钮时触发
mouseenter   在鼠标光标从元素外部首次移动到元素范围内时触发。此事件不冒泡
mouseleave   元素上方的光标移动到元素范围之外时触发。不冒泡
mousemove   光标在元素的内部不断的移动时触发
mouseover   鼠标指针位于一个元素外部,然后用户将首次移动到另一个元素边界之内时触发
mouseout   用户将光标从一个元素上方移动到另一个元素时触发
mouseup   在用户释放鼠标按钮时触发

keydown    当用户按下键盘上的任意键时触发。按住不放,会重复触发
keypress   当用户按下键盘上的字符键时触发。按住不放,会重复触发
keyup     当用户释放键盘上的键时触发
textInput   这是唯一的文本事件,用意是将文本显示给用户之前更容易拦截文本
事件描述
onchangeHTML 元素改变
onclick用户点击 HTML 元素
onmouseover鼠标指针移动到指定的元素上时发生
onmouseout用户从一个 HTML 元素上移开鼠标时发生
onkeydown用户按下键盘按键
onload浏览器已完成页面的加载

事件冒泡

当一个事件被触发时,它首先在最内层的元素(也称为目标元素或事件源)上发生

然后,这个事件会向上冒泡,依次触发其父元素上的同一类型事件,一直冒泡到最外层元素,通常是document对象

这种冒泡机制允许我们在父元素上设置事件处理器,以便在子元素的事件发生时执行特定的操作

<style>
    .p2{
        display: flex;
        justify-content: center;
        align-items: center;
    }
</style>
<div class="p1">
    <div class="p2">
        <div class="p3">我是p3</div>
    </div>
</div>
<script>
   const p1 = document.querySelector(".p1")
   const p2 = document.querySelector(".p2")
   const p3 = document.querySelector(".p3")
   p3.onclick = function (e){
       console.log("p3", e.target)
   }
   p2.onclick = function (e){
       console.log("p2", e.target)
       // event.stopPropagation()  // 阻止冒泡
   }
   p1.onclick = function (e){
       console.log("p1", e.target)
   }
</script>

阻止冒泡

event.stopPropagation()

阻止事件的默认行为

常规情况下点击a标签会自动跳转至页面这是事件的默认行为,若不想要这个效果,即可使用阻止事件的默认行为即可实现

<a href="baidu.com">百度</a>
<script>
    const a = document.querySelector("a")
    a.onclick = function(e){
        console.log(e.target)
    	e.preventDefault()  // 阻止事件的默认行为
    }
</script>

很多网站都有,点击外部链接会有安全提示

const a = document.querySelector("a")
a.onclick = function (e){
    const ok = confirm(`你确定要访问 ${e.target.getAttribute("href")}吗`)
    if (!ok){
        e.preventDefault() // 取消标签的默认行为
    }
}

事件委托

事件委托,又叫事件代理。事件委托就是利用事件冒泡,只指定一个事件处理程序,就可以管理某一类型的所有事件

比如说有100个子节点,像实现点击子节点执行某个函数,给100个子节点去绑定事件明显不划算,就可以通过事件委托来实现

<div class="box">
    <div class="s s1">s1</div>
    <div class="s s2">s2</div>
    <div class="s s3">s3</div>
    <div class="s s4">s4</div>
    <div class="s s5">s5</div>
</div>
<script>
    const box = document.querySelector(".box")
    box.onclick = function (e){
        console.log(e.target)
    }
</script>

事件循环

JavaScript事件循环是一种机制,用于处理异步事件和回调函数。它是JavaScript运行时环境的一部分,负责管理事件队列和调用栈

事件循环的基本原理是事件循环的核心是一个事件队列,所有的事件都被放入这个队列中,然后按照顺序依次执行。如果队列为空,JavaScript会等待新的任务加入队列。当JavaScript代码执行时,所有同步任务都会被立即执行,而异步任务则会被放入事件队列中

当所有同步任务执行完毕后,事件循环会从事件队列中取出一个任务,并将其放入调用栈中执行。当该任务执行完毕后,事件循环会再次从事件队列中取出下一个任务,并重复这个过程

// 什么是异步任务
console.log(1)
setTimeout(() => {
    console.log(3)
}, 0)
console.log(2)
// 顺序 1 2 3
// 当同步任务执行完之后,才会从任务队列中执行异步任务

宏任务和微任务

异步任务也分宏任务和微任务

宏任务包括setTimeoutsetInterval、I/O操作等

微任务包括PromiseMutationObserver

当事件循环从事件队列中取出一个任务时,它会先执行所有微任务然后再执行一个宏任务。这个过程会一直重复,直到事件队列中的所有任务都被执行完毕

console.log('1'); 
setTimeout(function() { 
    console.log('2'); 
    Promise.resolve().then(function() { 
        console.log('3'); 
    }); 
}, 0); 

Promise.resolve().then(function() { 
    console.log('4'); 
}); 
console.log('5'); 
// 输出结果为: 1 5 4 2 3

执行顺序:

  • 执行第一个console.log,输出1。

  • 执行setTimeout,将其回调函数放入宏任务队列中。

  • 执行Promise.resolve().then,将其回调函数放入微任务队列中。

  • 执行第二个console.log,输出5。

  • 当前任务执行结束,执行微任务队列中的所有任务,输出4。

  • 执行宏任务队列中的第一个任务,即setTimeout的回调函数,输出2。

  • 执行Promise.resolve().then的回调函数,输出3。

需要注意的是,微任务和宏任务的执行顺序是固定的,即先执行所有微任务,再执行宏任务。因此,如果在一个宏任务中产生了新的微任务,那么这些微任务会在下一个宏任务执行之前执行。

console.log('1'); 

setTimeout(function() { 
    console.log('2'); 
    Promise.resolve().then(function() { 
        console.log('3'); 
    }); 
}, 0); 

Promise.resolve().then(function() { 
    console.log('4'); 
    setTimeout(function() { 
        console.log('5'); 
    }, 0); 
}); 

console.log('6'); 

// 输出结果为:1 6 4 2 3 5

执行顺序:

  • 执行第一个console.log,输出1。

  • 执行setTimeout,将其回调函数放入宏任务队列中。

  • 执行Promise.resolve().then,将其回调函数放入微任务队列中。

  • 执行第三个console.log,输出6。

  • 当前任务执行结束,执行微任务队列中的所有任务,输出4。

  • 执行宏任务队列中的第一个任务,即setTimeout的回调函数,输出2。

  • 执行Promise.resolve().then的回调函数,将setTimeout的回调函数放入宏任务队列中。

  • 当前任务执行结束,执行微任务队列中的所有任务,输出3。

  • 执行宏任务队列中的第一个任务,即setTimeout的回调函数,输出5

<!-- -->

es6

解构赋值

// 一般用常量const声明,需要改的时候在改成变量let
const [a, b, c] = [1, 2, 3]
const str = `abc${a}`
const { username, age:userAge, ...otherInfo } = {
    username: '杨小槿',
    age: 18,
    gender: 'male',
    category: 'user'
}
console.log(username, userAge, otherInfo)

数组和对象的扩展

const arr1 = [1, 2, 3]
const arr2 = [4, 5, 6]
const arr3 = [...arr1, ...arr2, 10]
const obj1 = {
    a:1
}
const obj2 = {
    b:2,
    ...obj1
}
// 数组方法 Array.from()  arguments打印实参
function fn(){
    console.log(arguments)
    arguments.push(1)
}
fn(1,2,3,4)
// ------------
function fn(){
    Array.from(arguments).forEach(function(item){
        console.log(item)
    })
}
fn(1,2,3,4)
// 对象方法 Object.assign()
const objA = {
    name: '杨小槿',
    age: 18
}
const objB = Object.assign({}, objA)  // Object.assign({},objA,objB,objC)
objB.name='a'
console.log(objA,objB)

Class

class A{
    constructor (name, age) {
        this.name = name
        this.age = age
    }
    introduce(){
        console.log(`我的名字是${this.name},年龄${this.age}`)
    }
}
const a1 = new A('杨小槿', 18)
a1.introduce()

class B extends A {
     constructor (name, age, gender) {
         super(name, age)
         this.gender = gender
     }
    sayHello(){
        console.log('泥蒿'+this.name)
    }
}
const b1 = new B('小李', 19, '女')
b1.introduce()
b1.sayHello()

箭头函数

const getSum1 = function(n){
    return n+3
}
const getSum1 = n => n + 3
console.log(getSum1(10))
const getSum2 = (n1, n2) => n1 + n2
const getSum3 = (n1, n2, ...other) => console.log(n1, n2, other)
getSum3(10, 20, 100, 200, 300)

const getSum1 = n => {
    return n + 3
}

异步处理

promise解决异步写法中的嵌套问题

const p1 = new Promise((resolve, reject)=>{
    resolve('任务成功得到的数据')
    //reject()
})
p1.then(data = >{
    console.log(data)
})
const p1 = new Promise((resolve, reject)=>{
    // resolve('任务成功得到的数据')
    reject('任务失败得到的数据')
})
p1.then(data = >{
    console.log(data)
	return new Promise((resolve, reject)=>{
    // resolve('任务成功得到的数据')
    reject('任务失败得到的数据')
})
})
.catch(err => {
    console,log(err)
})
// Async await
function asyncTask(){
    return new Promise((resolve, reject)=>{
        const isSuccess = true
        if (isSuccess){
            resolve('任务二的成功处理结果')
        } else {
            reject('任务二的失败处理结果')
        }
    })
}

async function main(){
    console.log('任务一')
    cost data = await asyncTask()
    console.log(data)
    console.log('任务三')
}
main()
// Proxy代理对象
const obj = {name:'杨小槿', age:18}
const container = document.getElementById('container')
container.textContent = obj.name
obj.name = 'abc'

......

 

 

 

 


http://www.kler.cn/a/579318.html

相关文章:

  • Docker部署Ragflow(完美解决502 bad gateway)
  • FPGA设计时序约束用法大全保姆级说明
  • 如何让一个类作为可调用对象被thread调用?
  • SQL 别名
  • 对开源VLA sota π0的微调——如何基于各种开源数据集、以及你自己的私有数据集微调π0(含我司的微调实践)
  • Vue3、vue学习笔记
  • Pytorch 第九回:卷积神经网络——ResNet模型
  • Ae 效果详解:VR 平面到球面
  • CmBacktrace的学习跟移植思路
  • 基于国产芯片的AI引擎技术,打造更安全的算力生态 | 京东零售技术实践
  • 关于OceanBase与CDH适配的经验分享
  • VMware笔记(断续更新)
  • 引领变革!北京蜂巢世纪科技有限公司荣获“GAS消费电子科创奖-产品创新奖”!
  • 【面试】Java 集合
  • MWC 2025 | 紫光展锐与中国联通联合发布5G eSIM 平板
  • 【对话推荐系统综述】Broadening the View: Demonstration-augmented Prompt Learning for CR
  • http协议的三次握手机制
  • Browser Use+DeepSeek的使用教程
  • Android中AIDL和HIDL的区别
  • 【每日学点HarmonyOS Next知识】对话框去掉圆角、数组拼接、自定义对话框依附某个控件、平移动画、页面栈管理