资讯详情

前端面试八股文(超详细)

JavaScript

Promise 是一种异步解决方案,以避免回调地狱 2. Promise 是状态机: pending(进行中),fulfilled(成功)和rejected(已失败) 只有异步操作的结果才能决定目前的状态,任何其他操作都不能改变。

回调地狱

回调函数中嵌套回调函数的情况称为回调地狱。 回调地狱是一种实现代码顺序执行的操作,会导致我们的代码可读性很差,后期维护不好。

一、Promise是什么?

Promise它是社区最早提出和实现的异步编程解决方案,比其他传统解决方案(回调函数和事件)更合理、更强大。

ES6 将其写入语言标准,统一使用,原生提供Promise对象。 ES6 规定,Promise对象是生成构造函数的构造函数Promise实例。

二、Promise解决什么问题?

promise它是为了解决金字塔回调问题的异步处理

三、Promise的两个特点

1、Promise对象的状态不受外界影响

1)pending 初始状态

2)fulfilled 成功状态

3)rejected 失败状态

Promise 有三种状态,只有异步操作的结果才能决定目前的状态,任何其他操作都不能改变这种状态

2、Promise一旦状态发生变化,就不会再发生变化。这个结果可以随时得到。状态不能逆转,只能通过 pending变成fulfilled或者由pending变成rejected

四、Promise的三个缺点

1)无法取消Promise,一旦新建,将立即执行,中途不能取消 2)如果不设置回调函数,Promise内部抛出的错误不会反映在外部 3)当处于pending状态时,无法知道目前进展到哪个阶段,是刚刚开始还是即将完成

五、Promise成功回调序列和失败回调序列存储在哪里?

1)onResolvedCallbacks 成功后要执行的回调序列 是一个数组

2)onRejectedCallbacks 失败后要执行的回调序列 是一个数组

存储在上述两个数组中Promise 在创建实例时给予Promise默认情况下,这中,默认为空数组。 每次实例then的时候 传入 onFulfilled 成功回调 onRejected 如果此时的状态是失败回调pending 则将onFulfilled和onRejected push在相应的成功回调序列数组和失败回调序列数组中,假如此时的状态是fulfilled 则onFulfilled立即执行,假如此时的状态是rejected则onRejected立即执行

执行上述序列中的回调函数时 有序,即按顺序执行

箭头函数与普通函数的区别在于: ,因此,需要通过搜索作用域链来确定this这意味着如果箭头函数包含在非箭头函数中,this绑定是最近一层非箭头函数this, 2.箭头函数没有自己的arguments对象,但可以访问外围函数arguments对象 3、不能通过new关键词调用也没有new.target值和原型

1.语法更简洁、清晰 2.箭头函数不会创建自己this,它只会继承自己作用域链的上层this。 3.箭头函数继承this方向永远不变 4、.call()/.apply()/.bind()箭头函数无法改变this的指向 5.箭头函数不能用作构造函数 6.箭头函数没有自己的arguments,可用于箭头函数rest参数代替arguments访问箭头函数的参数列表 7.箭头函数没有原型prototype 8.箭头函数不能用作Generator不能使用函数yeild关键字 9、箭头函数不具有super,不具有new.target

. ES6新特性

1、let( let 允许创建块级作用域(最近的花括号有效),无变量提升,不允许重复声明: )、const( const 允许创建块级作用域(最接近的花括号内有效),不提升变量声明const 大写变量(默认规则)必须在声明中赋值; )、block作用域

2、箭头函数 ES6 箭头函数是函数的简写形式,使用括号包裹参数跟随 =>,紧接着是函数体:

3.默认函数参数值

ES6 允许您对函数参数设置默认值:

4、对象超类

ES6 允许在对象中使用 super 方法:

5、Map VS WeakMap

ES6 两种新的数据结构集:Map 和 WeakMap。事实上,每个对象都可以被视为一个对象 Map。

一个对象由多个对象组成 key-val 对构成,在 Map 中,任何类型都可以作为对象的 key,如:

6、类

ES6 中有 class 语法。值得注意的是,这里 class 不是新的对象继承模型,只是原型链的语法糖表达形式。

函数中使用 static 构建函数的方法和属性:

. Var let const 的区别

共同点:可以声明变量

不同点:var 在ECMAScript 所有版本都可以使用,const和let只能在ECMAScript6【ES2015年及更晚使用

var

let

const

作用域

函数作用域

块作用域

块作用域

声明提升

不能

不能

重复声明

不能

不能

全局声明为window对象的属性

不是

不是

  • var

    • ECMAScript6 增加了let 和 const 以后尽量少用var。因为let 和 const 声明的变量具有更清晰的作用域、声明位置和不变值。
    • 优先使用const声明变量,只在知道未来会提前修改时使用let。
  • let

    • 因为let作用域是块作用域!
      • 无条件声明
      • for循环使用let声明迭代变量不会导致迭代变量外渗透。
  • const

    • 声明必须直接初始化变量,不能修改const声明的变量值
      • 该限制仅适用于引用其指向的变量。如果它是一个对象,则可以修改对象的内部属性。

. 几种实现继承的方法

  1. 原型链继承

    父类的例子是子类的原型

    function Woman(){  } Woman.prototype= new People(); Woman.prototype.name = 'haixia'; let womanObj = new Woman(); 

    优点:

    简单易实现,可以访问父类的新例子和属性子类

    缺点:

    如果需要新的原型属性和方法,可以在子类中添加实例属性new 父类构造函数背后

    无法实现多继承

    创建子类实例时,参数不能传输到父类构造函数中

  2. 借用结构函数继承(伪造对象、经典继承)

    复制父类的实例属性给子类

    function Woman(name){  //继承了People   People.call(this); //People.call(this,'wangxiaoxia');    this.name = name || 'renbo' } let womanObj = new Woman();  

    优点:

    解决了子类构造函数向父类构造函数中传递参数

    可以实现多继承(call或者apply多个父类)

    缺点:

    方法都在构造函数中定义,无法复用

    不能继承原型属性/方法,只能继承父类的实例属性和方法

  3. 实例继承(原型式继承)

    function Wonman(name){
      let instance = new People();
      instance.name = name || 'wangxiaoxia';
      return instance;
    }
    let wonmanObj = new Wonman();
    

    优点:

    不限制调用方式

    简单,易实现

    缺点:不能多次继承

. Null 和 undefined 的区别

undefined和null的区别:. ● undefined 表示一个变量没有被声明,或者被声明了但没有被赋值(未初始化),一个没有传入实参的形参变量的值为undefined,如果一个函数什么都不返回,则该函数默认返回undefined。. null 则表示"什么都没有",即"空值"。. ● Javascript将未赋值的变量默认值设为 undefined ;Javascript从来不会将变量设为 null 。. 它是用来让程序员表明某个用var声明的变量时没有值的;

. Call bind apply的区别

apply接受两个参数,第一个参数是this的指向,第二个参数是函数接受的参数,,且当第一个参数为null、undefined的时候,默认指向window(在浏览器中),使用apply方法改变this指向后原函数会立即执行,且此方法只是临时改变this指向一次。

call方法

call方法的第一个参数也是this的指向,后面传入的是一个(注意和apply传参的区别)。当一个参数为null或undefined的时候,表示指向window(在浏览器中),和apply一样,call也只是临时改变一次this指向,并立即执行。

bind方法和call很相似,第一参数也是this的指向,后面传入的也是一个参数列表(但是这个参数列表可以分多次传入,call则必须一次性传入所有参数),但是它改变this指向后不会立即执行,而是返回一个永久改变this指向的函数。

8. 前端缓存的理解 或者 前端数据持久化的理解

前端缓存分为HTTP缓存和浏览器缓存

其中HTTP缓存是在HTTP请求传输时用到的缓存,主要在服务器代码上设置;而浏览器缓存则主要由前端开发在前端js上进行设置。

缓存可以说是性能优化中简单高效的一种优化方式了。一个优秀的缓存策略可以缩短网页请求资源的距离,减少延迟,并且由于,还可以减少带宽,降低网络负荷。

对于一个数据请求来说,可以分为发起三个步骤。浏览器缓存可以帮助我们在第一和第三步骤中优化性能。比如说直接使用缓存而不发起请求,或者发起了请求但后端存储的数据和前端一致,那么就没有必要再将数据回传回来,这样就减少了响应数据。

强制缓存就是向浏览器缓存查找该请求结果,并根据该结果的缓存规则来决定是否使用该缓存结果的过程,强制缓存的情况主要有三种,如下:

协商缓存就是强制缓存失效后,浏览器携带缓存标识向服务器发起请求,由服务器根据缓存标识决定是否使用缓存的过程

9. 防抖和节流

防抖(debounce)

非立即执行版的意思是触发事件后函数不会立即执行,而是在 n 秒后执行,如果在 n 秒内又触发了事件,则会重新计算函数执行时间。

立即执行版的意思是触发事件后函数会立即执行,然后 n 秒内不触发事件才能继续执行函数的效果。

节流(throttle)

**所谓节流,就是指连续触发事件但是在 n 秒中只执行一次函数。**节流会稀释函数的执行频率。

对于节流,一般有两种方式可以实现,分别是时间戳版和定时器版

. 闭包

1、变量作用域

要理解闭包,首先要理解 JavasSript 的特殊的变量作用域。

变量的作用域无非就两种:全局变量和局部变量。

JavasSript 语言的特别之处就在于:

**注意点:**在函数内部声明变量的时候,一定要使用 var 命令。如果不用的话,你实际上声明的是一个全局变量!

出于种种原因,我们有时候需要获取到函数内部的局部变量。但是,上面已经说过了,正常情况下,这是办不到的!只有通过变通的方法才能实现。

那就是在函数内部,再定义一个函数。

function f1(){
    var n=999;
    function f2(){
        alert(n); // 999
    }
}

在上面的代码中,函数 f2 就被包括在函数 f1 内部,这时 f1 内部的所有局部变量,对 f2 都是可见的。但是反过来就不行,f2 内部的局部变量,对 f1 就是不可见的。

这就是 JavasSript 语言特有的"链式作用域"结构(chain scope),

子对象会一级一级地向上寻找所有父对象的变量。所以,父对象的所有变量,对子对象都是可见的,反之则不成立。

既然 f2 可以读取 f1 中的局部变量,那么只要把 f2 作为返回值,我们不就可以在 f1 外部读取它的内部变量了吗!

3、闭包的概念

上面代码中的 f2 函数,就是闭包。

各种专业文献的闭包定义都非常抽象,我的理解是:

由于在 JavaScript 中,只有函数内部的子函数才能读取局部变量,所以说,闭包可以简单理解成"定义在一个函数内部的函数"。

所以,

4、闭包的用途

闭包可以用在许多地方。它的最大用处有两个,一个是前面提到的可以读取函数内部的变量,另一个就是让这些变量的值始终保持在内存中,不会在 f1 调用后被自动清除。

为什么会这样呢?原因就在于 f1 是 f2 的父函数,而 f2 被赋给了一个全局变量,这导致 f2 始终在内存中,而 f2 的存在依赖于 f1,因此 f1 也始终在内存中,不会在调用结束后,被垃圾回收机制(garbage collection)回收。

这段代码中另一个值得注意的地方,就是 这一行,首先在 nAdd 前面没有使用 var 关键字,因此 nAdd 是一个全局变量,而不是局部变量。其次,nAdd 的值是一个匿名函数(anonymous function),而这个匿名函数本身也是一个闭包,所以 nAdd 相当于是一个 setter,可以在函数外部对函数内部的局部变量进行操作。

5、使用闭包的注意点

  • (1)由于闭包会使得函数中的变量都被保存在内存中,内存消耗很大,所以不能滥用闭包,否则会造成网页的性能问题,在IE中可能导致内存泄露。解决方法是,在退出函数之前,将不使用的局部变量全部删除。
  • (2)闭包会在父函数外部,改变父函数内部变量的值。所以,如果你把父函数当作对象(object)使用,把闭包当作它的公用方法(Public Method),把内部变量当作它的私有属性(private value),这时一定要小心,不要随便改变父函数内部变量的值

. 数组去重

一、利用ES6 Set去重(ES6中最常用)

function unique (arr) {
  return Array.from(new Set(arr))
}
var arr = [1,1,'true','true',true,true,15,15,false,false, undefined,undefined, null,null, NaN, NaN,'NaN', 0, 0, 'a', 'a',{},{}];
console.log(unique(arr))
 //[1, "true", true, 15, false, undefined, null, NaN, "NaN", 0, "a", {}, {}]

不考虑兼容性,这种去重的方法代码最少。这种方法还无法去掉“{}”空对象,后面的高阶方法会添加去掉重复“{}”的方法。

二、利用for嵌套for,然后splice去重(ES5中最常用)

function unique(arr){            
        for(var i=0; i<arr.length; i++){
            for(var j=i+1; j<arr.length; j++){
                if(arr[i]==arr[j]){         //第一个等同于第二个,splice方法删除第二个
                    arr.splice(j,1);
                    j--;
                }
            }
        }
return arr;
}
var arr = [1,1,'true','true',true,true,15,15,false,false, undefined,undefined, null,null, NaN, NaN,'NaN', 0, 0, 'a', 'a',{},{}];
    console.log(unique(arr))
    //[1, "true", 15, false, undefined, NaN, NaN, "NaN", "a", {…}, {…}]     //NaN和{}没有去重,两个null直接消失了

双层循环,外层循环元素,内层循环时比较值。值相同时,则删去这个值。 想快速学习更多常用的ES6语法,可以看我之前的文章《学习ES6笔记──工作中常用到的ES6语法》。

三、利用indexOf去重

function unique(arr) {
    if (!Array.isArray(arr)) {
        console.log('type error!')
        return
    }
    var array = [];
    for (var i = 0; i < arr.length; i++) {
        if (array .indexOf(arr[i]) === -1) {
            array .push(arr[i])
        }
    }
    return array;
}
var arr = [1,1,'true','true',true,true,15,15,false,false, undefined,undefined, null,null, NaN, NaN,'NaN', 0, 0, 'a', 'a',{},{}];
console.log(unique(arr))
   // [1, "true", true, 15, false, undefined, null, NaN, NaN, "NaN", 0, "a", {…}, {…}]  //NaN、{}没有去重

新建一个空的结果数组,for 循环原数组,判断结果数组是否存在当前元素,如果有相同的值则跳过,不相同则push进数组。

四、利用sort()

function unique(arr) {
    if (!Array.isArray(arr)) {
        console.log('type error!')
        return;
    }
    arr = arr.sort()
    var arrry= [arr[0]];
    for (var i = 1; i < arr.length; i++) {
        if (arr[i] !== arr[i-1]) {
            arrry.push(arr[i]);
        }
    }
    return arrry;
}
     var arr = [1,1,'true','true',true,true,15,15,false,false, undefined,undefined, null,null, NaN, NaN,'NaN', 0, 0, 'a', 'a',{},{}];
        console.log(unique(arr))
// [0, 1, 15, "NaN", NaN, NaN, {…}, {…}, "a", false, null, true, "true", undefined]      //NaN、{}没有去重

利用sort()排序方法,然后根据排序后的结果进行遍历及相邻元素比对。

六、利用includes

function unique(arr) {
    if (!Array.isArray(arr)) {
        console.log('type error!')
        return
    }
    var array =[];
    for(var i = 0; i < arr.length; i++) {
            if( !array.includes( arr[i]) ) {//includes 检测数组是否有某个值
                    array.push(arr[i]);
              }
    }
    return array
}
var arr = [1,1,'true','true',true,true,15,15,false,false, undefined,undefined, null,null, NaN, NaN,'NaN', 0, 0, 'a', 'a',{},{}];
    console.log(unique(arr))
    //[1, "true", true, 15, false, undefined, null, NaN, "NaN", 0, "a", {…}, {…}]     //{}没有去重

七、利用hasOwnProperty

function unique(arr) {
    var obj = {};
    return arr.filter(function(item, index, arr){
        return obj.hasOwnProperty(typeof item + item) ? false : (obj[typeof item + item] = true)
    })
}
    var arr = [1,1,'true','true',true,true,15,15,false,false, undefined,undefined, null,null, NaN, NaN,'NaN', 0, 0, 'a', 'a',{},{}];
        console.log(unique(arr))
//[1, "true", true, 15, false, undefined, null, NaN, "NaN", 0, "a", {…}]   //所有的都去重了

利用hasOwnProperty 判断是否存在对象属性

八、利用filter

function unique(arr) {
  return arr.filter(function(item, index, arr) {
    //当前元素,在原始数组中的第一个索引==当前索引值,否则返回当前元素
    return arr.indexOf(item, 0) === index;
  });
}
    var arr = [1,1,'true','true',true,true,15,15,false,false, undefined,undefined, null,null, NaN, NaN,'NaN', 0, 0, 'a', 'a',{},{}];
        console.log(unique(arr))
//[1, "true", true, 15, false, undefined, null, "NaN", 0, "a", {…}, {…}]

九、利用递归去重

function unique(arr) {
        var array= arr;
        var len = array.length;

    array.sort(function(a,b){   //排序后更加方便去重
        return a - b;
    })

    function loop(index){
        if(index >= 1){
            if(array[index] === array[index-1]){
                array.splice(index,1);
            }
            loop(index - 1);    //递归loop,然后数组去重
        }
    }
    loop(len-1);
    return array;
}
 var arr = [1,1,'true','true',true,true,15,15,false,false, undefined,undefined, null,null, NaN, NaN,'NaN', 0, 0, 'a', 'a',{},{}];
console.log(unique(arr))
//[1, "a", "true", true, 15, false, 1, {…}, null, NaN, NaN, "NaN", 0, "a", {…}, undefined]

十、利用Map数据结构去重

function arrayNonRepeatfy(arr) {
  let map = new Map();
  let array = new Array();  // 数组用于返回结果
  for (let i = 0; i < arr.length; i++) {
    if(map .has(arr[i])) {  // 如果有该key值
      map .set(arr[i], true); 
    } else { 
      map .set(arr[i], false);   // 如果没有该key值
      array .push(arr[i]);
    }
  } 
  return array ;
}
 var arr = [1,1,'true','true',true,true,15,15,false,false, undefined,undefined, null,null, NaN, NaN,'NaN', 0, 0, 'a', 'a',{},{}];
    console.log(unique(arr))
//[1, "a", "true", true, 15, false, 1, {…}, null, NaN, NaN, "NaN", 0, "a", {…}, undefined]

创建一个空Map数据结构,遍历需要去重的数组,把数组的每一个元素作为key存到Map中。由于Map中不会出现相同的key值,所以最终得到的就是去重后的结果

. 深浅拷贝

深拷贝和浅拷贝的示意图大致如下:

img

示意图

. 原型链

简单理解就是原型组成的链,对象的__proto__它的是原型,而原型也是一个对象,也有__proto__属性,原型的__proto__又是原型的原型,就这样可以一直通过__proto__想上找,这就是原型链,当向上找找到Object的原型的时候,这条原型链就算到头了。

通过一个构造函数创建出来的多个实例,如果都要添加一个方法,给每个实例去添加并不是一个明智的选择。这时就该用上原型了。

在实例的原型上添加一个方法,这个原型的所有实例便都有了这个方法。

prototype属性,它是,它是从。它的含义是,也就是这个函数(其实所有函数都可以作为构造函数)所创建的实例的原型对象; 这个属性是一个指针,指向一个对象,这个对象的用途就是包含所有实例共享的属性和方法(我们把这个对象叫做原型对象);

是原型链查询中实际用到的,它总是指向 prototype,换句话说就是指向构造函数的原型对象,它是**对象独有的。**注意,为什么Foo构造也有这个属性呢,因为再js的宇宙里万物皆对象,包括函数

我们看到途中最中间灰色模块有一个constructor属性,这个又是做什么用的呢?** **

每个函数都有一个原型对象,该原型对象有一个constructor属性,指向创建对象的函数本身。

此外,我们还可以使用constructor属性,所有的实例对象都可以访问constructor属性,constructor属性是创建实例对象的函数的引用。我们可以使用constructor属性验证实例的原型类型(与操作符instanceof非常类似)。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-tbxes1Jd-1646559635648)(D:Typora原型链.png)]

. Require 和 import

require和import的区别

1.import在代码编译时被加载,所以必须放在文件开头,require在代码运行时被加载,所以require理论上可以运用在代码的任何地方,所以import性能更好。

2.import引入的对象被修改时,源对象也会被修改,相当于浅拷贝,require引入的对象被修改时,源对象不会被修改,官网称值拷贝,我们可以理解为深拷贝。

3.import有利于tree-shaking(移除JavaScript上下文中未引用的代码),require对tree-shaking不友好。 4.import会触发代码分割(把代码分离到不同的bundle中,然后可以按需加载或者并行加载这些文件),require不会触发。

5.import是es6的一个语法标准,如果要兼容浏览器的话必须转化成es5的语法,require 是 AMD规范引入方式。

目前所有的引擎都还没有实现import,import最终都会被转码为require,在webpack打包中,import和require都会变为_webpack_require_。

CSS

. 常见的块级元素和行内块元素,以及它们有何不同

  1. 块级元素和内联元素的区别: 1.块级元素,宽度默认是它容器的100%,各占据一行,垂直方向排列;内联元素,都是同一行,水平方向排列; 2.块级元素,能容纳其他块元素或者内联元素;内联元素,只能容纳文本或其他内联元素; 3.块级元素中height,line-height以及margin和padding都可以控制;行内元素设置width无效,height无效(可以设置line-height),margin上下无效,padding上下无效

2.行内元素和块级元素有哪些 常见的内联元素: a - 锚点 select - 项目选择 span - 常用内联容器,定义文本内区块 label - 粗体强调 img - 图片 input - 输入框 label - 表格标签 textarea - 多行文本输入框 br - 换行

常见的块级元素 div ul ,li 非排序列表 form - 交互表单 table - 表格 h1 -h6 标题 hr - 水平分隔线 p - 段落 dl -dt-dd - 定义列表 address - 地址 blockquote - 块引用 fieldset - form控制组

. 常见选择器

标签选择器

HTML标签名称作为选择器

//语法
标签名 {
	属性1:属性值1;
	属性2:属性值2;
	属性3:属性值3;
	...
}
类选择器
//语法
.类名 {
	属性1.属性值1;
	属性2.属性值2;
	属性3.属性值3;
	...
}
id选择器
#id名 {
	属性1:属性值1;
	...
}

口诀:样式#定义,结构id调用,只能调用一次,别人切勿使用

通配符选择器

选取页面中所有元素(标签)

* {
	属性名1: 属性名1;
	...
}

CSS的复合选择器

建立在基础选择器之上,对基础选择器进行组合形成的

后代选择器/包含选择器(重要)
<style>
	元素1 元素2 { 样式声明 }
</style>
#元素2只要包含在元素1里面即可,无论是儿子还是孙子
子选择器(重要)

只能选择某元素的最近一级的子元素

元素1>元素2 {样式声明}
并集选择器(重要)

可以选择多组标签为他们定义相同的样式,通常用于集体声明

标签1,标签2 {样式声明}

约定语法规范:并集选择器喜欢竖着写

伪类选择器

可以为某些选择器添加一些特殊的效果

链接伪类选择器
#写的时候按照顺序来
a:link	#选择未被访问的链接
a:visited	#选择所有已经被访问过的链接
a:hover		#选择鼠标指针位于其上的链接
a:active	#选择活动链接(鼠标按下未弹起的链接)
:foucus伪类选择器

用于选取获得焦点的元素

input:foucus {
	background-color: red;
}

. px em 和 rem的区别

一、px是固定的像素,一旦设置了就无法因为适应页面大小而改变。

二、em和rem相对于px更具有灵活性,他们是相对长度单位,意思是长度不是定死了的,更适用于响应式布局。

三、em是相对于其父元素来设置字体大小的,一般都是以的“font-size”为基准。这样就会存在一个问题,进行任何元素设置,都有可能需要知道他父元素的大小。而Rem是相对于根元素,这样就意味着,我们只需要在根元素确定一个参考值

总之:对于em和rem的区别一句话概括:

. 水平垂直居中的几种方法

1 使用flex布局

利用flex的alignItems:center垂直居中,justifycontent:center水平居中

2 利用相对定位和绝对定位的margin:auto

相对定位下,使用绝对定位将上下左右都设置为0,再设置margin:auto即可实现居中

3 利用相对定位和绝对定位,再加上外边距和平移的配合

相对定位下,使用绝对定位,利用margin偏移外容器的50%,再利用translate平移回补自身宽高的50%即可

4 利用textAlignverticalAlign

利用textAlign:center实现行内元素的水平居中,再利用verticalAlign:middle实现行内元素的垂直居中,前提是要先加上伪元素并给设置高度为100%,用过elementUI的可以去看看其消息弹窗居中实现方式就是如此

5 其他

上面都是在未知外容器和自身宽高下实现水平垂直居中的,如果已知其宽高,可以有更多种简单的方式实现居中,其原理无非是利用绝对定位的top/left偏移、margin偏移、padding填充,在此就不分析了。还有就是单纯文字的居中利用lineHeighttextAlign即可实现。

. 盒模型的理解

盒模型包括margin、border、padding、content四个部分,主要的设置属性是margin、border、padding。 盒子模型又分为两种W3C和IE盒子。

W3C的元素宽度=content的宽度 IE的元素宽度=content+padding+border

盒模型就是用来做容器,为了把内容打包和整理,为了不让页面显得杂乱无章。一个好的包装能够给用户不一样地体验。并且如果没有好的包装,再好的内容也不会也看下去的欲望。这就像一个干净整洁的桌面和堆满杂物的桌面给人的观感效果。 所以,合理灵活的应用好盒模型是前端的必要基础!!!

. Flex布局

一、Flex 布局是什么?

Flex 是 Flexible Box 的缩写,意为"弹性布局",用来为盒状模型提供最大的灵活性。

任何一个容器都可以指定为 Flex 布局。

注意,设为 Flex 布局以后,子元素的floatclearvertical-align属性将失效。

二、基本概念

采用 Flex 布局的元素,称为 Flex 容器(flex container),简称"容器"。它的所有子元素自动成为容器成员,称为 Flex 项目(flex item),简称"项目"。

三、容器的属性

以下6个属性设置在容器上。

  • flex-direction
  • flex-wrap
  • flex-flow
  • justify-content
  • align-items
  • align-content

. 怎么解决浮动中塌陷的问题

根据W3C的标准,在页面中元素都有一个隐含的属性 Block Formatting Context,简称BFC,默认是关闭的;

开启元素BFC后,元素将会具有以下特性:

  • 父元素的垂直外边距不会和子元素重叠
  • 开启BFC的元素不会被浮动元素所覆盖
  • 开启BFC的元素可以包含浮动元素

开启BFC的方法:。

** overflow【常见,副作用最小】**

overflow设置为非visible的值。推荐使用hidden(副作用最小)

a) auto (溢出显示滚动条)

b) scroll (默认就显示滚动条)

c) hidden (溢出隐藏)[常用]

注:但在IE6及以下的浏览器中不支持BFC,所以使用这种方式不兼容IE6。在IE6中有类似BFC的隐含属性 hasLayout,开启方式很多,推荐使用zoom:1

br元素本身没有高度,所以也就不会存在IE低版本下最小高度问题。只需要在浮动元素下添加一句 :

可以通过after伪类向元素的最后添加一个空白的块元素,然后对其清除浮动,和第二种方法原理相同,可达到相同的效果,而且不会在页面中添加多余的div,这是最推荐的方式,几乎没有副作用

8. CSS3新特性

CSS3 是 CSS 规范的最新版本,在 CSS2.1 的基础上增加了很多强大的新功能,以帮助开发人员解决一些实际面临的问题,并且不再需要非语义标签、复杂的 JavaScript 脚本以及图片。 例如,CSS3 支持圆角、多背景、透明度、阴影、动画、图表等功能。 CSS1 和 CSS2.1 都是单一的规范,其中 CSS1 主要定义了网页对象的基本样式,如字体、颜色、背景、边框等,CSS2 添加了高级概念,如浮动、定位、高级选择器(如子选择器、相邻选择器和通用选择器等)。 整个 CSS3 的规范发布不会因为部分存在争论而影响其他模块的推进。 对于浏览器来说,可以根据需要,决定哪些 CSS 功能被支持。

9. 前端常见的布局方式

一、静态布局

静态布局是最为原始的布局方式,没有什么技术性可言,往往是计算机行业刚刚入门的小白使用的布局方式。制作的网页上的元素尺寸一律以px为单位

布局特点: 页面上的布局是按最初写代码时候的布局方式进行布局的,常规的pc网站是进行设置了宽度值进行布局的,不会随着pc端的屏幕的大小而变化。 优点: 这种布局方式不管是对资深的前端开发工程师还是刚入门的小白来说都是最简单的,最让人容易以接受、学习的,没有我们所说的兼容性的问题。这种布局方式大多用在门户网站和企业的官网上,这些官网的设备的尺寸是固定的,这种布局方式往往是最简单的方法。 缺点: 不会随着pc端的屏幕大小而变化。

二、弹性布局(flexbox)

弹性布局可以简便、完整、响应的实现各种页面上的布局。与静态不同的是,使用em或rem单位(lem=16px,1rem=10px)进行相对布局,相对使用百分比更加方便、灵活,相应同时支持浏览器的字体大小调整和缩放的等正常显示。 优点: 1.适应性强,在做多种不同的屏幕分辨率不同的界面是非常使用。 2.随意按照宽度、比例划分元素的宽高。 3.可以轻松的改变元素的显示顺序。 4.网页布局实现快捷,维护起来更加容易。 如果做移动端时,如果客户对细微的之处的要求不高,使用弹性布局进行制作是最好的选择,一份css+一份js调节font-size搞定。 缺点: 浏览器兼容性较差,只能兼容到IE9及以上。

三、自适应布局(bootstrap)

自适应布局分别为不同屏幕不同分辨率定义布局,即是创建多个静态页面,每个静态页面对应一个屏幕分辨率的一个范围内。在改变不同的屏幕分辨率可以切换到不同的静态布局上,但是布局中的元素位置会发生改变,但是在每个静态布局中,页面中的元素不会随着窗口大小的调整发生变化。使用 @media 媒体查询给不同尺寸和介质的设备切换不同的样式。在优秀的响应范围设计下可以给适配范围内的设备最好的体验,在同一个设备下实际还是固定的布局。 优点: 1.对网站的复杂程度兼容性更大; 2.对开发工程师来说制作的成本代价更低; 3.代码执行效果更高效; 4.测试时更加容易,运营相对更加精准。 缺点: 在现如今的移动端设计百花齐放的时期之下,同一个网站往往需要为不同的设备制作不同的页面,不但会增加开发成本,还会因为客户的需求改变时,可能会改动多套代码、流程相比较来说较繁琐。

四、流式布局(fluid)

流式布局的布局方式是页面的元素的宽度按照屏幕的分辨率进行适配的调整,但是整体布局不变,也称之为栅栏系统。使用%百分比定义宽度,高度大都是用px来固定住,可以根据可视区域 (viewport) 和父元素的实时尺寸进行调整,尽可能的适应各种分辨率。往往配合 max-width/min-width 等属性控制尺寸流动范围以免过大或者过小影响阅读。 缺点: 屏幕大小变化时,页面元素也随之变化但是布局不变。这就会因为如果屏幕太大或太小都会布局时元素无法正常显示。

五、响应式布局

响应式布局是css3增加的新布局方式,该布局方式2010年提出来的一个概念,说白了就是一个网站能够兼容多个终端——而不是为每个终端做一个特定的版本。这个概念是为解决移动互联网浏览而诞生的。响应式布局可以为不同终端的用户提供更加舒适的界面和更好的用户体验,而且随着目前大屏幕移动设备的普及,用“大势所趋”来形容也不为过。响应式几乎成为优秀页面布局的标准。 设计方法: 媒体查询+流式布局。通常使用@media媒体查询,和网格系统配合相对布局单位进行布局,实际上说白了就是综合响应式等技术通过css给单一网页不同设备分辨率返回不式时的技术。 优点: 适应pc端和移动端,如果有足够的耐心,页面效果会很完美。 缺点: 1.只能适应主流的宽高; 2.如果匹配足够多的设备屏幕的大小,对于工程师来说工作量不小,设计更需要多个版本,工作量增大。

六、浮动布局

浮动布局进行调用浮动属性改变页面中元素的位置,浮动布局应该是目前各大网站用的最多的一种布局方式了,但是也特别复杂。浮动元素是脱离文档流的,但不脱离文本流。浮动元素有左浮动(float : left)和右浮动(float : right)两种

兼容性比较好 浮动带来的影响比较多,页面宽度不够的时候会影响布局。

七、定位布局

定位布局时利用position属性控制页面元素设置一些不规则布局。

HTML

. HTML的语义化标签

:页面主体内容。 :h1~h6,分级标题,

协调有利于搜索引擎优化。 <ul>:无序列表。 <li>:有序列表。 <header>:页眉通常包括网站标志、主导航、全站链接以及搜索框。 <nav>:标记导航,仅对文档中重要的链接群使用。 :页面主要内容,一个页面只能使用一次。如果是web应用,则包围其主要功能。 <article>:定义外部的内容,其中的内容独立于文档的其余部分。 <section>:定义文档中的节(section、区段)。比如章节、页眉、页脚或文档中的其他部分。 <aside>:定义其所处内容之外的内容。如侧栏、文章的一组链接、广告、友情链接、相关产品列表等。 <footer>:页脚,只有当父级是body时,才是整个页面的页脚。 <small>:呈现小号字体效果,指定细则,输入免责声明、注解、署名、版权。 <label>:和 em 标签一样,用于强调文本,但它强调的程度更强一些。 <em>:将其中的文本表示为强调的内容,表现为斜体。 <mark>:使用黄色突出显示部分文本。 </mark></em></label></small><figure>:规定独立的流内容(图像、图表、照片、代码等等)(默认有40px左右margin)。 <figcaption>:定义 figure 元素的标题,应该被置于 figure 元素的第一个或最后一个子元素的位置。 <cite>:表示所包含的文本对某个参考文献的引用,比如书籍或者杂志的标题。 :定义块引用,块引用拥有它们自己的空间。 <q>:短的引述(跨浏览器问题,尽量避免使用)。 <time>:datetime属性遵循特定格式,如果忽略此属性,文本内容必须是合法的日期或者时间格式。 <abbr>:简称或缩写。 <dfn>:定义术语元素,与定义必须紧挨着,可以在描述列表dl元素中使用。 </dfn></abbr></time></q></cite><address>:作者、相关人士或组织的联系信息(电子邮件地址、指向联系信息页的链接)。 <del>:移除的内容。 </del><ins>:添加的内容。 <code>:标记代码。 :定义已知范围或分数值内的标量测量。(Internet Explorer 不支持 meter 标签) :定义运行中的进度(进程)。 </code></ins></address></figcaption></figure></footer></aside></section></article></nav></header></li></ul>

. 前端优化的解决方案

我们的优化原则有以下几个:

. HTML5新特性

html5总的来说比html4多了十个新特性,但其不支持ie8及ie8以下版本的浏览器

一、语义标签

二、增强型表单

三、视频和音频

四、Canvas绘图

五、SVG绘图

六、地理定位

七、拖放API

八、WebWorker

九、WebStorage

十、WebSocket

详细地址 https://www.cnblogs.com/binguo666/p/10928907.html

. 常见的浏览器兼容问题

解决方案:css里增加通配符*{margin:0;padding:0}

解决方案:设置display:inline;

解决方案:设置display:inline;

解决方案:使用float为img布局

解决方案:opacity:0.5;filter:alfha(opacity=50);filter:progid:DXlmageTransform.Microsoft.Alfha(style=0,opacity=50);

解决方案: 当相邻两个元素都设置了margin边距时,margin将取最大值,舍弃最小值;

解决方案:统一使用cursor:pointer;

解决方案:父级元素设置position:relative

说明:Firefox下,可以使用const关键字来定义常量;IE下,只能使用var关键字来定义常量。

解决方法:统一使用var关键字来定义常量。

问题说明:IE下,event对象有srcElement属性,但是没有target属性;Firefox下,event对象有target属性,但是没有srcElement属性。

解决方法:使用srcObj = event.srcElementevent.srcElement:event.target;

IE:dom.attachEvent();

其他浏览器:dom.addEventListener();

标准浏览器采用事件捕获的方式对应IE的事件冒泡机制(即标准由最外元素至最内元素或者IE由最内元素到最外元素)最后标准方亦觉得IE这方面的比较合理,所以便将事件冒泡纳入了标准,这也是addEventListener第三个参数的由来,而且事件冒泡作为了默认值。

在ie9以下,不能操作tr的innerHTML

IE:ActiveXObject

其他:xmlHttpReuest

问题说明:FireFox中类似obj.style.height = imgObj.height的语句无效。

CSS

解决方法: 统一使用pointer

需用textContent。

IE:filter:progid:DXImageTransform.Microsoft.Alpha(style=0,opacity=60)。

FF:opacity:0.6。

在IE7和FF中width宽度不包括padding,在Ie6中包括padding.

详细地址 常见的浏览器兼容 - 知乎 (zhihu.com)

Vue

. Vuex

1.1 关于VueX

Vuex 是一个专为 Vue.js 应用程序开发的

把组件的共享状态抽取出来,以一个全局单例模式管理。在这种模式下,我们的组件树构成了一个巨大的“视图”,不管在树的哪个位置,任何组件都能获取状态或者触发行为!这就是“状态管理模式”。

应用场景有:单页应用中,组件之间的数据状态。 应用实例: 1、购物车功能; 2、下单页面有选择优惠券按钮,点击进入优惠券页面,选择后返回到下单页,数据会绑定回来,显示已选择的优惠券; 3、登录状态等等

Vuex有哪几种属性?

有五种,分别是 State、 Getter、Mutation 、Action、 Module

Vuex的State特性

1、Vuex就是一个仓库,仓库里面放了很多对象。其中state就是数据源存放地,对应于一般Vue对象里面的data

2、state里面存放的数据是响应式的,Vue组件从store中读取数据,若是store中的数据发生改变,依赖这个数据的组件也会发生更新

3、它通过mapState把全局的 state 和 getters 映射到当前组件的 computed 计算属性中

Vuex的Getter特性

1、getters 可以对State进行计算操作,它就是Store的计算属性

2、虽然在组件内也可以做计算属性,但是getters 可以在多组件之间复用

3、如果一个状态只在一个组件内使用,是可以不用getters

Vuex的Mutation特性

Action 类似于 mutation,不同在于:Action 提交的是 mutation,而不是直接变更状态;Action 可以包含任意异步操作。

Vuex的Module特性

Module 可以让每一个模块拥有自己的state、mutation、action、getters,使得结构非常清晰,方便管理。

使用Vuex的好处?

1、多层嵌套的组件、兄弟组件间的状态会更好管理维护。 2、缓存一些当前要使用请求远程或本地的数据集(刷新后会自己销毁)。 3、有了第二条,就可以减少向服务器的请求,节省资源。如果你的用户足够多,那么每多出一个请求,对公司来说,都是一大笔钱。 4、对开发者来说,如果你的项目足够复杂,团队的规模也不仅是一个人,数据集中处理更利于程序的稳定和维护

. 双向绑定的原理

以往的MVC模式是单向绑定,即Model绑定到View,当我们用JavaScript代码更新Model时,View就会自动更新

MVVM模式就是Model–View–ViewModel模式。它实现了View的变动,自动反映在 ViewModel,反之亦然。对于双向绑定的理解,就是用户更新了View,Model的数据也自动被更新了,这种情况就是双向绑定。再说细点,就是在单向绑定的基础上给可输入元素input、textare等添加了change(input)事件,(change事件触发,View的状态就被更新了)来动态修改model。

vue数据双向绑定是通过数据劫持结合发布者-订阅者模式的方式来实现的

我们已经知道实现数据的双向绑定,首先要对数据进行劫持监听,所以我们需要设置一个监听器Observer,用来监听所有属性。如果属性发上变化了,就需要告诉订阅者Watcher看是否需要更新。因为订阅者是有很多个,所以我们需要有一个消息订阅器Dep来专门收集这些订阅者,然后在监听器Observer和订阅者Watcher之间进行统一管理的。接着,我们还需要有一个指令解析器Compile,对每个节点元素进行扫描和解析,将相关指令(如v-model,v-on)对应初始化成一个订阅者Watcher,并替换模板数据或者绑定相应的函数,此时当订阅者Watcher接收到相应属性的变化,就会执行对应的更新函数,从而更新视图。

. 组件间传递数据

  1. 父组件向子组件传递数据,使用props属性;子组件向父组件中传递数据,在子组件中使用$emit派发事件,父组件中使用v-on 监听事件;缺点:组件嵌套层次多的话,传递数据比较麻烦。
  2. 祖先组件通过依赖注入(inject / provide)的方式,向其所有子孙后代传递数据;缺点:无法监听数据修改的来源,不支持响应式。
  3. 通过属性$root / $parent / $children / ref,访问根组件、父级组件、子组件中的数据;缺点:要求组件之间要有传递性。
  4. 通过事件总线(event bus)的方式,可以实现任意两个组件间进行数据传递;缺点:不支持响应式,这个概念是vue1.0版本中的,现

标签: 8px连接器cn

锐单商城拥有海量元器件数据手册IC替代型号,打造 电子元器件IC百科大全!

锐单商城 - 一站式电子元器件采购平台