刘述新的博客


  • Home

  • Categories

  • Archives

  • Tags

  • About

Webkit架构和模块

Posted on 2020-06-23 | In 浏览器原理

HTML网页和结构

Posted on 2020-06-16 | In 浏览器原理

网页构成

网页结构

框结构

frame,frameset,iframe,可以用来在当前网页中嵌入新的框

层次结构

网页中的层次结构指,网页中的元素可能分布在不同的层次中,
对于需要复杂变换和处理的元素,他们需要新层,所以,Webkit 为他们构建新层,其实是为了渲染引擎在处理上的方便和高效
但是对于不同的渲染引擎,他们的策略可能不一样,哪怕是同一渲染引擎不同浏览器分层策略也有可能不一样,后续我们会拿 Chromium 上来讲解

Webkit 的网页渲染过程

浏览器的主要作用就是将用户输入的 URL,转变成可视化的图像,这其中包含两个过程

  • 网页加载过程:从 URL 到构建 DOM 树
  • 网页渲染过程:从 DOM 树到页面图像

这两个过程也会交叉,所以很难给予明确的区分,

Webkit 的渲染过程

根据数据的流向,这里将渲染过程分成三个阶段

  1. 从网页的 URL 到构建完 DOM 树
  2. 从 DOM 树 到构建完 Webkit 的绘图上下文
  3. 从绘图上下文到生成最终的图像

一、从网页 URL 到 DOM 树

涉及两个事件:(对应 Performance 中两条竖线)

  • DOMContentLoaded(DOM 已经创建完成)
  • onLoad (资源都加载完成)

二、Webkit 利用 CSS 和 DOM 树构建 RenderObject 树直到绘图上下文

三、根据绘图上下文来生成最终的图像

注意:

上面介绍的是一个完整的渲染过程,现代网页很多都是动态的,这意味着在渲染之后,由于网页的动画和用户的交互,浏览器其实一直在不停地重复执行渲染过程

HTML5_Draggable

Posted on 2020-06-09 | In HTML5

拖拽

HTML 拖放(Drag and Drop)接口使应用程序能够在浏览器中使用拖放功能。例如,用户可使用鼠标选择可拖动(draggable)元素,将元素拖动到可放置(droppable)元素,并释放鼠标按钮以放置这些元素。拖动操作期间,可拖动元素会有一个半透明表示跟随着鼠标指针

拖拽事件

HTML 的 drag & drop 使用了 DOM event model 以及从 mouse events 继承而来的 drag events 。一个典型的拖拽操作开始于用户选中一个可拖动的(draggable)元素,并将其拖动(鼠标不放开)到一个可放置的(droppable)元素,然后释放鼠标。

接口

HTML 的拖拽接口有 DragEvent, DataTransfer, DataTransferItem 和 DataTransferItemList

DataTransfer

DataTransfer 对象用于保存拖动并放下(drag and drop)过程中的数据。它可以保存一项或多项数据,这些数据项可以是一种或者多种数据类型。关于拖放的更多信息
这个对象可以从所有拖动事件 drag events 的 dataTransfer 属性上获取。

基础

确定什么是可拖动的

让一个元素被拖动需要添加 draggable 属性,再加上全局事件处理函数 ondragstart,如下面的示例代码所示

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<script>
function dragstart_handler(ev) {
// Add the target element's id to the data transfer object
ev.dataTransfer.setData("text/plain", ev.target.id);
}

window.addEventListener("DOMContentLoaded", () => {
// Get the element by id
const element = document.getElementById("p1");
// Add the ondragstart event listener
element.addEventListener("dragstart", dragstart_handler);
});
</script>

<p id="p1" draggable="true">This element is draggable.</p>

定义拖动数据

应用程序可以在拖动操作中包含任意数量的数据项。每个数据项都是一个 string 类型,典型的 MIME 类型,如:text/html

每个 drag event 都有一个 dataTransfer 属性,其中保存着事件的数据。这个属性(DataTransfer 对象)也有管理拖动数据的方法。setData() 方法为拖拽数据添加一个项,如下面的示例代码所示:

1
2
3
4
5
6
7
8
9
function dragstart_handler(ev) {
// 添加拖拽数据
ev.dataTransfer.setData("text/plain", ev.target.innerText);
ev.dataTransfer.setData("text/html", ev.target.outerHTML);
ev.dataTransfer.setData(
"text/uri-list",
ev.target.ownerDocument.location.href
);
}

定义拖动图像

拖动过程中,浏览器会在鼠标旁显示一张默认图片。当然,应用程序也可以通过 setDragImage() 方法自定义一张图片,如下面的例子所示

1
2
3
4
5
6
7
8
function dragstart_handler(ev) {
// Create an image and then use it for the drag image.
// NOTE: change "example.gif" to a real image URL or the image
// will not be created and the default drag image will be used.
var img = new Image();
img.src = "example.gif";
ev.dataTransfer.setDragImage(img, 10, 10);
}

定义拖动效果

dropEffect 属性用来控制拖放操作中用户给予的反馈。它会影响到拖动过程中浏览器显示的鼠标样式。比如,当用户悬停在目标元素上的时候,浏览器鼠标也许要反映拖放操作的类型

  1. copy 表明被拖动的数据将从它原本的位置拷贝到目标的位置。
  2. move 表明被拖动的数据将被移动。
  3. link 表明在拖动源位置和目标位置之间将会创建一些关系表格或是连接。
1
2
3
function dragstart_handler(ev) {
ev.dataTransfer.dropEffect = "copy";
}

定义一个放置区

当拖动一个项目到 HTML 元素中时,浏览器默认不会有任何响应。想要让一个元素变成可释放区域,该元素必须设置 ondragover 和 ondrop 事件处理程序属性,下面的例子通过简单的事件处理展示了如何使用这些属性:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<script>
function dragover_handler(ev) {
ev.preventDefault();
ev.dataTransfer.dropEffect = "move";
}
function drop_handler(ev) {
ev.preventDefault();
// Get the id of the target and add the moved element to the target's DOM
var data = ev.dataTransfer.getData("text/plain");
ev.target.appendChild(document.getElementById(data));
}
</script>

<p
id="target"
ondrop="drop_handler(event)"
ondragover="dragover_handler(event)"
>
Drop Zone
</p>

处理放置效果

drop 事件的处理程序是以程序指定的方法处理拖动数据。一般,程序调用 getData() 方法取出拖动项目并按一定方式处理。程序意义根据 dropEffect 的值与/或可变更关键字的状态而不同

下面的例子展示了一个处理程序,从拖动数据中获取事件源元素的 id 然后根据 id 移动源元素到目标元素:

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
<script>
function dragstart_handler(ev) {
// Add the target element's id to the data transfer object
ev.dataTransfer.setData("application/my-app", ev.target.id);
ev.dataTransfer.dropEffect = "move";
}
function dragover_handler(ev) {
ev.preventDefault();
ev.dataTransfer.dropEffect = "move";
}
function drop_handler(ev) {
ev.preventDefault();
// Get the id of the target and add the moved element to the target's DOM
var data = ev.dataTransfer.getData("application/my-app");
ev.target.appendChild(document.getElementById(data));
}
</script>

<p id="p1" draggable="true" ondragstart="dragstart_handler(event)">
This element is draggable.
</p>
<div
id="target"
ondrop="drop_handler(event)"
ondragover="dragover_handler(event)"
>
Drop Zone
</div>

拖动结束

拖动操作结束时,在源元素(开始拖动时的目标元素)上触发 dragend 事件。不管拖动是完成还是被取消这个事件都会被触发。dragend 事件处理程序可以检查 dropEffect 属性的值来确认拖动成功与否

React系列之-事件代理

Posted on 2020-06-04 | In React

事件代理

   React 将事件统一化,使事件在不同浏览器上有一致属性,其内部通过合成事件(SyntheticEvent)的实例传递。如果处于某些原因想使用浏览器原生事件,可以通过 nativeEvent,属性获取。
每个合成事件都有以下属性

  • boolean bubbles
  • boolean cancelable
  • DOMEventTarget currentTarget
  • boolean defaultPrevented
  • Number eventPhase
  • boolean isTrusted
  • DOMEvent nativeEvent
  • void preventDefault()
  • void stopPropagation()
  • DOMEventTarget target
  • Date timeStamp
  • String type

React 支持的事件:
 下面的事件处理程序在事件冒泡阶段被触发,如果要注册事件捕获处理程序,应该使用事件 Capture 事件,所以应该使用 onClickCapture,处理点击事件的捕获阶段,而不是 onClick

Session在Node应用中的使用

Posted on 2020-06-04 | In Node

Cookie在应用中的使用

Posted on 2020-06-04 | In JavaScript

基本概念

  Cookie 是服务器保存在浏览器的一小段文本信息,每个 Cookie 的大小一般不能超过 4KB。浏览器每次向服务器发出请求,就会自动附上这段信息,
浏览器可以设置不接受 Cookie,也可以设置不向服务器发送 Cookie
window.navigator.cookieEnabled 返回一个 Boolean 值表示浏览器是否打开 Cookie 功能。

Cookie 主要用在以下三个方面:

  1. 会话状态管理(如用户登录状态、购物车)
  2. 个性化设置(如用户自定义设置)
  3. 浏览器行为跟踪(如跟踪分析用户行为)

Webpack-Core-Concept

Posted on 2020-06-04 | In webpack

课前小计: webpack 分析工具
webpack-visualizer:https://chrisbateman.github.io/webpack-visualizer/
webpack analyse:http://webpack.github.io/analyse/

Webpack 核心概念

Entry Points

JS-Unbelievable

Posted on 2020-06-04 | In JavaScript

变量提升

   1、将变量声明提升到它所在作用域的最开始的部分
变量提升导致以下输出结果并不是我们认为的那样

1
2
3
4
5
6
7
8
9
10

var tmp = new Date();

function f() {
console.log(tmp);
if (false) {
var tmp = ‘hello world’;
}
}
f();

输出结果 undefined ,惊不惊喜,意不意外。

let 死区

2、我们再看一个例子:

1
2
3
4
5
let a = "hey I am outside";
if (true) {
console.log(a); //Uncaught ReferenceError: a is not defined
let a = "hey I am inside";
}

javascript之-非常规特性

Posted on 2020-06-04 | In JavaScript

1、假值

值 类型
0 Number
NaN(非数值) Number
“” (空字符串) String
false Boolean
null Object
undefined Undefined

javascript之-JSON对象

Posted on 2020-06-04 | In JavaScript

Javascript 对象表示法(JavaScript Object Notation)

  是一种轻量级的数据交换格式,它是基于 JavaScript 对象字面量表示法,虽然它是 javaScript 的一个子集,但它与语言无关,可以在很多语言中进行数据交换。
JSON 有六种类型的值:对象,数组,字符串,数字,布尔(true,false)和特殊值 null.
JSON 字符串包含在一对双引号之间,\ 字符被用于转义

一个 JSON 解析器

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
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
export default function json_parse() {
//这是一个能把JSON 字符串转化为javascript数据结构的函数
//他是一个简单的递归降序的解析器
var at, //当前字符索引
ch, //当前字符
escapee = {
'"': '"',
"\\": "\\",
"/": "/",
b: "b",
f: "\f",
n: "\n",
r: "\r",
t: "\t",
},
text,
//当某处出错时,调用error
error = (m) => {
throw {
name: "SyntaxError",
message: m,
at: at,
text: text,
};
},
next = (c) => {
//如果提供了参数c,那么检测它是否匹配当前字符
if (c && c !== ch) {
error("Expected'" + c + "' instead of '" + ch + "'");
}
//获取下一个字符,当没有下一个字符时返回空字符串
ch = text.charAt(at);
at += 1;
return ch;
},
number = () => {
//解析一个数字值
var number,
string = "";
if (ch === "-") {
string = "-";
next("-");
}
while (ch >= "0" && ch <= "9") {
string += ch;
next();
}
if (ch === ".") {
string += ".";
while (next() && ch >= "0" && ch <= "9") {
string += ch;
}
}
if (ch === "e" || ch === "E") {
string += ch;
next();
if (ch === "-" || ch === "+") {
string += ch;
next();
}
while (ch >= "0" && ch <= "9") {
string += ch;
next();
}
}
number = +string;
if (isNaN(number)) {
error("Bad Number");
} else {
return number;
}
},
string = () => {
var hex, i, string, uffff;
//当解析字符串值时,我们必须找到“和\.
if (ch === '"') {
while (next()) {
if (ch === '"') {
next();
return string;
} else if (ch === "\\") {
next();
if (ch === "u") {
uffff = 0;
for (let i = 0; i < 4; i++) {
hex = parseInt(next(), 16);
if (!isFinate(hex)) {
break;
}
uffff = uffff * 16 + hex;
}
string += String.fromCharCode(uffff);
} else if (typeof escapee[ch] === "string") {
string += escapee[ch];
} else {
break;
}
} else {
string += ch;
}
}
}
error("Bad Strng!");
},
//跳过空白
white = () => {
while (ch && ch <= " ") {
next();
}
},
word = () => {
//true ,false,or null
switch (ch) {
case "t":
next("t");
next("r");
next("u");
next("e");
return true;
case "f":
next("f");
next("a");
next("l");
next("s");
next("e");
return false;
case "n":
next("n");
next("u");
next("l");
next("l");
return null;
}
error("Unexpected '" + ch + "'");
},
value, //值函数的占位符
//解析一个数组值
array = () => {
if (ch === "[") {
next("[");
white();
}
if (ch === "]") {
next("]");
return array; //空数组
}
while (ch) {
array.push(value());
white();
if (ch === "]") {
next("]");
return array;
}
next(",");
white();
}
error("Bad array");
},
object = () => {
var key,
object = {};
if (ch === "{") {
next("{");
white();
if (ch === "}") {
next("}");
return object; //空对象
}
while (ch) {
key = string();
white();
next(":");
object[key] = value();
white();
if (ch === "}") {
next("}");
return object;
}
next(",");
white();
}
}
error("Bad Object");
},
value = () => {
//解析一个JSON值,他可以是对象,数组,字符串,数字或一个词。
white();
switch (ch) {
case "{":
return object();
case "[":
return array();
case '"':
return string();
case "-":
return number();
default:
return ch >= "0" && ch <= "9" ? number() : word();
}
};
return (source, reviver) => {
var result;
text = source;
at = 0;
ch = " ";
result = value();
white();
if (ch) {
error("Syntax error");
}
//如果存在reviver函数,我们就递归的对这个新结构调用walk函数,
//开始时先创建一个临时的启动对象,并以一个空字符串作为键名保存结果,
//然后传递每个”键/值“ 对给reviver函数去处理可能存在的转换,
//如果没有reviver函数,我们就简单的返回这个结果
return typeof reviver === "function"
? (function walk(holder, key) {
var k,
v,
value = holder[key];
if (value && typeof value === "object") {
for (key in value) {
if (Object.hasOwnProperty.call(value, k)) {
v = walk(value, k);
if (v !== undefined) {
value[k] = v;
} else {
delete value[k];
}
}
}
}
return reviver.call(holder, key, value);
})({"": result}, "")
: result;
};
}
12…4

shuxinliu

31 posts
18 categories
26 tags
© 2020 shuxinliu
Powered by Hexo
|
Theme — NexT.Muse v5.1.4