updating...

2020-11-21  本文已影响0人  Howie126313

CSS

1、三栏布局问题(左右固定宽度 中间自适应)

flex
<div class="container">
     <div class="left"></div>
     <div class="middle"></div>
     <div class="right"></div>
</div>

.container {
    display: flex;
}

.left, .right {
    width: 200px
}

.middle {
    flex: 1;
}

优点:比较完美 移动端首选;
缺点:不兼容 ie9 及以下;
grid
<div class="container">
     <div class="left"></div>
     <div class="middle"></div>
     <div class="right"></div>
</div>


.container {
    display: grid;
    grid-template-columns: 200px auto 200px;
}

优点:简单强大 解决二维布局问题;
缺点:不兼容 ie9 及以下,很多国产手机浏览器有兼容问题;
float + margin
<div class="container">
     <div class="left"></div>
     <div class="middle"></div>
     <div class="right"></div>
</div>

.container {
    overflow: hidden;
}

.left {
    float:left;
    height:100%;
    width:200px;
}

.right {
    float:right;
    height:100%;
    width:200px;
}

.middle{
    height:100%;
    margin:0 200px;
}

优点:快捷 简单 兼容性较好;
缺点: 有局限性 脱离文档流 需要清除浮动等;

2、CSS 盒模型

margin-area: 外边距区域;
border-area: 边框区域;
padding-area: 内边距区域;
content-area: 内容区域;

标准盒模型和 IE 盒模型:
标准盒模型: box-sizing 值为 content-box 时,在高度和宽度之外绘制内外边距以及边框;
IE盒模型:box-sizing 值为 border-box 时,内边距和边框在已设置的宽高内绘制;


3、BFC

BFC(Block Formatting Context)块级格式化上下文,是 Web 页面中盒模型布局的 CSS 渲染模式,指一个独立的渲染区域或者说是一个隔离的独立容器。

形成条件:

特征:

4、外边距重叠

块的上外边距(margin-top)下外边距(margin-bottom)有时合并(折叠)为单个边距,其大小为单个边距的最大值(或如果它们相等,则仅为其中一个),这种行为称为边距折叠

注意有设定floatposition=absolute的元素不会产生外边距重叠行为。

相关文章:MDN 文档


DOM

1、DOM 事件级别

DOM 0级:

写法:el.οnclick=function(){}
DOM 0事件绑定,给元素的事件行为绑定方法,这些方法都是在当前元素事件行为的冒泡阶段(或者目标阶段)执行的。

DOM 2级

写法:el.addEventListener(event-name, callback, useCapture)
event-name: 事件名称,可以是标准的DOM事件;
callback: 回调函数,当事件触发时,函数会被注入一个参数为当前的事件对象 event;
useCapture: 默认是false,代表事件句柄在冒泡阶段执行;

DOM 3级

写法和DOM2级一致 只是在DOM 2级事件的基础上添加了更多的事件类型
新增事件:


2、事件模型 事件流

事件模型: 捕获和冒泡;
事件流:


3、事件代理

由于在冒泡阶段事件从下而上传播,因此可以将子节点的监听函数放置在父节点上,统一处理子节点的事件。减少内存消耗,提高性能(不需要为每一个子元素绑定事件)。


4、Event 对象

阻止默认行为:

event.preventDefault()

阻止冒泡:
target 和 currentTarget:

currentTarget始终是监听事件者,而target是事件的真正发出者。


5、自定义事件

// 创建事件:
// event 不能传参
let event = new Event('eventName')
// CustomEvent是可以传递参数的
let customEvent = new CustomEvent('eventName',  {})
// 监听事件
/*
*  addEventListener(event, function, useCapture)
*  useCapture 指定事件是否 在捕获或冒泡阶段执行;
*      true - 事件在捕获阶段执行
*      false- 默认,事件在冒泡阶段执行
*/
dom.addEventListener('eventName', function (e) {...}, false)

// 触发事件
dom. dispatchEvent('eventName')


JavaScript

1、JavaScript 单线程

js 作为浏览器脚本语言,其主要用途是与用户互动,以及操作DOM。如果存在多个线程就会有很复杂的同步问题,例如:一个线程在某个DOM节点上添加内容,另一个线程删除了这个节点,这时浏览器应该以哪个线程为准?

2、JavaScript 同步任务与异步任务

由于 js 单线程的特点,每次只能执行单个任务。如果前序任务始终没有结束,后序的任务只能等待,效率较低。所以增加了同步任务和异步任务的区分。

3、Event-Loop 事件轮询:

Javascript 的“线程”有一种机制:在每次调用 JS 引擎时,可以随着时间的推移执行你的程序的多个代码块儿,这称为“事件轮询(Event Loop)。

JavaScript 实现异步的具体方式:

宏任务与微任务

宏任务:

分类:

函数 浏览器 node
I/O
setTimeout
setInterval
setImmediate
requestAnimationFrame

特性:

微任务:

分类:

函数 浏览器 node
process.nextTick
mutionObserver
promise.then/catch/finally

mutionObserver:

经典面试题
console.log(1);

setTimeout(()=>{
    console.log(2);
    new Promise((resolve,reject)=>{
    console.log(3);
    resolve()
}).then(res=>{
    console.log(4);
})
})

new Promise((resolve,reject)=>{
    resolve()
}).then(res=>{
    console.log(5);
}).then(res=>{
    console.log(6);

})

new Promise((resolve,reject)=>{
    console.log(7);
    resolve()
}).then(res=>{
    console.log(8);
}).then(res=>{
    console.log(9);

})

setTimeout(()=>{
    console.log(10);
    new Promise((resolve,reject)=>{
    console.log(11);
    resolve()
}).then(res=>{
    console.log(12);
})
})

console.log(13);

输出结果:
依次 1、7、13、5、8、6、9、2、3、4、10、11、12

4、创建对象:

let obj = { test: a}
function Test () {
    this.test =  a
}
let obj = new Test()
//Object.create()方法创建的对象时,属性是在原型下面的
let obj = Object.creat({test: a})

5、原型链:

原型链和原型对象是js的核心,原型链保证函数或对象中的方法、属性可以让向下传递,js通过原型链才得以实现函数或对象的继承

prototype 和 constructor:

prototype 指向函数的原型对象,只有函数才拥有该属性。
constructor 指向原型对象的构造函数。


_proto_:

每个对象都有 proto,指向了创建该对象的构造函数原型。由于js中是没有类的概念,而为了实现继承,通过 proto 将对象和原型联系起来组成原型链,就可以让对象访问到不属于自己的属性。

Foo、Function 和 Object 都是函数,它们的 proto 都指向 Function.prototype.

原型对象 _proto_都指向了 Object.prototype,js原型链最终指向的是 Object 原型对象。


总结

实例的 _proto_ 指向原型对象的 prototype,实例远行对象的 _proto_ 是 Object 的原型对象(null 除外)


image.png

举例:

<script>
function Person(){
}
function Foo(){
}

//显示改变Foo.prototype指向Person的实例对象(原型继承)

Foo.prototype=new Person()

let a=new Foo()

console.log(a.__proto__===Foo.prototype); //true

console.log(a instanceof Foo);//true

console.log(Foo.prototype.__proto__===Person.prototype);//true

console.log(a instanceof Person);//true

console.log(a instanceof Object);//true

// 这个时候改变Foo.prototype的指向

Foo.prototype={}

// Foo.prototype已经不在a的原型链上面了

console.log(a.__proto__===Foo.prototype);//false

console.log(a instanceof Foo);//false

//Person.prototype依然在a的原型链上面

console.log(a instanceof Person);//true
</script>
function _new(func) {
    // 第一步 创建新对象
    let obj= {};
    // 第二步 空对象的_proto_指向了构造函数的prototype成员对象
    obj.__proto__ = func.prototype;//
    // 一二步合并就相当于 let obj=Object.create(func.prototype)

    // 第三步 使用apply调用构造器函数,属性和方法被添加到 this 引用的对象中
    let result = func.apply(obj);
    if (result && (typeof (result) == "object" || typeof (result) == "function")) {
    // 如果构造函数执行的结果返回的是一个对象,那么返回这个对象
        return result;
    }
    // 如果构造函数返回的不是一个对象,返回创建的新对象
    return obj;
}

5、继承实现:

声明父类:

function Father(name) {
      this.name = name || "father";
      this.sayName = function() {
        console.log(this.name);
      }
      this.color = ["red", "blue"]
}

Father.prototype.age = 18;
Father.prototype.sayAge = function() {
      console.log(this.age)    
}
1) 原型链继承
function Son(name) {
    this.name = name || 'son'
}

Son.prototype = new Father()

优点:

缺点:

2)构造继承:复制父类的实例属性给子类
function Son(name) {
    Father.call(this, '父级需要的参数')
    this.name = name
}

let s = new Son("son");
console.log(s.name); // son
//s.sayAge(); // 抛出错误(无法继承父类原型方法)
 s.sayName(); // son
console.log(s.age); // undefined (无法继承父类原型属性)
console.log(s instanceof Father); // false
console.log(s instanceof Son); // true

优点:

缺点:

3)原型链、构造函数组合继承

使用原型链实现对原型属性和方法的继承,而通过构造函数来实现对实例属性的继承。

function Son(name) {
   // 第一次调用父类构造器 子类实例增加父类实例
    Father.call(this, "我是传给父类的参数");
    this.name = name || "son";
}
// 经过new运算符 第二次调用父类构造器 子类原型也增加了父类实例
Son.prototype = new Father();

let s = new Son("son");
console.log(s.name); // son
s.sayAge(); // 18
s.sayName(); // son
console.log(s.age); // 18
console.log(s instanceof Father); // true
console.log(s instanceof Son); // true
console.log(s.constructor === Father); // true
console.log(s.constructor === Son); // false

优点:

缺点:

4)*寄生组合继承:

通过寄生方式,砍掉父类的实例属性,避免了组合继承生成两份实例的缺点;

function Son (name) {
    let f = Father.call(this, '传递给父级的参数')
    f.name = name || 'son'
}

# 借用Object.create()方法
Son.prototype = Object.create(Father.prototype)
Son.prototype.constructor = Son

# 自己动手创建一个中间类
// (function() {
//   let NoneFun = function() {};
//   NoneFun.prototype = Father.prototype;
//   Son.prototype = new NoneFun();
//   Son.prototype.constructor = Son;
// })();

let s = new Son("son");
console.log(s.name); // son
s.sayAge(); // 18
s.sayName(); // son
console.log(s.age); // 18
console.log(s instanceof Father); // true
console.log(s instanceof Son); // true
console.log(s.constructor === Father); // false
console.log(s.constructor === Son); // true

优点:

缺点:

5)实例继承:为父类实例添加新特征,作为子类实例返回
function Son (name) {
    let f = new Father('传递给父级的参数')
    f.name = name || 'son'
    return f
}

let s = new Son("son"); //或者直接调用子类构造函数 let s = Son("son");
console.log(s.name); // son
s.sayAge(); // 18
s.sayName(); // son
console.log(s.age); // 18
console.log(s instanceof Father); // true
console.log(s instanceof Son); // false
console.log(s.constructor === Father); // true
console.log(s.constructor === Son); // false

优点:

缺点:

6)拷贝继承:对父类实例中的的方法与属性拷贝给子类的原型
function Son (name) {
    let f = new Father('要传给父级的数据')
    for (let k in f) {
        Son.prototype[k] = f[k]
    }
    Son.prototype.name = name
}

let s = new Son("son");
console.log(s.name); // son
s.sayAge(); // 18
s.sayName(); // son
console.log(s.age); // 18
console.log(s instanceof Father); // false
console.log(s instanceof Son); // true
console.log(s.constructor === Father); // false
console.log(s.constructor === Son); // true

优点:

缺点:

7)ES6 Class 继承
class Son extends Father {
constructor(name) {
    super(name);
        this.name = name || "son";
      }
 }

let s = new Son("son");
console.log(s.name); // son
s.sayAge(); // 18
s.sayName(); // son
console.log(s.age); // 18
console.log(s instanceof Father); // true
console.log(s instanceof Son); // true
console.log(s.constructor === Father); // false
console.log(s.constructor === Son); // true

6、节流和防抖

节流:一定时间内执行的操作只执行一次。

应用场景:

function throttle (fn, timer) {
    let canRun = true
    return function () {
        if ( !canRun ) return 
        canRun = false
        setTimeout(() => {
            fn().apply(this, arguments)
            canRun = true
        }, timer)
    }
}
防抖:动作停止后的时间超过设定的时间时执行一次函数。注意:这里的动作停止表示你停止了触发这个函数,从这个时间点开始计算,当间隔时间等于你设定时间,才会执行里面的回调函数。如果你一直在触发这个函数并且两次触发间隔小于设定时间,则函数一直不会执行.

应用场景:

function debance (fn, delayTime) {
    let timer = null
    return function () {
        if (timer) {
            clearTimeout(timer)      
        } 
        timer = setTimeout(() => {
            fn.call(this, arguments)
        },  delayTime)
    }
}

HTTP 相关


框架 Framework

1、SSR 框架的选择, Nuxt、Next、Nest?

Next:性能居中,lighthouse 测试报告中比其他两者低。
优势:

缺点:

Nuxt:性能为三者中最低,lighthouse 测试报告中的大多项都是领先者。
优点:

缺点:

Nest:性能是三者中最好的,lighthouse 测试报告得分较低。
优点:

缺点:

参考文章原文链接

上一篇 下一篇

猜你喜欢

热点阅读