前端语言的基本能力
基础的前端三剑客HTML、CSS、JavaScript
- HTML(超文本标记语言) : HTML 是 Web 页面的基础结构。它用于描述网页的内容和结构。HTML 使用一系列标记(称为标签)来定义页面元素,如标题、段落、列表、图片和链接等。浏览器解析 HTML 代码,并根据标签的语义来显示页面内容。HTML 为网页提供了基本的骨架,使浏览器能够呈现文本、图像和其他媒体。
- CSS(级联样式表) : CSS 用于描述 HTML 元素的外观和布局。CSS 允许我们定义如何显示 HTML 元素,例如字体、颜色、大小、间距等。通过使用 CSS,我们可以将样式与 HTML 结构分离,使得网站的设计和维护更加简便。CSS 还允许我们根据不同的设备和屏幕尺寸应用不同的样式(媒体查询),以实现响应式设计。
- JavaScript: JavaScript 是一种脚本语言,用于在浏览器中增加交互性和动态效果。它允许我们编写脚本来处理用户操作,例如点击按钮、输入表单、拖动元素等。通过使用 JavaScript,我们也可以操作 HTML 和 CSS,动态更改页面内容和样式,从而提供丰富的用户体验。JavaScript 也可以与服务器进行通信,以便在不刷新整个页面的情况下获取或提交数据(例如,通过 AJAX)。
HTML
对于HTML是什么,MDN是这样定义的:
HTML 不是一门编程语言,而是一种用于定义内容结构的标记语言。HTML 由一系列的元素组成,这些元素可以用来包围不同部分的内容,使其以某种方式呈现或者工作。一对标签可以为一段文字或者一张图片添加超链接,将文字设置为斜体,改变字号,等等。
CSS
和 HTML 类似,CSS 也不是真正的编程语言,甚至不是标记语言。它是一门样式表语言,这也就是说人们可以用它来选择性地为 HTML 元素添加样式。
- 对于视频中提到的另一张图片,我觉得MDN提供的会更容易理解,这里附上MDN的讲解:
整个结构称为 规则集(通常简称“规则”),各部分释义如下:
其他更加细节的部分我觉得自行去查阅MDN或者W3C文档会好,这里只摘取其中一小部分与视频中讲解有关的部分
上图标记 | 释义 |
---|---|
选择器(Selector) | HTML 元素的名称位于规则集开始。它选择了一个或多个需要添加样式的元素(在这个例子中就是 p 元素)。要给不同元素添加样式只需要更改选择器就行了 |
声明(Declaration) | 一个单独的规则,如 color: red; 用来指定添加样式元素的属性 |
属性(Properties) | 改变 HTML 元素样式的途径。(本例中 color 就是 `` 元素的属性。)CSS 中,由编写人员决定修改哪个属性以改变规则 |
属性的值(Property value) | 在属性的右边,冒号后面即属性的值,它从指定属性的众多外观中选择一个值(我们除了 red 之外还有很多属性值可以用于 color ) |
常见选择器
选择器名称 | 选择的内容 | 示例 |
---|---|---|
元素选择器(也称作标签或类型选择器) | 所有指定 (该) 类型的 HTML 元素 | p 选择 <p> |
ID 选择器 | 具有特定 ID 的元素(单一 HTML 页面中,每个 ID 只对应一个元素,一个元素只对应一个 ID) | #my-id 选择 <p id="my-id"> 或 <a id="my-id"> |
类选择器 | 具有特定类的元素(单一页面中,一个类可以有多个实例) | .my-class 选择 <p class="my-class"> 和 <a class="my-class"> |
属性选择器 | 拥有特定属性的元素 | img[src] 选择 <img src="myimage.png"> 而不是 <img> |
伪(Pseudo)类选择器 | 特定状态下的特定元素(比如鼠标指针悬停) | a:hover 仅在鼠标指针悬停在链接上时选择 <a> 。 |
阅读文档
这里他告诉了你如何阅读文档,但其实也只是略要的概括了一下,且并没有给出文档的地址,这里我进行补充:CSS Syntax (w3schools.com)
视频中的案例图片也是来自于此
W3C和W3School的区别?
- W3C(万维网联盟): W3C 是一个国际组织,成立于 1994 年,负责制定和维护 Web 标准。它的目标是确保 Web 发展的长期可持续性和可访问性。W3C 制定了许多 Web 技术的规范,如 HTML、CSS、XML、SVG 等。W3C 的官方网站是 www.w3.org/。在 W3C 网站上,可以找到关于 Web 标准的详细信息和技术规范。
- W3Schools: W3Schools 并非 W3C 的官方网站,而是一个独立的在线教育平台。它成立于 1998 年,提供了大量关于 HTML、CSS、JavaScript 等 Web 技术的教程和实例。W3Schools 的目标是为 Web 开发者提供一个易于理解的学习资源。W3Cschools 的官方网站是 www.w3schools.com/。在 W3Cshools 网站上,可以找到关于 Web 技术的教程、示例和实践练习。
而他们最主要的区别(其实是完全不同的两家组织,一开始学习的我一直以为他们是同一家的):
- W3C 是一个国际组织,负责制定和维护 Web 标准。
- W3Schools 是一个在线教育平台,提供关于 Web 技术的教程和实例。
JavaScript
coderwhy老师曾经说过了解真相才能获得真正的自由,那么了解一门语言的前生今世同样对于我们理解它有着很棒的作用(不了解它的曾经,又怎么能理解它为什么要做出这样的变化)
1995 年:JavaScript 的诞生 JavaScript 最早是由 Netscape 公司的程序员 Brendan Eich 开发的,原名叫 Mocha。最初的目标是提供一种浏览器端脚本语言,用于操作 HTML 文档,增加互动性和动态效果。几个月后,Mocha 被重命名为 LiveScript,随后又改名为 JavaScript。尽管名字里包含 "Java",但实际上 JavaScript 和 Java 并无直接关系,这个命名更多是当时为了借助 Java 语言的热度。
1996 年:ECMAScript 的诞生 为了让 JavaScript 成为一个通用的脚本语言标准,Netscape 将 JavaScript 提交给了欧洲计算机制造商协会(ECMA)。ECMA 开发了一种名为 ECMAScript 的标准化脚本语言规范。自此,JavaScript 成为 ECMAScript 规范的一种实现。
1997 年:ECMAScript 1.0 发布 ECMA 发布了 ECMAScript 的第一个版本(1.0),标志着 JavaScript 语言正式成为一个独立的编程语言。
1999 年:ECMAScript 3.0 发布 ECMAScript 3.0 是 JavaScript 发展历程中的一个重要版本,它引入了许多核心功能,如正则表达式、错误处理、更严格的变量声明等。
2005 年:Ajax 和 Web 2.0 的兴起 2005 年,Ajax(Asynchronous JavaScript and XML)技术兴起,它允许在不刷新整个页面的情况下进行局部数据更新,大大提高了 Web 应用的交互性。这一时期,Web 2.0 的概念开始流行,JavaScript 在 Web 开发中的地位得到了极大的提升。
2009 年:ECMAScript 5 发布 ECMAScript 5 版本引入了许多新特性,如 JSON 支持、严格模式、访问器属性等。同时,它还优化了一些老旧的功能和语法,使得 JavaScript 更加易用和高效。
2010 年:Node.js 的诞生 2010 年,程序员 Ryan Dahl 创立了 Node.js,将 JavaScript 扩展到了服务器端。Node.js 的出现使得 JavaScript 成为一种全栈开发语言。
2015 年:ECMAScript 6(ES2015)发布 ECMAScript 6(也称为 ES2015)是 JavaScript 发展史上最重要的版本之一。ES6(ECMAScript 2015)引入了许多重要的新特性,改进了 JavaScript 语言的编程模式和可读性。这些新特性包括:
- 类(Class)语法:提供了基于原型的面向对象编程的语法糖。
- 模块化(Module):引入了模块化编程的概念,使得开发者可以将代码拆分为可重用的模块。
- 箭头函数(Arrow Function):简化了函数定义的语法,同时自动绑定
this
上下文。- Promise:提供了一种更好的异步编程模式,帮助开发者更容易处理异步操作。
- 解构赋值(Destructuring Assignment):一种更简洁的变量解构和赋值方式。
- 默认参数(Default Parameters):允许函数参数具有默认值。
- 模板字符串(Template Literals):提供了一种简单的字符串插值和多行字符串的表示方法。
- 增强的对象字面量:增加了对于简写属性和方法的支持。
- let 和 const 关键字:引入了块级作用域,并允许更精确地声明变量和常量。
2016 年至今:ECMAScript 的年度更新 自 ES6(ECMAScript 2015)发布以来,ECMAScript 规范开始了每年的更新周期。这意味着每年都会有一个新版本的 ECMAScript,其中包括一些新特性和改进。这使得 JavaScript 的发展更加稳定和可预测。
现代 Web 开发框架和库的兴起 近年来,随着 JavaScript 的发展,许多现代 Web 开发框架和库应运而生。这些框架和库(如 Angular、React、Vue.js 等)极大地提高了开发者的生产力,改变了 Web 开发的方式和规模。
基础语法
JavaScript的七种基本数据类型:
这些类型分为两大类:原始类型(Primitive)和对象类型(Object)。
- Number(数字): Number 类型用于表示整数和浮点数。在 JavaScript 中,所有数字都是双精度浮点数(64位),遵循 IEEE 754 标准。这意味着 JavaScript 中并没有真正的整数类型。另外,Number 类型还包括特殊值如:Infinity(正无穷大)、-Infinity(负无穷大)和 NaN(非数值)。
- String(字符串): String 类型表示一串字符。在 JavaScript 中,字符串是不可变的,这意味着一旦创建了一个字符串,就不能对其内容进行修改。字符串可以用单引号、双引号或反引号(模板字符串)括起来。
- Boolean(布尔值): Boolean 类型只有两个值:true(真)和 false(假)。布尔值通常用于表示条件、逻辑操作或比较的结果。
- Null(空值): Null 类型只有一个值:null。它表示一个空值或不存在的引用。通常用于表示变量没有被赋值,或表示一个空对象。
- Undefined(未定义): Undefined 类型只有一个值:undefined。当一个变量声明了,但尚未赋值时,其默认值为 undefined。它表示变量的值尚未确定。
- Symbol(符号): Symbol 类型是 ECMAScript 6(ES2015)引入的新类型。Symbol 类型的值是唯一且不可变的,主要用于创建对象的唯一属性名,以防止属性名冲突。
- Object(对象): Object 类型用于表示复杂的数据结构,如对象、数组和函数。对象是键值对的集合,键是字符串,值可以是任何数据类型。数组是值的有序集合,而函数是可调用的代码块。
在 JavaScript 中,原始类型(Number、String、Boolean、Null、Undefined 和 Symbol)是不可变的基本数据类型,而对象类型(Object)是可变的引用数据类型
声明赋值
//这个表达式涉及到了 JavaScript 中的变量声明、赋值操作以及类型转换
var a = 7 + "2"
//执行过程:
//首先,var a 声明了一个名为 a 的新变量。然后,执行 7 + "2" 的操作。因为其中一个操作数("2")是一个字符串,所以 + 会执行字符串连接操作。在这种情况下,JavaScript 会自动将数字 7 转换为字符串 "7"(隐式转换),然后将两个字符串连接起来,得到新字符串 "72"。最后,将得到的字符串 "72" 赋值给变量 a。
让我们详细剖析这个表达式中的含义:
var
:var
关键字用于声明一个变量。在这里,var
表示我们将要创建一个新变量。a
:这是我们声明的变量的名称。变量名可以是任何有效的 JavaScript 标识符,通常用于表示该变量存储的数据的含义。=
:赋值操作符,用于将等号右侧的值赋给等号左侧的变量。在这里,它表示我们要将等号右侧的表达式的计算结果存储在变量a
中。7
:这是一个数字字面量,表示整数 7。它的类型是 Number。+
:这是一个加法操作符。通常,它用于对两个数字进行加法运算。然而,当它的操作数之一或两者都是字符串时,+
会变成字符串连接操作符。在这种情况下,它会将两个操作数连接成一个字符串。"2"
:这是一个字符串字面量,表示字符 "2"。它的类型是 String。注意,这里的 "2" 是一个字符串,而不是数字。
但是这里我想要扩充另一个知识点,当我们换一种形式的话,它的类型转换还会是隐式拼接字符串吗?
let a = 7 - "2"
console.log(a)//5
- a会输出
5
,且是Number数字类型。因为-
操作符仅适用于数字,所以 JavaScript 会尝试将字符串 "2" 转换为数字。在这种情况下,字符串 "2" 可以成功转换为数字 2 - 通过这种系列的《黑魔法》式操作会降低可读性,所以我们应该尽量避免这种操作
Object
在 JavaScript 中,Object(对象)是一种引用数据类型,用于表示一组键值对。对象可以用来存储和操作数据,它是 JavaScript 中最基本和重要的数据结构。
以下包括函数部分全部都是简要概括,深入的了解和运用场所还得通过其他视频或者文档或者项目实践去进一步学习
- 键值对(Key-Value Pair): 对象由一组键值对组成,键是字符串,值可以是任何数据类型(包括原始类型和引用类型)。键也称为属性名(Property Name),而值称为属性值(Property Value)。键和值之间用冒号分隔,键值对之间用逗号分隔。
- 对象字面量(Object Literal): 对象字面量是创建对象的一种简洁表示方式。它使用大括号
{}
包围一组键值对。例如:
//在这个例子中,person 对象有三个属性:name、age 和 greet。name 和 age 分别存储字符串和数字,而 greet 存储一个函数
const person = {
name: "XiaoYu",
age: 20,
greet: function() {
console.log("Hello, my name is " + this.name);
}
};
- 属性访问(Property Access): 可以使用点表示法(Dot Notation)或方括号表示法(Bracket Notation)访问对象的属性。例如:
console.log(person.name); // Output: "XiaoYu"
console.log(person["age"]); // Output: 20
- 属性操作(Property Manipulation): 可以通过赋值操作符为对象添加新属性,也可以通过赋值操作符修改现有属性的值。要删除对象的属性,可以使用
delete
操作符。例如:
person.gender = "Man"; // 添加新属性
person.name = "小满"; // 修改现有属性的值
delete person.gender; // 删除属性
- 方法(Method): 对象的属性值可以是函数。这种类型的属性称为方法(Method)。方法通常用于表示对象的行为,它们可以访问和操作对象的其他属性。例如:
person.greet(); // Output: "Hello, my name is XiaoYu"
-
this
关键字: 在对象的方法中,可以使用this
关键字引用该对象本身。这使得方法可以访问和操作对象的其他属性。例如,在上面的person
对象中,greet
方法使用this.name
访问name
属性。- this是JavaScript中的一大难点,在《你不知道的JavaScript》上卷中,将它分为了默认调用、隐式调用、显式调用、new调用四种情况,具体过程需要自行去学习,或者在我的GitHub中也有提供对应的笔记
Function
函数(Function)是一种特殊的对象,它封装了一段可执行的代码。函数的主要作用是实现代码的复用、模块化和抽象。
-
函数声明(Function Declaration): 函数声明是定义函数的一种方法。函数声明以
function
关键字开始,后面跟着函数名、一对圆括号(包含参数列表)和一对大括号(包含函数体)function greet(name) { console.log("Hello, " + name); }
-
函数表达式(Function Expression): 函数表达式是另一种定义函数的方法。函数表达式将一个匿名函数赋值给一个变量。
const greet = function(name) { console.log("Hello, " + name); };
-
箭头函数(Arrow Function): 箭头函数是 ECMAScript 6(ES2015)引入的一种简洁的函数语法。箭头函数使用
=>
符号,它可以使代码更简洁、易读。const greet = (name) => { console.log("Hello, " + name); };
-
参数(Parameters)和实参(Arguments): 函数可以接受参数(Parameters)。参数是在函数声明或表达式中定义的,用于接收调用函数时传递的实参(Arguments)。实参是在调用函数时传递给函数的值。
function add(a, b) { return a + b; } const sum = add(3, 4); // 传递实参 3 和 4
-
返回值(Return Value): 函数可以返回一个值,这个值可以是任何数据类型。要返回一个值,可以在函数体内使用
return
语句。如果函数没有return
语句或者return
语句后面没有任何值,那么函数的返回值默认为undefined
。function add(a, b) { return a + b; } const sum = add(3, 4); // sum 将接收返回值 7
-
调用(Calling)或执行(Invoking)函数: 要调用或执行一个函数,可以使用函数名后跟一对圆括号(包含实参列表)。
greet("Alice"); // Output: "Hello, Alice"
-
作用域(Scope): 在 JavaScript 中,函数有自己的作用域。这意味着在函数内部声明的变量和函数只能在函数内部访问。同样,函数外部的变量和函数在函数内部也是可访问的(除非被其他嵌套函数阻止)。
-
闭包(Closure): 闭包是 JavaScript 中一个强大的特性(也是一个很难的知识点,在《你不知道的JavaScript》上卷中一样有详细介绍)。闭包是指一个函数可以访问并操作其外部作用域中的变量,即使在外部作用域已经结束或函数已返回之后。闭包的一个常见用途是在一个函数内部创建另一个函数,这样内部函数可以访问和操作外部函数的变量。
function makeCounter() { let count = 0; return function() { count += 1; console.log(count); }; } const counter = makeCounter(); counter(); // Output: 1 counter(); // Output: 2,数量变成2,证明上一次调用的结果并没有被垃圾回收掉 //在这个例子中,makeCounter 函数返回一个匿名函数,这个匿名函数可以访问和操作 makeCounter 函数内的 count 变量。即使 makeCounter 函数已经执行完毕,counter(匿名函数的引用)仍然可以访问和操作 count 变量。这就是闭包的作用。
-
高阶函数(Higher-Order Function): 高阶函数是指接受其他函数作为参数或返回一个函数作为结果的函数。高阶函数在 JavaScript 中非常常见,特别是在函数式编程中。例如,
Array.prototype.map
、Array.prototype.filter
和Array.prototype.reduce
等内置函数都是高阶函数。const numbers = [1, 2, 3, 4, 5]; const doubled = numbers.map(function(num) { return num * 2; }); console.log(doubled); // Output: [2, 4, 6, 8, 10] //在这个例子中,我们使用 map 高阶函数将一个数组中的每个元素乘以 2。map 函数接受一个函数作为参数,并将这个函数应用于数组的每个元素。这个在React中会经常出现,用来替代for循环
三剑客在浏览器中的运行
- HTTP 请求:浏览器向服务器发送请求,获取网页的 HTML、CSS、JavaScript 文件以及其他资源(如图片、字体等)。
- 构建 DOM 树:浏览器解析 HTML 文件,构建一个 DOM(Document Object Model)树。DOM 树是一个以节点形式表示的 HTML 文档结构。每个节点代表 HTML 文档中的一个元素、属性或文本。
- 计算 CSS 树:浏览器解析 CSS 文件,构建一个 CSSOM(CSS Object Model)树。CSSOM 树是一个以节点形式表示的 CSS 规则结构。
- 排版(Layout):浏览器将 DOM 树和 CSSOM 树结合,生成一个渲染树(Render Tree)。渲染树包含了 DOM 中的可见元素及其对应的 CSS 规则。接着,浏览器会计算渲染树中每个节点的位置和大小,这个过程称为排版或布局(Layout)。
- 渲染合成:浏览器将渲染树中的各个节点分层,创建渲染层(Render Layers)。每个层包含一个或多个节点,具有独立的绘制和合成上下文。
- 绘制(Painting):浏览器根据渲染层绘制每个节点的视觉效果(如文本、颜色、图像、边框、阴影等),生成位图(Bitmaps)。绘制过程可能会在 GPU(图形处理器)上完成,以提高性能。
- 合成(Compositing):浏览器将渲染层的位图合成为一个完整的屏幕图像,然后显示在屏幕上。合成过程通常由 GPU 完成,以实现高效的图像合成。
在这个过程中,JavaScript 代码的解析与执行可能穿插在各个阶段,因为 JavaScript 可以操作 DOM、CSSOM 和浏览器 API,从而改变页面的内容、样式和交互行为。这些变化可能需要浏览器重新执行排版、绘制和合成等任务。因此,在编写 JavaScript 代码时,应尽量减少对 DOM 和 CSSOM 的操作,以提高页面性能。
Browser(V8引擎工作流程)
JavaScript本质上也是一段文本,需要通过解释器才能够运行
- Source code:JavaScript 源代码作为 V8 引擎的输入。
- Parser:V8 引擎将 JavaScript 源代码解析成一个抽象语法树(Abstract Syntax Tree,简称 AST)。AST 是源代码的一种树状表示,其中每个节点表示一个源代码中的语法结构(如变量声明、函数调用等)。
- AST:生成的抽象语法树将用于接下来的编译和优化过程。
- Ignition:V8 引擎中的 Ignition 是一个解释器(Interpreter),它负责将 AST 转换为字节码(Bytecode)。字节码是一种中间表示,比源代码更接近机器代码,但仍具有平台无关性。
- Bytecode Execute:Ignition 解释器执行字节码,实现 JavaScript 源代码的功能。在执行字节码的过程中,V8 会收集代码的运行时信息(如类型信息等),用于后续的优化过程。
- Feedback:V8 引擎收集的运行时信息(如变量类型、函数调用频率等)称为反馈(Feedback)。这些信息将用于指导后续的即时编译(JIT)过程,生成更高效的机器代码。
- TurboFan:V8 引擎中的 TurboFan 是一个即时编译器(Just-In-Time Compiler,简称 JIT),它负责将字节码优化为机器代码。TurboFan 会根据收集到的反馈信息对代码进行特定的优化(如内联函数、消除数组边界检查等),生成性能更好的机器代码。
- Machine code (Intel, ARM, MIPS):TurboFan 生成的机器代码是针对特定处理器架构(如 Intel x86/x64、ARM、MIPS 等)的低级代码。这些机器代码可以直接在目标处理器上执行,实现更高的性能。
V8 引擎通过这个工作流程实现了 JavaScript 源代码的高效执行。在实际使用过程中,V8 会根据代码的运行情况动态调整优化策略,确保在不同场景下都能实现最佳性能。
前端语言的协作配合
前端协作发展史
从下面这张图片中,我们可以看到我目前编写笔记用的markdown语法早在2005年前就诞生了,直到现在依旧是主流方便的编写笔记的好工具。而JavaScript2010年前的技术基本上没有活到现在的,足以体现其日新月异的变化,目前则是Vue、React与Angular各占半边天,越靠近现在的节点,工具类的发展像webpack就越发的繁荣。
通过观察,我们能发现作为基础的HTML、CSS、JavaScript在各自的道路上随着时间的流逝越发的深入,然后诞生在那个时间段的最佳实践方案,跨端框架、工具链都是这个最佳实践延伸出来的结果
CSS in HTML
JavaScript in HTML
JavaScript 是单线程的,意味着在一个时间点只能执行一个任务。为了处理异步操作和事件回调,JavaScript 引入了事件循环(Event Loop)。事件循环使用任务队列(Task Queues)来管理要执行的任务。任务队列分为两种类型:宏任务队列(Macro-Task Queue)和微任务队列(Micro-Task Queue)。
宏任务队列(Macro-Task Queue): 宏任务队列存放宏任务(Macro-Task),它们通常是由外部事件触发的较大的任务。例如:
- setTimeout 和 setInterval 的回调函数
- I/O 操作(如文件读写、网络请求等)的回调函数
- 用户交互事件(如点击、滚动等)的回调函数
- 其他异步 API 的回调函数
事件循环会按顺序执行宏任务队列中的任务。当一个宏任务执行完毕后,事件循环会检查微任务队列,执行其中的所有任务,然后再执行下一个宏任务。
微任务队列(Micro-Task Queue): 微任务队列存放微任务(Micro-Task),它们通常是 JavaScript 代码中产生的较小的、需要尽快执行的任务。例如:
- Promise 的 then、catch 和 finally 回调函数
- async/await
- MutationObserver 的回调函数
- 其他微任务 API
当事件循环执行一个宏任务后,它会检查微任务队列。在执行下一个宏任务之前,事件循环会一直执行微任务队列中的所有任务,直到微任务队列为空。这意味着在两个宏任务之间,JavaScript 会尽可能多地执行微任务。
事件循环的执行顺序如下:
- 从宏任务队列中取出一个任务并执行。
- 检查微任务队列,执行其中的所有任务。
- 如果有必要,进行渲染操作(如更新 DOM、执行动画等)。
- 返回第 1 步,重复执行。
通过区分宏任务和微任务,事件循环可以实现对异步操作和事件回调的有效管理。微任务队列确保了在宏任务之间可以尽快执行一些紧急的、短小的任务,从而提高了整体性能。
- HTML同样可以写在JavaScript中,这个语法的文件后缀名是JSX,延伸的有TSX。分别表示使用JS编写和TS编写。这种 语法在React中尤其常见
CSS in JavaScript
React 为了提高 CSS 样式管理的可维护性和局部性,引入了 CSS Modules 和 JSS 等技术。它们分别使用不同的方法来解决组件样式的作用范围和动态化问题。
- CSS Modules: CSS Modules 是一种将 CSS 样式与 React 组件关联的方法。通过使用模块化的 CSS 文件,可以确保每个组件的样式都是独立的,避免样式污染和命名冲突。使用 CSS Modules 的方法如下:
(1)创建一个模块化的 CSS 文件,文件名通常以
.module.css
结尾,例如Button.module.css
:
/* Button.module.css */ .button { background-color: blue; color: white; padding: 10px; }
(2)在 React 组件中,使用
import
语句导入 CSS 文件,并将其作为一个对象使用:
// Button.js import React from 'react'; import styles from './Button.module.css'; const Button = ({ children, onClick }) => { return ( <button className={styles.button} onClick={onClick}> {children} </button> ); }; export default Button;
通过这种方式,组件的样式将被限制在组件的作用范围内,不会影响其他组件。
JSS(JavaScript Style Sheets): JSS 是一种将 CSS 样式以 JavaScript 对象的形式编写和管理的技术。它允许我们在 JavaScript 代码中动态生成和修改样式。在 React 中,我们可以使用
@material-ui/styles
等库来使用 JSS。以下是使用 JSS 的方法:(1)安装
@material-ui/styles
:npm install @material-ui/styles
(2)在 React 组件中,使用 JSS 创建样式:
使用 JSS,我们可以在 JavaScript 代码中直接创建和管理样式。这使得样式的动态化和维护更加方便
// Button.js import React from 'react'; import { makeStyles } from '@material-ui/styles'; const useStyles = makeStyles({ button: { backgroundColor: 'blue', color: 'white', padding: '10px', }, }); const Button = ({ children, onClick }) => { const classes = useStyles(); return ( <button className={classes.button} onClick={onClick}> {children} </button> ); }; export default Button;
你不知道的HTML
HTML DTD
HTML并非图灵完备,它只是一门标记语言。
标签分类
HTML body 功能性标签
只需要大致了解,不需要去背
HTML ARIA
ARIA(Accessible Rich Internet Applications)是一套让 Web 应用和网站更具可访问性的技术规范。ARIA 通过在 HTML 中添加特定的属性,帮助屏幕阅读器等辅助技术更好地理解页面内容和交互。
了解ARlA并非只是为了供盲人阅读,它可以为我们设计UI系统提供指导意义
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>ARIA Example</title>
</head>
<body>
<!--为无法通过文本内容描述的元素(如 <nav>)提供一个可访问的标签-->
<nav aria-label="Main Navigation">
<ul>
<li><a href="#home">Home</a></li>
<li><a href="#about">About</a></li>
<li><a href="#contact">Contact</a></li>
</ul>
</nav>
<main>
<h1 id="home">Welcome to our Website!</h1>
<!--将一个元素关联到一个或多个可见的标签元素,通常是标题元素(如 <h2>)。在这个例子中,我们将每个 <section> 元素关联到对应的标题元素-->
<section aria-labelledby="about-section">
<h2 id="about-section">About Us</h2>
<p>We are a company that specializes in creating accessible web applications.</p>
</section>
<section aria-labelledby="contact-section">
<h2 id="contact-section">Contact Us</h2>
<p>Feel free to reach out to us for any questions or inquiries.</p>
</section>
</main>
</body>
</html>
HTML的规范和特性
HTML5语义化标签
建议:用对比不用好,不用比用错好。虽然这些语义化标签名字各不相同,但其实本质都是div标签
HTML5表单增强
- 新的表单元素:HTML5 引入了一些新的表单元素,如 date、time、email、url 等,使得开发者可以更容易地创建各种类型的表单。
- 自动聚焦:在 HTML5 中,可以通过将
autofocus
属性添加到表单元素中,使得页面加载时自动将焦点放在指定的表单元素上,方便用户操作。- 表单验证:HTML5 提供了内置的表单验证功能,可以通过添加
required
、pattern
、min
、max
、step
等属性来限制表单元素的输入。在用户提交表单时,浏览器会自动验证表单内容,并在不合法时给出相应的提示信息。- 自定义错误提示:HTML5 提供了
oninvalid
属性,使得开发者可以自定义表单元素验证失败时的错误提示信息,增强了用户体验。- 表单自动保存:HTML5 允许浏览器自动保存表单数据,方便用户在下次填写相同表单时直接调用已保存的数据。
- 支持拖放上传文件:HTML5 的拖放功能可以使得用户直接将文件拖到表单区域,实现文件上传操作。
HTML5 存储
术语含义:
- Cookies:Cookies 是存储在客户端计算机上的小文件,用于存储用户与网站之间的数据。常用于记录用户的登录状态、购物车内容等信息。
- Local Storage:Local Storage 是 HTML5 新增的一种 Web 存储机制,用于在客户端存储持久化数据。与 Cookies 不同,Local Storage 的数据不会在每次请求时被发送到服务器,而是保存在客户端的本地存储空间中。
- Session Storage:Session Storage 与 Local Storage 类似,也是用于在客户端存储数据。不同之处在于,Session Storage 的数据只在用户会话期间有效,即在浏览器窗口或标签页关闭时自动清除。
- Capacity:Capacity 指的是 Local Storage 或 Session Storage 可以存储的最大数据量,通常为 5MB 到 10MB 不等。
- Browsers:Browsers 指的是 Web 浏览器,如 Google Chrome、Firefox、Safari 等。
- Accessible from:Accessible from 指的是可以从哪些网址访问到 Local Storage 或 Session Storage 中的数据。通常情况下,只有在同一域名下的页面才能够访问相同的 Local Storage 或 Session Storage 数据。
- Expires:Expires 指的是 Cookie 的过期时间,即 Cookie 将在何时失效。当 Cookie 的 Expires 属性为一个固定的时间点时,该 Cookie 将在该时间点失效;当 Expires 属性为 0 时,该 Cookie 将在浏览器关闭时失效。
- Storage Location:Storage Location 指的是 Local Storage 或 Session Storage 的存储位置。通常情况下,Local Storage 或 Session Storage 的数据是保存在客户端的本地存储空间中,而不是发送到服务器。
- Sent with requests:Sent with requests 指的是 Cookie 是否随着 HTTP 请求一起发送到服务器。通常情况下,浏览器会将 Cookie 的值添加到 HTTP 请求头中,以便服务器进行身份验证等操作。
Cookies | Local Storage | Session Storage | |
---|---|---|---|
Capacity | 4kb | 10mb | 5mb |
Browsers | HTML4 / HTML5 | HTML5 | HTML5 |
Accessible from | Any window | Any window | Same tab |
Expires | Manually set | Never | On tab close |
Storage Location | Browser and server | Browser only | Browser only |
Sent with requests | Yes | No | No |
HTML5 IndexedDB
IndexedDB 是 HTML5 中新增的一种客户端存储机制,用于在浏览器中存储大量的结构化数据。它是一种键值对存储方式,类似于关系型数据库,可以通过索引快速访问数据。
IndexedDB 的主要特点包括:
- 异步访问:IndexedDB 的读写操作是异步进行的,不会阻塞主线程,从而提高了页面的性能。
- 支持事务:IndexedDB 支持事务,可以确保数据的一致性和完整性。
- 支持索引:IndexedDB 支持多个索引,可以提高数据的查询效率。
- 可存储大量数据:IndexedDB 可以存储大量的结构化数据,不会受到存储容量的限制。
- 支持离线应用:IndexedDB 可以使得应用在离线状态下也能够正常工作,从而提高用户体验。
HTML5 PWA & AMP
PWA(Progressive Web Apps):PWA 是一种 Web 应用程序的开发方式,旨在提供类似于原生应用程序的用户体验。它使用 Web 技术开发,可以在任何设备上运行,包括桌面、移动设备和平板电脑。PWA 具有以下特点:
- 可靠性:PWA 可以离线使用,并且具有快速的加载速度。
- 响应式设计:PWA 能够自适应不同的设备和屏幕尺寸。
- 安全性:PWA 使用 HTTPS 进行通信,确保用户的数据和隐私得到保护。
- 独立性:PWA 可以添加到设备的主屏幕上,就像原生应用程序一样。
AMP(Accelerated Mobile Pages):AMP 是一种 Web 页面的开发方式,旨在提供快速的加载速度和优化的移动体验。它使用精简的 HTML 和 CSS,以及 AMP JavaScript 库来实现。AMP 具有以下特点:
- 快速加载:AMP 页面能够快速加载,提供更好的用户体验。
- 移动友好:AMP 页面被设计为移动优先,适应各种屏幕尺寸。
- 安全性:AMP 页面使用 AMP CDN 来缓存页面,并使用 HTTPS 进行通信。
- 限制性:AMP 页面不能包含一些复杂的功能和 JavaScript 库,以确保页面的速度和可靠性。
HTML5 Audio
// 创建音频上下文
const audioCtx = new AudioContext();
// 创建正弦振荡器
const oscillator = audioCtx.createOscillator();
oscillator.type = 'sine'; // 正弦波
oscillator.frequency.value = 440; // 设置频率为 440Hz
// 创建音量增幅器
const gainNode = audioCtx.createGain();
gainNode.gain.value = 0.5; // 设置增益为 0.5
// 正弦振荡器关联音量增幅器
oscillator.connect(gainNode);
// 音量增幅器关联音频上下文的音频输出器
gainNode.connect(audioCtx.destination);
// 开始振荡
oscillator.start();
HTML5 Video
实现了创建一个媒体源,将该媒体源与一个 video 元素关联,为该媒体源添加媒体数据,并开始播放该视频的功能
// 创建媒体源
const mediaSource = new MediaSource();
// 创建 video 元素
const video = document.createElement('video');
// 将 video 元素与媒体源关联
video.src = URL.createObjectURL(mediaSource);
// 为媒体源添加媒体数据
const sourceBuffer = mediaSource.addSourceBuffer('video/mp4; codecs="avc1.42E01E, mp4a.40.2"');
fetch('video.mp4')
.then(response => response.arrayBuffer())
.then(buffer => sourceBuffer.appendBuffer(buffer));
// 开始播放视频
video.play();
HTML5 二进制
实现了一个函数
loadAsText()
,用于从本地文件读取数据,并将其转换为不同的格式输出
function loadAsText(file) {
// 创建一个 FileReader 对象
const reader = new FileReader();
// 设置加载完成事件处理程序
reader.onload = function(loadedEvent) {
// 输出读取到的文件内容
console.log(loadedEvent.target.result);
}
// 以文本字符串格式读取文件内容
reader.readAsText(file);
// 以二进制数组格式读取文件内容
reader.readAsArrayBuffer(file);
// 以DataURL格式字符串读取文件内容
reader.readAsDataURL(file);
}
HTML5 API(简略)
GeoLocation API 示例
使用
navigator.geolocation.getCurrentPosition()
方法获取当前设备的地理位置信息。当该方法调用成功时,将执行position
回调函数,传入一个position
对象,该对象包含了当前位置的经纬度信息。我们可以从position.coords.latitude
和position.coords.longitude
属性中获取当前位置的纬度和经度,并输出到控制台中。如果获取当前位置信息失败,将执行
error
回调函数,传入一个error
对象,该对象包含了错误信息。我们可以从error.message
属性中获取错误消息,并输出到控制台中
// 获取当前位置的经纬度信息
navigator.geolocation.getCurrentPosition(position => {
const latitude = position.coords.latitude;
const longitude = position.coords.longitude;
console.log(`当前位置:纬度 ${latitude},经度 ${longitude}`);
}, error => {
console.error(error.message);
});
Drag and Drop API 示例
首先,我们为拖拽源元素
dragSource
添加dragstart
事件处理程序。在该处理程序中,我们使用event.dataTransfer.setData()
方法设置拖拽数据,该方法接受两个参数:数据类型和数据内容。我们将数据类型设置为'text/plain'
,数据内容设置为'Hello, World!'
。然后,我们设置拖拽效果为'copy'
。接着,我们为拖放目标元素
dropTarget
添加dragover
和drop
事件处理程序。在dragover
处理程序中,我们首先阻止默认行为,允许元素被拖放到此处。然后,我们设置拖放效果为'copy'
。在drop
处理程序中,我们同样阻止默认行为,防止浏览器打开拖放的文件
// 为拖拽源元素添加拖拽事件处理程序
const dragSource = document.getElementById('dragSource');
dragSource.addEventListener('dragstart', event => {
// 设置拖拽数据
event.dataTransfer.setData('text/plain', 'Hello, World!');
// 设置拖拽效果
event.dataTransfer.effectAllowed = 'copy';
});
// 为拖放目标元素添加拖放事件处理程序
const dropTarget = document.getElementById('dropTarget');
dropTarget.addEventListener('dragover', event => {
// 阻止默认行为,允许元素被拖放到此处
event.preventDefault();
// 设置拖放效果
event.dataTransfer.dropEffect = 'copy';
});
dropTarget.addEventListener('drop', event => {
// 阻止默认行为,防止浏览器打开拖放的文件
event.preventDefault();
// 读取拖拽数据
const data = event.dataTransfer.getData('text/plain');
// 将拖拽数据输出到控制台中
console.log(data);
});
HTML5 Web Worker
HTML5 Web Socket
Web Socket 是一种在 Web 应用程序中实现实时通信的协议。它提供了一种双向通信机制,允许客户端和服务器之间进行实时的数据传输。与传统的 HTTP 请求/响应模式不同,Web Socket 采用了一种持久化的连接,可以在客户端和服务器之间保持通信通道,从而实现实时通信的功能。
Web Socket 协议基于 TCP 协议实现,使用了类似 HTTP 协议的握手过程来建立连接。客户端和服务器之间的通信采用帧(Frame)的形式进行,每个帧包含一个标识、一些附加信息和一段数据。客户端和服务器可以通过发送不同类型的帧来实现不同的功能,比如文本消息、二进制数据、ping-pong 等。
Web Socket 协议可以与任何支持该协议的服务器进行通信,包括自己开发的服务器和第三方提供的服务。它通常被用于实现实时聊天室、实时游戏、实时协作等应用场景。由于其实时性和高效性,越来越多的 Web 应用程序开始采用 Web Socket 技术来实现实时通信的功能
// 创建 Web Socket 连接
const socket = new WebSocket('ws://localhost:8080');
// 当连接打开时,发送一条消息到服务器
socket.addEventListener('open', event => {
socket.send('Hello, Server!');
});
// 当收到服务器发送的消息时,输出到控制台中
socket.addEventListener('message', event => {
console.log(`Received message from server: ${event.data}`);
});
// 当连接关闭时,输出一条消息到控制台中
socket.addEventListener('close', event => {
console.log('Web Socket connection closed');
});
// 当连接发生错误时,输出错误消息到控制台中
socket.addEventListener('error', event => {
console.error(`Web Socket error: ${event.message}`);
});
HTML5 Shadow DOM
Shadow DOM 是 Web Components 技术中的一部分,用于实现 Web 页面上的组件化开发。它允许开发者将 HTML、CSS 和 JavaScript 封装到一个独立的、可重用的组件中,以便在不同的页面和应用程序中进行复用。
Shadow DOM 通过创建一个“影子树”来实现组件的封装和隔离。在一个 Shadow DOM 中,组件的 HTML 结构、CSS 样式和 JavaScript 行为都被包裹在一个独立的命名空间中,与外部页面的 HTML、CSS 和 JavaScript 不会互相干扰。这种隔离性使得组件可以在不同的页面和应用程序中进行复用,而不用担心样式和行为的冲突。
使用 Shadow DOM 可以创建一些高度可定制化的组件,比如自定义的表单控件、交互式组件等。Shadow DOM 还提供了一些 API,可以让开发者更加方便地控制组件的行为和样式。比如,可以使用 JavaScript 修改组件内部的 DOM 结构、监听组件内部的事件、控制组件内部的样式等。
HTML5 Web Component
HTML5 的 Web Component 是一种基于标准 Web 技术实现的组件化开发模型,它由三个技术规范组成:Custom Elements、Shadow DOM 和 HTML Templates。
Custom Elements 允许开发者自定义 HTML 元素,可以通过 JavaScript API 来创建、注册和使用自定义元素。这样,开发者就可以将多个 HTML 元素封装为一个独立的组件,并在 Web 页面中进行复用。Custom Elements 还提供了一些生命周期方法和事件,可以让开发者控制自定义元素的创建和销毁过程。
Shadow DOM 允许开发者创建一个独立的、封装的 DOM 树,用于包含和隔离组件内部的 HTML 结构、CSS 样式和 JavaScript 行为。这样,开发者就可以将组件内部的实现细节隐藏起来,避免与外部页面的 HTML、CSS 和 JavaScript 冲突。Shadow DOM 还提供了一些 API,可以让开发者更加方便地控制组件内部的样式和行为。
HTML Templates 允许开发者将 HTML 片段封装为一个可重用的模板,并在 Web 页面中进行复用。HTML Templates 还支持使用 JavaScript API 来动态生成和填充模板内容,以适应不同的使用场景。
代码示例
<!-- 定义一个自定义元素 my-button,使用 Shadow DOM 封装组件内部的样式和行为 -->
<template id="my-button-template">
<style>
button {
background-color: #007bff;
color: white;
border: none;
border-radius: 3px;
padding: 10px 20px;
font-size: 16px;
cursor: pointer;
}
button:hover {
background-color: #0069d9;
}
</style>
<button>Click me!</button>
</template>
<!-- 在页面中使用自定义元素 my-button -->
<my-button></my-button>
// 定义一个 MyButton 类,继承自 HTMLButtonElement,用于创建自定义元素
class MyButton extends HTMLButtonElement {
constructor() {
super();
// 创建 Shadow DOM,并将模板内容插入其中
const shadow = this.attachShadow({ mode: 'open' });
const template = document.getElementById('my-button-template');
const clone = template.content.cloneNode(true);
shadow.appendChild(clone);
// 绑定按钮的点击事件
const button = shadow.querySelector('button');
button.addEventListener('click', () => {
console.log('Button clicked!');
});
}
}
// 将 MyButton 注册为自定义元素
customElements.define('my-button', MyButton, { extends: 'button' });
HTML5 SVG & Canvas
WebGL & WebGPU
WebGL 是一种在浏览器中呈现 3D 和 2D 图形的 JavaScript API,它是基于 OpenGL ES 2.0 的标准,支持硬件加速,并可与 HTML、CSS 和 JavaScript 无缝集成。使用 WebGL,开发者可以在浏览器中创建高性能的 3D 游戏、可视化工具和数据展示应用等。
WebGPU 是一个新的 Web 标准,旨在为 Web 平台提供低级别、跨平台的图形和计算 API,支持使用现代硬件的强大功能。WebGPU 由 Khronos Group 开发,它是 Metal、Vulkan 和 DirectX 12 的 Web 版本,支持多线程和多 GPU,并可以在 WebAssembly 上运行。WebGPU 的目标是为 Web 开发者提供更高效、更灵活的图形和计算功能,从而打造更加丰富和复杂的 Web 应用。
地址:Some Amazing Demo:davidwalsh.name/webgl-demo
PS:确实特别的震撼,可以通过这里的链接跳转过去看一看
HTML5 WebAssembly
WebAssembly(WASM)是一种新的编码方式,可以直接在浏览器中运行
WebAssembly(简称为 wasm)是一种新型的虚拟机技术,是一种由 W3C、Mozilla 和其他浏览器厂商共同推出的新 Web 标准。WebAssembly 可以将高性能的 C、C++、Rust 等语言的代码编译成二进制格式,在浏览器中运行,从而提供了比 JavaScript 更高的性能和更好的可移植性。
WebAssembly 具有许多优点,比如:
- 高性能:WebAssembly 的代码可以直接在浏览器中运行,可以比 JavaScript 更高效地利用硬件资源。
- 跨平台:WebAssembly 的二进制格式是跨平台的,可以在任何支持 WebAssembly 的平台上运行,包括浏览器、移动设备、IoT 设备等。
- 安全性:WebAssembly 的代码运行在沙箱环境中,不会对浏览器和计算机造成安全风险。
- 可扩展性:WebAssembly 可以与 JavaScript 无缝集成,并且可以与浏览器中的其他 Web 技术一起使用,比如 Canvas、WebGL 等。
HTML5 支持 WebAssembly 技术,并且可以通过 JavaScript 脚本来调用 WebAssembly 的函数,实现更高效、更复杂的 Web 应用程序。WebAssembly 技术在 Web 游戏、图像和音频处理、虚拟现实和人工智能等方面具有广泛的应用前景。
拓展分享
Web的风靡
大前端
MVC & MVVM & MVP
MVC、MVVM 和 MVP 是三种常见的前端架构设计模式。
MVC 是 Model-View-Controller(模型-视图-控制器)的缩写。它是一种分层设计模式,通过将应用程序分为三个组件:模型(Model)、视图(View)和控制器(Controller),实现了应用程序逻辑和界面之间的分离。模型表示应用程序的数据和业务逻辑,视图表示用户界面,控制器负责协调模型和视图之间的通信。
MVVM 是 Model-View-ViewModel(模型-视图-视图模型)的缩写。它是一种基于数据绑定的设计模式,通过将应用程序分为三个组件:模型(Model)、视图(View)和视图模型(ViewModel),实现了数据的双向绑定。模型表示应用程序的数据和业务逻辑,视图表示用户界面,视图模型负责将模型数据绑定到视图上,并处理用户输入的数据。
MVP 是 Model-View-Presenter(模型-视图-表示器)的缩写。它是一种基于事件驱动的设计模式,通过将应用程序分为三个组件:模型(Model)、视图(View)和表示器(Presenter),实现了应用程序逻辑和界面之间的分离。模型表示应用程序的数据和业务逻辑,视图表示用户界面,表示器负责协调模型和视图之间的通信,并响应用户的事件。