CSS 最佳实践 + 套路(一) -- 概述

资源

  1. Google: 关键词 MDN
  2. CSS Tricks
  3. Google: 阮一峰 css
  4. 张鑫旭的 240 多篇 CSS 博客
  5. Codrops 炫酷 CSS 效果
  6. CSS揭秘
  7. CSS 2.1 中文 spec
  8. Magic of CSS 免费在线书

    引入CSS

  9. 内联样式 ==> style属性 ==> style= 'color: red; width: 200px; height:200px;'
  10. 内嵌样式 ==> style 标签 ==>

    1
    2
    3
    4
    5
    6
    <style>
    body{
    background: gray;
    font-size: 12px;
    }
    </style>
  11. 外联样式 ==> <link> 标签 ==>

    1
    <link rel= 'stylesheet' href= ''>
  12. @import url(./b/css)

最佳实践 & 套路

reset CSS

1
2
*{ margin: 0; padding: 0; }
h1, h2, h3, h4, h5, h6, p{ margin: 0; padding: 0; }

清除浮动

添加到浮动元素的父元素上。

1
2
3
4
5
.clearfix::after{
content: '';
display: block;
clear: both;
}

相关知识点

元素分类:

  • 块级元素:block ==> display: block;
  • 内联元素:inline ==> display: inline;
  • 内联块级元素:inline-block ==> display: inline-block;

JS进阶 -- MVC 思想

概述

MVC 是一种思想,它会让我们写代码时更加简洁、高效、模块化,了解这种方法对于前端程序员来说是很有必要的。首先说明下 MVC 代表的含义:

  • M ==> Model ==> 模型
  • V ==> View ==> 视图
  • C ==> Controller ==> 控制器

MVC 各自作用

MVC 主要是按功能划分模块

  1. view:js 代码所操纵的视图(HTML),负责显示给用户和通知 controller(控制器)
  2. Model:view(视图)所需要的所有的数据操作,包括:

    • 初始化数据
    • 读取数据
    • 存入数据

      负责和向 server(服务器)请求数据和响应 server(服务器)

  3. controller:所有的逻辑操作,负责监控和更新 view(视图) + 调用和接收 model(数据)

MVC 使用技术点

  1. 立即执行函数,这里有所有的立即执行函数的写法,但是这里推荐大家使用

    1
    !function(){}.call()

    立即执行函数避免了我们是用全局变量,隔离作用域,从而达到了使用局部变量的目的

  2. 闭包
    闭包就是如果一个函数使用了它范围外的值,那么这个函数 + 这个变量就叫做闭包
    闭包使得模块之间可以进行相互访问。具体实现:
    闭包 + 操作局部变量

    • 函数 fn 中局部变量 obj 和 return 的函数构成了闭包
    • return 的函数便是接口,可以供外部调用,从而来操纵局部变量 obj
    • 外部除了使用函数 fn 的接口,没有任何其他方法可以访问到局部变量 obj
  3. 全局变量
    模块与模块之间是在不同的 js 文件中,例如模块2想去操纵模块1的数据,通过上述方式显然是不够的,那么只能退而求其次,使用全局变量。具体实现:
    全局变量
    通过使用全局变量保存了匿名函数的地址,从而全局都可以使用这个全局属性

总结

以上3种技术点的结合 ==> 立即执行函数 + 闭包 + 全局变量 实现了 MVC 中 Controller(控制器) 的相应需求,从而让前端更好的使用 MVC 思想

细节问题

  1. this 的使用,在 MVC 中要着重使用 this
  2. 箭头函数,其实在 MVC 中使用箭头函数,主要就是为了 this ,原因在于箭头函数内外 this 不变
  3. HTML 中每一块都是一个 view ,当我们为 HTML 分块的时候,是可以嵌套的,所以我们的 view 也是可以嵌套的

使用模板

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
!function(){
let view = 操纵的 HTML 模块
let model = {
init: function(){},
fetch: function(){} // 注意此处最好返回 Promise 对象
save: function(){} // 注意此处最好返回 Promise 对象
}
let controller = {
view = null,
model = null,
...... = null,
init: function(){
this.view = view
this.model = model
......
this.bindEvents()
},
bindEvents: function(){
// 绑定事件,与绑定事件无关的放在 controller 属性上
},
......
}
controller.init( controller,model )
//controller.init.call( controller,view, model )
}.call()

实际应用

代码示例

HTTP系列 -- AJAX 进阶

相关代码链接

AJAX 设置响应 和 获取请求

AJAX 设置请求 header

第一部分:request.open( 'POST', 'http://www.baidu.com/search' )
第二部分:request.setRequestHeader( hander, value )

1
2
request.setRequestHeader( 'Content-Type', 'application/x-www-form-urlencoded' )
request.setRequestHeader( 'who', 'bowen' )

第四部分:request.send( 'a=1&b=2' )

请求
1
2
3
4
5
6
7
8
1. POST /search HTTP/1.1
2. Host: www.baidu.com
Content-Type: application/x-www-form-urlencoded
who: bowen
Content-Length:
Cookie:
3.
4. a=1&b=2

AJAX 获取响应 header

第一部分:request.statusrequest.statusText
第二部分:

1
2
request.getResponseHeader( headerName ) 
request.getAllResponseHeaders()

第四部分:request.responseText

响应
1
2
3
4
1. HTTP/1.1 200 ok
2. key: value
3.
4. 数据

Node.js(后端)设置响应 header

详解

callback(回调)

callback 就是一个回调函数,如下图所示。
callback 示例

  1. 给 window 添加一个方法 fn123 ,这个方法接受一个对象 options 。
  2. 使用 window 下的方法 fn123 ,并传入一个对象,这个对象有一个方法 fn456 ,它是一个函数。
  3. window 下的 fn123 接受到对象后将调用 fn456,将其 call back
  4. fn456 中接受的 this 就是 window 下的方法中 call 时传的第一个参数,x 就是 call 时传的第二个参数

实现 jQuery.ajax

  1. 首先回顾下 window.jQuery

  2. 将 AJAX-基础 的代码 进行封装,封装为 window.jQuery.ajax,代码地址

  3. 将封装的 window.jQuery.ajax 进行代码优化(给参数命名)。由于传入参数过多,将其参数设置为有结构的数据 ==> 对象,代码地址

  4. 实现传入不定个参数的优化。既可以传入一个对象,也可以传入 url + 对象。代码地址。此时由于要使用 arguments ,所以不能使用箭头函数。

  5. 优化代码,使用 ES6 解构赋值达到优化代码的目的,并增加 request.setRequestHeader() 功能。代码地址

  6. 如果不实现传入不定个参数,还可以进一步使用 ES6 解构赋值优化。代码地址

  7. 使用 Promise 规范进行优化,return new Promise(function(resolve,reject){}),成功 === 调用 resolve,失败 === 调用 reject,之后在调用时使用 .then 方法。代码地址

  8. Promise 实现原理

    1
    2
    3
    4
    5
    6
    window.Promise = function(fn){
    // ......
    return {
    then: function(){}
    }
    }

HTTP系列 -- AJAX 基础

参考代码

概述

AJAX(Async JavaScript And XML):异步 JavaScript 和XML,远程编程脚本,使 JavaScript 能够在 Web 服务器上运行的程序通信,它是一种无需重新加载整个网页的情况之下能够更新部分网页的技术。

条件

  1. 使用 XMLHttpRequest 发请求
  2. 服务器返回 XML / JSON 格式的字符串
  3. JS 解析 XML / JSON,并更新局部页面

    说明

    HTTP 的 path(路径)都是绝对路径

如何发送请求

form 表单

使用 form 表单可以发请求,但是会刷新页面或新开页面
form 标签创建

form 标签发送请求

form 标签发送 GET 请求

form 标签发送 POST 请求

a 标签

使用 a 标签可以发 GET 请求,但是也会刷新页面或新开页面
a 标签创建

a 标签发送 GET 请求

img 标签

使用 img 标签可以发 GET 请求,但是只能以图片的形式展示
img 标签创建

img 标签发送 GET 请求

使用 link 标签可以发 GET 请求,但是只能以 CSS、favicon 的形式展示
link 标签创建

link 标签发送 GET 请求

script 标签(JSONP)

使用 script 标签可以发 GET 请求,但是只能以脚本的形式运行
script 标签创建

script 标签发送 GET 请求

XMLHttpRequest 对象

XMLHttpRequest 是一个 API,它为客户端提供了在客户端和服务器之间传输数据的功能。它提供了一个通过 URL 来获取数据的简单方式,并且不会使整个页面刷新。这使得网页只更新一部分页面而不会打扰到用户。XMLHttpRequestAJAX 中被大量使用。

挂载在 window 下的 XMLHttpRequest 对象

属性

onreadystatechange
  • 类型:function
  • JavaScript函数对象,当readyState属性改变时会调用它。
readyState

类型:Number
显示 XMLHttpRequest 代理当前所处的状态,值:

  • 0 ==> 代理被创建,但尚未调用 open() 方法
  • 1 ==> open() 方法已经被调用
  • 2 ==> send() 方法已经被调用,并且头部和状态已经可获得
  • 3 ==> 下载中,requestText 属性已经包含部分数据
  • 4 ==> 下载操作以完成
responseText
  • 类型:String
    响应的文本
responseType

设置响应类型,值:

  • “” ==> 字符串(默认值)
  • “arraybuffer”
  • “blob”
  • “document”
  • “json” ==> JavaScript 对象,解析自服务器传递回来的JSON 字符串
  • “text” ==> 字符串
status

请求的响应状态码
详见

statusText

请求的响应状态信息,包含一个状态码和原因短语(”200 OK”)

方法

1. open()

初始化一个请求。该方法用于JavaScript代码中

1
2
let request = new XMLHttpRequest
request.open( method, url, async )

参数
  • methos ==> 请求所使用的HTTP方法
  • url ==> 该请求所要访问的 URL / 路径
  • async ==> 默认为true(异步),表示是否执行异步操作
2. setRequestHeader()

给指定的HTTP请求头赋值.在这之前,你必须确认已经调用 open()

1
2
3
let request = new XMLHttpRequest
request.open( 'POST', '/xxx' )
request.setRequestHeader( header, value )

request.setRequestHeader( ‘Content-type’ , ‘application/x-www-form=urlcoded’ )

参数
  • header ==> 将要被赋值的请求头名称
  • value ==> 给指定的请求头赋的值
3. send()

发送请求。如果该请求是异步模式(默认),该方法会立刻返回。相反,如果请求是同步模式,则直到请求的响应完全接受以后,该方法才会返回

getAllResponseHeaders()

返回所有响应头信息(响应头名和值),如果响应头还没接受,则返回null

getResponseHeader()

返回指定的响应头的值,如果响应头还没被接受,或该响应头不存在,则返回null

JSON 对象

JSON对象包含用于解析 JSON 的方法,并将值转换为 JSON。它不能被调用或者作为构造函数

方法

JSON.parse()

解析一个JSON字符串,可选地转换生成的值及其属性,并返回值

JSON.stringify()

返回与指定值相对应的一个JSON字符串,可选地仅包含某些属性或以用户定义的方式替换属性值

原生 JavaScript 发送 AJAX 请求

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
let request = new XMLHttpRequest()
//open() 方法有第三个参数,true 为异步(默认),false为同步
request.open( 'GET', '路径' ) // 配置 request

//request.open( 'POST', '路径' )
// 配置 request ,如果是 POST 方法,必须设置 setRequestHeader
//request.setRequestHeader( 'Content-type' , 'application/x-www-form-urlcoded' )

request.send()
request.onreadystatechange = () =>{
if( request.readyState === 4 ){ //请求响应都完毕了
if( request.status >= 200 && request.status < 300 ){
console.log( '说明请求成功' )
let string = request.responseText
// 把符合 JSON 语法的字符串转换成 JS 对应的值
let object = window.JSON.parse( string )
}
}
}

说明:

  • HTTP 第四部分永远是字符串,只不过是符合 JSON 对象语法的字符串(解析 JSON.parse())

  • 如何判断代码执行时长

    1
    2
    3
    console.time()
    要判断的代码
    console.end()
  • 如何判断同步异步

    1
    2
    3
    console.log( 'start' )
    要判断的代码
    console.log( 'end' )

JSON

JSON(JavaScript Object Notation):存储和交换文本信息的语法,类似 XML,它采用键值对的方式来组织,易于人们阅读和编写,同时也易于机器解析和生成。它是一门新的语言

JSON 语法

JSON 铁轨图
JSON 中有 String、null、Number、true、false、Array 和 Object

JSON 和 JavaScript 的区别

JSON 和 JavaScript 是两门语言,JSON 是抄袭的 JavaScript,两者区别主要体现在:

  • JSON 没有 undefined、function 和 Symbol
  • JSON 必须使用双引号
  • JSON 没有变量
  • JSON 中对象仅仅是一个哈希

同源策略

概述

  • 当一个资源从与该资源本身所在的服务器不同的域或端口发送 AJAX 请求一个资源时,资源会发起一个跨域 HTTP 请求,出于安全原因,浏览器限制从脚本内发起的跨源HTTP请求

  • 只有 AJAX 被限制,其他的都可以(img、form、link 和 script)

  • 原页面用 form 提交到另一个域名之后,原页面的脚本无法获取新页面的内容,所以浏览器认为这是安全的。而 AJAX 是可以读取相应内容的,因此浏览器将阻止你这样做

  • 如果使用 AJAX 向其他源发送请求,会成功,但是报错(request.status === 0)

  • AJAX 请求已经发送出去了,却拿不到响应
    request.status === 0

  • 同源策略本质:一个域名的 JS ,在未经允许的情况下,不得读取另一个域名的内容,但是浏览器并不阻止向另一个域名发送请求。只有协议、域名和端口一模一样才允许发送 AJAX 请求

为什么要使用同源策略

安全,如果没有同源策略,AJAX 就可以向另一个域名发送 GET / POST 请求,GET 请求可以获取信息,POST 请求可以直接转账,那样互联网就没有隐私可言

跨域

  1. JSONP:但是 JSONP 有局限,不能发送 POST 请求

  2. CORS(Cross-Orogin Resource Sharing 跨域资源共享):请求的域名的后端需要在相应的接口添加响应头,此时就可以发送 POST 请求

    1
    response.setHeader( "Access-Control-Allow-Origin", "http://......" )

HTTP系列 -- JSONP

参考代码

概述

数据库是用来长久储存数据的。

发送请求

form 表单提交

缺点:刷新页面 + 用户后退 + 用户刷新 = 数据变动

form + iframe 提交

form 表单提交到 iframe 中,页面不会刷新。
缺点:用户刷新页面 ==> 数据变动

JS动态创建 img 标签

1
2
3
4
let img = document.createElement('img');
img.src = '路径'
img.onload = function(){} ==> HTTP状态码
img.onerror = function(){} ==> HTTP状态码

通过路径,在 Nodejs 中设置成功或者失败,之后返回状态码,前端通过返回的HTTP状态码,进而来判断成功失败。

动态创建 script 标签

1
2
3
4
5
let script = document.createElement('script');
script.src = '路径';
document.body.appendChild(script);
script.onload = function(){}
script.onerror = function(){}
  • 通过设置响应头中的类型进而来确定返回内容的格式(第四部分),从而保证返回的是 JavaScript 代码。
  • 当创建 script 标签插入 body 后,返回的内容会立即执行,之后再去执行 onloadonerror 事件,所以说 onload 可以进行删除, 之后将处理逻辑交给后端(处理逻辑中应该包括使用完 script 标签之后立刻删除),但是此时前后端耦合。
  • scriptsrc 属性可以访问其他地址

JSONP

动态创建 script 并调用前端传给后端的 callback 技术

版本一

Nodejs:
1
response.write(` callback.call(undefined,' success ') `);
JS:
1
2
window.callback = function(){}  //返回之后进行处理
script.src = http://....../路径?callback = xxx

版本二

Nodejs
1
2
3
4
response.write(` ${ query.callback }.call(undefined,{
"success": true,
"left": ${ newAmount }
}) `)

返回的数据是 JSON 数据
特点:

  • 请求方创建 scriptsrc 属性指向响应方
  • 响应方根据查询参数,构造形如 xxx.call(undefined,”传给前端的数据”) 这样的响应。

JSONP

什么是 JSONP

请求方:前端(浏览器)
响应方:后端(服务器)

  1. 请求方创建 scriptsrc 指向响应方,同时传入一个查询参数 ?callback = 随机数
  2. 响应方根据查询参数 callback ,构造形如 随机数.call(undefined,"传给前端的数据") 这样的响应
  3. 浏览器接收到响应,就会执行 随机数.call(undefined,"传给前端的数据")
  4. 请求方获取到数据

    完整代码

    JS
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    button.addEventlistener('click', (e) => {
    let script = document.createElement('script');
    let functionName = 'bowen' + parseInt(Math.random()*100000,10);
    window[ functionName ] = function(result){
    if( result === 'success' ){
    // do something
    }else{
    // do something
    }
    }
    script.src = 'http://....../路径?callback = ' + functionName
    document.body.appendChild( script );
    script.onload = function(event){
    event.currentTarget.remove();
    delete window[ functionName ]
    }
    script.onerror = function(){
    alert('fail');
    event.currentTarget.remove();
    delete window[ functionName ]
    }
    })
jQ:
1
2
3
4
5
6
7
8
9
button.addEventListener('click',(event) => {
$.ajax({
url: 'http://....../路径',
dataType: 'jsonp',
success: function( response ){
// do something
}
})
})

套路:为什么 JSONP 不支持 POST 请求

JSONP 是动态创建 script 标签 + 传入 callback 查询参数,script 标签,只能发送 GET 请求,不能使用 POST。

相关知识点

如果后端没有写

1
2
3
4
response.write(` ${ query.callback }.call(undefined,{
"success": true,
"left": ${ newAmount }
}) `)

前端虽然有响应内容,但是使用不到

HTTP系列 -- Node.js

Node.js 服务器代码

精华

1
2
3
4
5
let string = fs.readFileSync( '路径', 'UTF-8' )
response.setHeader( 'Content-Type', '类型' )
response.statusCode = 200
response.write()
response.end()

response.setHeader( ‘Content-Type’, ‘类型’ )

类型:

  • HTML ==> response.setHeader( 'Content-Type, 'text/html; charset = utf-8' )
  • CSS ==> response.setHeader( 'Content-Type', 'text/css' )
  • JavaScript ==> response.setHeader( 'Content-Type', 'application/javascript' )

创建 Node.js 服务器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
var http = require('http')
var fs = require('fs')
var url = require('url')
var port = process.argv[2]

if(!port){
console.log('请指定端口号好不啦?\nnode server.js 8888 这样不会吗?')
process.exit(1)
}

var server = http.createServer(function(request, response){
var parsedUrl = url.parse(request.url, true)
var path = request.url
var query = ''
if(path.indexOf('?') >= 0){ query = path.substring(path.indexOf('?')) }
var pathNoQuery = parsedUrl.pathname
var queryObject = parsedUrl.query
var method = request.method



console.log('HTTP 路径为\n' + path)
if(path == '/style'){
response.setHeader('Content-Type', 'text/css; charset=utf-8')
response.write('body{background-color: #ddd;}h1{color: red;}')
response.end()
}else if(path == '/script'){
response.setHeader('Content-Type', 'text/javascript; charset=utf-8')
response.write('alert("这是JS执行的")')
response.end()
}else if(path == '/index'){
response.setHeader('Content-Type', 'text/html; charset=utf-8')
response.write('<!DOCTYPE>\n<html>' +
'<head><link rel="stylesheet" href="/style">' +
'</head><body>' +
'<h1>你好</h1>' +
'<script src="/script"></script>' +
'</body></html>')
response.end()
}else{
response.statusCode = 404
response.end()
}

})

server.listen(port)
console.log('监听 ' + port + ' 成功\n请用在空中转体720度然后用电饭煲打开 http://localhost:' + port)

解析 Node.js 服务器

  1. console.log('HTTP 路径为\n' + path) 表示在命令行中或者Console面板中打印出当前请求的 HTTP 路径

  2. 下方代码表示如果请求路径为/style,设置响应头信息为'Content-Type', 'text/css; charset=utf-8'(即响应内容 [ 第四部分 ] 的类型 [ css ] 和编码 [ utf-8 ]),响应内容( 第四部分 )为 body{background-color: #ddd;}h1{color: red;} ,之后完成响应

    1
    2
    3
    4
    5
    if(path == '/style'){
    response.setHeader('Content-Type', 'text/css; charset=utf-8')
    response.write('body{background-color: #ddd;}h1{color: red;}')
    response.end()
    }
  3. 下方代码表示如果请求路径为 /script ,设置响应头信息为 'Content-Type', 'text/javascript; charset=utf-8' (即响应内容 [ 第四部分 ] 的类型 [ javascript ] 和编码 [ utf-8 ]),响应内容( 第四部分 )为 alert("这是JS执行的"),之后完成响应

    1
    2
    3
    4
    5
    if(path == '/script'){
    response.setHeader('Content-Type', 'text/javascript; charset=utf-8')
    response.write('alert("这是JS执行的")')
    response.end()
    }
  4. 下方代码表示如果请求路径为 /index ,设置响应头信息为 ('Content-Type', 'text/html; charset=utf-8' (即响应内容 [ 第四部分 ] 的类型 [ html ] 和编码 [ utf-8 ]),响应内容( 第四部分 )为 HTML 页面,之后完成响应

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    if(path == '/index'){
    response.setHeader('Content-Type', 'text/html; charset=utf-8')
    response.write('<!DOCTYPE>\n<html>' +
    '<head><link rel="stylesheet" href="/style">' +
    '</head><body>' +
    '<h1>你好</h1>' +
    '<script src="/script"></script>' +
    '</body></html>')
    response.end()
    }
  5. 下方代码表示如果请求的路径不是上述路径,则返回状态码为 404 ,之后完成响应。

    1
    2
    3
    4
    else{
    response.statusCode = 404
    response.end()
    }

创建过程

  1. 新建目录和进入

    1
    2
    mkdir node-demo
    cd node-demo
  2. 创建文件并编辑

    1
    2
    touch server.js
    start server.js //内容如上
  3. 运行文件

    1
    node server.js 端口号

使用 Node.js 发起请求

  1. 在新的 Bash 窗口运行 curl http://localhost:你的指定的端口/xxx 或者 curl http://127.0.0.1:你指定的端口/xxx即可发起请求

  2. 在浏览器窗口地址栏中输入 http://localhost:你的指定的端口/xxx 或者 http://127.0.0.1:你指定的端口/xxx 回车,即可发起请求。

  3. curl -s -v -- "http://localhost:port/xxx"可以查看完整的请求体和响应体。

响应

  • 在运行 node server.js 端口号 Bash 窗口中可以查看到打印出来的路径(console.log('HTTP 路径为\n' + path)),并且在发起请求的 Bash 窗口中可以查看请求体和响应体

  • 在浏览器窗口中可以看到实际运行效果

相关知识点

  1. 任意一台电脑都是服务器

  2. 创建的Node.js服务器提供 HTTP 服务,所以需要提供 HTTP 服务的程序

  3. 用脚本可以提供 HTTP 服务

当在浏览器地址栏输入地址回车后发生的事情

  1. DNS 域名解析。首先浏览器会查找缓存,如果没有,就向运营商查找,运营商会提供 DNS 服务,从而得到域名所对应的 IP 地址。DNS 域名解析就是一个域名到 IP 地址的转换

  2. TCP 连接。浏览器根据 IP 地址向服务器发起 TCP 连接,与服务器建立 TCP 三次握手,浏览器对服务器说:“您好,我可以链接你么?”,服务器对浏览器说:“您好,你可以连接我”,浏览器对服务器说:“好的,那我连接你了!”,通过 TCP 的三次握手,从而确定双方都有收发文件的能力,自此浏览器和服务器建立了链接

  3. 浏览器发送 HTTP 请求。请求包括了请求行、请求头和请求正文

  4. 浏览器拿到响应、解析并渲染页面。浏览器是一个边解析边渲染的过程,首先浏览器解析HTML文件构建 DOM 树,然后解析 CSS 文件构建渲染树,等到渲染树构建完成后,浏览器开始布局渲染树并将其绘制到屏幕上

  5. 通过四次挥手关闭 TCP 连接。浏览器对服务器说:“不早了,我该走了”,服务器对浏览器说:“知道了”,之后服务器又对浏览器说:“我也该走了”,浏览器回应服务器:“好的”,至此 TCP 连接结束

注意:后缀是没有用的。HTTP 路径不是文件路径。

HTTP系列 -- 网络 与 IP

概述

HTTP协议的底层是由 TCP 协议IP 协议(简称TCP/IP)构建的。HTTP只规定了请求格式和相应格式,即如何书写内容的协议。

TCP(Transmission Control Protocol)

TCP 是传输控制协议,它规定了如何传输协议。

TCP 和 UDP 的区别是什么

  • TCP 可靠、面向连接、相对 UDP 较慢
  • UDP 不可靠,不面向连接、相对 TCP 较快。

TCP 的三次握手指的是什么

每次建立连接前,客户端和服务端之前都要先进行三次对话才开始正式传输内容,三次对话大概是这样的:

1
2
3
4
1. 客户端:我要连接你了,可以吗
2. 服务端:嗯,我准备好了,连接我吧
3. 客户端:那我连接你咯。
4. 开始后面步骤

通过上述对话,从而确定了双方都可以收发内容。

IP(Internet Protocol)

IP 是网络协议,它规定了如何联网协议。

相关知识点

  1. 只要在互联网中,那么就会有一个 IP。IP 分为内网 IP外网 IP

  2. 内网:以路由器为核心的以及所有连接路由器的设备统称为内网

  3. 外网:以路由器为出口的外面的网络都是外网

  4. 服务商提供 DNS 服务(告知你你想要请求的域名所对应的 IP
    地址)

  5. 路由器可以广播出来 WIFI ,连接之后便可以上网

  6. 路由器连接服务商的服务器,那么路由器就会有一个外网IP,表示用户在互联网中的地址

  7. 如果重启路由器,则有可能会重新分配外网IP,所以路由器没有固定的外网IP

  8. 可以租用固定的外网IP,从而为用户提供稳定的服务(eg. 阿里、腾讯等公司)

  9. 内网中的设备使用内网IP,一般来说这个 IP 的格式都是192.168.xxx.xxx

  10. 一般路由会给自己分配一个好记的内网 IP,如192.168.1.1。之后给每个设备分配不同的内网IP

  11. 路由器会有两个IP,分别是内网IP外网IP

  12. 内网中的设备可以互相访问(比如你可以用电脑或手机进入http://192.168.1.1来查看你的路由器「因为路由器内置一个HTTP服务器」),但是不能直接访问外网,内网设备想要访问外网,就必须经过路由器中转

  13. 外网中的设备可以互相访问(比如 qq.com 可以把首页发送给你的路由器,你的路由器有外网 IP),但是外网中的设备无法访问你的内网设备(这很好理解,内网是一个封闭的网络,外人进不来,所以实际上 qq.com 无法直接把首页放送给你的电脑和手机)

  14. 路,就是「必由之路」中的路。由,就是「必由之路」中的由(由是经过、缘由的意思)。所有的信息都要经过路由器,然后被指向一条它该去的路

  15. 内网外网通过路由器连接

  16. 本地IP:127.0.0.1:表示设备本身

  17. hosts:可以设置任意域名对应的IP

  18. hosts文件中会有一行127.0.0.1 localhost,意思就是 localhost 指向 127.0.0.1,所以 localhost 也表示设备本身

  19. 特别特殊的 IP:0.0.0.0,它不表示任何设备。这个 IP 不同的地方含义不同

  20. 使用 HTTP 协议访问另一个 IP 时,比如同时提供 IP 和端口号,缺一不可。如果没有提供,浏览器会加上默认端口号80。

端口(port)

端口其实就是一个编号。一个服务器(硬件)不一定只提供一种服务,比如一个服务器既提供 HTTP 服务(网页服务),又提供 FTP 服务(文件下载服务),还提供 SMTP 服务(邮件服务),那么只用一个 IP 是无法告诉服务器你想要使用哪种服务,所以一个端口对应一个服务,是固定的。

端口服务

  1. 提供 HTTP 服务 ==> 80 端口

  2. 提供 HTTPS 服务 ==> 443 端口

  3. 提供 FTP 服务 ==> 21 端口

  4. 提供代理服务器端口 ==> 1080端口

端口基础

每个机器一共有 65535(2的16次方减1)个端口(这是协议规定的)。不过这些端口的使用有一些规定

  1. 0 到 1023(2的10次方减1)号端口是留给系统使用的,你只有拥有了管理员权限后,才能使用这 1024 个端口

  2. 其他端口可以给普通用户使用

  3. 如果一个端口正在提供服务,也就是被占用了,那么就不能再使用这个端口。除非你先停掉正在占用这个端口的服务。

HTTP系列 -- 请求与响应

概述

  1. Server(服务器):服务器作为硬件来说,通常是指那些具有较高计算能力,能够提供给多个用户使用的计算机

  2. Client(客户端):是指与服务器相对应,为客户提供本地服务的程序

浏览器 + 服务器 + HTTP 三者关系

  • 浏览器负责发起请求
  • 服务器在80端口接收请求
  • 服务器负责返回内容(响应)
  • 浏览器负责下载响应内容

HTTP 的作用就是指导浏览器和服务器如何进行沟通。

请求

请求头(Request Headers)格式

1
2
3
4
1.请求类型 路径 协议/版本 // 请求行
2.key: value // 请求头
3.
4.要上传的数据 // 其他消息体

请求类型

  1. GET ==> 用于获取数据。

  2. POST ==> 用于提交数据,请求服务器进行处理。

  3. PUT ==> 向指定资源位置上传其最新内容(所有内容都更新)。

  4. PATCH ==> 用于将局部修改应用到资源。

  5. DELETE ==> 请求服务器删除Request-URI所标识的资源。

  6. HEAD ==> 向服务器发出指定资源的请求,但服务器将不传回资源的本文部分。

  7. OPTIONS ==> 使服务器传回该资源所支持的所有HTTP请求方法,向Web服务器发送OPTIONS请求,可以测试服务器功能是否正常运作。

路径

必须以 / 开头,如果不设置,默认为 / ,路径包括查询参数,但是不包括锚点

版本:

版本大部分都是 HTTP/1.1,还有HTTP/2.

请求头(key: value):

请求头定义一些操作参数。其中

1
2
3
4
5
Host: www.baidu.com  // 域名
User-Agent: // 用的什么软件发起的请求
Content-Type: application/x-www-form-urlcoded //标识了第4部分的格式,POST 请求
Content-Length:
Cookie:

第3部分:

是一个空行(回车)。

第4部分:

上传的数据,可以没有

说明

  • https 协议 ==> 所有数据在网络上请求和传输的时候都是加密的
  • http 协议 ==> 所有数据在网络上请求和传输的时候都是明文的

响应

响应头(Response Headers)格式

1
2
3
4
1.协议/版本 状态码 状态解释
2.key: value
3.
4.要下载的数据

状态码:

表示网页服务器超文本传输协议响应状态的3位数字代码。

  • 2xx成功 ==> 代表请求已成功被服务器接收、理解、并接受。

    1
    2
    a.200 OK 请求已成功,请求所希望的响应头或数据体将随此响应返回(GET)。
    b.204 No Content 服务器成功处理了请求,没有返回任何内容(创建成功 ==> POST)。
  • 3xx重定向 ==> 类状态码代表需要客户端采取进一步的操作才能完成请求。

    1
    2
    3
    a.301 Move Permanently 被请求的资源已永久移动到新位置,并且将来任何对此资源的引用都应该使用本响应返回的若干个URI之一。
    b.302 Found 要求客户端执行临时重定向。
    c.304 Not Modified 表示资源未被修改。在这种情况下,由于客户端仍然具有以前下载的副本,因此不需要重新传输资源。
  • 4xx客户端错误 ==> 这类的状态码代表了客户端看起来可能发生了错误,妨碍了服务器的处理。

    1
    2
    a.403 Forbidden 客户端错误,服务器已经理解请求,但是拒绝执行  它。
    b.404 Not Found 请求失败,请求所希望得到的资源未被在服务器上发 现,但允许用户的后续请求。
  • 5xx服务器错误 ==> 表示服务器无法完成明显有效的请求。

    1
    2
    a.500 Internal Server Error 通用错误消息,服务器遇到了一个未曾预料的状况,导致了它无法完成对请求的处理。
    b.502 Bad Gateway 作为网关或者代理工作的服务器尝试执行请求时,从上游服务器接收到无效的响应。

HTML 与 HTTP

所有 App 都会内置一个浏览器(WebView)用来展示 HTML,而 HTML 都是通过 HTTP 下载的,而如果你要使用 HTTP 一般都会用到 URL。

HTTP系列 -- 基础知识

代码链接

脚本

JavaScript 是一门动态类型、面向对象的脚本语言

bash 脚本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
mkdir ~/local
cd ~/local
touch demo.txt
start demo.txt

//内容如下:
//mkdir demo
//cd demo
//mkdir css js
//touch index.html css/style.css js/main.js
//exit

//(Windows 用户请跳过这一步)给 demo.sh 添加执行权限,加上可执行的操作
//chmod +x demo.txt

// 在任意位置执行 'sh ~/local/demo.txt' 即可运行此脚本,sh ==> shell
cd ~/desktop
sh ~/local/demo.txt
// 你会看到当前目录里多出一个 demo 目录,demo 目录里面还有一些文件
// demo.txt 就是你写出的第一个 Bash 脚本了。

// 将 ~/local 添加到 PATH 里
cd ~/local;pwd
touch ~/.bashrc
start ~/.bashrc
//在最后一行添加
export PATH="local的绝对路径:$PATH"
source ~/.bashrc
// 之前你要运行 sh ~/local/demo.txt,现在你只需要运行 demo.txt 就行 了
// 原因:将这个路径添加到 '~/.bashrc' 之后,就是在进入 git bash 之前就运行了 '~/.bashrc'

// 删掉demo.txt 的后缀 .txt
mv ~/local/demo.txt ~/local/demo
// 现在只要运行 demo 就能执行该脚本了。
说明:
  1. PATH 的作用
    你每次在 Bash 里面输入一个命令时(比如 ls、cp、demo),Bash 都会去 PATH 列表里面寻找对应的文 件,如果找到了就执行。(each $PATH查看PATH,’目录:目录…’)
  2. type demo 可以看到寻找过程
  3. which demo 可以看到寻找结果,最终结果
  4. 文件后缀的作用:毫无作用,windows有一个用处,告诉计算机,用什么打开文件
  5. 所有命令都是可执行文件,都是一个脚本文件,可执行文件就是命令,不可执行文件就是配置
参数

让 demo 脚本创建的目录可变,更改 demo 的内容为

1
2
3
4
5
mkdir $1
cd $1 // $1 ==> 表示传递的第一个参数
mkdir css js
touch index.html css/style js/main.js
exit

返回值

exit 1 表示错误代码1

exit 0表示没有错误

1
demo xxx && echo 'end' //表示之后 demo xxx 成功了才会执行 echo 'end'

Node.js 脚本

www(World Wide Web)

1990年万维网(World Wide Web)诞生。Tim Berners-Lee 发明了第一个网页、第一个浏览器和第一个服务器

主要概念

  1. URI(Uniform Resource Identifier):统一资源标识符,是一个用于标识某一互联网资源名称的字符串,其中包括 URL 和 URN 。

    • URL(Uniform Resource Locator):统一资源定位符,或者称为URL地址网页地址(网址)。统一资源定位符的标准格式如下:
      协议类型:[//服务器地址[:端口号]][/资源层级UNIX文件路径]文件名[?查询][#片段ID]
      URL地址

    • URN(Uniform Resource Name):统一资源名称,其目的是通过提供一种途径,用于在特定的命名空间资源的标识,以补充网址。

  2. HTTP(HyperText Transfer Protocol):超文本传输协议,是一种用于分布式、协作式和超媒体信息系统的应用层协议。就是两个电脑之间传输内容的协议。

  3. HTML(HyperText Markup Language):超文本标记语言,是一种用于创建网页的标准标记语言。第一个网页

  4. DNS(Domain Name System):域名系统,是互联网的一项服务。它作为将域名和IP地址相互映射的一个分布式数据库,能够使人更方便地访问互联网。(输入一个域名,将得到一个IP

    • 输入域名

      1
      2
      3
      //在命令行中输入以下任意一条,即可返回包括IP地址的一些信息
      nslookup baidu.com
      ping baidu.com
    • 输出IP

说明:

  • 可以修改本地 hosts 文件从而让域名指向特定的IP
  • URL 的作用是能让你访问一个页面
  • HTTP 的作用是让你能下载这个页面
  • HTML 的作用是让你能看懂这个页面。

HTML Element

根元素

  • <html> 表示一个HTML文档的根(顶级元素),所所以它也被称为根元素。其他所有其他元素必须是此元素的后代

文档元数据

元数据(Metadata)含有页面的相关信息,包括样式、脚本及数据,能帮助一些软件 (如搜索引擎, 浏览器等等)更好地运用和渲染页面。对于样式和脚本的元数据,可以直接在网页里定义,也可以链接到包含相关信息的外部文件

  • <link> 指定了外部资源与当前文档的关系. 这个元素的使用方法包括为导航定义关系框架.这个元素经常用来链接css文件

  • <meta> 表示那些不能由其它HTML元相关元素 (<base><link><script><style><title>)之一表示的任何元数据信息

  • <style> 包含了文档的样式化信息或者文档的一部分。指定的样式化星系包含的该元素内,通常是CSS的格式

内容分区

内容分区元素允许你将文档内容从逻辑上进行组织划分。使用包括页眉(header)、页脚(footer)、导航(nav)和标题(h1~h6)等分区元素,来为页面内容创建明确的大纲,以便区分各个章节的内容

  • <address> 可以让作者为它最近的<article>或者<body>祖先元素提供联系信息。在后一种情况下,它应用于整个文档

  • <article> 表示文档、页面、应用或网站中的独立结构,其意在成为可独立分配的或可复用的结构,如在发布中,它可能是论坛帖子、杂志或新闻文章、博客、用户提交的评论、交互式组件,或者其他独立的内容项目

  • <aside> 表示一个和其余页面内容几乎无关的部分,被认为是独立于该内容的一部分并且可以被单独的拆分出来而不会使整体受影响。其通常表现为侧边栏或者嵌入内容

  • <footer> 示最近一个章节内容或者根节点(sectioning root )元素的页脚。一个页脚通常包含该章节作者、版权数据或者与文档相关的链接等信息

  • <h1-h6> 标题信息

  • <header> 表示一组引导性的帮助,可能包含标题元素,也可以包含其他元素,像logo、分节头部、搜索表单等

  • <hgroup> 代表一个段的标题

  • <nav> 描绘一个含有多个超链接的区域,这个区域包含转到其他页面,或者页面内部其他部分的链接列表

  • <section> 表示文档中的一个区域(或节),比如,内容中的一个专题组,一般来说会有包含一个标题(heading)

文本内容

使用 HTML 文本内容元素来组织在开标签<body>和闭标签</body> 里的块或章节的内容。这些元素能标识内容的宗旨或结构,而这对于 accessibility 和 SEO很重要

  • <blockquote> 引用块

  • <div> 是一个通用型的流内容容器

  • <dl> 是一个包含术语定义以及描述的列表,通常用于展示词汇表或者元数据 (键-值对列表)

  • <dt> 用于在一个定义列表中声明一个术语。通常在该元素后面会跟着 <dd>元素

  • <dd> 用来指明一个描述列表 ( <dl> ) 元素中一个术语的描述。这个元素只能作为描述列表元素的子元素出现,并且必须跟着一个 <dt> 元素

  • <hr> 表示段落级元素之间的主题转换。在HTML的早期版本中,它是一个水平线。现在它仍能在可视化浏览器中表现为水平线,但目前被定义为语义上的,而不是表现层面上

  • <main> 呈现了文档<body>或应用的主体部分

  • <ol> 表示多个有序列表项,通常渲染为有带编号的列表

  • <ul> 代表多项的无序列表,即无数值排序项的集合,且它们在列表中的顺序是没有意义的

  • <li> 用于表示列表里的条目。它必须被包含在一个父元素 <ul> <ol>

  • <p> 表示文本的一个段落。该元素通常表现为一整块与相邻文本分离的文本,或以垂直的空白隔离或以首行缩进

  • <pre> 表示预定义格式文本

内联文本语义

使用 HTML 内联文本语义(Inline text semantics)定义语句,结构,可以是一个词,一段,或任意风格的文字

  • <a> 可以创建一个到其他网页、文件、同一页面内的位置、电子邮件地址或任何其他URL的超链接

  • <abbr> 代表缩写,并可选择提供一个完整的描述

  • <b> 表示相对于普通文本字体上的区别,但不表示任何特殊的强调或者关联,通常以粗体显示

  • <bdi> (双向隔离元素) 会隔离可能以不同方向进行格式化的外部文本

  • <bdo> (HTML双向覆盖元素)用于覆盖当前文本的朝向,它使得字符按给定的方向排列

  • <br> 文本中产生一个换行(回车键)

  • <cite> 表示一个作品的引用

  • <code> 现一段计算机代码. 默认情况下, 它以浏览器的默认等宽字体显示

  • <data> 将一个指定内容和机器可读的翻译联系在一起

  • <em> 标记出需要用户着重阅读的内容

  • <i> 用于表现因某些原因需要区分普通文本的一系列文本。例如技术术语、外文短语或是小说中人物的思想活动等,它的内容通常以斜体显示

  • <kbd> 用于表示用户输入,它将产生一个行内元素,以浏览器的默认monospace字体显示

  • <mark> 代表突出显示的文字

  • <q> 表示一个封闭的并且是短的行内引用的文本。这个标签是用来引用短的文本,所以请不要引入换行符; 对于长的文本的引用请使用<blockquote>替代

  • <s> 使用删除线来渲染文本

  • <small> 使文本的字体变小一号

  • <span> 短语内容的通用行内容器,并没有任何特殊语义

  • <strong> 表示文本十分重要,一般用粗体显示

  • <sub> 定义了一个文本区域,出于排版的原因,与主要的文本相比,应该展示得更低并且更小。下标

  • <sup> 定义了一个文本区域,出于排版的原因,与主要的文本相比,应该展示得更高并且更小。上标

  • <u> 使文本在其内容的基线下的一行呈现下划线

图片和多媒体

HTML 支持各种多媒体资源,例如图像,音频和视频

  • <area> 在图片上定义一个热点区域

  • <audio> 用于在文档中表示音频内容。 <audio>元素可以包含多个音频资源, 这些音频资源可以使用 src属性或者<source>元素来进行描述; 浏览器将会选择最合适的一个来使用。对于不支持 <audio> 元素的浏览器,<audio> 元素也可以作为浏览器不识别的内容加入到文档中

  • <img> 代表文档中的一个图像

  • <track> 被当作媒体元素—<audio><video>的子元素来使用。它允许指定计时字幕(或者基于事件的数据),例如自动处理字幕

  • <video> 用于在HTML或者XHTML文档中嵌入视频内容

内嵌内容

除了常规的多媒体内容,HTML 可以包括各种其他的内容,即使它并不容易交互

  • <embed> 用于表示一个外部应用或交互式内容的集合点,换句话说,就是一个插件

  • <object> 表示引入一个外部资源,这个资源可能是一张图片,一个嵌入的浏览上下文,亦或是一个插件所使用的资源

  • <param> 定义了 <object>的参数

  • <source>

脚本

为了创建动态内容和 Web 应用程序,HTML 支持使用脚本语言,最突出的就是 JavaScript。某些元素支持此功能

  • <canvas> 可被用来通过脚本(通常是JavaScript)绘制图形

  • <noscript> 如果页面上的脚本类型不受支持或者当前在浏览器中关闭了脚本,则HTML

  • <script> 用于嵌入或引用可执行脚本

编辑标识

这些元素能标示出某个文本被更改过的部分

  • <del> 表示已经从文档中删除的文本范围。此元素通常是(但不必)呈现删除线的文本

  • <ins> 定义已经被插入文档中的文本

表单

HTML 提供了许多可一起使用的元素,这些元素能用来创建一个用户可以填写并提交到网站或应用程序的表单

  • <button> 表示一个可点击的按钮

  • <datalist> 包含了一组<option>元素,这些元素表示其它表单控件可选值

  • <fieldset> 用来对表单中的控制元素进行分组(也包括 label 元素)

  • <form> 表示了文档中的一个区域,这个区域包含有交互控制元件,用来向web服务器提交信息

  • <input> 用于为基于Web的表单创建交互式控件,以便接受来自用户的数据

  • <label> 表示用户界面中项目的标题

  • <legend> 代表一个用于表示它的父元素<fieldset>的内容的标题

  • <meter> 用来显示已知范围的标量值或者分数值

  • <option> 用于定义在<select><optgroup><datalist> 元素中包含的项

  • <output> 表示计算或用户操作的结果

  • <progress> 用来显示一项任务的完成进度。通常情况下,该元素都显示为一个进度条形式

  • <select> 一种表单控件,可创建选项菜单

  • <textarea> 表示一个多行纯文本编辑控件

交互元素

HTML 提供了一系列有助于创建交互式用户界面对象的元素

  • <details> 被用作发现小部件,用户可以从其中检索附加信息

  • <dialog> 表示一个对话框或其他交互式组件,例如一个检查员或窗口

  • <menu> 呈现了一组用户可执行或激活的命令。这既包含了可能出现在屏幕顶端的列表菜单,也包含了那些隐藏在按钮之下、当点击按钮后显示出来的文本菜单

  • <menuitem> 生成一个弹出式菜单。这包括上下文菜单,以及按钮可能附带的菜单。

  • <summary> 用作 一个 <details> 元素的一个内容的摘要,标题或图例

web组件

Web 组件是种近似 HTML(HTML-related) 的技术,这使得它能够,从本质上讲,创建和使用自定义元素,就好像它是普通的 HTML。此外,你甚至可以创建自定义版本的标准 HTML 元素

  • <slot> web组件技术的一部分,slot是web组件的一个占位符,可以用来插入自定义的标记文本。可以创建不同的DOM树并进行渲染

  • <template> 一种用于保存客户端内容的机制,该内容在页面加载时不被渲染,但可以在运行时使用JavaScript进行实例化