面试总结

248 阅读8分钟

#面试题总结

HTML知识

DOCTYPE 的作用是什么?

  • 声明位于 HTML 文档中的第一行,处于 html 标签之前。告知浏览器的 解析器用什么文档标准解析这个文档。

当DOCTYPE 不存在或格式不正确会导致文档以兼容模式呈现。一般指定了之后会以标准模式来 进行文档解析,否则就以兼容模式进行解析。

在标准模式下,浏览器的解析规则都是按 照最新的标准进行解析的。 在兼容模式下,浏 览器会以向后兼容的方式来模拟老式浏览器的行为,以保证一些老的网站的正确访问。

CSS基础知识

行内元素

 一个行内元 素只占据它对应标签的边框所包含的空间。
 a b span img strong sub sup button input label select textarea

块级元素

 块级元素占据其父元素(容器)的整个宽度,因此创建了一个“块”
 div ul ol li dl dt dd h1 h2 h3 h4 h5 h6 p

页面导入样式时,使用 link 和 @import 有什么区别?

  • 从属关系区别。 @import 是 CSS 提供的语法规则,只有导入样式表的作用;link 是 HTML 提供的标签,不仅可以加载 CSS 文件,还可以定义 RSS、rel 连接属性、引入网 站图标等。
  • 加载顺序区别。加载页面时,link 标签引入的 CSS 被同时加载;@import 引入 的 CSS 将在页面加载完毕后被加载。
  • 兼容性区别。@import 是 CSS2.1 才有的语法,故只可在 IE5+ 才能识别;link 标 签作为 HTML 元素,不存在兼容性问题。
  • DOM 可控性区别。可以通过 JS 操作 DOM ,插入 link 标签来改变样式;由于 DOM 方法是基于文档的,无法使用 @import 的方式插入样式

HTML与CSS 理论题

你对浏览器的理解?

  • 浏览器的主要功能是将用户选择的 web 资源呈现出来,它需要从服务器请求资源,并将其显示在浏览器窗口中,资源的格式通常是 HTML,也包括 PDF、image 及其他格式。用户用 URI(Uniform Resource Identifier 统一资源标识符)来指定所请求资源的位置。
  • HTML 和 CSS 规范中规定了浏览器解释 html 文档的方式,由 W3C 组织对这些规范 进行维护,W3C 是负责制定 web 标准的组织。
  • 浏览器的主要核心是内核(渲染引擎和JS引擎)和shell (浏览器的外壳:菜单工具栏等)

主流浏览器的内核有

  • IE 浏览器内核:Trident 内核,也是俗称的 IE 内核;
  • Chrome 浏览器内核:统称为 Chromium 内核或 Chrome 内核,以前是 Webkit 内核,现在是 Blink 内核;
  • Firefox(火狐) 浏览器内核:Gecko 内核,俗称 Firefox 内核;
  • Safari(苹果) 浏览器内核:Webkit 内核;
  • Opera 浏览器内核:最初是自己的 Presto 内核,后来加入谷歌大军,从 Webkit 又到了 Blink 内核;

重绘和重排

  • 重绘\color{#FF3030}{重绘} : 当渲染树中的一些元素需要更新属性,而这些属性只是影响元素的外观、风格,而 不会影响布局的操作,比如 background color,我们将这样的操作称为重绘。
  • 重排\color{#FF3030}{重排} :当渲染树中的一部分(或全部)因为元素的规模尺寸、布局、隐藏等改变而需要重 新构建的操作,会影响到布局的操作,这样的操作我们称为重排。

常见引起重排属性和方法: 任何会改变元素几何信息(元素的位置和尺寸大小)的操作,都会触发重排。

  • 添加或者删除可见的 DOM 元素;
  • 元素尺寸改变——边距、填充、边框、宽度和高度
  • 内容变化,比如用户在 input 框中输入文字
  • 浏览器窗口尺寸改变——resize 事件发生时
  • 计算 offsetWidth 和 offsetHeight 属性
  • 设置 style 属性的值
  • 当你修改网页的默认字体时。 重排必定会发生重绘,重绘不一定会引发重排。重排所需的成本比重绘高的多,改变父节点里的子节点很可能会导致父节点的一系列重排。

如何减少重排(浏览器绘制过程)

  • 使用 transform 替代 top
  • 不要把节点的属性值放在一个循环里当成循环里的变量
  • 不要使用 table 布局,可能很小的一个小改动会造成整个 table 的重新布局
  • 把 DOM 离线后修改。如:使用 documentFragment 对象在内存里操作 DOM
  • 不要一条一条地修改 DOM 的样式。与其这样,还不如预先定义好 css 的 class, 然后修改 DOM 的 className。

函数题编程题

编写求和函数 sum,要求满足: sum(1,2)=>3 sum(1)(2)=>3

function sum() {
  var num = arguments[0];
  if (arguments.length == 1) {
    return function(sec) {
      console.log(num + sec);
    };
  } else {
    for (var i = 1; i < arguments.length; i++) {
      num += arguments[i];
    }
    console.log(num);
  }
}
sum(2, 3); //5
sum(2)(3);

统计数组[1,2,3,1,5,7,2,3,58,9,4]中出现的数字并输出

var map={}
var str = [1, 2, 1, 3, 4, 5, 6, 1, 2, 1, 4, 5, 3];
for (var i = 0; i < str.length; i++) {
  var s = str[i];
  var r = map[s];
  if (r) {
    map[s] += 1;
  } else {
    map[s] = 1;
  }
}
console.log(map);

实现判断整形的函数 isInsteger

function isInsteger(str) {
  var g = /^[0-9]*$/;
  return g.test(str);
}
console.log(isInsteger('132dsajbh42782'));

写出下面代码的输出,解释原因

for(var  i = 0; i < 5; i++){
    setTimeout(fucntion(){
    	cosnole.log(i)
    }, i * 1000)
}
打印结果: 55
  • setTimeout 是一个异步的函数只会等到主线程中的数据全部完成才会把数据返回出来

实现原生数组的扩展,复制自身

var obj2 = {
  name: 'xiaoli2',
  age: 21,
  speak: function() {
    alert('hi,I am' + name);
  }
};

//复制对象方法
function cloneObj(oldObj) {
  if (typeof oldObj != 'object') return oldObj;
  if (typeof (oldObj == null)) return oldObj;
  var newObj = Object();
  for (var i in oldObj) newObj[i] = cloneObj(oldObj[i]);
  return newObj;
}

//扩展对象
function extendObj() {
  var args = arguments; //将传递过来的参数数组赋值给args变量
  var temp = cloneObj(args[0]);
  for (var n = 1; n < args.length; n++) {
    for (var i in args[n]) temp[i] = args[n][i];
  }
  return temp;
}
var obj = extendObj(obj2);
console.log(obj); //{ name: 'xiaoli2', age: 22, speak: [Function] }

实现函数:对象数据,按照 age 正序排序

var list = [
  {
    name: 'zhangsan',
    age: '45'
  },
  {
    name: 'bocai',
    age: '21'
  },
  {
    name: 'qingyi',
    age: '33'
  }
];
//定义一个函数
function compare(pro) {
  return function(obj1, obj2) {
    var val1 = obj1[pro];
    var val2 = obj2[pro];
    if (val1 < val2) {
      //正序
      return 1;
    } else if (val1 > val2) {
      return -1;
    } else {
      return 0;
    }
  };
}
//使用方法
list.sort(compare('age'));
console.log(list);

检查页面中是否有重复的 id 值

window.onload = function() {
  var tags = document.getElementsByTagName('*'),
    count = tags.length,
    time,
    ret = {},
    id;
  time = new Date();
  console.log(tags);
  for (var i = 0; i < count; i++) {
    id = tags[i].id;
    if (id) {
      if (ret[id]) {
        alert(id + '用时:' + (new Date() - time));
        return;
      } else {
        ret[id] = true;
      }
    }
  }
  alert('未找到相同ID');
};

实现数据去重

//方法1  一行代码去重
//Array.from()方法就是将一个类数组对象或者可遍历对象转换成一个真正的数组
var arr = new Set([12, 5, 5, 8, 4, 1, '52', 1, 2, 3, '45', 5, 7, 2, 1, 55]);
let newArr = Array.from(arr); // 获取去重后的数组
//方法2 通过indexOf 进行去重
function uniq(array) {
  var temp = []; //一个新的临时数组
  for (var i = 0; i < array.length; i++) {
    if (temp.indexOf(array[i]) == -1) {
      temp.push(array[i]);
    }
  }
  return temp;
}

var aa = [1, 2, 2, 4, 9, 6, 7, 5, 2, 3, 5, 6, 5];
console.log(uniq(aa));

js理论题

事件委托也叫事件代理

  • 事件委托就是利用事件冒泡把当前元素的事件冒泡的父组件中

html

 <input type="button" name="" id="btn" value="添加" />
        <ul id="ul1">
            <li>111</li>
            <li>222</li>
            <li>333</li>
            <li>444</li>
        </ul>

js

    <script>
        window.onload = function () {
            var oBtn = document.getElementById("btn");
            var oUl = document.getElementById("ul1");
            var aLi = oUl.getElementsByTagName('li');
            var num = 4;

            //事件委托,添加的子元素也有事件
            oUl.onmouseover = function (ev) {
                console.log(window.event);
                var ev = ev || window.event;
                //ev.srcElement 兼容ie 的
                var target = ev.target || ev.srcElement;
                // console.log(ev.target)
                // 获取当前的标签名称 target.nodeName LI  toLowerCase() 转换成小写  
                // 给当前的 ul 注册一个事件  在获取到当前移动到位置的事件对象 获取到 target.nodeName 当前元素的节点名称  判断是否是li之后设置元素
                if (target.nodeName.toLowerCase() == 'li') {
                    target.style.background = "red";
                }

            };
            oUl.onmouseout = function (ev) {
                var ev = ev || window.event;
                var target = ev.target || ev.srcElement;
                if (target.nodeName.toLowerCase() == 'li') {
                    target.style.background = "#fff";
                }

            };

            //添加新节点
            oBtn.onclick = function () {
                num++;
                var oLi = document.createElement('li');
                oLi.innerHTML = 111 * num;
                oUl.appendChild(oLi);
            };
        }
    </script>

浏览器页面开始到结束的过程

  1. 在浏览器中输入网址;
  2. 发送至DNS服务器并获得域名对应的web服务器的IP地址;
  3. 与web服务器建立起TCP连接;
  4. 浏览器向服务器的IP地址发送相应的http请求;
  5. web服务器响应请求并返回指定URL的数据,或错误信息,如果设定重定向,则重定向到新的 URL地址;
  6. 浏览器下载数据后解析HTML源文件,解析的过程中实现对页面的排版,解析完后在浏览器中显示基础页面;
  7. 分析页面中的超链接并显示在当前页面,重复以上过程直至无超链接需要发送,完成全部显示

DOM树是什么

  • 首先 DOM 结构构成的基本要素是 “节点“,而文档的结构就是由层次化的节点组成。在 DOM 模型中,节点的概念很宽泛,整个文档 (Document) 就是一个节点,称为文档节点。除此之外还有元素(Element)节点、属性节点、Entity节点、注释(Comment)节点等。
  • 文档以 HTMLDocument 为根节点,其余节点为子节点,组织成一个树的数据结构的表示就是 DOM树。
<html lang="en">
<head>
    <title>Document</title>
</head>
<body>
</body>
</html>

事件捕获和事件冒泡

  • 事件捕获:首先window会获捕获到事件,之后document、documentElement、body会捕获到,再之后就是在body中DOM元素一层一层的捕获到事件,有wrapDiv、innerP;
  • 目标阶段:真正点击的元素textSpan的事件发生了两次,因为在上面的JavaScript代码中,textSapn既在捕获阶段绑定了事件,又在冒泡阶段绑定了事件,所以发生了两次;
  • 事件冒泡:和捕获阶段相反的将事件一步一步地冒泡到window;

cookie、session sessionStorage,localStorage 的区别

  • SessionStorage, LocalStorage 存在于H5中的WebStorage中通常用于存储客户端的大型数据,而 cookie 是网站为了标示用户身份而储存在用户本地终端上的数据(通常 经过加密)。cookie 数据始终在同源(协议、主机、端口相同)的 http 请求中携带(即使 不需要),会在浏览器和服务器间来回传递。
  • cookie 是 每次发送请求时都会被携带,在页面上的存储时间是自己定义的 有时间限制,如果没有设置时间 是一个会话级别的,关闭浏览器就不存在了, 而且存储的数据大小有限制只有 4kb 大小,存储在浏览器中
  • session: session 是存储在服务端的数据 存储一些登陆的数据 ,数据保存安全
  • sessionStorage 是保存在本地的是一个会话级别 存储数据大小在 4M,页面会话是在浏览器打开期间一直保持, 并且重新加载或恢复页面仍会保持原来的页面会话。在新标签或窗口打开一个页面时会在顶级浏览上下文中初始化一个新的会话。
  • localStorage 是永久保存在本地的存储的数据大小是 20M

如何实现固定尺寸盒模型的水平和垂直居中?

  • 父级设置 position:relative  子盒子设置 position:abso lute;    top:50%    left:50%; transform: translate(-50%, -50%);
  • 父级设置 dispaly:table-cell; vertical-align:middle;   子:margin:0 auto;
  • 弹性布局 flex 父级设置 display:flex;align-items:center;justify-content:center;
  • [注意点] 如果父级没有宽度和高度用 flex 布局

如何将页面请求图片次数减少

  • 使用精灵图把多个图片给压缩成一个大的图片 减少图片的请求

8.处理上亿条数据的查询指定关键字的功能,遍历上亿条时间太长,怎么处理 前端做的是数据的封装,做云端数据托管,和大数据工程师配合做数据脏值检测

懒加载和预加载的区别?实现方式

  • 图片预加载即提前加载图片,可保证图片快速、无缝地发布,用户需要查看时可直接从本地缓存中渲染,适用于图片占据很大比例的网站。意义:牺牲服务器前端性能,换取更好的用户体验,这样可以使用户的操作得到最快的反映。
  • 懒加载:将图片 src 赋值为一张默认图片,当用户滚动滚动条到可视区域图片时候,再去加载真正的图片,意义:页面加载速度快、可以减轻服务器的压力、减少请求数或延迟请求数

JQ 中如何找父元素的多种方式

  • parent() 取得一个包含着所有匹配元素的唯一父元素的元素集合。
  • :parent 匹配含有子元素或者文本的元素
  • parents([expr])取得一个包含着所有匹配元素的祖先元素的元素集合(不包含根元素)。可以通过一个可选的表达式进行筛选。
$('#item1')
  .parent()
  .parent('.parent1');
$('li:parent');
$('#items').parents('.parent1');
  1. 如何处理 git 冲突,如何使用 git 重置操作
    • 发现 git 冲突时直接找到冲突的地方修改当前代码
    • git reset
  2. 浏览器的前端存储除了 localstorage sessiostorage cookie 还有什么储存方式
  • UserData、GlobalStorage、Google Gear
  • userData 是 IE 浏览器专属,它的容量可以达到 640K,这种方案可靠,不需要安装额外插件,只不过它仅在 IE 下有效~
  • globalStorage 适用于 Firefox 2+的浏览器,类似于 IE 的 userData~
  • google gear 是谷歌开发出的一种本地存储技术,需要安装 Gear 组件。
  1. 前端 Xss,CSRF 攻击是什么意思,如何防范
  • XSS 攻击 跨站脚本攻击
  • 特点: 能注入恶意的 HTML/JavaScript 代码到用户浏览的网页上,从而达到 Cookie 资料窃取、会话劫持、钓鱼欺骗等攻击。
  • 原因 前端的代码 浏览器都可以解析出来,不安全,而且开发人员都不怎么注重安全意识,xxs 攻击方式灵活多变
  • 防御方法:
    • a:HttpOnly 浏览器禁止页面的 JS 访问带有 HttpOnly 属性的 Cookie。
    • b:输入检查 XSS Filter 对输入内容做格式检查,类似“白名单”,可 以让一些基于特 殊字符的攻击失效。在客户端 JS 和服务器端代码中实现相同的输入检查(服务器端必须有)。
    • c 输出检查 在变量输出到 html 页面时,可以使用编码或转义的方式来防御 XSS 攻击
  1. http 与 https 的区别
  • http 是一种超文本传输协议 信息是明文传输 端口号是 80
  • https 是一种安全的超文本传输协议 则是具有安全性的 ssl 加密传输协议。 端口号是 443。

内存泄漏的原因及解决方法

  • 在页面中移动或者替换元素时,没有解绑当前元素的事件
  • 过多的使用闭包
  • 定时器setTimeout setInterval 没有使用clearInterval 进行清楚定时器
  • mounted/created 钩子中使用了on解决方法需要在beforeDestroy中做对应解绑(on 解决方法 需要在beforeDestroy 中做对应解绑(off)处理
  • 没有定义的全局变量

数组扁平化以及排序、去重

  • 先进行遍历数组 拿到单个的数据
  • 通过 Array.from(new Set(newArr1)) 进行去重并 获取到去重后的数组
  • 通过 数组中的 sort 方法进行排序
    arr.sort(function(a, b) {
      return a - b;
    });
    

深浅拷贝

  • 深拷贝 拷贝的是当前的所有数据并从新生成一个地址
  • 浅拷贝 拷贝的是一个地址 ,只是当前对象的指针改变了

es6

es6的 class

// 定义一个类
  class Person{
      constructor(name,age){
          this.name = name;
          this.age = age;
      }
      //一旦一个函数被static修饰,那么这个函数就属于类了,可以直接由类名来调用Person.say()。而普通函数是不能直接由类进行调用的,普通函数只能由实例化的对象来调用,被static修饰的函数是不能被实例化的对象调用的只能通过类直接来进行调用
       static say(){
          console.log("由类调用");
      }
        // 可以被子类对象直接调用的方法
      sayHi(){
          console.log("父类的方法");
      }
  }
  console.log(typeof Person )// "function"
  console.log( Person === Person.prototype.constructor)  // true
  //一个类可以继承一个类,被继承的类我们一般称为父类,另一个称为子类,通过extends来实现:
  class Student extends Person{
  //在子类中使用constructor来初始化属性,首先使用super来对可继承的属性进行初始化,然后在通过this添加自身特有的属性,this只有在调用super()之后才会存在。
      constructor(name,age,sex){
          super(name,age);
          this.sex = sex;
      }
  }
  var stu = new Student("zt",23,"男")
  stu.sayHi()
  console.log(stu.sex);//男

es6数组中新增的方法

  • arr.indexOf() 如果只有一个参数是查询当前元素的下标 如果有两个参数第一个是查询的元素,第二个是从第几个位置开始查询元素 下标从0开始
  • arr.some every reduce(累加计算数据) isArray map filter

es6 新增加的东西

  • let const 扩展运算符 ... 结构赋值 箭头函数 模板字符串 ${} 多行字符串 继承的方法 extends 和 super
  • 参数可以通过 = 号来设置默认值
  • 数组中的方法
    • includes('要判断的字符') 判断是否包含某个字符 布尔
    • startsWith('要判断的字符') 判断是否以什么字符开头 布尔
    • endsWith('要判断的字符') 判断是否以什么字符结尾 布尔
    • padStrat(当前字符串的长度,添加的数据) 为数值补全指定位数数值补全指定位数 必须是字符串

箭头函数里 this 的指向

  • 指向的是当前函数外部的 this
  • 箭头函数不能当做构造函数使用

用户的操作是无序的,怎么阻止用户多余的操作(比如下拉刷新,用户可以触发多次,怎么解决)最少两种方法

  • 使用节流函数,在每次执行时设置一个定时器,到了一定时间才能执行下一次,不能进行连续的点击或者下拉 (节流就是保证一段时间内只执行一次核心代码)
  • 函数防抖 事件保持触发,一定时间内没有触发 (在一定时间段的连续函数调用,只让其执行一次)

常用的状态码

  • 200 请求被成功处理
  • 204 No Content 服务器接收到的请求已经处理完毕,但是服务器不需要返回响应体.
  • 301 永久性重定向
  • 302 临时性重定向。
  • 400 请请求报文中存在语法错误,导致服务器无法理解该请求
  • 403 表明对请求资源的访问被服务器拒绝了。
  • 404 该状态码表明服务器上无法找到指定的资源
  • 500 该状态码表明服务器端在执行请求时发生了错误
  • 503 该状态码表明服务器暂时处于超负载或正在进行停机维护,现在无法处理请求。

webpack 知识

webpack 有热更新的功能,如果浏览器热更新比较慢,怎么优化

vue 框架知识

vue是什么

  • vue 是一个单向数据流

Vue 中,如何实现父子组件的值传递,分别列出父传子和子传父?

父传子 : 父组件中定义一个属性 发送到 子组件中 子组件通过 props 属性来接收 子传父 :1. 子组件中定义一个方法 2. 传递给子组件 3. 子组件通过 this.$emit('接收的方法名',返回的数据)

vue组建render跟template对比

  • template适合逻辑简单,render适合复杂逻辑。
  • Render属于自定义函数,灵活性高,性能较高,但对使用者要求较高,template属于声明是渲染理解起来相对容易,但灵活性不足,性能较低

vue 中的双向绑定原理

  • html 中的 input 来双向绑定 通过 oninput 来设置事件之后通过 Object.defineProperty() 这个方法重新定义了对象获取属性值(get)和设置属性值(set)的操作来实现的。它接收三个参数,第一个参数 : 对象,给哪个对象添加属性 第二个参数 : 属性名,给这个对象添加什么属性 第三个参数 : 属性修饰符 get set

vue 打包项目时怎么进行优化

  • 在你引入文件的模块设置按需加载
  • 插件的 js 和 css 修改成 CDN 模式 内容分发式获取数据 最好是用官网上的 cdn
  • 懒加载模式
  • 压缩代码

说说你对 vuex 的理解,vuex 为什么不能通过全局变量替代

  • vuex 是用来管理项目的全局变量的,用于组件之间通信。

  • 父级向子级传值可以用 props,子级向父级传值可以用 v-on:和 this.$emit 组合实现。非父子组件间通信比较复杂,我们可以用 vuex 实现。

  • 全局变量如果多了之后非常的不容易进行管理 而 vuex 中的 stroe 这个属性可以声明一些全局共享的变量

作用域插槽的两大优点

  • 控制html模板的显示与不显示。作用域插槽其实就是带数据的插槽
  • 作用域插槽就可以通过子组件绑定数据传递给父组件

Methods 和 computed 的区别,两个都可以改变值,有啥不一样

  • computed 是基于它的依赖缓存,只有相关依赖发生改变时才会重新取值。 写起来像一个方法 用的时候是一个属性
  • methods 在重新渲染的时候,函数总会重新调用执行。

Vue的watch和computed及methods方法的使用及区别介绍

  • watch 是一个数据影响多个数据,监听某一个值的变化执行对应的方法,watch的回调里面会传入监听属性的新旧值,通过这两个值可以做一些特定的操作,应用场景(一个值变化后会引起一系列操作,或者一个值变化会引起一系列值的变化(一对多))
  • computed 是一个数据受到多个数据的影响,computed的值在getter执行后是会缓存的,只有在它依赖的属性值改变之后,下一次获取computed的值时才会重新调用对应的getter来计算
  • methods 里的方法需要手动进行调用,但是更加灵活多变

vue 组件之间进行数据双向绑定

  • 首先父组件通过 属性.sync 方法进行传值,子组件通过props 进行接收,当父组件中的数据发生变化时,子组件的数据也会发生变化,但是子组件中不能进行数据修改,这里需要通过this.$emit('updata:name',返回的值) 进行返回数据,这样就实现了双向数据绑定
//关键代码
<new-input v-bind:name.sync="name"> </new-input>  // 父组件传给子组件数据
this.$emit('update:name',this.newName);  	//子组件返回给父组件数据

vuex 在每次页面刷新时会丢失数据的原因

  • 因为在js的代码存储在内存中,每次刷新页面时,之前在内存中的数据都会被销毁掉,数据重新加载,所以会出现数据丢失的原因
  • 我们通过localStorage来存储数据,每次刷新页面时获取到localStorage里的数据就可以使用了

this.$nextTick()

  • 在数据变化后要执行的某个操作,而这个操作需要使用随数据改变而改变的DOM结构的时候,这个操作都应该放进Vue.nextTick()的回调函数中。

promise

  • 解决了回调地狱的问题
  • 代码的可读型更加的高
  • 更好地进行错误捕获 try{} catch(err){}

vue 生命周期的理解

  • beforeCreate(){} 在 vm 实例完全被初始化之前调用 这里 vm 中的方法和 data 都还没有被初始化

  • create() 这时 vm 中的 data 和方法已经被初始化完毕了,可以进行操作 data 中的属性和 methods 的方法

  • beforeMount() 渲染 DOM 之前调用,执行时页面中的元素还没有被真正替换过来,只是一些之前写的模板字符串

  • mounted() 渲染 DOM 之后调用 在 mounted 执行时内存中的模板已经被挂载到页面中,用户已经可以看到渲染好的数据了

  • beforeUpdate() 更新数据之前调用

  • updated() 在执行 updated 时页面中的数据内存中的数据已经完成同步了 更新数据之后调用

  • beforeDestroy() 销毁之前

  • destroyed() 当执行 destroyed 时所有的数据都已经被销毁了所有的东西已经不可用了

vuex 是什么,怎么使用,那种功能场景使用

  • vuex 是 vue 中的状态管理工具
  • 一般把一些全局中需要共享的数据放到 state 中
  • 因为用的时候非常复杂,适合一些大型页面进行开发

config-index 内 proxyTable:{}配置项是做什么的?如何配置?

  • proxyTable 是用来配置一些反向代理的数据所用,是为了处理跨域的问题
proxyTable: {
      '/myapi': {
        // 代理的目标服务器地址
        // https://api.douban.com/v2/movie/in_theaters
        // /myapi/movie/in_theaters
        target: 'http://localhost:3008',
        pathRewrite: {
          '^/myapi': ''
        },

        // 设置https
        secure: false,
        // 必须设置该项
        changeOrigin: true
      }
    },

ajax 与 axios 区别

  • 传统 Ajax 指的是 XMLHttpRequest(XHR), 最早出现的发送后端请求技术,隶属于原始 js 中,核心使用 XMLHttpRequest 对象,多个请求之间如果有先后关系的话,就会出现回调地狱。

    • 缺点
    • 本身是针对 MVC 的编程,不符合现在前端 MVVM 的浪潮
    • 基于原生的 XHR 开发,XHR 本身的架构不清晰。
    • JQuery 整个项目太大,单纯使用 ajax 却要引入整个 JQuery 非常的不合理(采取个性化打包的方案又不能享受 CDN 服务)
    • 嵌套请求会形成回调地狱
  • axios axios 是一个基于 Promise 用于浏览器和 nodejs 的 HTTP 客户端,本质上也是对原生 XHR 的封装,只不过它是 Promise 的实现版本,符合最新的 ES 规范

    • 特点
    • 1.从浏览器中创建 XMLHttpRequest
    • 2.支持 Promise API
    • 3.客户端支持防止 CSRF
    • 4.提供了一些并发请求的接口(重要,方便了很多的操作)
    • 5.从 node.js 创建 http 请求
    • 6.拦截请求和响应 7.转换请求和响应数据
    • 7.自动转换 JSON 数据

用 async 与 awite 同时发送两个请求有什么问题

  • 如果两个请求存在依赖就会存在问题 反之不会

vue-router中的导航构子函数

  • router.beforeEach 前置守卫 用来设置登陆拦截
  • router.beforeResolve 解析守卫
  • router.afterEach 后置守卫

优化问题

  • 请减少 HTTP 请求 使用精灵图
  • 少定义全局变量
  • 减少重绘和重排
    • Repaint(重绘)就是在一个元素的外观被改变,但没有改变布局(宽高)的情况下发生,如改变 visibility、outline、背景色等等。
    • Reflow(重排)就是 DOM 的变化影响到了元素的几何属性(宽和高),浏览器会重新计算元素的几何属性,会使渲染树中受到影响的部分失效,浏览器会验证 DOM 树上的所有其它结点的 visibility 属性,这也是 Reflow 低效的原因。
  • 减少对 DOM 的操作
  • 使用 JSON 格式来进行数据交换
  • 高效使用 HTML 标签和 CSS 样式 语义化的标签 如 nav header
  • js 放到底部 css 放到顶部
  • 在打包上线项目时使用 CDN 加速(内容分发网络)
  • 按需加载页面
  • 开启gzip进行压缩
  • 将打包生成之后的index.html里的js文件的引入方式放到body的最后