迈出了勇敢且踏实的第一步,是时候记下自己的薄弱点了

一、VUE

1. $attrs

前端知识点汇总(1) - 图1
如果在第二层组件声明第三层组件的加入属性 v-bind="$attrs" ,则第三层组件能接收到除第二层组件props声明的变量之外第一层组件传递给第二层组件的属性。

  1. <template>
  2. <div>
  3. <h1>grandparent组件</h1>
  4. <Parent
  5. :a="123"
  6. :b="456"
  7. :c="789"
  8. @confirm="onConfirm"
  9. @cancel="onCancel"
  10. />
  11. </div>
  12. </template>
  13. <script>
  14. import Parent from './parent';
  15. export default {
  16. components: { Parent },
  17. name: 'Grandparent',
  18. methods: {
  19. onConfirm: e => console.log(`grandparent onConfirm ${e}`),
  20. onCancel: e => console.log(`grandparent onCancel ${e}`)
  21. }
  22. };
  23. </script>
  1. <template>
  2. <div>
  3. <br />
  4. <h1>parent组件</h1>
  5. <h3 @click="$emit('confirm', 'parent')">a: {{ a }}</h3>
  6. <Child v-bind="$attrs" v-on="$listeners" />
  7. </div>
  8. </template>
  9. <script>
  10. import Child from './child';
  11. export default {
  12. components: { Child },
  13. props: ['a'],
  14. name: 'Parent'
  15. };
  16. </script>
  1. <template>
  2. <div>
  3. <br />
  4. <h2 @click="$emit('confirm', 'child')">child组件</h2>
  5. <h3 @click="$emit('cancel', 'child')">b: {{ b }}</h3>
  6. <h3>c: {{ c }}</h3>
  7. <h4>a: {{ a }}</h4>
  8. </div>
  9. </template>
  10. <script>
  11. export default {
  12. props: ['a', 'b', 'c'],
  13. name: 'Child'
  14. };
  15. </script>

拓展:$listeners
与$attrs类似,只不过不会说第二层组件传递过的事件,第三层组件就无法传递,所有事件,子孙组件都能响应。只不过需要在第二层组件内声明第三层组件的属性中加入 v-on="$listeners"

2. vue-router中钩子

2.1 全局钩子

beforeEach(to, from, next)
afterEach(to, from)

2.2 路由内共享

befoterEnter(to, from, next)

2.3 组件内拦截

beforeRouterEnter(to, from, next)

3. v-model 和 v-bind

3.1 v-model

  • v-model 是 :value="msg" @input="msg=$event.target.value" 的语法糖
  • v-model 建立的双向绑定对输入型元素input, textarea, select等具有优先权,会强制实行双向绑定

3.2 vue底层Object.defineProperty()

Vue底层通过Object.defineProperty()劫持各个属性的getter和setter来实现双向绑定(订阅发布者模式)

vue/index.js
前端知识点汇总(1) - 图2

4. hash和history区别

前端知识点汇总(1) - 图3
总结来看就是hash(默认hash模式)和history模式都就可以变更URL而无需重新加载页面,但是history模式需要后台配置所有资源都返回同一个index.html页面。

5. 状态存储

  • 传参的方法对于多层嵌套的组件将会非常繁琐,并且对于兄弟组件间的状态传递无能为力。
  • 经常会采用父子组件直接引用或者通过事件来变更和同步状态的多份拷贝。以上的这些模式非常脆弱,通常会导致无法维护的代码。

5.1 Mutation 需遵守 Vue 的响应规则

前端知识点汇总(1) - 图4
mutation 必须是同步函数

5.2 Action

  • Action 提交的是 mutation,而不是直接变更状态。
  • Action 可以包含任意异步操作。
  • Action 函数接受一个与 store 实例具有相同方法和属性的 context 对象,因此你可以调用context.commit 提交一个 mutation,
  • 或者通过 context.state 和 context.getters 来获取 state 和 getters。
  • 当我们在之后介绍到 Modules 时,你就知道 context 对象为什么不是 store 实例本身了。
  • 一个 store.dispatch 在不同模块中可以触发多个 action 函数。在这种情况下,只有当所有触发函数完成后,返回的 Promise 才会执行。

6. v-for为什么不能跟v-if一起用

v-for 的优先级比 v-if 更高,这意味着 v-if 将分别重复运行于每个 v-for 循环中。
v-for的优先级高会造成性能浪费,v-if会每个v-for循环体内都执行一遍

7. vue生命周期

前端知识点汇总(1) - 图5

8. v-for中key的作用

vue文档中有两段内容描述此问题,具体内容如下:
前端知识点汇总(1) - 图6
前端知识点汇总(1) - 图7

默认使用“就地更新”的策略。如果数据项的顺序被改变,Vue 将不会移动 DOM 元素来匹配数据项的顺序,而是就地更新每个元素,并且确保它们在每个索引位置正确渲染

  1. 声明 key 之后 vue跟踪每个节点的身份,从而重用和重新排序现有元素,你需要为每项提供一个唯一 key attribute
  2. 字符串或数值类型的值。
  3. 前端知识点汇总(1) - 图8

9. data 为什么要声明为一个函数

因为组件可能被用来创建多个实例。如果 data 仍然是一个纯粹的对象,则所有的实例将共享引用同一个数据对象!通过提供 data 函数,每次创建一个新实例后,我们能够调用 data 函数,从而返回初始数据的一个全新副本数据对象

10. computedwatch

  • computed: 有缓存,依赖于另一些值,当那些值变更时才会变更
  • watch: 需要在数据变化时执行异步开销较大的操作

11. MVVM

  • model
    • 真实状态内容的领域模型(面向对象),或指代表内容的数据访问层(以数据为中心)。
  • view
    • 用户在屏幕上看到的结构、布局和外观(UI)。
  • viewmodel

    • 暴露公共属性和命令的视图的抽象。MVVM没有MVC模式的控制器,也没有MVP模式的presenter,有的是一个绑定器。在视图模型中,绑定器在视图和数据绑定器(英语:Data binding)之间进行通信。

      12. name的作用

  • keep-alive 缓存过滤(:include=”[]” :exclude=”[]”)

  • vue-devtools 显示的组件名称

13. $nextTick

  • 官方文档:

    在下次 DOM 更新循环结束之后执行延迟回调。在修改数据之后立即使用这个方法,获取更新后的 DOM。

Vue 在更新 DOM 时是异步执行的。只要侦听到数据变化,Vue 将开启一个队列,并缓冲在同一事件循环中发生的所有数据变更。如果同一个 watcher 被多次触发,只会被推入到队列中一次。这种在缓冲时去除重复数据对于避免不必要的计算和 DOM 操作是非常重要的。然后,在下一个的事件循环“tick”中,Vue 刷新队列并执行实际 (已去重的) 工作。Vue 在内部对异步队列尝试使用原生的 Promise.then、MutationObserver 和 setImmediate,如果执行环境不支持,则会采用 setTimeout(fn, 0) 代替。

例如,当你设置 vm.someData = ‘new value’,该组件不会立即重新渲染。当刷新队列时,组件会在下一个事件循环“tick”中更新。多数情况我们不需要关心这个过程,但是如果你想基于更新后的 DOM 状态来做点什么,这就可能会有些棘手。虽然 Vue.js 通常鼓励开发人员使用“数据驱动”的方式思考,避免直接接触 DOM,但是有时我们必须要这么做。为了在数据变化之后等待 Vue 完成更新 DOM,可以在数据变化之后立即使用 Vue.nextTick(callback)。这样回调函数将在 DOM 更新完成后被调用。

14. vue父子组件生命周期函数执行顺序

image.png
由上图可知:
1. 父组件 beforeCreate

  1. 父组件 created
  2. 父组件 beforeMount
  3. 子组件 beforeCreate
  4. 子组件 created
  5. 子组件 beforeMount
  6. 子组件 mounted
  7. 父组件 moutend

15. mixin选项合并策略

  • data 数据对象在内部会进行递归合并,并在发生冲突时以组件数据优先

  • 同名钩子函数将合并为一个数组,因此都将被调用。另外,混入对象的钩子将在组件自身钩子之前调用。先调用混入的钩子

  • 值为对象的选项,例如 methods、components 和 directives,将被合并为同一个对象。两个对象键名冲突时,取组件对象的键值对

16. Keep-alive原理

原文:https://www.cnblogs.com/wangjiachen666/p/11497200.html

副本:图片副本展示

17. 单向数据流和双向绑定

17.1 单向数据流

  • 所有的 prop 都使得其父子 prop 之间形成了一个单向下行绑定:父级 prop 的更新会向下流动到子组件中,但是反过来则不行。这样会防止从子组件意外变更父级组件的状态,从而导致你的应用的数据流向难以理解。
  • view层无法直接变更model层,view层会通知model层变更,model层变更完数据后,引起view层变更

17.2 双向绑定

v-model 是单向数据流的语法糖

18. props自定义验证函数

  1. // 自定义验证函数
  2. propFunc: {
  3. validator: function (value) {
  4. // 这个值必须匹配下列字符串中的一个
  5. return ['success', 'warning', 'danger'].indexOf(value) !== -1
  6. }
  7. }

二、JS

1. 事件循环机制

js运行时有 队列 以及
当点击事件触发的时候,进入队列(先进先出),然后向栈中压入一个栈(先进后出)帧,相关的对象变量存入堆中,如果需要第二个变量就再次压入一个栈帧,直至栈空,队列首出队,继续执行下一个事件。所以说是一个事件循环,且非阻塞的

  1. while (queue.waitForMessage) {
  2. queue.processNextMessage();
  3. }

思维导图

2. js值引用和对象引用

  • 值引用:基本类型直接使用的是值本身
  • 对象引用:非基本类型使用的是内存地址

3. 箭头函数与普通函数区别

  • 箭头函数
    • 作用:
      • 更简短的函数
      • 不绑定this
  • 箭头函数是匿名函数,不能作为构造函数,不能使用new
  • 箭头函数不会创建自己的this,它只会从自己的作用域链的上一层继承this
  • 普通函数作用:
    • 如果是该函数是一个构造函数,this指针指向一个新的对象
    • 在严格模式下的函数调用下,this指向undefined
    • 如果是该函数是一个对象的方法,则它的this指针指向这个对象

4. Object.defineProperty

  1. // 使用 __proto__
  2. var obj = {};
  3. var descriptor = Object.create(null); // 没有继承的属性
  4. // 默认没有 enumerable,没有 configurable,没有 writable
  5. descriptor.value = 'static';
  6. Object.defineProperty(obj, 'key', descriptor);
  7. // 显式
  8. Object.defineProperty(obj, "key", {
  9. enumerable: false,
  10. configurable: false,
  11. writable: false,
  12. value: "static"
  13. });
  14. // 循环使用同一对象
  15. function withValue(value) {
  16. var d = withValue.d || (
  17. withValue.d = {
  18. enumerable: false,
  19. writable: false,
  20. configurable: false,
  21. value: null
  22. }
  23. );
  24. d.value = value;
  25. return d;
  26. }
  27. // ... 并且 ...
  28. Object.defineProperty(obj, "key", withValue("static"));
  29. // 如果 freeze 可用, 防止后续代码添加或删除对象原型的属性
  30. // (value, get, set, enumerable, writable, configurable)
  31. (Object.freeze||Object)(Object.prototype);

4.1 Object.defineProperty缺陷

原文:https://www.jianshu.com/p/f78bb8ac06b4
副本:图片副本展示

5. 区分array和object

  1. Object.prototype.toString.call
    • Object.prototype.toString.call(arr);//”[object Array]”
    • Object.prototype.toString.call(arr); //”[object Object]”
  1. 前端知识点汇总(1) - 图10
  2. 前端知识点汇总(1) - 图11
  3. 前端知识点汇总(1) - 图12
  4. 前端知识点汇总(1) - 图13

6. instanceof和typeof区别

  • instanceof 运算符用于检测构造函数的 prototype 属性是否出现在某个实例对象的原型链上。
  • typeof 操作符返回一个字符串,表示未经计算的操作数的类型。

6.1 typeof

  • 数据类型
    • 基本数据类型(可用typeof判断)
      • undefined:typeof instance === “undefined”
      • Boolean:typeof instance === “boolean”
      • Number:typeof instance === “number”
      • String:typeof instance === “string
      • BigInt:typeof instance === “bigint”
      • Symbol :typeof instance === “symbol”
      • null:typeof instance === “object”。(特殊:视为对象的空指针)
    • 引用数据类型
      • Object:typeof instance === “object”。任何 constructed 对象实例的特殊非数据结构类型,也用做数据结构:new Object,new Array,new Map,new Set,new WeakMap,new WeakSet,new Date,和几乎所有通过 new keyword 创建的东西。所以要用instanceOf

网页捕获_6-8-2021_95525_developer.mozilla.org.jpeg

因为 **Class** 是 function 的语法糖,所以 **typeeof class A {}** 返回为 ‘function

7. set和map区别

  • set类似于数组,但是数据不会重复,使用 new set() 创建set对象
  • map数据会重复,类似于对象,key可以是任意数据类型
  • 求长度 .size()
  • 作用:数组去重 **[...new Set(Array)]**;
  • arguments 也属于类数组范围

8. callapplybind

注意:该方法的语法和作用与 apply() 方法类似,只有一个区别,就是 call() 方法接受的是一个参数列表,而 apply() 方法接受的是一个包含多个参数的数组

8.1 call

function.call(thisArg, arg1, arg2, ...)

  • 参数列表
    • thisArg
      在 function 函数运行时使用的 this 值
    • arg1, arg2, ...
      指定的参数列表。
  • 返回值:使用调用者提供的 this 值和参数调用该函数的返回值。若该方法没有返回值,则返回 undefined
  • 如果没有传递第一个参数,this 的值将会被绑定为全局对象
  • 注意:在严格模式下,this 的值将会是 undefined

8.2 apply

func.apply(thisArg, [argsArray])

  • 参数列表
    • thisArg
      必选的。在 func 函数运行时使用的 this 值。
    • argsArray
      可选的。一个数组或者类数组对象,其中的数组元素将作为单独的参数传给 func 函数。如果该参数的值为 null 或 undefined,则表示不需要传入任何参数。从ECMAScript 5 开始可以使用类数组对象。
  • 返回值:调用有指定this值和参数的函数的结果

8.2.1 将数组各项添加到另一个数组
  1. push
    将该数组作为单个元素添加,而不是将这个数组内的每个元素添加进去,因此我们最终会得到一个数组内的数组。但是我觉得使用 ... 可解决此问题
  2. concat
    不是将元素添加到现有数组,而是创建并返回一个新数组
  3. apply

    1. let arr1 = [1, 2, 3];
    2. let arr2 = [4, 5, 6];
    3. arr1.push.apply(arr1, arr2);
    4. console.info(arr1); // [1, 2, 3, 4, 5, 6]
  4. call

    1. let arr1 = [1, 2, 3];
    2. let arr2 = [4, 5, 6];
    3. arr1.push.call(arr1, ...arr2);
    4. console.info(arr1); // [1, 2, 3, 4, 5, 6]

8.2.2 找出数组中最大/小的数字
  1. Math.max()
  2. Math.min()
  3. Math.max(...arr)
  4. apply
    1. let arr1 = [1, 3, -23, 56, 78, -56, 32, 85];
    2. /* 使用Math.min/Math.max以及apply 函数时的代码 */
    3. let max = Math.max.apply(null, arr1); /* 基本等同于 Math.max(numbers[0], ...) 或 Math.max(5, 6, ..) */
    4. let min = Math.min.apply(null, arr1);

8.3 bind

function.bind(thisArg[, arg1[, arg2[, ...]]])

  • bind() 方法创建一个新的函数,在 bind() 被调用时,这个新函数的 this 被指定为 bind() 的第一个参数,而其余参数将作为新函数的参数,供调用时使用。
  • 参数
    • thisArg
      调用绑定函数时作为 this 参数传递给目标函数的值。 如果使用new运算符构造绑定函数,则忽略该值。当使用 bind 在 setTimeout 中创建一个函数(作为回调提供)时,作为 thisArg 传递的任何原始值都将转换为 object。如果 bind 函数的参数列表为空,或者thisArg是null或undefined,执行作用域的 this 将被视为新函数的 thisArg。
    • arg1, arg2, ...
      当目标函数被调用时,被预置入绑定函数的参数列表中的参数。
  • 返回值
    返回一个原函数的拷贝,并拥有指定的 this 值和初始参数。

8.3.1 将一个类似于数组的对象(array-like object)转换成一个真正的数组
  1. Array.prototype.slice.apply(arguments);
  1. let funcSlice = Function.prototype.apply.bind(Array.prototype.slice);
  2. funcSlice(arguments);

9. 类数组

前端知识点汇总(1) - 图15

  • 类数组定义
    • length 属性
    • (0...length-1) 范围的整数属性
  • 比如:{length: 3, 0: 'a', 1: 'b', 2: 'c'}

9.1 类数组转换为真正的数组

前端知识点汇总(1) - 图16

  1. Array.prototype.slice.call(arguments)
  2. [].slice.call(arguments)
  3. Array.prototype.slice.apply(arguments)
  4. [].slice.apply(arguments)
    1. let funcSlice = Function.prototype.apply.bind(Array.prototype.slice);
    2. funcSlice(arguments);
  5. Array.from(arguments);

  6. [...arguments] 使用此方法有个前提,该元素必须包含iterable,VM287:1 Uncaught TypeError: arr is not iterable

9.1.1 Iterator(遍历器)的概念

Iterator(遍历器)的概念

MDN 迭代协议

  • next
    一个无参数函数,返回一个应当拥有以下两个属性的对象:
    • done(boolean)
      • 如果迭代器可以产生序列中的下一个值,则为 false。(这等价于没有指定 done 这个属性。)
      • 如果迭代器已将序列迭代完毕,则为 true。这种情况下,value 是可选的,如果它依然存在,即为迭代结束之后的默认返回值。
  • value
    • 迭代器返回的任何 JavaScript 值。done 为 true 时可省略。
  • next() 方法必须返回一个对象,该对象应当有两个属性: done 和 value,如果返回了一个非对象值(比如 false 或 undefined),则会抛出一个 TypeError 异常(”iterator.next() returned a non-object value”)。
  1. let arrLike = {length: 3, 0: 'a', 1: 'b', 2: 'c'};
  2. arrLike[Symbol.iterator] = function() {
  3. let nextIndex = 0;
  4. return {
  5. next: () => {
  6. return nextIndex < this.length ? {
  7. value: this[nextIndex++],
  8. done: false
  9. } : {
  10. done: true
  11. };
  12. }
  13. };
  14. }
  15. [...arrLike]; // ["a", "b", "c"]

10. for…of和for…in区别

前端知识点汇总(1) - 图17

  • for...in 遍历可枚举属性
  • for...of 迭代的数据

11. 防抖和节流

  • 防抖(debounce):**触发事件后n秒内函数只会执行一次,如果n秒内高频事件再次被触发,则重新计算时间。**
  • 节流(throttle):**高频事件触发,但在n秒内只会执行一次,所以节流会稀释函数的执行频率。**


  1. // 防抖
  2. function debounce(func, delay) {
  3. const [func1, delay2, ...args] = arguments;
  4. let timer = null;
  5. return () => {
  6. if (timer) {
  7. clearTimeout(timer);
  8. }
  9. timer = setTimeout(() => func.apply(this, args), delay);
  10. }
  11. }
  1. // 节流
  2. function throttle(fn, delay){
  3. const [func1, delay2, ...args] = arguments;
  4. let timer = null;
  5. return () => {
  6. if (!timer) {
  7. timer = setTimeout(() => {
  8. fn.apply(this, ...args);
  9. timer = null;
  10. }, delay)
  11. }
  12. }
  13. }
  1. // (立刻执行版)节流
  2. function throttle (action, delay) {
  3. let timeout = null
  4. let lastRun = 0
  5. return function () {
  6. if (timeout) {
  7. return
  8. }
  9. let elapsed = Date.now() - lastRun
  10. let context = this // 重新设定this指向用
  11. let args = arguments // 获取请求参数
  12. let runCallback = function () {
  13. lastRun = Date.now()
  14. timeout = false
  15. action.apply(context, args) // 使用apply将this执行绑定到当前函数
  16. }
  17. if (elapsed >= delay) {
  18. runCallback()
  19. } else {
  20. timeout = setTimeout(runCallback, delay)
  21. }
  22. }
  23. }

12. symbol

symbol无法被 for…in 以及 数组遍历到

13. 多维数组展开成一维数组

  1. function expand(arr) {
  2. while(arr.some(item=> Array.isArray(item))){
  3. // 关键点
  4. arr = [].concat(...arr)
  5. }
  6. return arr
  7. }
  8. expand([1, [2, 3, [4, 5]], [6, [[7, 8]]]]) // log: [1, 2, 3, 4, 5, 6, 7, 8]

14. splice和slice区别

14.0 区别

  • splice会修改原有数组,slice不会
  • splice返回值是修改的元素,slice返回值是选中的左闭右开区间内的元素

14.1 splice

splice() 方法通过删除或替换现有元素或者原地添加新的元素来修改数组,并以数组形式返回被修改的内容。此方法会改变原数组。

  1. let test = [0, 1, 2, 3, 4, 5]
  2. test.splice(2, 0, 666, 777); // out: [], test: [0, 1, 666, 777, 2, 3, 4, 5]
  3. test.splice(2, 1); // out: [666], test: [0, 1, 777, 2, 3, 4, 5]

image.png

14.2 slice

slice() 方法返回一个新的数组对象,这一对象是一个由 begin 和 end 决定的原数组的浅拷贝(包括 begin,不包括end)。原始数组不会被改变。

左闭右开区间

image.png

15. new

15.1 new做了什么操作

new 关键字会进行如下的操作:

  1. 创建一个空的简单JavaScript对象(即{});
  2. 为步骤1新创建的对象添加属性proto,将该属性链接至构造函数的原型对象 ;
  3. 将步骤1新创建的对象作为this的上下文 ;
  4. 如果该函数没有返回对象,则返回this

15.2 new演示说明

当代码 new Foo(…) 执行时,会发生以下事情:

  1. 一个继承自 Foo.prototype 的新对象被创建。
  2. 使用指定的参数调用构造函数 Foo,并将 this 绑定到新创建的对象。new Foo 等同于 new Foo(),也就是没有指定参数列表,Foo 不带任何参数调用的情况。
  3. 由构造函数返回的对象就是 new 表达式的结果。如果构造函数没有显式返回一个对象,则使用步骤1创建的对象。(一般情况下,构造函数不返回值,但是用户可以选择主动返回对象,来覆盖正常的对象创建步骤)

16. substr和substring区别

16.1 substr

image.png

16.2 substring

image.png

17. reduce

MDN参考文档
image.png
image.png

18. Array.of

image.png

三、CSS

1. 垂直居中方法

  1. display: flex;
  2. flex-direction: row;
  3. align-items: center;
  4. justify-content: center;
  1. line-height: 100px;
  1. display: inline-block;
  2. vertical-align:middle;
  • 绝对定位(缺点:需要计算)
  • **margin: 0 auto;**
  • top、margin

    1. position: relative; /* 相对定位或绝对定位均可 */
    2. width:500px;
    3. height:300px;
    4. top: 50%;
    5. left: 50%;
    6. margin: -150px 0 0 -250px; /* 外边距为自身宽高的一半 */
  • top、transform

    1. position: absolute; /* 相对定位或绝对定位均可 */
    2. width:500px;
    3. height:300px;
    4. top: 50%;
    5. left: 50%;
    6. transform: translate(-50%, -50%);

2. flex布局

页面分为中部无限滑动内容区三个部分,如何使用flex布局解决:

  1. <div style="display:flex; height: 100vh">
  2. <div style="height:40px"></div>
  3. <div style="flex:1; overflow:scroll">中部无限滑动区</div>
  4. <div style="height:40px"></div>
  5. </div>

3. transform、translate和transition

3.1 transform

前端知识点汇总(1) - 图25

3.2 translate

前端知识点汇总(1) - 图26

3.3 transition

前端知识点汇总(1) - 图27

4. 清除浮动

  1. .clear-fix
  2. &::after
  3. content: ""
  4. display: table
  5. clear: both

5. 0.5px边框

  1. .border-top-1px, .border-right-1px, .border-bottom-1px, .border-left-1px
  2. position: relative
  3. &::before, &::after
  4. content: ""
  5. display: block
  6. position: absolute
  7. transform-origin: 0 0
  8. .border-top-1px
  9. &::before
  10. border-top: 1px solid $color-row-line
  11. left: 0
  12. top: 0
  13. width: 100%
  14. transform-origin: 0 top
  15. .border-right-1px
  16. &::after
  17. border-right: 1px solid $color-col-line
  18. top: 0
  19. right: 0
  20. height: 100%
  21. transform-origin: right 0
  22. .border-bottom-1px
  23. &::after
  24. border-bottom: 1px solid $color-row-line
  25. left: 0
  26. bottom: 0
  27. width: 100%
  28. transform-origin: 0 bottom
  29. .border-left-1px
  30. &::before
  31. border-left: 1px solid $color-col-line
  32. top: 0
  33. left: 0
  34. height: 100%
  35. transform-origin: left 0
  36. @media (min-resolution: 2dppx)
  37. .border-top-1px
  38. &::before
  39. width: 200%
  40. transform: scale(.5) translateZ(0)
  41. .border-right-1px
  42. &::after
  43. height: 200%
  44. transform: scale(.5) translateZ(0)
  45. .border-bottom-1px
  46. &::after
  47. width: 200%
  48. transform: scale(.5) translateZ(0)
  49. .border-left-1px
  50. &::before
  51. height: 200%
  52. transform: scale(.5) translateZ(0)
  53. @media (min-resolution: 3dppx)
  54. .border-top-1px
  55. &::before
  56. width: 300%
  57. transform: scale(.333) translateZ(0)
  58. .border-right-1px
  59. &::after
  60. height: 300%
  61. transform: scale(.333) translateZ(0)
  62. .border-bottom-1px
  63. &::after
  64. width: 300%
  65. transform: scale(.333) translateZ(0)
  66. .border-left-1px
  67. &::before
  68. height: 300%
  69. transform: scale(.333) translateZ(0)

6. 重排和重绘

  • 重排
    • 重排一定引起重绘
    • DOM节点几何尺寸变更
  • 重绘
    • 仅DOM节点背景颜色,颜色之类的变更,不涉及几何变更
  • 故优化方案是尽可能修改className的方式变更元素,而不是style修改

7. 阻止用户复制

**user-select:none;**

8. flex-direction默认值

**row**

四、HTML

svg、canvas、语义化(footer、nav)、worker、audio和video

五、网络

1. HTTPS和HTTP

1.1 HTTP

  • 运行在TCP之上
  • 无状态协议
  • 一般是80端口
  • 请求报文:请求行 - 通用信息头 - 请求头 - 实体头 - 报文主体
  • 应答报文:状态行 - 通用信息头 - 响应头 - 实体头 - 报文主体
  • 请求过程:由HTTP客户端发起一个请求,创建一个到服务器指定端口(默认是80端口)的TCP连接。HTTP服务器则在那个端口监听客户端的请求。一旦收到请求,服务器会向客户端返回一个状态,比如”HTTP/1.1 200 OK”,以及返回的内容,如请求的文件、错误消息、或者其它信息。
  • 状态码
    • 1xx消息——请求已被服务器接收,继续处理
    • 2xx成功——请求已成功被服务器接收、理解、并接受
    • 3xx重定向——需要后续操作才能完成这一请求
      • 301 永久重定向,更新书签
      • 302 临时重定向,不更新数签
      • 303 跟302类似功能,只不过明确表示将POST请求改成GET请求
      • 前端知识点汇总(1) - 图28
      • 304 服务器允许请求访问资源,但未满足条件
      • 307 跟302类似功能,只不过会按照标准,不会将POST请求变更为GET请求
  • 4xx请求错误——请求含有词法错误或者无法被执行,客户端错误
  • 5xx服务器错误——服务器在处理某个正确请求时发生错误,服务器错误
  • HTTP缺点
    • 明文传送
    • 消息完整性检测的缺乏 (报文头部包含了本次传输数据的长度, 而对内容是否被篡改不作确认)

1.2 HTTPS

  • 一般是443端口
  • 提供对网站服务器的身份认证,保护交换数据的隐私与完整性。
  • HTTPS报文中的任何东西都被加密,包括所有报头和荷载
  • HTTPS = HTTP + SSL
  • HTTPS 在 HTTP 应用层的基础上使用安全套接字层作为子层。

1.3 HTTPS和HTTP区别

前端知识点汇总(1) - 图29
前端知识点汇总(1) - 图30

1.4 GET和POST区别

get把参数放在URL连接上,不安全,且在不同的浏览器有最大长度限制,理论上没限制。可缓存
post把请求参数放在消息主体里,不可缓存,后退刷新会重复提交,可携带更多参数。

1.5 三次握手

为了保证服务端能收接受到客户端的信息并能做出正确的应答而进行前两次(第一次和第二次)握手,为了保证客户端能够接收到服务端的信息并能做出正确的应答而进行后两次(第二次和第三次)握手。

1.6 用户浏览器地址栏输入到展示网页过程

前端知识点汇总(1) - 图31

2. header请求头 ???

3. HTTP缓存

  • 强缓存
    • 不发起http请求,直接使用本地缓存,浏览器地址栏回车,浏览器刷新按钮。Expires / max-age 生效的情况下,触发的都是
    • Expires 绝对过期时间
    • max-age 相对过期时间
    • cache-control=no-cache
  • 弱缓存(协商缓存)
    • 使用本地缓存前,先与服务器协商,核对缓存文件是否为最新。

4. 预检请求

  • 详细描述链接详见MDN

  • 重点讲一下为什么要预检请求:

    • 浏览器的同源策略,就是出于安全考虑(避免跨站请求伪造(英语:Cross-site request forgery)CSRF),浏览器会限制从脚本发起的跨域HTTP请求,像XMLHttpRequest和Fetch都遵循同源策略。

    • 浏览器限制跨域请求一般有两种方式:

      • 方式一:浏览器限制发起跨域请求
      • 方式二:跨域请求可以正常发起,但是返回的结果被浏览器拦截


  • 一般浏览器都是第二种方式限制跨域请求,造成的后果就是请求已到达服务器,并有可能对数据库里的数据进行了操作,但是返回的结果被浏览器拦截了,那么我们就获取不到返回结果,这是一次失败的请求,但是可能对数据库里的数据产生了影响

  • 为了防止这种情况的发生,规范要求,对这种可能对服务器数据产生副作用的HTTP请求方法,浏览器必须先使用 **OPTIONS** 方法发起一个预检请求,从而获知服务器是否允许该跨域请求:如果允许,就发送带数据的真实请求;如果不允许,则阻止发送带数据的真实请求

5. Cache-Control

image.png
image.png

六、git

1. reset和revert的区别

reset是真正意义上的回退到指定的以前的commit,提交需要添加‘-f
revert是反作用力,撤销之前提交的某个commit,中间的commit,之后的不撤销用此方法。
git revert -n commit-id

七、单元测试

组件的单元测试有很多好处:

  • 提供描述组件行为的文档
  • 节省手动测试的时间
  • 减少研发新特性时产生的 bug
  • 改进设计
  • 促进重构