前端

前端

前端:任何与用户直接打交道的操作界面都可以称之为前端
比如:电脑界面 手机界面 平板界面

后端:后端类似于幕后操作者(一堆让人头皮发麻的代码),不直接跟用户打交道

HTML:网页的骨架 没有任何的样式
CSS:给骨架添加各种样式 变得好看
JS:控制网页的动态效果

前端框架:BOOTSTRAP、JQuery、Vue
提前封装好很多操作 你只需要按照固定的语法调用即可

软件开发架构

cs  客户端 服务端
bs  浏览器 服务端
ps:bs本质也是cs

浏览器窗口输入网址回车发生了几件事

1 浏览器朝服务端发送请求
2 服务端接受请求(eg:请求百度首页)
3 服务端返回相应的响应(eg:返回一个百度首页)
4 浏览器接收响应 根据特定的规则渲染页面展示给用户看

浏览器可以充当很多服务端的客户端(百度 腾讯视频 优酷视频...)

如何做到浏览器能够跟多个不同的客户端之间进行数据交互?
1.浏览器能够自动识别不同服务端做不同处理
2.制定一个统一的标准 如果你想要让你写的服务端能够跟客户端之间做正常的数据交互,那么你就必须要遵循一些规则

1.HTTP协议

1.HTTP协议

即超文本传输协议,用来规定服务端和浏览器之间的数据交互的格式

2.四大特性

1.基于请求响应
2.基于TCP/IP作用于应用层之上的协议
3.无状态(不保存用户的信息)
由于HTTP协议是无状态的 所以后续出现了一些专门用来记录用户状态的技术(cookie、session、token...)
4.无/短链接
请求来一次响应一次 之后就没有任何链接和关系

长链接:双方建立连接之后默认不断开 websocket

3.数据格式

1.请求数据格式

请求首行(标识HTTP协议版本,当前请求方式)

请求(一大堆k,v键值对)

\r\n(不可省略)

请求(并不是所有的请求方式都有get没有post有 存放的是post请求提交的敏感数据)

请求方式

1.get请求

朝服务端要数据
eg:输入网址获取对应的内容
2.post请求

朝服务端提交数据
eg:用户登陆 输入用户名和密码之后 提交到服务端后端做身份校验

url:统一资源定位符(大白话 网址)

2.响应数据格式

响应首行(标识HTTP协议版本,响应状态码)
响应(一大堆k,v键值对)

\r\n(不可省略)

响应(返回给浏览器展示给用户看的数据)

响应状态码

用一串简单的数字来表示一些复杂的状态或者描述性信息 404:请求资源不存在

1XX:服务端已经成功接收到了你的数据正在处理,你可以继续提交额外的数据
2XX:服务端成功响应了你想要的数据(200 OK请求成功)
3XX:重定向(当你在访问一个需要登陆之后才能看的页面 你会发现会自动跳转到登陆页面)
4XX:请求错误
    404:请求资源不存在
    403:当前请求不合法或者不符合访问资源的条件
5XX:服务器内部错误(500)

2.HTML

html:超文本标记语言,是一种用于创建网页的标记语言

想要让浏览器能够渲染出你写的页面,必须遵循HTML语法

浏览器看到的页面,内部其实都是HTML代码(所有的网站内部都是HTML代码)

服务端

import socket
server = socket.socket()
server.bind(("127.0.0.1", 8080))
server.listen(5)
while True:
    conn, addr = server.accept()
    data = conn.recv(1024)
    conn.send(b"HTTP/1.1 200 OK\r\n\r\n")
    with open ('a.txt','rb') as f:
        conn.send(f.read())
    conn.close()

a.txt内容

<h1>hello big baby~</h1>
<a href="https://www.mzitu.com/">click me!give you some color to see see!</a>
<img src="https://dss1.bdstatic.com/70cFuXSh_Q1YnxGkpoWK1HF6hhy/it/u=2159057472,1466656787&fm=26&gp=0.jpg" />

浏览器输入:127.0.0.1:8080

先启动服务端,然后在浏览器输入127.0.0.1:8080,运行结果如下:

1.png

HTML就是书写网页的一套标准

# 注释:注释是代码之母
<!--单行注释-->
<!--
多行注释1
多行注释2
多行注释3
-->

用注释来划定区域方便后续的查找
<!--导航条开始-->
导航条所有的html代码
<!--导航条结束-->
<!--左侧菜单栏开始-->
左侧菜单栏的HTMl代码
<!--左侧菜单栏结束-->

1.HTML文档结构

<html>
    <head></head>:head内的标签不是给用户看的 而是定义一些配置主要是给浏览器看的
  <body></body>:body内的标签 写什么浏览器就渲染什么 用户就能看到什么
</html>

PS:文件的后缀名其实是给用户看到的,只不过对应不同的 文件后缀名有不同的软件来处理并添加很多功能

注意:HTML代码是没有格式的,可以全部写在一行都没有问题,只不过我们习惯了缩进来表示代码

  1. 1. <!DOCTYPE html>声明为HTML5文档。
    2. <html>、</html>是文档的开始标记和结束的标记。是HTML页面的根元素,在它们之间是文档的头部(head)和主体(body)。
    3. <head>、</head>定义了HTML文档的开头部分。它们之间的内容不会在浏览器的文档窗口显示。包含了文档的元(meta)数据。
    4. <title>、</title>定义了网页标题,在浏览器标题栏显示。
    5. <body>、</body>之间的文本是可见的网页主体内容。
    

    几个很重要的属性:

    • id:定义标签的唯一ID,HTML文档树中唯一
    • class:为html元素定义一个或多个类名(classname)(CSS样式类名)
    • style:规定元素的行内样式(CSS样式)

2.两种打开HTML文件的方式

  • 找到文件所在的位置右键选择浏览器打开
  • 在pycharm内部,集成了自动调用浏览器的功能,直接点击即可(前提是你的电脑上安装了对应的浏览器) 直接全部使用谷歌浏览器

3.标签的分类1

<h1></h1>
<a href="https://www.mzitu.com/"></a>
<img/>

1 双标签
2 单标签(自闭和标签)

4.head内常用标签

html代码的书写:写标签名,然后tab自动补全

<title>Title</title>  网页标题
<style>
        h1 {
            color: greenyellow;
        }
</style>  内部用来书写css代码,颜色

<script>
        alert(123)
</script>  内部用来书写js代码,弹框
<script src="myjs.js"></script>  还可以引入外部js文件

<link rel="stylesheet" href="mycss.css">  引入外部css文件
html之head内常用标签.png

Meta标签

Meta标签介绍:

  • <meta>元素可提供有关页面的元信息(mata-information),针对搜索引擎和更新频度的描述和关键词。

  • <meta>标签位于文档的头部,不包含任何内容。

  • <meta>提供的信息是用户不可见的。

meta标签的组成:meta标签共有两个属性,它们分别是http-equiv属性和name 属性,不同的属性又有不同的参数值,这些不同的参数值就实现了不同的网页功能。

1.http-equiv属性:相当于http的文件头作用,它可以向浏览器传回一些有用的信息,以帮助正确地显示网页内容,与之对应的属性值为content,content中的内容其实就是各个参数的变量值。

<!--指定文档的编码类型(需要知道)-->
<meta http-equiv="content-Type" charset=UTF8">  
<!--2秒后跳转到对应的网址,注意引号(了解)-->
<meta http-equiv="refresh" content="2;URL=https://www.oldboyedu.com">
<!--告诉IE以最高级模式渲染文档(了解)-->
<meta http-equiv="x-ua-compatible" content="IE=edge">

2.name属性: 主要用于描述网页,与之对应的属性值为content,content中的内容主要是便于搜索引擎机器人查找信息和分类信息用的。

<meta name="keywords" content="meta总结,html meta,meta属性,meta跳转">
<meta name="description" content="老男孩教育Python学院">

<meta name="keywords" content="老男孩教育,老男孩,老男孩培训,Python培训,Linux培训,网络安全培训,Go语言培训,人工智能培训,云计算培训,Linux运维培训,Python自动化运维,Python全栈开发,IT培训"> 
当你在用浏览器搜索的时候 只要输入了keywords后面指定的关键字那么该网页都有可能被百度搜索出来展示给用户

<meta name="keyword" content="淘宝,掏宝,网上购物,C2C,在线交易,交易市场,网上交易,交易市场,网上买,网上卖,购物网站,团购,网上贸易,安全购物,电子商务,放心买,供应,买卖信息,网店,一口价,拍卖,网上开店,网络购物,打折,免费开店,网购,频道,店铺">

<meta name="description" content="淘宝网 - 亚洲较大的网上交易平台,提供各类服饰、美容、家居、数码、话费/点卡充值… 数亿优质商品,同时提供担保交易(先收货后付款)等安全交易保障服务,并由商家提供退货承诺、破损补寄等消费者保障服务,让你安心享受网上购物乐趣!">  网页的描述性信息

5.body内常用标签

你肉眼能够在浏览器上面看到的花里胡哨的页面。内部都是HTML代码

1.基本标签

<h1>我是h1</h1>  标题标签 1~6级标题
<b>加粗</b>
    <i>斜体</i>
    <u>下划线</u>
    <s>删除线</s>
    <p>段落</p>
     <br>  换行
      <hr>  水平分割线

2.标签的分类2

# 1 块儿级标签:独占一行
        h1~h6   p div
# 2 行内标签:自身文本多大就占多大
        i u s b span  

1.块儿级标签可以修改长宽 行内标签不可以 修改了也不会变化
2.块儿级标签内部可以嵌套任意的块儿级标签和行内标签
但是p标签虽然是块儿级标签 但是它只能嵌套行内标签 不能嵌套块儿级标签

总结:
只要是块儿级标签都可以嵌套任意的块儿级标签和行内标签,但是p标签只能嵌套行内标签(HTML书写规范)

行内标签不能嵌套块儿级标签 可以嵌套行内标签

3.特殊符号

&nbsp;  空格
&gt;   大于号
&lt;   小于号
&amp;  &
&yen;  ¥
&copy;  ©
商标&reg; ®

4.常用标签

div  块儿级标签
span  行内标签

页面的布局一般先用div和span占位之后再去调整样式

div使用非常的频繁
div的作用:用div来提前规定所有的区域,之后往该区域内部填写内容即可
普通的文本先用span标签

5.img标签

# 图片标签
<img src="" alt="">

src:存放指定的图片路径;
src:存放指定的url,会向指定的网站发送get请求。
alt:图片无法成功加载时显示的图片描述文字。
title:鼠标悬浮在图片上时展示的图片信息。
height:高度
width:宽度

高度和宽度只修改一个的时候 另外一个参数会等比例缩放

若两个都修改,则失真

6.a标签

1.链接标签
<a href=""></a>
"""
a标签指定的网址未被点击过 那么a标签的字体颜色是蓝色,点击过为紫色
"""

href
1.放url,用户点击就会跳转到该url页面
2.放其他标签的id值 点击即可跳转到对应的标签位置

target
默认a标签是在当前页面完成跳转 _self
可以修改为新建页面跳转 _blank

2.a标签的锚点功能

点击一个文本标题 页面自动跳转到标题对应的内容区域

<a href="" id="d1">顶部</a>
<h1 id="d111">hello world</h1>
<div style="height: 1000px;background-color: red"></div>
<a href="" id="d2">中间</a>
<div style="height: 1000px;background-color: greenyellow"></div>
<a href="#d1">底部</a>
<a href="#d2">回到中间</a>
<a href="#d111">回到顶部</a>

7.标签具有的两个重要书写

1.id值
类似于标签的身份证号 在同一个html页面上id值不能重复
2.class值
该值有点类似于面向对象里面的继承 一个标签可以继承多个class值

标签既可以有默认的书写也可以有自定义的书写

<p id="d1" class="c1" username="jason" password="123"></p>

8.列表标签

  • 无序列表(较多)

    <ul>
            <li>第一项</li>
            <li>第二项</li>
            <li>第二项</li>
            <li>第二项</li>
    </ul>
    

    默认使用实心圆点,可以指定type属性。
    circle:空心圆点
    square:实心方块
    none:无

  • 有序列表(了解)

    <ol type="1" start="5">
        <li>111</li>
        <li>222</li>
        <li>333</li>
    </ol>
    

    编号默认是数字,可以指定type属性。
    A:字母
    I:罗马数字

    start属性用于指定起始计数位置。

  • 标题列表(了解)

    <dl>
        <dt>标题1</dt>
        <dd>内容1</dd>
        <dt>标题2</dt>
        <dd>内容2</dd>
        <dt>标题3</dt>
        <dd>内容3</dd>
    </dl>
    

9.表格标签

jason 123 read
egon 123 dbj
tank 123 hecha

<table>
 <thead>
 <tr>  一个tr就表示一行
 <th>username</th>  加粗文本
 <td>username</td>  正常文本
 </tr>
 </thead>  表头(字段信息)
 <tbody>
 <tr>
 <td>jason</td>
 <td>123</td>
 <td>read</td>
 </tr>
 </tbody>   (数据信息)
</table>
​
​
<table border="1">  加外边宽
<td colspan="2">egon</td>  水平方向占多行
<td rowspan="2">DBJ</td>   垂直方向占多行<

10.表单标签

能够获取前端用户数据(用户输入的、用户选择、用户上传...)基于网络发送给后端服务器

1.form标签
<form action=""></form> 

form标签内部书写的获取用户的数据都会被form标签提交到后端

action:控制数据提交的后端路径(给哪个服务端提交数据) 1.不写 默认就是朝当前页面所在的url提交数据 2.写全路径:https://www.baidu.com 朝百度服务端提交 3.只写路径后缀action='/index/' 自动识别出当前服务端的ip和port拼接到前面 host:port/index

发送文件必须要修改的两个参数

1.method :控制请求方式 1.默认是get请求 也可以携带数据 但是数据是直接破解在url后面的 不安全并且大小有限制 url?username=jason&password=123 2.可以修改为post请求 携带的数据放在请求体里面的

2.enctype :控制数据的编码方式 默认是urlencoded 只能发送普通的文本 不能发送文件 如果你要发送文件 必须改为 form-data

 <form action="http://127.0.0.1:5000/index/" method="post" enctype="multipart/form-data"></form>
2.input与label标签

input:获取用户数据的(输入 选择 上传...),通过type属性变形

<input type=''></input>
  • type可以书写的类型

    1.text 普通文本

     <label for="d1">
      username:<input type="text" id="d1" name="username">
     </label></pre>
2.**password** 展示密文
    <label for="d2">password:</label>
      <input type="password"id="d2" name="password">
3.**date** 日期
     <p>birthday:
      <input type="date" name="birthday">
     </p>
4.**radio** 单选

默认选择可以用**checked**(属性名和属性值一样的时候就可以简写)
     <p>gender:
     <!--    <input type="radio" name="gender" checked="checked">male-->
      <input type="radio" name="gender" value="male" checked>male
      <input type="radio" name="gender" value="female">female
     </p>
5.**checkbox** 多选

默认选择可以用**checked**
   <p>hobby:
     <input type="checkbox" name="hobby" value="read">checked>read
     <input type="checkbox" name="hobby" value="dance">dance
     <input type="checkbox" name="hobby" value="shopping" checked>shopping
    </p>
6.**file** 获取文件
    <input type="file" name="myfile">
     <p>文件:
      <input type="file" multiple name="myfile">
     </p>
了解:可以加**multiple** 支持**传多个文件**

7.**hidden**:隐藏当前input框(钓鱼网站)
    <input type="hidden">
8.**submit** 触发form表单**提交**动作
    <input type="submit" value="注册">
9.**button** 什么功能都没有 就是一个**普通的按钮**

```

<input type="button" value="按钮">
<button>点我</button>可以自定义各种功能

    10.**reset**  **重置**按钮
 <input type="reset" value="重置">

**label**:给input加上对于的注释信息

<label for="d1">第一种 直接讲input框写在label内
username:<input type="text" id="d1">

</label>第二种 通过id链接即可 无需嵌套
<label for="d2">password:</label>
<input type="text" id="d2">


##### 3.select标签

select标签 :下拉框

默认是单选,可以加multiple成多选。一个个下拉框选项是一个个的option标签,option标签默认选中可以加**selected**

**单选:**

<p>province
<select name="" id="">
<option value="" selected>上海</option>
<option value="">北京</option>
<option value="">深圳</option>
</select>
</p>


**多选:**

<p>province
<select name="" id="">
<option value="" selected>上海</option>
<option value="" selected>北京</option>
<option value="">深圳</option>
</select>
</p>

##### 4.textarea标签

textarea标签:获取大段文本内容

<input type="submit" value="注册">
<button>点我</button>

##### 6.所有获取用户输入的标签 都应该有name属性

name就类似于字典的key,用户的数据就类似于字典的value

<p>gender:
<input type="radio" name="gender">男
<input type="radio" name="gender">女
<input type="radio" name="gender">其他
</p>>

#### 11.验证form表单提交数据

安装FLASK

pip3 install FLASK


from flask import Flask, request

app = Flask(name)

form表单默认提交数据的方式 是get请求 数据是直接放在url后面的

http://127.0.0.1:5000/index/?username=sdadasdsda&gender=on
@app.route('/index/', methods=['GET', 'POST']) #method指定提交方式
def index():

获取form表单提交的非文件数据。

print(request.form)

ImmutableMultiDict([('username', 'abc'), ('password', 'abc'), ('birthday', '2020-05-01'), ('sex', 'male'), ('file', '书.txt')])

获取文件数据

print(request.files)

ImmutableMultiDict([('file', < FileStorage: '书.txt' ('text/plain') >)])

file_obj = request.files.get('file')
print(file_obj.name) # file
file_obj.save(file_obj.name)

return 'OK'

app.run()


<!DOCTYPE html>
 <html>
 <head>
  <title></title>
 </head>
 <body>
  <form action="http://127.0.0.1:5000/index" method="post" enctype="multipart/form-data">
  username: <input id="username" type="text" name="username">
  <br>
  password: <input id="password" type="password" name="password">
  <br>
  birthday: <input id="birthday" type="date" name="birthday">
  <br>
  sex:
  <input type="radio" name="sex" value="male" checked />Male
  <input type="radio" name="sex" value="female" />Female
  <br>
  <input type="file" name="file" />
  <br>
  <input id="submitBtn" type="submit" value="提交">
  </form>
 </body>
 </html>

form表单提交文件需要注意 1.method必须是post 2.enctype="multipart/form-data" enctype类似于数据提交的编码格式 默认是urlencoded 只能够提交普通的文本数据 formdata 就可以支持提交文件数据

 <form action="http://127.0.0.1:5000/index/" method="post" enctype="multipart/form-data">

针对用户选择的标签,不需要输入内容,但要提前给标签添加内容value值

 <p>gender:
  <input type="radio" name="gender" value="male">男
  <input type="radio" name="gender" checked value="female">女
  <input type="radio" name="gender" value="others">其他
 </p>

针对用户输入的标签,加value就是默认值

<label for="d1">username:<input type="text" id="d1" name="username" value="默认值"></label>

disable 禁用 readonly只读 当表单以post或get方式提交时,设置为disable的标签的值不会被传递,而设置为readonly的标签的值会被传递出去。

3.css层叠样式

层贴样式表:就是给HTML标签添加样式的

1.注释

 /*单行注释*/
 /*
 多行注释1
 多行注释2
 多行注释3
 */
 ​
 /*这是博客园首页的css样式文件*/
 /*顶部导航条样式*/
 ...
 /*左侧菜单栏样式*/
 ...
 /*右侧菜单栏样式*/

2.css的语法结构

选择器 {
  属性1:值1;
  属性2:值2;
  属性3:值3;
  属性4:值4;
 }

3.css的三种引入方式

1.style标签内部直接书写

<style>
  h1  {
  color: burlywood;
  }
 </style>

2.link标签引入外部css文件(最正规的方式 解耦合)

mycss.css文件

 h1{
  color:red;
 }

<link href="mycss.css" rel="stylesheet">

3.行内式(一般不用)

<h1 style="color: green">老板好 要上课吗?</h1>

4.css选择器

1.基本选择器

  • id选择器 选择id="d1"的所有元素
     #d1 {}</pre>
  • 类选择器 选择class="c1"的所有元素
     div {}</pre>
  • 通用选择器 选择所有元素。
    * {}</pre>
  !DOCTYPE html>
     <html lang="en">
     <head>
      <meta charset="UTF-8">
      <title>xiaosi</title>
      <style>
      /*id选择器*/
      /*#d1 {  !*找到id是d1的标签 将文本颜色变成绿黄色*!*/
      /*    color: greenyellow;*/
      /*}*/
      /*类选择器*/
      /*.c1 {  !*找到class值里面包含c1的标签*!*/
      /*    color: red;*/
      /*}*/
      /*元素(标签)选择器*/
      /*span {  !*找到所有的span标签*!*/
      /*    color: red;*/
      /*}*/
      /*通用选择器*/
      * {  /*将html页面上所有的标签全部找到*/
      color: green;
      }
      </style>
     </head>

     <body>
      <div id="d1" class="c1 c2">
      <p>div里面的p</p>
      <span>div里面的span</span>
      </div>
      <p id="d2" class="c1 c2">ppp</p>
      <span id="d3" class="c2">span111</span>
      <span id="d4" class="c3">span222</span>

#### 2.组合选择器

<pre spellcheck="false" class="md-fences md-end-block md-fences-with-lineno ty-contain-cm modeLoaded" lang="python" cid="n247" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: var(--monospace); font-size: 0.9em; display: block; break-inside: avoid; text-align: left; white-space: normal; background-image: inherit; background-position: inherit; background-size: inherit; background-repeat: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(248, 248, 248); position: relative !important; border: 1px solid rgb(231, 234, 237); border-radius: 3px; padding: 8px 4px 6px 0px; margin-bottom: 15px; margin-top: 15px; width: inherit; color: rgb(51, 51, 51); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;"> """
 在前端 我们将标签的嵌套用亲戚关系来表述层级
  <div>div
  <p>div p</p>
  <p>div p
  <span>div p span</span>
  </p>
  <span>span</span>
  <span>span</span>
  </div>
  div里面的p span都是div的后代
  p是div的儿子
  p里面的span是p的儿子 是div的孙子
  div是p的父亲
 """</pre>

*   后代选择器 选择 div 元素内部的所有 span 元素。
div span
*   儿子选择器 选择父元素为 div 元素的所有 p 元素(div 元素内部第一层的所有 p 元素)
div>span

*   毗邻选择器 选择紧接在 div 元素之后(同级别,中间不能有其它标签)的所有 p 元素
div+span

*   弟弟选择器 选择在 div 元素之后(同级别,不一定紧接)的所有 p 元素
div~span

#### 3.属性选择器

以中括号 [ ] 作为标志。

1 含有某个属性 **[username]**  选择带有 usernamet 属性所有元素。

``` [username]```

2.含有某个属性并且有某个值 **[username='jason']**  找到所有属性名是username并且属性值是jason的标签

``` [username='jason']```

3.含有某个属性并且有某个值的某个标签**input[username='jason']** 找到所有属性名是username并且属性值是jason的input标签

``` input[username='jason']```

#### 4.分组与嵌套

**分组**: 多个元素的样式相同 , 用逗号分隔的分组选择器来统一设置元素样式

/逗号表示并列关系/
div,
p,
span {
color: yellow;
}

d1,.c1,span {

color: orange;
}


**嵌套** 多种选择器可以混合起来使用,比如:.c1类内部所有p标签设置字体颜色为红色

.c1 p {
color: red;
}


#### 5.伪类选择器

/* a标签访问前的状态 /
a:link

/
鼠标悬浮态 /
a:hover

/
激活态 鼠标按住不松开的状态 /
a:active

/
访问后的状态 /
a:visited

/
input输入框获取焦点 */
input:focus


#### 6.伪元素选择器

/* 第一个字符 /
p:first-leter

/
通过CSS添加文本内容,无法选中。 */
p:before {
content: "Hello";
color: red;
}
p:after {
content: "Bye";
color: red;
}


before和after通常都是用来清除浮动带来的影响:父标签塌陷的问题

#### 7.选择器优先级

1.选择器相同 书写顺序不同  就近原则:谁离标签更近就听谁的  2.选择器不同 ...  行内 > id选择器 > 类选择器 > 标签选择器  精确度越高越有效

### 5.css属性相关(操作标签样式)

#### 1.宽和高

width属性可以为元素设置宽度。

height属性可以为元素设置高度。

块级标签才能设置宽度,内联标签的宽度由内容来决定。

p {
background-color: red;
height: 200px;
width: 300px;
}


#### 2.字体属性

p {
font-family: "Times New Roman", Georgia, Serif, "宋体";
font-weight: bolder; /* 100~900、normal、bolder、inherit(继承父元素的字体粗细) */
font-size: 24px;#字体大小

设置颜色的四种方式:

/color:red;/
/color:#ee762e;/
/color:rgb(128,23,45);/
color:rgba(128,23,45,0.9);
}

提取颜色

1.pycharm提供的提取色
2.qq或微信截图功能


#### 3.文字属性

p {
text-align: center; /* left, right, justify文字对齐 /
text-decoration: underline; /
overline, line-through, none 文字装饰/
text-indent: 2em; /
首行缩进2个字符 32px/
}
a {
text-decoration: none; /
去掉a标签的下划线。 */
}


#### 4.背景属性

div {
background-color: blue;
background-image: url("111.jpg");
background-repeat: no-repeat; /* 默认全部铺满repeat /
background-position: 20px 20px; /
调节背景图片位置 /
background-position: center center; /
使背景图片居中 /
}
/
多个属性名前缀相同,可以简写。位置不限 */
div {
background: blue url("111.jpg") no-repeat center center;
}

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<style>

d1 {

height: 500px;
background-color: red;
}

d2 {

height: 500px;
background-color: green;
}

d3 {

height: 500px;
background-image: url("111.png");
background-attachment: fixed;
}

d4 {

height: 500px;
background-color: aqua;
}
</style>
</head>
<body>
<div id="d1"></div>
<div id="d2"></div>
<div id="d3"></div>
<div id="d4"></div>
</body>
</html>


#### 5.边框

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<style>

p {
background-color: red;

border-width: 5px;
border-style: solid;
border-color: green;

}
div {
/border-left-width: 5px;/
/border-left-color: red;/
/border-left-style: dotted;/

/border-right-width: 10px;/
/border-right-color: greenyellow;/
/border-right-style: solid;/

/border-top-width: 15px;/
/border-top-color: deeppink;/
/border-top-style: dashed;/

/border-bottom-width: 10px;/
/border-bottom-color: tomato;/
/border-bottom-style: solid;/
border: 3px solid red; /三者位置可以随意写/

}

d1 {

background-color: greenyellow;
height: 400px;
width: 400px;
border-radius: 50%; /直接写50%即可 长宽一样就是圆 不一样就是椭圆/
}
</style>
</head>
<body>
<p>人和人终究是不一样的.png</p>
<div>人生自古谁无死,留取丹心照汗青</div>
<div id="d1"></div>
</body>
</html>


#### 6.display属性

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<style>
/#d1 {/
/* !display: none; !隐藏标签不展示到前端页面并且原来的位置也不再占有了 但是还存在于文档上!!/
/
display: inline; !将标签设置为行内标签的特点!/
/
}/
/
#d2 {/
/
display: inline;/
/
}/
/
#d1 {/
/
display: block; !将标签设置成块儿级标签的特点!/
/
}/
/
#d2 {/
/
display: block;/
/
}/
/
#d1 {/
/
display: inline-block;/
/
}/
/
#d2 {/
/
display: inline-block; !标签即可以在一行显示又可以设置长宽!/
/
}*/
</style>
</head>
<body>
<div style="display: none">div1</div>
<div>div2</div>
<div style="visibility: hidden">单纯的隐藏 位置还在</div>
<div>div4</div>







</body>
</html>


#### 7.盒子模型

1.  外边距 Margin  边框外的区域,可以理解为标签与标签之间的距离。

2.  边框 Border  围绕在内边距外的边框。

3.  内边距 Padding  边框以内内容周围的区域。

4.  内容 Content  标签实际显示的数据

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<style>
body {
margin: 0; /上下左右全是0
/
margin: 10px 20px; !* 第一个上下 第二个左右!/
/margin: 10px 20px 30px; !第一个上 第二个左右 第三个下!/
/margin: 10px 20px 30px 40px; !上 右 下 左!/
}
/p {/
/* margin-left: 0;/
/
margin-top: 0;/
/
margin-right: 0;/
/
margin-bottom: 0;/
/
}*/

d1 {

margin-bottom: 50px;
}

d2 {

margin-top: 20px; /不叠加 只取大的/
}

dd {

margin: 0 auto; /只能做到标签的水平居中/
}
p {
border: 3px solid red;
/padding-left: 10px;/
/padding-top: 20px;/
/padding-right: 20px;/
/padding-bottom: 50px;/

/padding: 10px;/
/padding: 10px 20px;/
/padding: 10px 20px 30px;/
/padding: 10px 20px 30px 40px;/ /规律和margin一模一样/
}
</style>
</head>
<body>






<p>ppp</p>

</body>
</html>


#### 8.浮动

浮动使标签脱离标准文档流,漂浮起来并向左或向右移动。

只能水平方向向左或向右浮动,不能上下浮动;  一个浮动元素会尽量向左或向右移动,直到其外边缘碰到包含框或另一个浮动框的边框为止;  浮动元素不再是块级元素,即本身多大就占多大空间,不再占单独一行;  周围的元素也会重新排列,浮动元素之后的元素将围绕它,浮动元素之前的元素将不会受到影响。

#### 9.解决浮动带来的影响

浮动带来的影响:父标签塌陷

解决方法:

1.自己加一个div设置高度,利用clear属性

d4 {

clear: left; /该标签的左边(地面和空中)不能有浮动的元素/
}


2.**通用**的解决浮动带来的影响方法:在写html页面之前 先提前写好处理浮动带来的影响的 css代码

.clearfix:after {
content: '';
display: block;
clear:both;
}


之后只要标签出现了塌陷的问题就给该塌陷的标签加一个clearfix属性即可

#### 10.溢出属性

p {
height: 100px;
width: 50px;
border: 3px solid red;
/overflow: visible; !默认就是可见 溢出还是展示!/
/overflow: hidden; !溢出部分直接隐藏!/
/overflow: scroll; !设置成上下滚动条的形式!/
/overflow: auto;/
}


#### 11.定位

*   静态

    所有的标签默认都是静态的static,无法改变位置

*   相对定位(了解)

    相对于标签原来的位置做移动relative

*   绝对定位(常用)

    相对于已经定位过的父标签做移动(如果没有父标签那么就以body为参照)

    eg:小米网站购物车

    当你不知道页面其他标签的位置和参数,只给了你一个父标签的参数,让你基于该标签做定位

*   固定定位(常用)

    相对于浏览器窗口固定在某个位置

    eg:右侧小广告

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<style>
body {
margin: 0;
}

d1 {

height: 100px;
width: 100px;
background-color: red;
left: 50px; /从左往右 如果是负数 方向则相反/
top: 50px; /从上往下 如果是负数 方向则相反/
/position: static; !默认是static无法修改位置!/
position: relative;
/*相对定位
标签由static变为relative它的性质就从原来没有定位的标签变成了已经定位过的标签
虽然你哪怕没有动 但是你的性质也已经改变了
*/
}

d2 {

height: 100px;
width: 200px;
background-color: red;
position: relative; /已经定位过了/
}

d3 {

height: 200px;
width: 400px;
background-color: yellowgreen;
position: absolute;
left: 200px;
top: 100px;
}

d4 {

position: fixed; /写了fixed之后 定位就是依据浏览器窗口/
bottom: 10px;
right: 20px;

height: 50px;
width: 100px;
background-color: white;
border: 3px solid black;
}
</style>
</head>
<body>






<div style="height: 500px;background-color: red"></div>
<div style="height: 500px;background-color: greenyellow"></div>
<div style="height: 500px;background-color: blue"></div>
<div id="d4">回到顶部</div>

</body>
</html>


#### 12.验证浮动和定位是否脱离文档流

**不脱离文档流**

相对定位

**脱离文档流**

1.浮动

2.绝对定位

3.固定定位

</div>-->







<div style="height: 100px;width: 200px;background-color: red;"></div>
<div style="height: 100px;width: 200px;background-color: greenyellow;position: fixed;bottom: 10px;right: 20px"></div>
<div style="height: 100px;width: 200px;background-color: blue;"></div>


#### 14.z-index模态框

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<style>
body{
margin:0;
}
.cover{
position:fixed;
left: 0;
right: 0;
top: 0;
bottom: 0;
background-color:rgba(0,0,0,0.5);
z-index: 99;
}
.modal{
background-color: white;
height:200px;
width:300px;
position: fixed;
left:50%;
top:50%;
z-index: 100;
margin-left: -150px;
margin-top: -100px;
}
</style>
</head>
<body>
<div>这是最底层的页面内容</div>
<div class="cover"></div>
<div class="modal">
<h1>登录界面</h1>
<p>username:<input type="text"></p>
<p>password:<input type="text"></p>
<button>点我</button>
</div>

</body>
</html>


#### 15.透明度opacity

颜色和文字的透明度

rgba:只能影响颜色

opacity:可以修改颜色和字体

## 4.JavaScrip

js也是一门编程语言 它也是可以写后端代码的,用js一统天下 前后端都可以写

ECMAScript和JavaScript的关系是,前者是后者的规格,后者是前者的一种实现

JS版本:主要还是用的5.1和6.0

JavaScript 是脚本语言  JavaScript 是一种轻量级的编程语言。

JavaScript 是可插入 HTML 页面的编程代码。

JavaScript 插入 HTML 页面后,可由所有的现代浏览器执行。

JavaScript 很容易学习。

### 1.引入方式

#### 1.Script标签内写代码

<script>
// 在这里写你的JS代码
</script>


#### 2.引入额外的JS文件

<script src="myscript.js"></script>


### 2.语言规范

**注释**

// 单行注释

/*
多行注释1
多行注释2
多行注释3
*/


**结束符**

js是以**分号**(;)作为语句的结束

### 3.变量

#### 1.变量

*   在js中 首次定义一个变量名的时候需要用关键字声明  1.关键字var

var name='jason'


2.es6推出的新语法

let name='jason'


如果你的编辑器支持的版本是**5.1**那么**无法使用let**

如果是**6.0**则**向下兼容** var let

``` ​
 var n=10;
 for(var n=0;n<5;n++){console.log(n)}
 /0 1 2 3 4/
 n;/5/
 ​
 let n=10;
 for(let n=0;n<5;n++){console.log(n)}
 /0 1 2 3 4/
 n;/10/
 ​
 /*
 var在for循环里面定义也会影响到全局
 let在局部定义只会在局部生效
 */
  • js变量命名规范

    1.变量名只能是 (数字 字母 下划线 $) 2.变量名命名规范(不遵循也可以) 1.js中推荐使用驼峰式命名 userName dataOfDb 2.python推荐使用下划线的方式 user_name data_of_db 3.不能用关键字作为变量名

2.常量

python中没有真正意义上的常量 默认全大写就是表示常量

js中是有真正意义上的常量的

const pi = 3.14
  • js代码的书写位置 1.可以单独开设js文件书写 2.还可以直接在浏览器提供的console界面书写 左上方的清空按钮只是清空当前页面,代码还在 彻底清空需重新开设页面

2.数据类型

js是一门面向对象的编程语言,即一切皆对象.

js/python是一门拥有动态类型

name = 'jason'
 name = 123
 name = [1,2,3,4]
 # name可以指向任意的数据类型 
 # 但是有一些语言中,变量名之内指向一种后续不能更改 

1.数值类型(number)

不区分整型和浮点型,就只有一种数字类型

var a=11;
 var b=11.11;
 // 查看当前数据类型
 typeof a;
 "number"
 typeof b;
 "number"
 ​
 // 特殊的 NaN:数值类型 表示的意思是“不是一个数字” NOT A NUMBER
 ​
 // 类型转换
 parseInt()
 parseFloat()
 ​
 parseInt('12312312')
 12312312
 parseFloat('11.11')
 11.11
 parseInt('11.11')
 11
 parseInt('123sdasdajs2312dasd')
 123
 parseInt('asdasdad123sdasdajs2312dasd')
 NaN

2.字符类型(string)

 var s = 'jason' //支持单引号
 undefined
 typeof s
 "string"
 var s1 = "jason" //支持双引号
 undefined
 typeof s1;
 "string"
 var s2 = '''egon'''  // 不支持三引号
 VM665:1 Uncaught SyntaxError: Unexpected string
 ​
 // 模版字符串(``)
 var s3 = `
 asdkajsd
 sdjkladj
 asdjlajdkl
 `
 typeof s3
 "string"
 // 模版字符串可以定义多行文本,还可以实现格式化字符串操作
 // 书写${} 会自动去前面找大括号里面的变量名对应的值 如果没有定义直接报错
 var name = 'jason'
 var age = 18
 var sss = `
  my name is ${name} and my age is ${age}`
 sss
 "
  my name is jason and my age is 18
 "
 //没有定义直接报错
 var s4 = `my name is ${namemmmmm}`
 VM1140:1 Uncaught ReferenceError: namemmmmm is not defined
  at <anonymous>:1:24
 // 在写js代码的时候 不要去管左侧箭头的内容
 ​
 ​
 // 字符串的拼接
 // 在python中不推荐你使用+做拼接 使用join
 // 在js中推荐直接使用+做拼接
 name + age //"jason18"

3.字符类型常用方法

方法 说明
.length 返回长度
.trim() 移除空白
.trimLeft() 移除左边的空白
.trimRight() 移除右边的空白
.charAt(n) 返回第n个字符
.concat(value, ...) 拼接
.indexOf(substring, start) 子序列位置
.substring(from, to) 根据索引获取子序列
.slice(start, end) 切片
.toLowerCase() 小写
.toUpperCase() 大写
.split(delimiter, limit) 分割

记忆方法:对比python记忆

 var c=' egonDsB ';
 ​
 c.length
 9
 ​
 c.trim();//不能加括号指定去除的内容
 "egonDsB"
 ​
 c.trimLeft();
 "egonDsB "
 ​
 c.trimRight();
 " egonDsB"
 ​
 c.charAt(5);
 "D"
 ​
 c.concat(18);//js是弱类型(内部会自动转换成相同的数据类型做操作)
 " egonDsB 18"
 ​
 c.indexOf('on');
 3
 ​
 c.substring(0,5);//不识别负数
 " egon"
 ​
 c.slice(3,7); //可以识别负数
 "onDs"
 ​
 c.toLocaleLowerCase();
 " egondsb "
 ​
 c.toLocaleUpperCase();
 " EGONDSB "
 ​
 c.split(' ');
 (3) ["", "egonDsB", ""]0: ""1: "egonDsB"2: ""length: 3__proto__: Array(0)
 ​
 var name = 'tank|hecha|liaomei|mengsao|...'
 ​
 name.split('|')
 (5) ["tank", "hecha", "liaomei", "mengsao", "..."]
 ​
 name.split('|',2)
 (2) ["tank", "hecha"]0: "tank"1: "hecha"length: 2__proto__: Array(0)
 name.split('|',10)  //第二个参数不是限制切割字符的个数而获取切割之后元素的个数
 (5) ["tank", "hecha", "liaomei", "mengsao", "..."]
 ​
 l = [1,2,3,4,5,6,7]
 res = '|'.join(l)  // 直接报错
 print(res)

4.布尔值

1.在python中布尔值是首字母大写的 True,False 2.但是在js中布尔值是全小写的 true,false

布尔值是false的有:

(空字符串、0、null、undefined、NaN)

5.null与undefined

null:表示值为空 一般都是指定或者清空一个变量时使用

name='json';
 "json"
 name=null
 null
 name
 "null"

undefined:表示声明了一个变量 但是没有做初始化操作(没有给值),函数没有指定返回值的时候,返回的也是undefined

6.对象

一切皆对象

  • 数组(类似于python里面的列表) []

    1.常用方法

    方法 说明
    .length 数组的大小
    .push(ele) 尾部追加元素
    .pop() 获取尾部元素
    .unshift(ele) 头部插入元素
    .shift() 头部移除元素
    .slice(start,end) 切片
    .reverse() 反转
    .join(seq) 将数组元素连成字符串
    .concat(val,...) 连接数组
    .sort() 排序
    .forEach() 将数组的每个元素传递给回调函数
    .splice() 删除元素,并向数组添加新元素。
    .map() 返回一个数组元素调用函数处理后的值的新数组

var l = [11,22,33,44,55]

typeof l
"object"
var l1 = [11,'sdasd',11.11,true]

l1[1]
"sdasd"
l1[-1] # 不支持负数索引


var l = [111,222,333,444,555,666]
undefined
l.length
6
l.push(777)
7
l
(7) [111, 222, 333, 444, 555, 666, 777]
l.pop()
777
l
(6) [111, 222, 333, 444, 555, 666]
l.unshift(123)
7
l
(7) [123, 111, 222, 333, 444, 555, 666]
l.shift()
123
l.slice(0,3)
(3) [111, 222, 333]
l.reverse()
(6) [666, 555, 444, 333, 222, 111]
l.join('/pre>) # 跟python刚好相反
"666555444333222$111"

l.concat([111,222,333]) # extend
(9) [666, 555, 444, 333, 222, 111, 111, 222, 333]
l.sort()
(6) [111, 222, 333, 444, 555, 666]


    **2.三个比较重要的方法**:

    **forEach()**

    **语法:**

    forEach(function(currentValue, index, arr), thisValue)

    参数:

    1.function(currentValue, index, arr)

    currentValue: 必需。当前元素

    index: 可选。当前元素的索引值

    arr: 可选。当前元素所属的数组对象。

    2.thisValue: 可选。传递给函数的值一般用 "this" 值。  如果这个参数为空, "undefined" 会传递给 "this" 值
var ll = [111,222,333,444,555,666]
 ll.forEach(function(value){console.log(value)},ll)
 VM2277:1 111  # 一个参数就是数组里面每一个元素对象
 VM2277:1 222
 VM2277:1 333
 VM2277:1 444
 VM2277:1 555
 VM2277:1 666
 ​
 ll.forEach(function(value,index){console.log(value,index)},ll)
 VM2346:1 111 0  # 两个参数就是元素 + 元素索引
 VM2346:1 222 1
 VM2346:1 333 2
 VM2346:1 444 3
 VM2346:1 555 4
 VM2346:1 666 5
 undefined
 ll.forEach(function(value,index,arr){console.log(value,index,arr)},ll)  # 元素 + 元素索引 + 元素的数据来源
 VM2430:1 111 0 (6) [111, 222, 333, 444, 555, 666]
 VM2430:1 222 1 (6) [111, 222, 333, 444, 555, 666]
 VM2430:1 333 2 (6) [111, 222, 333, 444, 555, 666]
 VM2430:1 444 3 (6) [111, 222, 333, 444, 555, 666]
 VM2430:1 555 4 (6) [111, 222, 333, 444, 555, 666]
 VM2430:1 666 5 (6) [111, 222, 333, 444, 555, 666]
 undefined
 ​
 ll.forEach(function(value,index,arr,xxx){console.log(value,index,arr,xxx)},ll)  # 最多三个
 VM2532:1 111 0 (6) [111, 222, 333, 444, 555, 666] undefined
 VM2532:1 222 1 (6) [111, 222, 333, 444, 555, 666] undefined
 VM2532:1 333 2 (6) [111, 222, 333, 444, 555, 666] undefined
 VM2532:1 444 3 (6) [111, 222, 333, 444, 555, 666] undefined
 VM2532:1 555 4 (6) [111, 222, 333, 444, 555, 666] undefined
 VM2532:1 666 5 (6) [111, 222, 333, 444, 555, 666] undefined

    **splice()**

    **语法:**

    splice(index,howmany,item1,.....,itemX)

    **参数:**

    index : 必需。规定从何处添加/删除元素。该参数是开始插入和(或)删除的数组元素的下标,必须是数字。

    howmany: 必需。规定应该删除多少元素。必须是数字,但可以是 "0"。如果未规定此参数,则删除从 index 开始到原数组结尾的所有元素。

    item1, ..., itemX: 可选。要添加到数组的新元素
 ll
 (6) [111, 222, 333, 444, 555, 666]
 ll.splice(0,3)  # 两个参数 第一个是起始位置 第二个是删除的个数
 (3) [111, 222, 333]
 ll
 (3) [444, 555, 666]
 ll.splice(0,1,777)  # 先删除后添加
 [444]
 ll
 (3) [777, 555, 666]
 ll.splice(0,1,[111,222,333,444])
 [777]
 ll
 (3) [Array(4), 555, 666]

    ####

**map()**

**语法:**

map(function(currentValue,index,arr), thisValue)

**参数:**

function(currentValue, index,arr)

currentValue : 必须。当前元素的值

index: 可选。当期元素的索引值

arr: 可选。当期元素属于的数组对象

thisValue : 可选。对象作为该执行回调时使用,传递给函数,用作 "this" 的值。如果省略了 thisValue ,"this" 的值为 "undefined"

var l1 = [11,22,33,44,55,66]
undefined
l1.map(function(value){console.log(value)},l1)
VM3115:1 11
VM3115:1 22
VM3115:1 33
VM3115:1 44
VM3115:1 55
VM3115:1 66
l1.map(function(value,index){return value2},l1)
(6) [22, 44, 66, 88, 110, 132]
l1.map(function(value,index,arr){return value
2},l1)
(6) [22, 44, 66, 88, 110, 132]


#### 7.运算符

**算术运算符**

+ - * / % ++ --

var x = 10;
var res1 = x++;
var res2 = ++x;
res1 10
res2 12
++表示自增1 类似于 +=1
加号在前先加后赋值 加号在后先赋值后加


**比较运算符**

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

1 == “1” # true 弱等于 内部自动转换成相同的数据类型比较了
1 === "1" # false 强等于 内部不做类型转换
1 != '1' # false
1 !== '2'# true


**逻辑运算符**

python中 and or not

js中 && || !


5 && '5'
"5"

0|| 1;
1

!5 &&'5'
false

**赋值运算符**

= += -= *= /=



### 3.流程控制

#### 1.**if**

if判断

var age = 28;

if(条件){条件成立之后指向的代码块}

if (age>18){
console.log('来啊 来啊')
}

if-else

if (age>18){
console.log('来啊 来啊')
}else{
console.log('没钱 滚蛋')
}

if-else if else

if (age<18){
console.log("培养一下")
}else if(age<24){
console.log('小姐姐你好 我是你的粉丝')
}else{
console.log('你是个好人')
}

()条件,{}代码块


#### 2.switch语法

提前列举好可能出现的条件和解决方式

var num=2;
undefined
switch(num){
case 0:
console.log('吃饭');
break;
case 2:
console.log('睡觉');
break;
case 3:
console.log('打豆豆');
break;
case 4:
console.log('唱歌');
break;
default:
console.log('条件都没有匹配上 默认走的流程')
}
VM5995:6 睡觉


**switch中的case子句通常都会加break语句,否则程序会继续执行后续case中的语句。**

#### 3.for

打印0-9数字

for(let i=0;i<10;i++){
console.log(i)
}

循环打印出数组里面的每一个元素

var l1 = [111,222,333,444,555,666]
for(let i=0;i<l1.length;i++){
console.log(l1[i])
}


#### 4.while

var i = 0
while(i<100){
console.log(i)
i++;
}


#### 5.三元运算符

python中三元运算符 res = 1 if 1>2 else 3

JS中三元运算 res = 1>2?1:3

条件成立取问号(?)后面的1 不成立取冒号(:)后面的3
res = 2>5?8:10 # 10
res = 2>5?8:(8>5?666:444) # 666
"""
三元运算符不要写的过于复杂
"""


### 4.函数

```# 在python定义函数需要用到关键字def
 # 在js中定义函数需要用到关键字function</pre>

**格式**:function 函数名(形参1,形参2,形参3...){函数体代码}

**无参函数**

function func1(){
console.log('hello world')
}
func1()


**有参函数**

function func2(a,b){
console.log(a,b)
}
func2(1,2)# 值多值少都没关系


**关键字arguments**

function func2(a,b){
console.log(arguments) # 能够获取到函数接受到的所有的参数
console.log(a,b)
}

function func2(a,b){
if(arguments.length<2){
console.log('传少了')
}else if (arguments.length>2){
console.log('传多了')
}else{
console.log('正常执行')
}
}


**函数的返回值 return**

function index(){
return 666
}
function index(){
return 666,777,888,999
}
res = index();
999
res
999 # 只能拿到最后一个

function index(){
return [666,777,888,999]
}

js不支持解压赋值\


**匿名函数**

function(){
console.log('哈哈哈')
}
var res = function(){
console.log('哈哈哈')
}


**箭头函数**

主要用来处理简单的业务逻辑 类似于python中的匿名函数

var func1 = v => v; """箭头左边的是形参 右边的是返回值"""
等价于
var func1 = function(v){
return v
}

var func2 = (arg1,arg2) => arg1+arg2
等价于
var func1 = function(arg1,arg2){
return arg1+arg2
}


#### 函数的全局变量与局部变量

跟python查找变量的顺序一致

1.

var city = "BeiJing";
undefined
function f() {
var city = "ShangHai";
function inner(){
var city = "ShenZhen";
console.log(city);
}
inner();
}
undefined
f();
VM45:5 ShenZhen

2.

var city='beijing'
undefined
function Bar(){
console.log(city);
}
undefined
function f(){
var city='shanghai';
return Bar;
}
undefined
var ret=f();
undefined
ret()
VM262:2 beijing

3.闭包

var city = "BeiJing";
function f(){
var city = "ShangHai";
function inner(){
console.log(city);
}
return inner;
}
var ret = f();
ret(); #ShangHai


### 5.内置方法/模块

#### 1.自定义对象

JavaScript的对象(Object)本质上是键值对的集合(Hash结构),但是只能用字符串作为键。

**创建自定义对象**

第一种创建自定义对象的方式

var d={'name':'json','age':18}
undefined
typeof d
"object"
d['name']
"json"
d.name
"json"
d.age
18

for(let i in d){
console.log(i,d[i])
}
VM758:2 name json
VM758:2 age 18


**第二种创建自定义对象的方式** 需要使用关键字**new**

var d2=new Object()
undefined
d2.name='css'
"css"
d2['age']=18
18
d2
{name: "css", age: 18}


#### 2.Date对象

let d3=new Date()
undefined
d3
Sun May 17 2020 11:04:56 GMT+0800 (中国标准时间)
d3.toLocaleString()
"2020/5/17 上午11:04:56"

也支持自己手动输入时间

let d4 = new Date('2200/11/11 11:11:11')
d4.toLocaleString()
"2200/11/11 上午11:11:11"

let d5 = new Date(1111,11,11,11,11,11)
d5.toLocaleString() # 月份从0开始0-11月
"1111/12/11 上午11:11:11"

时间对象具体方法

let d6 = new Date();
d6.getDate() 获取日
d6.getDay() 获取星期
d6.getMonth() 获取月份(0-11)
d6.getFullYear() 获取完整的年份
d6.getHours() 获取小时
d6.getMinutes() 获取分钟
d6.getSeconds() 获取秒
d6.getMilliseconds() 获取毫秒
d6.getTime() 时间戳


#### 3.JSON对象

在python中序列化反序列化  dumps 序列化  loads  反序列化

在js中也有序列化反序列化  JSON.stringify()  dumps  JSON.parse()  loads

let d7={'name':'json','age':18}
let res666=JSON.stringify(d7)
res666
"{"name":"json","age":18}"
JSON.parse(res666)
{name: "json", age: 18}


#### 4.RegExp对象

在python中如果需要使用正则 需要借助于re模块  在js中需要你创建正则对象

**第一种创建正则对象的方法**

let reg1 = new RegExp('^[a-zA-Z][a-zA-Z0-9]{5,11}')


**第二种创建正则对象的方法**

let reg2 = /^[a-zA-Z][a-zA-Z0-9]{5,11}/


**匹配内容**

reg1.test('egondsb')
reg2.test('egondsb')


**获取字符串里面所有的字母s**

let sss = 'egondsb dsb dsb'
sss.match(/s/) # 拿到一个就停止了
["s", index: 5, input: "egondsb dsb dsb", groups: undefined]
sss.match(/s/g) # 全局匹配 g就表示全局模式
(3) ["s", "s", "s"]


**全局匹配模式吐槽点**1

let reg3 = /^[a-zA-Z][a-zA-Z0-9]{5,11}/g
reg3.test('egondsb')
true
reg3.test('egondsb')
false
reg3.lastIndex #全局匹配时有一个lastIndex属性
0
reg3.test('egondsb')
true
reg3.lastIndex
7


**吐槽点2**

let reg4 = /^[a-zA-Z][a-zA-Z0-9]{5,11}/
reg4.test()
true
reg4.test() # 什么都不传 默认传的是undefined
true
reg4.test()
true
reg4.test(undefined)
true

let reg5=/undefined/
undefined
reg5.test('json')
false
reg5.test()
true


#### 5.Math对象

abs(x) 返回数的绝对值。
exp(x) 返回 e 的指数。
floor(x) 对数进行下舍入。
log(x) 返回数的自然对数(底为e)。
max(x,y) 返回 x 和 y 中的最高值。
min(x,y) 返回 x 和 y 中的最低值。
pow(x,y) 返回 x 的 y 次幂。
random() 返回 0 ~ 1 之间的随机数。
round(x) 把数四舍五入为最接近的整数。
sin(x) 返回数的正弦。
sqrt(x) 返回数的平方根。
tan(x) 返回角的正切。


## 5.BOM与DOM操作

**BOM**(Browser Object Model)是指**浏览器对象模型**,它使 JavaScript 有能力与浏览器进行“对话”。(js代码操作浏览器)

**DOM** (Document Object Model)是指**文档对象模型**,通过它,可以访问HTML文档的所有元素。(js代码操作标签)

### 1.BOM操作

#### 1.window对象

window对象指代的就是浏览器窗口

window.innerHeight 浏览器窗口的高度

window.innerWidth 浏览器窗口的宽度

window.open('[https://www.taobao.com/](https://www.taobao.com/)','','height=400px,width=400px,top=400px,left=400px')

新建窗口打开页面 第二个参数写空即可 第三个参数写新建的窗口的大小和位置

window.close() 关闭当前页面

#### 2.window子对象

Web浏览器全称

window.navigator.appName
"Netscape"

Web浏览器厂商和版本的详细字符串

window.navigator.appVersion
"5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.138 Safari/537.36"

掌握:用来表示当前是否是一个浏览器,客户端绝大部分信息

window.navigator.userAgent
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.138 Safari/537.36"

浏览器运行所在的操作系统

window.navigator.platform
"Win32"

如果是window的子对象 那么window可以省略不写


**扩展**:**仿爬措施**  1.最简单最常用的一个就是校验当前请求的发起者是否是一个浏览器  userAgent  user-agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.138 Safari/537.36  **如何破解该措施**:在代码中加上上面的user-agent配置即可

#### 3.history对象

window.history 对象包含浏览器的历史
## 5.BOM与DOM操作

**BOM**(Browser Object Model)是指**浏览器对象模型**,它使 JavaScript 有能力与浏览器进行“对话”。(js代码操作浏览器)

**DOM** (Document Object Model)是指**文档对象模型**,通过它,可以访问HTML文档的所有元素。(js代码操作标签)

### 1.BOM操作

#### 1.window对象

window对象指代的就是浏览器窗口

window.innerHeight 浏览器窗口的高度

window.innerWidth 浏览器窗口的宽度

window.open('[https://www.taobao.com/](https://www.taobao.com/)','','height=400px,width=400px,top=400px,left=400px')

新建窗口打开页面 第二个参数写空即可 第三个参数写新建的窗口的大小和位置

window.close() 关闭当前页面

#### 2.window子对象

Web浏览器全称

window.navigator.appName
"Netscape"

Web浏览器厂商和版本的详细字符串

window.navigator.appVersion
"5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.138 Safari/537.36"

掌握:用来表示当前是否是一个浏览器,客户端绝大部分信息

window.navigator.userAgent
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.138 Safari/537.36"

浏览器运行所在的操作系统

window.navigator.platform
"Win32"

如果是window的子对象 那么window可以省略不写

扩展:仿爬措施 1.最简单最常用的一个就是校验当前请求的发起者是否是一个浏览器 userAgent user-agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.138 Safari/537.36 如何破解该措施:在代码中加上上面的user-agent配置即可

window.history.back() 回退到上一页
window.history.forward() 前进到下一页
对应的就是你浏览器左上方的两个的箭头

4.location对象(掌握)

 window.location.href  # 获取当前页面的url
 window.location.href = url  # 跳转到指定的url
 window.location.reload()  # 刷新页面

5.弹出框

  • 警告框
alert('123')
  • 确认框
confirm('你确定吗?')
   true
   confirm('你确定吗?')
   false
  • 提示框
prompt('请输入验证码','')
     "12345"

6.计时器相关

计时事件:通过使用 JavaScript,我们可以在一定时间间隔之后来执行代码,而不是在函数被调用后立即执行

setTimeout()

语法:

 var t=setTimeout("JS语句",毫秒)

setTimeout() 方法会返回某个值, 第一个参数是含有 JavaScript 语句的字符串 , 第二个参数指示从当前起多少毫秒后执行第一个参数(1000 毫秒等于一秒)

clearTimeout()

语法:

 clearTimeout(setTimeout_variable)

例子:

# 在指定时间之后执行一次相应函数
 function func1(){
  alert(123)
 }
 let t=setTimeout(func1,3000);#毫秒为单位 3秒之后自动执行func1函数
 # 取消setTimeout设置即取消定时任务
 clearTimeout(t);
setInterval()

setInterval() 方法可按照指定的周期(以毫秒计)来调用函数或计算表达式。

setInterval() 方法会不停地调用函数,直到 clearInterval() 被调用或窗口被关闭。由 setInterval() 返回的 ID 值可用作 clearInterval() 方法的参数。

语法:

 setInterval("JS语句",时间间隔)

返回值

一个可以传递给 Window.clearInterval() 从而取消对 code 的周期性执行的值。

clearInterval()

clearInterval() 方法可取消由 setInterval() 设置的timeout

clearInterval() 方法的参数必须是由 setInterval() 返回的 ID 值。

语法:

clearInterval(setinterval返回的ID值)

例:

<script>
  function func2() {
  alert(123)
  }
  function show(){
  let t = setInterval(func2,3000);  // 每隔3秒执行一次
  function inner(){
  clearInterval(t)  // 清除定时器
  }
  setTimeout(inner,9000)  // 9秒中之后触发
  }
  show()
 </script>

2.DOM操作

DOM(Document Object Model)是一套对文档的内容进行抽象和概念化的方法。

当网页被加载时,浏览器会创建页面的文档对象模型(Document Object Model)。

HTML DOM 模型被构造为对象的树

1.HTML DOM 树

htm DOM树.png

DOM标准规定HTML文档中的每个成分都是一个节点(node):

  • 文档节点(document对象):代表整个文档

  • 元素节点(element 对象):代表一个元素(标签)

  • 文本节点(text对象):代表元素(标签)中的文本

  • 属性节点(attribute对象):代表一个属性,元素(标签)才有属性

  • 注释是注释节点(comment对象)

JavaScript 可以通过DOM创建动态的 HTML:

  • JavaScript 能够改变页面中的所有 HTML 元素

  • JavaScript 能够改变页面中的所有 HTML 属性

  • JavaScript 能够改变页面中的所有 CSS 样式

  • JavaScript 能够对页面中的所有事件做出反应

DOM操作操作的是标签 而一个html页面上的标签有很多 1.如何查找标签 2.DOM操作标签 DOM操作需要用关键字document起首

2.查找标签

  • 直接查找(必须掌握)

    id查找,类查找,标签查找

document.getElementById 根据ID获取一个标签
document.getElementsByClassName 根据class属性获取
document.getElementsByTagName 根据标签名获取标签合集


    ```
document.getElementById('d1')
     <div id=•"d1">•…•</div>•
     ​
     document.getElementsByClassName('c1')
     HTMLCollection [p.c1]
     ​
     document.getElementsByTagName('div')
     HTMLCollection(3) [div#d1, div, div, d1: div#d1]

     let divEle=document.getElementsByTagName('div')
     undefined
     divEle
     HTMLCollection(3) [div#d1, div, div, d1: div#d1]
用变量名指代标签对象的时候 一般情况下都推荐书写成  xxxEle,divEle,aEle,pEle
  • 间接查找(熟悉)
parentElement            父节点标签元素
  children                 所有子标签
  firstElementChild        第一个子标签元素
  lastElementChild         最后一个子标签元素
  nextElementSibling       下一个兄弟标签元素
  previousElementSibling   上一个兄弟标签元素
```
let pEle=document.getElementsByClassName('c1')[0] # # 注意是否需要索引取值
 ​
 pEle.parentElement  # 拿父节点
 <div id=•"d1">•…•</div>•
 ​
 pEle.parentElement.parentElement
 <body>•…•</body>•
 ​
 pEle.parentElement.parentElement.parentElement
 <html lang=•"en">•<head>•…•</head>•<body>•…•</body>•</html>•
 ​
 pEle.parentElement.parentElement.parentElement.parentElement
 null
 ​
 let divEle=document.getElementById('d1')
 divEle.children ## 获取所有的子标签
 HTMLCollection(3) [div, p.c1, p]
 ​
 divEle.children[0]
 <div>•div>div•</div>•
 divEle.firstElementChild
 <div>•div>div•</div>•
 ​
 divEle.lastElementChild
 <p>•div>div•</p>•
 divEle.nextElementSibling # 同级别下面第一个
 <div>•div下面的div•</div>•
 divEle.previousElementSibling # 同级别上面第一个
 <div>•div上面的div•</div>•

#### 3.节点操作

*   **创建节点**

    语法:

    createElement(标签名)

    示例:

var divEle = document.createElement("div");


*   **添加节点**

    语法:

    追加一个子节点(作为最后的子节点)

    .appendChild(newnode);

    把增加的节点放到某个节点的前边。

    somenode.insertBefore(newnode,某个节点);

例:通过DOM操作动态的创建img标签,并且给标签加属性,最后将标签添加到文本中

let imgEle=document.createElement('img')

imgEle.src='111.png' # 给标签设置默认的属性
"111.png"
imgEle.username='jason'# 自定义的属性没办法点的方式直接设置
"jason"
imgEle
<img src=•"111.png">•

imgEle.setAttribute('username','jason') # 既可以设置自定义的属性也可以设置默认的书写
imgEle
<img src=•"111.png" username=•"jason">•
imgEle.setAttribute('title','喵喵喵')
imgEle
<img src=•"111.png" username=•"jason" title=•"喵喵喵">•

let divEle=document.getElementById('d1')
undefined
divEle.appendChild(imgEle) # 标签内部添加元素(尾部追加)
<img src=•"111.png" username=•"jason" title=•"喵喵喵">•


例:创建a标签,设置属性,设置文本,添加到标签内部,添加到指定的标签的上面

let aEle = document.createElement('a')

aEle
<a>•</a>•
aEle.href = 'https://www.taobao.com/'
"https://www.taobao.com/"
aEle
<a href=•"https:•/•/•www.taobao.com/•">•</a>•

aEle.innerText = '点我' # 给标签设置文本内容
"点我"
aEle
<a href=•"https:•/•/•www.taobao.com/•">•点我•</a>•

let divEle = document.getElementById('d1')
undefined
let pEle = document.getElementById('d2')
undefined
divEle.insertBefore(aEle,pEle) # 添加标签内容指定位置添加
<a href=•"https:•/•/•www.taobao.com/•">•点我•</a>•
​```

额外补充 appendChild() removeChild() replaceChild() setAttribute() 设置属性 getAttribute() 获取属性 removeAttribute() 移除属性

替换节点

语法:

somenode.replaceChild(newnode, 某个节点);

属性节点

获取文本节点的值:

 var divEle = document.getElementById("d1")
 divEle.innerText # 获取标签内部所有的文本
 divEle.innerHTML # 内部文本和标签都拿到

设置文本节点的值:

 var divEle = document.getElementById("d1")
 divEle.innerText="1"
 divEle.innerHTML="<p>2</p>"

3.获取值操作

语法:

elementNode.value

适用于以下标签:

  • .input

  • .select

  • .textarea

1.获取用户数据标签内部的数据

 let seEle = document.getElementById('d2')
 seEle.value
 "111"
 seEle.value
 "333"
 ​
 let inputEle = document.getElementById('d1')
 inputEle.value

2.如何获取用户上传的文件数据

 let fileEle=document.getElementById('d2')
 undefined
 fileEle.value # 无法获取到文件数据
 "C:\fakepath\3.垃圾管理机制 用户交互 格式化输出 运算符.md"
 fileEle.files
 FileList {0: File, length: 1}
 ​
 fileEle.files[0] # 获取文件数据
 File {name: "3.垃圾管理机制 用户交互 格式化输出 运算符.md", lastModified: 1589713934934, lastModifiedDate: Sun May 17 2020 19:12:14 GMT+0800 (中国标准时间), webkitRelativePath: "", size: 16622, …}

4.class、css操作

 let divEle = document.getElementById('d1')
 undefined
 divEle.classList  # 获取标签所有的类属性
 DOMTokenList(3) ["c1", "bg_red", "bg_green", value: "c1 bg_red bg_green"]
 ​
 ​
 divEle.classList.remove('bg_red')  # 移除某个类属性
 undefined
 ​
 divEle.classList.add('bg_red')  # 添加类属性
 undefined
 divEle.classList.contains('c1')  # 验证是否包含某个类属性
 true
 divEle.classList.contains('c2')
 false
 ​
 divEle.classList.toggle('bg_red')  # 有则删除无则添加
 false
 divEle.classList.toggle('bg_red')
 true
 divEle.classList.toggle('bg_red')
 false
 divEle.classList.toggle('bg_red')
 true
 divEle.classList.toggle('bg_red')
 false
 divEle.classList.toggle('bg_red')
 true
 ​
 ​
 ​
 # DOM操作操作标签样式 统一先用style起手
 let pEle = document.getElementsByTagName('p')[0]
 undefined
 pEle.style.color = 'red'
 "red"
 pEle.style.fontSize = '28px'
 "28px"
 pEle.style.backgroundColor = 'yellow'
 "yellow"
 pEle.style.border = '3px solid red'
 "3px solid red"

5.事件

事件:达到某个事先设定的条件 自动触发的动作

 onclick        当用户点击某个对象时调用的事件句柄。
 ondblclick     当用户双击某个对象时调用的事件句柄。
 ​
 onfocus        元素获得焦点。 
 onblur         元素失去焦点。 
 onchange       域的内容被改变。 
 ​
 onkeydown      某个键盘按键被按下。          
 onkeypress     某个键盘按键被按下并松开。
 onkeyup        某个键盘按键被松开。
 onload         一张页面或一幅图像完成加载。
 onmousedown    鼠标按钮被按下。
 onmousemove    鼠标被移动。
 onmouseout     鼠标从某元素移开。
 onmouseover    鼠标移到某元素之上。
 ​
 onselect      在文本框中的文本被选中时发生。
 onsubmit      确认按钮被点击,使用的对象是form。

1.绑定事件的两种方式

 <button onclick="func1()">点我</button>
 <button id="d1">点我</button>
 <script>
 #第一种
  function func1(){
  alert(123)
  }
  #第二种
  let btnEle = document.getElementById('d1');
  btnEle.onclick = function () {
  alert(222)
  }
 </script>

script标签既可以放在head内 也可以放在body内 但是通常情况下都是放在body内的最底部

 # 等待浏览器窗口加载完毕之后再执行代码
 <script>
 window.onload = function () {
  // 第一种绑定事件的方式
  function func1() {
  alert(111)
  }
  // 第二种
  let btnEle = document.getElementById('d1');
  btnEle.onclick = function () {
  alert(222)
  }
  }
 </script>

6.原生事件js绑定

  • 开关灯案例
<!DOCTYPE html>
 <html lang="en">
 <head>
  <meta charset="UTF-8">
  <title>Title</title>
  <style>
  .c1{
  height:400px;
  width: 400px;
  border-radius: 50%;
  }
  .bg_red{
  background-color: red;
  }
  .bg_green{
  background-color: green;
  }
  </style>
 ​
 </head>
 <body>
 <div id="d1" class="c1 bg_green bg_red"></div>
 <button id="d2">变色</button>
 <script>
  let btnEle=document.getElementById('d2')
  let divEle=document.getElementById('d1')
  btnEle.onclick=function(){
  # 绑定点击事件, 动态的修改div标签的类属性
  divEle.classList.toggle('bg_green')
  }
 </script>
 </body>
 </html>
  • input框获取焦点失去焦点案例

<input type="text" value="一起去吃饭吧" id="d1">
<script>
let iEle=document.getElementById('d1')
#获取焦点事件
iEle.onfocus=function () {
# 将input框内部值去除
# 点value就是获取 等号赋值就是设置
}
# 失去焦点事件
iEle.onblur=function(){
# 给input标签重写赋值
iEle.value='不想去'
}
</script>


*   实时展示当前时间

 <!DOCTYPE html>
 <html lang="en">
 <head>
  <meta charset="UTF-8">
  <title>Title</title>
 </head>
 <body>
 <input type="text" id="d1" style="display:block;hei ght:50px;width:200px">
 <button id="d2">开始</button>
 <button id="d3">结束</button>
 <script>
  # 先定义一个全局存储定时器的变量
  let t=null
  let inputEle=document.getElementById('d1')
  let startEle=document.getElementById('d2')
  let endEle=document.getElementById('d3')
  # 1 访问页面之后 将访问的时间展示到input框中
  # 2 动态展示当前时间
  # 3 页面上加两个按钮 一个开始 一个结束
  function showTime(){
  let currentTime=new Date();
  inputEle.value=currentTime.toLocaleString()
  }
  startEle.onclick = function () {
  # 限制定时器只能开一个
  if(!t){#t非空时开设
  t=setInterval(showTime,1000)#每点击一次就会开设一个定时器 而t只指代最后一个
  }
  }
  endEle.onclick=function (){
  clearInterval(t)
  #t重置为空
  t=null
 ​
  }
 </script>
 </body>
 </html>

*   省市联动

    ```
     <!DOCTYPE html>
     <html lang="en">
     <head>
      <meta charset="UTF-8">
      <title>Title</title>
     </head>
     <body>
     <select name="" id="d1">
      <option value="" selected></option>
     </select>
     <select name="" id="d2"></select>
     <script>
      let proEle=document.getElementById('d1')
      let cityEle=document.getElementById('d2')
      data = {
      "河北": ["廊坊", "邯郸",'唐山'],
      "北京": ["朝阳区", "海淀区",'昌平区'],
      "山东": ["威海市", "烟台市",'临沂市'],
      '上海':['浦东新区','静安区','黄浦区'],
      '深圳':['南山区','宝安区','福田区']
      };
      //选for循环获取省
      for(let key in data){
      // 将省信息做成一个个option标签 添加到第一个select框中
      // 1 创建option标签
      let opEle=document.createElement('option')
      // 2 设置文本
      opEle.innerText=key
      // 3 设置value
      opEle.value=key
      // 4 将创建好的option标签添加到第一个select中
      proEle.appendChild(opEle)
      }
      //固定用法,获取select修改了后,就执行内容{} 
      proEle.onchange=function () {
      // 先获取到用户选择的省
      let currentpro=proEle.value
      // 获取对应的市信息 
      let currrntCityList=data[currentpro]
      // 清空市select中所有的option
      cityEle.innerHTML=''
      // for循环所有的市 渲染到第二个select中
      for (let i=0;i<currrntCityList.length;i++){
      let currentCity=currrntCityList[i]
      // 1 创建option标签
      let opEle=document.createElement('option')
      // 2 设置文本
      opEle.innerText=currentCity
      // 2 设置value
      opEle.value=currentCity
      // 4 将创建好的option标签添加到第一个select中
      cityEle.appendChild(opEle)
      }
      }
     ​
     </script>
     </body>
     </html>

6.jQuery

1.jQuery的简介

1.jQuery内部封装了原生的js代码(还额外添加了很多的功能) 能够让你通过书写更少的代码 完成js操作,类似于python里面的模块 在前端模块不叫模块 叫 “类库

2.兼容多个浏览器的

3.jQuery的宗旨:write less do more 即用更少的代码完成更多的事情

4.python导入模块和jQuery导入的区别:

python导入模块需要消耗资源,会影响网络速度,但jQuery的文件非常小(几十kb),基本不影响网络速度

2.jQuery的优势

  1. 一款轻量级的JS框架。jQuery核心js文件才几十kb,不会影响页面加载速度。

  2. 丰富的DOM选择器,jQuery的选择器用起来很方便,比如要找到某个DOM对象的相邻元素,JS可能要写好几行代码,而jQuery一行代码就搞定了,再比如要将一个表格的隔行变色,jQuery也是一行代码搞定。

  3. 链式表达式。jQuery的链式操作可以把多个操作写在一行代码里,更加简洁。

  4. 事件、样式、动画支持。jQuery还简化了js操作css的代码,并且代码的可读性也比js要强。

  5. Ajax操作支持。jQuery简化了AJAX操作,后端只需返回一个JSON格式的字符串就能完成与前端的通信。

  6. 跨浏览器兼容。jQuery基本兼容了现在主流的浏览器,不用再为浏览器的兼容问题而伤透脑筋。

  7. 插件扩展开发。jQuery有着丰富的第三方的插件,例如:树形菜单、日期控件、图片切换插件、弹出窗口等等基本前端页面上的组件都有对应插件,并且用jQuery插件做出来的效果很炫,并且可以根据自己需要去改写和封装插件,简单实用。

3.jQuery内容

  1. 选择器

  2. 筛选器

  3. 样式操作

  4. 文本操作

  5. 属性操作

  6. 文档处理

  7. 事件

  8. 动画效果

  9. 插件

  10. each、data、Ajax

下载链接:jQuery官网

中文文档:jQuery AP中文文档

4.jQuery版本

  • 1.x:兼容IE678,使用最为广泛的,官方只做BUG维护,功能不再新增。因此一般项目来说,使用1.x版本就可以了,最终版本:1.12.4 (2016年5月20日)

  • 2.x:不兼容IE678,很少有人使用,官方只做BUG维护,功能不再新增。如果不考虑兼容低版本的浏览器可以使用2.x,最终版本:2.2.4 (2016年5月20日)

  • 3.x:不兼容IE678,只支持最新的浏览器。需要注意的是很多老的jQuery插件不支持3.x版。目前该版本是官方主要更新维护的版本。

维护IE678是一件让人头疼的事情,一般我们都会额外加载一个CSS和JS单独处理。值得庆幸的是使用这些浏览器的人也逐步减少,PC端用户已经逐步被移动端用户所取代,如果没有特殊要求的话,一般都会选择放弃对678的支持。

5.jQuery文件下载

jQuery文件下载.png

压缩:容量更小

jQuery在使用之前 一定要确保已经导入了

6.针对导入问题

1 文件下载到了本地 如何解决多个文件反复书写引入语句的代码

可以借助于pycharm自动初始化代码功能完成自动添加

先找到settings-->editor-->file and code template

然后输入

<script src="jquery-3.5.1.min.js"></script>

先点击应用,再点击ok

2 直接引入jQuery提供的CDN服务(基于网络直接请求加载)

CDN:内容分发网络 CDN有免费的也有收费的 前端免费的cdn网站:bootcdn

<script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.5.1/jquery.min.js"></script>

必须有网络

7.jQuery基本语法

jQuery(选择器).action()

jQuery简写为jQuery() ===()

jQuery与js代码对比

eg:将p标签内部的文本颜色改为红色 原生js代码操作标签 let pEle = document.getElementById('d1') pEle.style.color = 'red'

jQuery操作标签 $('p').css('color','blue')

8.如何查找标签

1.基本选择器

 #id选择器
 $('#d1')
 w.fn.init [div#d1]0: div#d1length: 1__proto__: Object(0)
 #css选择器
 $('.c1')
 w.fn.init [p.c1, prevObject: w.fn.init(1)]0: p.c1length: 1prevObject: w.fn.init [document]__proto__: Object(0) 
 #标签选择器
 $('span')
 w.fn.init(3) [span, span, span, prevObject: w.fn.init(1)]

jQuery对象如何变成标签对象(重点)

 $('#d1')[0]
 <div id=•"d1">•…•</div>•
 document.getElementById('d1')
 <div id=•"d1">•…•</div>•

标签对象如何转jQuery对象(重点)

 $(document.getElementById('d1'))
 w.fn.init [div#d1]

2.组合选择器/分组与嵌套

 $('div')
 $('div.c1') # 找到有c1 class类的div标签
 $('div#d1') #找到有d1 id为d1的div标签
 $('*')  #所有元素选择器
 w.fn.init(19) [html, head, meta, title, meta, link, script, script, body, span, span, div#d1, span, p#d2, span, span, div.c1, span, span, prevObject: w.fn.init(1)]
 $('#d1,.c1,p')  # 并列+混用
 $('div span')  # 后代
 $('div>span')  # 儿子
 $('div+span')  # 毗邻
 $('div~span')  # 弟弟

3.基本筛选器

$('ul li')
 $('ul li:first')#第一个
 $('ul li:last')#最后一个
 $('ul li:eq(index)')# 索引等于index的那个元素
 $('ul li:even')  # 偶数索引 0包含在内
 $('ul li:odd')  # 奇数索引
 $('ul li:gt(2)')  # 大于索引
 $('ul li:lt(2)')  # 小于索引
 $('ul li:not("#d1")')  # 移除满足条件的标签
 $('div:has("p")')  # 选取出包含一个或多个标签在内的标签(指的是从后代元素找)

4.属性选择器

 [attribute]
 [attribute=value]// 属性等于
 [attribute!=value]// 属性不等于
 ​
 $('[username]')
 $('[username="Jason"]')
 $('p[username="egon"]')
 $('[type]')
 $('[type="text"]')

5.表单筛选器

:text
 :password
 :file
 :radio
 :checkbox
 :submit
 :reset
 :button
 $('input[type="text"]')
 #等价于
 $(':text')
 ​
 $('input[type="password"]')
 #等价于
 $(':password')

表单对象属性

 :enabled
 :disabled
 :checked
 :selected
  # 会将checked和selected都拿到
 #解决方法:
 $('input:checked')  # 加一个限制条件
 $(':selected') #只能拿到selected

6.筛选器方法

下一个元素

 $("#id").next() # 同级别下一个
 $("#id").nextAll()
 $("#id").nextUntil("#i2")

上一个元素

 $("#id").prev()
 $("#id").prevAll()
 $("#id").prevUntil("#i2")

父亲元素

$("#id").parent()
 $("#id").parents()  // 查找当前元素的所有的父辈元素
 $("#id").parentsUntil() // 查找当前元素的所有的父辈元素,直到遇到匹配的那个元素为`止。

儿子和兄弟元素

 $("#id").children();// 儿子们
 $("#id").siblings();// 兄弟们,同级别上下所有

查找

搜索所有与指定表达式匹配的元素。这个函数是找出正在处理的元素的后代元素的好方法。

 $("div").find("p") # find从某个区域内筛选出想要的标签 
 #等价于
 $("div p")
 ​
 $('div span:first')
 #等价于
 $('div span').first()
 ​
 $('div span:last')
 #等价于
 $('div span').last()
 ​
 $('div span:not("#d3")')
 #等价于
 $('div span').not('#d3')

筛选

筛选出与指定表达式匹配的元素集合。这个方法用于缩小匹配的范围。用逗号分隔多个表达式。

 $("div").filter(".c1")  // 从结果集中过滤出有c1样式类的
 #等价于 
 $("div.c1")

补充:

.first() // 获取匹配的第一个元素
.last() // 获取匹配的最后一个元素
.not() // 从匹配元素的集合中删除与指定表达式匹配的元素
.has() // 保留包含特定后代的元素,去掉那些不含有指定后代的元素。
.eq() // 索引值等于指定值的元素

7.jQuery练习题

  1. 找到本页面中id是i1的标签

  2. 找到本页面中所有的h2标签

  3. 找到本页面中所有的input标签

  4. 找到本页面所有样式类中有c1的标签

  5. 找到本页面所有样式类中有btn-default的标签

  6. 找到本页面所有样式类中有c1的标签和所有h2标签

  7. 找到本页面所有样式类中有c1的标签和id是p3的标签

  8. 找到本页面所有样式类中有c1的标签和所有样式类中有btn的标签

  9. 找到本页面中form标签中的所有input标签

  10. 找到本页面中被包裹在label标签内的input标签

  11. 找到本页面中紧挨在label标签后面的input标签

  12. 找到本页面中id为p2的标签后面所有和它同级的li标签

  13. 找到id值为f1的标签内部的第一个input标签

  14. 找到id值为my-checkbox的标签内部最后一个input标签

  15. 找到id值为my-checkbox的标签内部没有被选中的那个input标签

  16. 找到所有含有input标签的label标签

    $('#il')
    $('h2')
    $('input')
    $('.c1')
    $('.btn-defult')
    $('.c1,h2')
    $('.c1,#p3')
    $('.c1,.btn')
    $('form').find('input')
    $('label input')
    $('label+input')
    $('#p2~li')
    $('#f1 input').first()
    $('#my-checkbox input').last()
    $('#my-checkbox input[checked!="checked"]')
    $('label:has("input")')
    

9.操作标签

1.样式操作

样式类

js版本 jQuery版本
classList.add() addClass()
classList.remove() removeClass()
classList.contains() hasClass()
classList.toggle() toggleClass()

addClass();// 添加指定的CSS类名。
removeClass();// 移除指定的CSS类名。
hasClass();// 判断样式存不存在
toggleClass();// 切换CSS类名,如果有就移除,如果没有就添加。

css操作

<p>111</p>
<p>222</p>
"""一行代码将第一个p标签变成红色第二个p标签变成绿色"""
$('p').first().css('color','red').next().css('color','green')

jQuery的链式操作 使用jQuery可以做到一行代码操作很多标签

jQuery对象调用jQuery方法之后返回的还是当前jQuery对象 也就可以继续调用其他方法

类似于python

class MyClass(object):
    def func1(self):
        print('func1')
        return self

    def func2(self):
        print('func2')
        return self
obj = MyClass()
obj.func1().func2()

2.位置操作

offset()// 获取匹配元素在当前窗口的相对偏移或设置元素位置
position()// 获取匹配元素相对父元素的偏移
scrollTop()// 获取匹配元素相对滚动条顶部的偏移(需要了解)
scrollLeft()// 获取匹配元素相对滚动条左侧的偏移

$(window).scrollTop()
0
$(window).scrollTop()
969
$(window).scrollTop()  # 括号内不加参数就是获取
1733
$(window).scrollTop(0)  # 加了参数就是设置
n.fn.init [Window]  $(window).scrollTop(500)
n.fn.init [Window]

.offset()方法允许我们检索一个元素相对于文档(document)的当前位置。

.position()的差别在于: .position()是相对于相对于父级元素的位移。

3.尺寸

height() #文本
width()
innerHeight() #文本+padding
innerWidth()
outerHeight() #文本+padding+border 
outerWidth()
$('p').height()  # 文本
20
$('p').width()
1670
$('p').innerHeight()  # 文本+padding
26
$('p').innerWidth()
1674
$('p').outerHeight()  # 文本+padding+border
26
$('p').outerWidth()
1674

4.文本操作

操作标签内部文本
js jQuery
innerText text() 括号内不加参数就是获取加了就是设置
innerHTML html()

$('div').text() #获取
"
  有些人走着走着就散了
"
$('div').html() #获取
"
  <p>有些人走着走着就散了</p>
"
$('div').text('无所谓') #设置
S.fn.init [div, prevObject: S.fn.init(1)]
$('div').text('<h1>无所谓<\h1>')
S.fn.init [div, prevObject: S.fn.init(1)]
$('div').html('<h1>无所谓<\h1>')#可以识别标签
S.fn.init [div, prevObject: S.fn.init(1)]

5.获取值操作

js jQuery
.value .val()

$('#d1').val() #括号内不加参数就是获取
"111"
$('#d1').val('520快乐')  # 括号内加了就是设置

$('#d2').val()
"C:\fakepath\01_测试路由.png"

$('#d2')[0].files[0]  # 牢记两个对象之间的转换
File {name: "01_测试路由.png", lastModified: 1557043083000, lastModifiedDate: Sun May 05 2019 15:58:03 GMT+0800 (中国标准时间), webkitRelativePath: "", size: 28733, …}

$(':checkbox')
S.fn.init(3) [input, input, input, prevObject: S.fn.init(1)]
$(':checkbox').val()
"111"
$(':checkbox').val(666)
S.fn.init(3) [input, input, input, prevObject: S.fn.init(1)]

6.属性操作

js中 jQuery
setAttribute() attr(name,value)设置
getAttribute() attr(name)获取
removeAttribute() removeAttr(name)移除

在用变量存储对象的时候 js中推荐使用 (XXXEle) 标签对象
jQuery中推荐使用 ($XXXEle) jQuery对象

let $pEle = $('p')
undefined
$pEle.attr('id')
"d1"
$pEle.attr('class')
undefined
$pEle.attr('class','c1')
w.fn.init [p#d1.c1, prevObject: w.fn.init(1)]
$pEle.attr('id','id666')
w.fn.init [p#id666.c1, prevObject: w.fn.init(1)]
$pEle.attr('password','jason123')
w.fn.init [p#id666.c1, prevObject: w.fn.init(1)]
$pEle.removeAttr('password')
w.fn.init [p#id666.c1, prevObject: w.fn.init(1)]       
      

对于标签上有的能够看到的属性和自定义属性用attr
对于返回布尔值比如checkbox radio option是否被选中用prop

$('#d3').attr('checked')
"checked"
$('#d2').attr('checked')
undefined
$('#d2').attr('checked')
undefined
$('#d4').attr('checked')
undefined
$('#d3').attr('checked')
"checked"
$('#d3').attr('checked','checked')  # 无效
w.fn.init [input#d3]
           
           
$('#d2').prop('checked')
false
$('#d2').prop('checked')
true
$('#d3').prop('checked',true)
w.fn.init [input#d3]
$('#d3').prop('checked',false)
w.fn.init [input#d3]

7.文档处理

js jQuery
createElement('p') $('<p>')
appendChild() append()

添加到指定元素内部的后面

$(A).append(B)// 把B追加到A
$(A).appendTo(B)// 把A追加到B

添加到指定元素内部的前面

$(A).prepend(B)// 把B前置到A
$(A).prependTo(B)// 把A前置到B

添加到指定元素外部的后面

$(A).after(B)// 把B放到A的后面
$(A).insertAfter(B)// 把A放到B的后面

添加到指定元素外部的前面

$(A).before(B)// 把B放到A的前面
$(A).insertBefore(B)// 把A放到B的前面

移除和清空元素

remove()// 从DOM中删除所有匹配的元素。
empty()// 删除匹配的元素集合中所有的子节点。
let $pEle = $('<p>')
$pEle.text('你好,小哥哥')
$pEle.attr('id','d1')          
$('#d1').append($pEle)  # 内部尾部追加
$pEle.appendTo($('#d1')) 
           
$('#d1').prepend($pEle)  # 内部头部追加
w.fn.init [div#d1]
$pEle.prependTo($('#d1'))
w.fn.init [p#d1, prevObject: w.fn.init(1)]
         
$('#d2').after($pEle)  # 放在某个标签后面
w.fn.init [p#d2]
$pEle.insertAfter($('#d1'))
        
$('#d1').before($pEle)
w.fn.init [div#d1]
$pEle.insertBefore($('#d2'))

$('#d1').remove()  # 将标签从DOM树中删除
w.fn.init [div#d1]
           
$('#d1').empty()  # 清空标签内部所有的内容
w.fn.init [div#d1]

10.事件

绑定事件的两种方式:

#第一种
$('#d1').click(function(){
        alert('123')
});
#第二种(功能强大,支持事件委托)
$('#d2').on('click',function(){
        alert('555')
})
  • 克隆事件

克隆

clone()// 参数
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="jquery-3.5.1.min.js"></script>
      <style>
            #d1{
                height:100px;
                width:100px;
                background-color: yellow;
                border: 1px solid blue;
            }
        </style>
</head>
<button id="d1">点我复制</button>
<script>
    $('#d1').on('click',function(){
        // console.log(this) //this指代是当前被操作的标签对象
        // $(this).clone().insertAfter($('body'))// clone默认情况下只克隆html和css 不克隆事件
        $(this).clone(true).insertAfter($('body'))
    })
</script>
</body>
</html>
  • 自定义模态框

模态框内部本质就是给标签移除或者添加上hide属性

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="jquery-3.5.1.min.js"></script>
    <style>
        .cover{
            position:fixed;
            top:0;
            left:0;
            right:0;
            bottom:0;
            background-color: rgba(0,0,0,0.3);
            z-index: 99;
        }
        .model{
            position: fixed;
            height:400px;
            width:600px;
            background-color: #eeeeee;
            top:50%;
            left: 50%;
            margin-left:-300px;
            margin-top: -200px;
            z-index: 99;
        }
        .hide{
            display:none;
        }
    </style>
</head>
<body>
<div>我是最下面的</div>
<button id="d1">弹</button>
<div class="cover hide"></div>
<div class="model hide">
    <p>username:<input type="text"></p>
    <p>password:<input type="text"></p>
    <input type="button" value="确认">
    <input type="button" value="取消" id="d2">

</div>
<script>
    $('#d1').click(function(){
        var coverEle=$('.cover')[0];
        var modelEle=$('.model')[0];
        $(coverEle).removeClass('hide');
        $(modelEle).removeClass('hide')
    })
    $('#d2').on('click',function(){
        var coverEle=$('.cover')[0];
        var modelEle=$('.model')[0];
        $(coverEle).addClass('hide');
        $(modelEle).addClass('hide')
    })
</script>
</body>
</html>
  • 左侧菜单
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="jquery-3.5.1.min.js"></script>
    <style>
        .left{
            float:left;
            background-color: peachpuff;
            width: 20%;
            height: 100%;
            position: fixed;
        }
        .title{
            font-size: 24px;
            color: black;
            text-align: center;
        }
        .items{
            border:solid 1px aliceblue;
        }
        .hide{
            display: none;
        }
    </style>
</head>
<body>
<div class="left">
    <div class="title">菜单1
        <div class="items">1</div>
        <div class="items">2</div>
        <div class="items">3</div>
    </div>
    <div class="title">菜单2
        <div class="items">4</div>
        <div class="items">5</div>
        <div class="items">6</div>
    </div>
    <div class="title">菜单3
        <div class="items">7</div>
        <div class="items">8</div>
        <div class="items">9</div>
    </div>
</div>
<script>
    $('.title').click(function(){
        // 先给所有的items加hide
        // $('.items').addClass('hide')
        // //然后将被点击标签内部的hide移除
        // $(this).children().removeClass('hide')
        $(this).find('.items').addClass('hide').parsent().find('.title').children.removeClass('hide')
    })
</script>
</body>
</html>
  • 返回顶部
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="jquery-3.5.1.min.js"></script>
</head>
<body>
<div style="height:500px;background-color: red" id="d1"></div>
<div style="height:500px;background-color: yellow"></div>
<div style="height:500px;background-color: green"></div>
<a href="#d1" class="hide">回到顶部</a>
<script>
    $(window).scroll(function(){
        if($(window).scrollTop()>300){
         $('#d1').removeClass('hide')
        }else{
            $('#d1').addClass('hide')
        }

    })
</script>
</body>
</html>
  • 自定义登陆校验
<p>username:
    <input type="text" id="username">
    <span style="color: red"></span>
</p>
<p>password:
    <input type="text" id="password">
    <span style="color: red"></span>
</p>
<button id="d1">提交</button>

<script>
    let $userName = $('#username')
    let $passWord = $('#password')
    $('#d1').click(function () {
        // 获取用户输入的用户名和密码 做校验
        let userName = $userName.val()
        let passWord = $passWord.val()
        if (!userName){
            $userName.next().text("用户名不能为空")
        }
        if (!passWord){
            $passWord.next().text('密码不能为空')
        }
    })
    $('input').focus(function () {
        $(this).next().text('')
    })
</script>
  • input实时监控
<input type="text" id="d1">

<script>
    $('#d1').on('input',function () {
        console.log(this.value)
    })
</script>
  • hover事件
<script>
    // $("#d1").hover(function () {  // 鼠标悬浮 + 鼠标移开
    //     alert(123)
    // })

    $('#d1').hover(
        function () {
            alert('我来了')  // 悬浮
    },
        function () {
            alert('我溜了')  // 移开
        }
    )
</script>
  • 键盘按键按下事件
<script>
    $(window).keydown(function (event) {
        console.log(event.keyCode)
        if (event.keyCode === 16){
            alert('你按了shift键')
        }
    })
</script>

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 199,271评论 5 466
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 83,725评论 2 376
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 146,252评论 0 328
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,634评论 1 270
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,549评论 5 359
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 47,985评论 1 275
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,471评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,128评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,257评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,233评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,235评论 1 328
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,940评论 3 316
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,528评论 3 302
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,623评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,858评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,245评论 2 344
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,790评论 2 339