内容简介:记录一些前端常用的基础知识点
记录一些前端常用的基础知识点
技能树
BFC
BFC 定义: BFC(Block formatting context)直译为"块级格式化上下文"。它是一个独立的渲染区域,只有Block-level box参与, 它规定了内部的Block-level Box如何布局,并且与这个区域外部毫不相干。
BFC布局规则:
- 内部的Box会在垂直方向,一个接一个地放置。
- Box垂直方向的距离由margin决定。属于同一个BFC的两个相邻Box的margin会发生重叠
- 每个元素的margin box的左边, 与包含块border box的左边相接触(对于从左往右的格式化,否则相反)。即使存在浮动也是如此。
- BFC的区域不会与float box重叠。
- BFC就是页面上的一个隔离的独立容器,容器里面的子元素不会影响到外面的元素。反之也如此。
- 计算BFC的高度时,浮动元素也参与计算
哪些元素会生成BFC:
- 根元素
- float属性不为none
- position为absolute或fixed
- display为inline-block, table-cell, table-caption, flex, inline-flex
- overflow不为visible
浏览器渲染页面过程
- 用户输入URL地址
- 对URL地址进行DNS域名解析
- 建立TCP连接(三次握手)
- 浏览器发送HTTP请求报文
- 服务器返回HTTP响应报文
- 关闭TCP连接(四次挥手)
- 浏览器解析文档资源并渲染页面
TCP
TCP三次握手
TCP四次挥手
JS单线程运行机制
- 消息队列:消息队列是一个先进先出的队列,它里面存放着各种消息。
- 事件循环:事件循环是指主线程重复从消息队列中取消息、执行的过程。
主线程只会做一件事情,就是从消息队列里面取消息、执行消息,再取消息、再执行。当消息队列为空时,就会等待直到消息队列变成非空。而且主线程只有在将当前的消息执行完成后,才会去取下一个消息。这种机制就叫做事件循环机制,取一个消息并执行的过程叫做一次循环。消息就是注册异步任务时添加的回调函数。
事件循环
macroTask(宏任务): 主代码块, setTimeout, setInterval, setImmediate, requestAnimationFrame, I/O, UI rendering
microTask(微任务): process.nextTick, Promise, Object.observe, MutationObserver
事件
事件流
- 事件捕获阶段
- 处于目标阶段
- 事件冒泡阶段
事件委托
不在事件的发生地(直接dom)上设置监听函数,而是在其父元素上设置监听函数,通过事件冒泡,父元素可以监听到子元素上事件的触发,通过判断事件发生元素DOM的类型,来做出不同的响应。
举例:最经典的就是ul和li标签的事件监听
HTML
基础标签
<head></head> <meta /> <link rel="stylesheet" href="" /> <title></title> <body></body> <center></center> <section></section> <article></article> <aside></aside> <div></div> <ul></ul> <li></li> <p></p> <h1></h1> ~ <h6></h6> <button></button> <input type="text" /> <a href=""></a> <span></span> <strong></strong> <i></i>
CSS
CSS 样式
优先级: 行内样式 > 链接式 > 内嵌式 > @import 导入式
选择器
/* 选择所有元素 */
* {
}
/* 选择 div 元素 */
div {
}
/* 选择类名元素 */
.class {
}
/* 选择 id 元素 */
#id {
}
/* 选择 div 元素内的所有 p 元素 */
div p {
}
/* 选择 div 元素内下一层级的 p 元素 */
div > p {
}
css选择器权重: !important -> 行内样式 -> #id -> .class -> 元素和伪元素 -> * -> 继承 -> 默认
文本溢出
// 文本溢出单行显示
.single {
overflow: hidden;
text-overflow:ellipsis;
white-space: nowrap;
}
// 文本溢出多行显示
.multiple {
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 3;
overflow: hidden;
}
CSS3 新特性
- transition:过渡
- transform:旋转、缩放、移动或者倾斜
- animation:动画
- gradient:渐变
- shadow:阴影
- border-radius:圆角
Javascript
原型与原型链
- 实例的 proto 属性(原型)等于其构造函数的 prototype 属性。
- Object.proto === Function.prototype
- Function.prototype.proto === Object.prototype
- Object.prototype.proto === null
继承实现
function extend(child, parent) {
var F = function() {}; // 空函数为中介,减少实例时占用的内存
F.prototype = parent.prototype; // f继承parent原型
child.prototype = new F(); // 实例化f,child继承,child、parent原型互不影响
child.prototype.constructor = child; // child构造函数指会自身,保证继承统一
child.super = parent.prototype; // 新增属性指向父类,保证子类继承完备
}
深拷贝
function deepCopy(s, t) {
t = t || (Object.prototype.toString.call(t) === "[object Array]" ? [] : {});
for (var i in s) {
if (typeof s[i] === "object") {
t[i] = deepCopy(s[i], t[i]);
} else {
t[i] = s[i];
}
}
return t;
}
Ajax
var ajax = {};
ajax.get = function(url, fn) {
var xhr = new XMLHttpRequest();
xhr.open("GET", url, true);
xhr.onreadystatechange = function() {
if (
xhr.readyState === 4 &&
(xhr.status === 200 || xhr.status === 403)
) {
fn.call(this, xhr.responseText);
}
};
xhr.send();
};
ajax.post = function(url, data, fn) {
var xhr = new XMLHttpRequest();
xhr.open("POST", url, true);
xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
xhr.onreadystatechange = function() {
if (
xhr.readyState === 4 &&
(xhr.status === 200 || xhr.status === 403)
) {
fn.call(this, xhr.responseText);
}
};
xhr.send(data);
};
格式化日期
function formatDate(date, format) {
if (arguments.length === 0) return null;
format = format || "{y}-{m}-{d} {h}:{i}:{s}";
if (typeof date !== "object") {
if ((date + "").length === 10) date = parseInt(date) * 1000;
date = new Date(date);
}
const dateObj = {
y: date.getFullYear(),
m: date.getMonth() + 1,
d: date.getDate(),
h: date.getHours(),
i: date.getMinutes(),
s: date.getSeconds(),
a: date.getDay()
};
const dayArr = ["一", "二", "三", "四", "五", "六", "日"];
const str = format.replace(/{(y|m|d|h|i|s|a)+}/g, (match, key) => {
let value = dateObj[key];
if (key === "a") return dayArr[value - 1];
if (value < 10) {
value = "0" + value;
}
return value || 0;
});
return str;
}
new 实现
function New(Class) {
let obj = {};
obj.__proto__ = Class.prototype;
let res = Class.call(obj);
return typeof res === 'object' ? res : obj;
}
call 实现
Function.prototype.callfb = function (ctx) {
if (typeof this !== 'function') {
throw new Error('Function undefined');
}
ctx = ctx || window;
const fn = ctx.fn;
ctx.fn = this;
const args = [...arguments].slice(1);
const res = ctx.fn(...args);
ctx.fn = fn;
return res;
}
apply 实现
Function.prototype.applyFb = function (ctx) {
if (typeof this !== 'function') {
throw new Error('Function undefined');
}
ctx = ctx || window;
const fn = ctx.fn;
ctx.fn = this;
const arg = arguments[1];
const res = Array.isArray(arg) ? ctx.fn(...arg) : ctx.fn();
ctx.fn = fn;
return res;
}
bind 实现
Function.prototype.bindFb = function (ctx) {
const fn = this;
const args = [...arguments].slice(1);
const F = function () {};
const fBind = function () {
return fn.apply(this instanceof fBind ? this : ctx, args.concat(...arguments))
}
if (fn.prototype) {
F.prototype = fn.prototype;
}
fBind.prototype = new F();
return fBind;
}
instanceof 实现
function instanceofFb(left, right) {
let proto, prototype = right.prototype;
proto = left.__proto__;
while (proto) {
if (proto === prototype) {
return true;
}
proto = proto.__proto__;
}
return false;
}
Promise 实现
function promiseFb(fn) {
const _this = this;
this.state = 'pending'; // 初始状态为pending
this.value = null;
this.resolvedCallbacks = []; // 这两个变量用于保存then中的回调,因为执行完Promise时状态可能还是pending
this.rejectedCallbacks = []; // 此时需要吧then中的回调保存起来方便状态改变时调用
function resolve(value) {
if (_this.state === 'pending') {
_this.state = 'resolved';
_this.value = value;
_this.resolvedCallbacks.map(cb => { cb(value) }); // 遍历数组,执行之前保存的then的回调函数
}
}
function reject(value) {
if (_this.state === 'pending') {
_this.state = 'rejected';
_this.value = value;
_this.rejectedCallbacks.map(cb => { cb(value) });
}
}
try {
fn(resolve, reject);
} catch (e) {
reject(e);
}
}
promiseFb.prototype.then = function (onFulfilled, onRejected) {
// 因为then的两个参数均为可选参数,
// 所以判断参数类型本身是否为函数,如果不是,则需要给一个默认函数如下(方便then不传参数时可以透传)
// 类似这样: Promise.resolve(4).then().then((value) => console.log(value))
onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : fn => fn;
onRejected = typeof onRejected === 'function' ? onRejected : e => { throw e };
switch (this.state) {
case 'pending':
// 若执行then时仍为pending状态时,添加函数到对应的函数数组
this.resolvedCallbacks.push(onFulfilled);
this.rejectedCallbacks.push(onRejected);
break;
case 'resolved':
onFulfilled(this.value);
break;
case 'rejected':
onRejected(this.value);
break;
default: break;
}
}
debounce 防抖
function debounce(fn, wait, immediate) {
let timer;
return function () {
if (immediate) {
fn.apply(this, arguments);
}
if (timer) clearTimeout(timer);
timer = setTimeout(() => {
fn.apply(this, arguments);
}, wait)
}
}
throttle 节流
function throttle(fn, wait) {
let prev = new Date();
return function () {
const now = new Date();
if (now - prev > wait) {
fn.apply(this, arguments);
prev = now;
}
}
}
双向绑定
双向绑定:视图(View)的变化能实时让数据模型(Model)发生变化,而数据的变化也能实时更新到视图层.
Object.defineProperty
<!DOCTYPE html>
<html lang="en">
<head>
<title>mvvm</title>
</head>
<body>
<p>数据值:<span id="data"></span></p>
<p><input type="text" onkeyup="keyup()"></p>
<script>
var obj = {
data: ''
}
function keyup(e) {
e = e || window.event;
obj.data = e.target.value; // 更新数据值
}
Object.defineProperty(obj, 'data', {
get: function () {
return this.data;
},
set: function (newVal) {
document.getElementById('data').innerText = newVal; // 更新视图值
}
})
</script>
</body>
</html>
Proxy
<!DOCTYPE html>
<html lang="en">
<head>
<title>mvvm</title>
</head>
<body>
<p>数据值:<span id="data"></span></p>
<p><input type="text" onkeyup="keyup()"></p>
<script>
var obj = new Proxy({}, {
get: function (target, key, receiver) {
return Reflect.get(target, key, receiver);
},
set: function (target, key, value, receiver) {
if (key === 'data') {
document.getElementById('data').innerText = value; // 更新视图值
}
return Reflect.set(target, key, value, receiver);
}
})
function keyup(e) {
e = e || window.event;
obj.data = e.target.value; // 更新数据值
}
</script>
</body>
</html>
算法
冒泡排序
两两对比
function bubble(arr) {
const len = arr.length;
for (let i = 0; i < len; i++) {
for (let j = 0; j < len - i - 1; j++) {
if (arr[j] > arr[j + 1]) {
let temp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = temp;
}
}
}
return arr;
}
选择排序
寻找最小的数,将索引保存
function selection(arr) {
const len = arr.length;
let minIndex, temp;
for (let i = 0; i < len - 1; i++) {
minIndex = i;
for (let j = i + 1; j < len; j++) {
if (arr[j] < arr[minIndex]) {
minIndex = j;
}
}
temp = arr[i];
arr[i] = arr[minIndex];
arr[minIndex] = temp;
}
return arr;
}
Webpack
常用loader
- file-loader: 加载文件资源,如 字体 / 图片 等,具有移动/复制/命名等功能;
- url-loader: 通常用于加载图片,可以将小图片直接转换为 Date Url,减少请求;
- babel-loader: 加载 js / jsx 文件, 将 ES6 / ES7 代码转换成 ES5,抹平兼容性问题;
- ts-loader: 加载 ts / tsx 文件,编译 TypeScript;
- style-loader: 将 css 代码以<style>标签的形式插入到 html 中;
- css-loader: 分析@import和url(),引用 css 文件与对应的资源;
- postcss-loader: 用于 css 的兼容性处理,具有众多功能,例如 添加前缀,单位转换 等;
- less-loader / sass-loader: css预处理器,在 css 中新增了许多语法,提高了开发效率;
常用plugin
- UglifyJsPlugin: 压缩、混淆代码;
- CommonsChunkPlugin: 代码分割;
- ProvidePlugin: 自动加载模块;
- html-webpack-plugin: 加载 html 文件,并引入 css / js 文件;
- extract-text-webpack-plugin / mini-css-extract-plugin: 抽离样式,生成 css 文件;
- DefinePlugin: 定义全局变量;
- optimize-css-assets-webpack-plugin: CSS 代码去重;
- webpack-bundle-analyzer: 代码分析;
- compression-webpack-plugin: 使用 gzip 压缩 js 和 css;
- happypack: 使用多进程,加速代码构建;
- EnvironmentPlugin: 定义环境变量;
以上所述就是小编给大家介绍的《前端知识汇总》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!
猜你喜欢:本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Beginning ARKit for iPhone and iPad
Wallace Wang / Apress / 2018-11-5 / USD 39.99
Explore how to use ARKit to create iOS apps and learn the basics of augmented reality while diving into ARKit specific topics. This book reveals how augmented reality allows you to view the screen on ......一起来看看 《Beginning ARKit for iPhone and iPad》 这本书的介绍吧!