前端面试复习干货最初版(仅用于个人使用)

前端面试复习干货

一、什么是跨域?

跨域,是指浏览器不能执行其他网站的脚本。它是由浏览器的同源策略造成的,是浏览器对JavaScript实施的安全限制。

这里说明一下,无法跨域是浏览器对于用户安全的考虑,如果自己写个没有同源策略的浏览器,完全不用考虑跨域问题了。是浏览器的锅,对。

同源策略限制了一下行为:

Cookie、LocalStorage 和 IndexDB 无法读取

DOM 和 JS 对象无法获取

Ajax请求发送不出去

二、ajax请求原理?

通过浏览器内置对象xmlHttpRequest向服务器端发送数据,然后通过js操作dom实现数据刷新。

三、盒模型

一个盒子中主要的属性就5个:width、height、padding、border、margin。如下:

  • width和height:内容的宽度、高度(不是盒子的宽度、高度)。
  • padding:内边距。
  • border:边框。
  • margin:外边距。

标准盒模型: width 不包含border padding
ie盒模型: width 包含border padding

四、深拷贝和浅拷贝的区别 (只针对引用数据类型)

1、浅拷贝

  // 浅拷贝
  var arr = [1,2,3,4] 
      arr1 = arr
  arr[0] = 0;
  console.log(arr,arr1)

改变arr的同时arr1也发生了改变这就是浅拷贝
浅拷贝

2、深拷贝

  var arrList = [1,2,3,4,{"list":[1,2,3,4,6]}]
  // 深拷贝(针对引用数据类型的拷贝)
  // 方法一 deepClone(arrList)就是拷贝的新数组
  function deepClone(obj){
    // 判断是对象还是数组并创建一个空的来承接
    var arr = Array.isArray(obj)?[]:{};
    // 如果属于对象的话
    if(obj && typeof obj === 'object'){
      for(key in obj){
        // 如果对象中含有私有属性
        if(obj.hasOwnProperty(key)){
          //判断obj子元素是否为对象,如果是,递归复制
          if(obj[key] && typeof obj[key] === 'object'){
            arr[key] = deepClone(obj[key])
          }else{
            arr[key] = obj[key]
          }
        }
      }
      return arr
    }
  }
  console.log(deepClone(arrList))
  // 方法二 newArrList就是拷贝的新数组
  var newArrList = JSON.parse(JSON.stringify(arrList))

四、什么是继承?

JS继承的实现方式:

// 定义一个动物类
function Animal (name) {
  // 属性
  this.name = name || 'Animal';
  // 实例方法
  this.sleep = function(){
    console.log(this.name + '正在睡觉!');
  }
}
// 原型方法
Animal.prototype.eat = function(food) {
  console.log(this.name + '正在吃:' + food);
};

1、原型链继承

function Cat(){ 
}
Cat.prototype = new Animal();
Cat.prototype.name = 'cat';

var cat = new Cat();
console.log(cat.name);
console.log(cat.eat('fish'));
console.log(cat.sleep());
console.log(cat instanceof Animal); //true 
console.log(cat instanceof Cat); //true

2、构造继承

function Cat(name){
  Animal.call(this);
  this.name = name || 'Tom';
}

var cat = new Cat();
console.log(cat.name);
console.log(cat.sleep());
console.log(cat instanceof Animal); // false
console.log(cat instanceof Cat); // true

3、实例继承

function Cat(name){
  var instance = new Animal();
  instance.name = name || 'Tom';
  return instance;
}

var cat = new Cat();
console.log(cat.name);
console.log(cat.sleep());
console.log(cat instanceof Animal); // true
console.log(cat instanceof Cat); // false

4、拷贝继承

function Cat(name){
  var animal = new Animal();
  for(var p in animal){
    Cat.prototype[p] = animal[p];
  }
  this.name = name || 'Tom';
}

var cat = new Cat();
console.log(cat.name);
console.log(cat.sleep());
console.log(cat instanceof Animal); // false
console.log(cat instanceof Cat); // true

5、组合继承

function Cat(name){
  Animal.call(this);
  this.name = name || 'Tom';
}
Cat.prototype = new Animal();
Cat.prototype.constructor = Cat;

var cat = new Cat();
console.log(cat.name);
console.log(cat.sleep());
console.log(cat instanceof Animal); // true
console.log(cat instanceof Cat); // true

6、寄生组合继承

function Cat(name){
  Animal.call(this);
  this.name = name || 'Tom';
}
(function(){
  // 创建一个没有实例方法的类
  var Super = function(){};
  Super.prototype = Animal.prototype;
  //将实例作为子类的原型
  Cat.prototype = new Super();
})();

var cat = new Cat();
console.log(cat.name);
console.log(cat.sleep());
console.log(cat instanceof Animal); // true
console.log(cat instanceof Cat); //true
Cat.prototype.constructor = Cat; 

五、节流和防抖

  • 防抖:举个例子当屏幕滚动的时候会持续的触发scroll事件但是如果设置了防抖的话,如果我设置防抖时长是一秒的话,我会在scroll事件触发后一秒的时候执行,如果我再次触发scroll事件时间又会重新计算
  • 节流:举个例子当屏幕滚动不停的触发scroll事件的时候,我会每隔一秒执行以下不管scroll触发多少次我都会一秒以后执行一次

六、闭包

闭包的特点

  • .函数嵌套函数,内部函数可以引用外部函数的参数和变量
  • 参数和变量不会被垃圾回收机制所收回

闭包的好处

  • 变量长期保存在内存当中
  • 避免变量被全局环境污染
  function fnAn(){
    var a = 1;
    return function(){
      return a
    } 
  }
  var a = fnAn() 
  console.log(a())

七、链式调用

这个很容易理解,例如:

$('div').setStyle('color', 'red').show();
  function fn(){
    this.age=28;
    this.name='行走的五花肉'
    this.work = function(){
      console.log(this.age)
      return this;
    }
    this.like = function(){
      console.log(this.name)
      return this;
    }
  }
  var tellMsg = new fn();
  //一般的函数调用
  // tellMsg.work()
  // tellMsg.like()
  //链式调用
  tellMsg.work().like()

一般的函数调用和链式调用的区别:链式调用完方法后,return this返回当前调用方法的对象。
优点是:简化代码,让代码更加简洁、易读,同时也避免多次重复使用一个对象变量

八、同步和异步

参考文献:
JS 是单线程,你了解其运行机制吗 ?
关于setTimeOut和Promise执行顺序的问题

知识点:宏任务(macrotask)和微任务(microtask)

  • 同步任务指的是,在主线程上排队执行的任务,只有前一个任务执行完毕,才能执行后一个任务;
  • 异步任务指的是,不进入主线程、而进入"任务队列"(task queue)的任务,只有等主线程任务执行完毕,"任务队列"开始通知主线程,请求执行任务,该任务才会进入主线程执行。
    异步任务包括宏任务和微任务,宏任务的优先级高于微任务

九、递归

函数自身调用自身就是递归具体可以参考js原生深拷贝的方法

十、冒泡排序

  function guLuSort(arr) {
    var len = arr.length;
    for (var i = 0; i < len - 1; i++) {
      for (var j = 0; j < len - 1 - i; j++) {
        // 相邻元素两两对比,元素交换,大的元素交换到后面
        if (arr[j] > arr[j + 1]) {
          var temp = arr[j];
          arr[j] = arr[j + 1];
          arr[j + 1] = temp;
        }
      }
    }
    return arr;
  }
  //使用函数
  console.log(guLuSort([34, 18, 27, 19, 35]))

相邻两个元素进行比较如果前一个元素大那么就交换位置

十一、块级格式化上下文

参考文献:块级格式化上下文

具有BFC属性的元素也属于普通流定位方式,与普通容器没有什么区别,但是在功能上,具有BFC的元素可以看做是隔离了的独立容器,容器里面的元素不会在布局上影响到外面的元素,并且具有普通容器没有的一些特性,比如包含浮动元素,以防止出现高度塌陷问题。

如何触发BFC

  • 浮动元素:float除none以外的值
  • 绝对定位元素:position(absolute、fixed)
  • display为以下其中之一的值inline-block、flex、inline-flex、table-cell、table-caption
  • overflow除了visible以外的值(hidden、auto、scroll)

十二、常见兼容问题

  • Ie盒模型和标准盒模型不同
  • 块属性标签float后,又有横行的margin情况下,在IE6显示margin比设置的大
  • 设置较小高度标签(一般小于10px),在IE6,IE7,遨游中高度超出自己设置高度
  • 行内属性标签,设置display:block后采用float布局,又有横行的margin的情况,IE6间距bug
  • 图片默认有间距
  • 标签最低高度设置min-height不兼容
  • 透明度的兼容CSS设置

十三、this指向问题

谁调用它指向得就是谁(是否有调用者),无调用者默认是window

  //this指向问题
  var num = 10;
  function test() {
    console.log(num);
    num = 100;
    console.log(this.num);
    var num;
    console.log(num);
  }
  test(); //undefined、10、100
  //undefined 因为num = 100变量提升了所以是undefined
  //10 因为没有对象调用test()方法,this指向window.输出10
  //100 

十四、vue中key的作用

key 的特殊 attribute 主要用在 Vue 的虚拟 DOM 算法,在新旧 nodes 对比时辨识 VNodes。如果不使用 key,Vue 会使用一种最大限度减少动态元素并且尽可能的尝试就地修改/复用相同类型元素的算法。而使用 key 时,它会基于 key 的变化重新排列元素顺序,并且会移除 key 不存在的元素。

有相同父元素的子元素必须有独特的 key。重复的 key 会造成渲染错误。
最常见的用例是结合 v-for:

<ul>
  <li v-for="item in items" :key="item.id">...</li>
</ul>

它也可以用于强制替换元素/组件而不是重复使用它。当你遇到如下场景时它可能会很有用:

  • 完整地触发组件的生命周期钩子
  • 触发过渡

例如:

<transition>
  <span :key="text">{{ text }}</span>
</transition>

当 text 发生改变时, 总是会被替换而不是被修改,因此会触发过渡。

十五、call bind apply的区别

call apply不仅改变this指向,而且会调用函数
bind只是改变了this但是函数并不会执行

十六、如何解决vue打开白屏时间过长的问题?

1.路由懒加载
2.cdn引入外部资源
3.图片用网图
4.修改config里面的sourcemap属性

十七、二维数组转一维数组?

参考链接:二维数组转一维数组的多种方法

  var erwArr = [1, 2, 3, [4, 5, 6],[10, 12, 33]]
  //es5写法
  function resArray1(arr){
    return [].concat.apply([],arr)
  }
  console.log(resArray1(erwArr))
  //es6写法
  function resArray(arr) {
    return [].concat(...arr.map((item)=>Array.isArray(item)?resArray(item):item))
  }
  console.log(resArray(erwArr))

十八、如何优化vue运行过慢,打包完以后体积过大的问题

十九、双飞翼布局和圣杯布局

参考文献

中间固定两边自适应,双飞翼是借住margin-left负数 圣杯布局是借住position relative

二十、事件冒泡和事件捕获通过什么节点传递的

二十一、vue路由的几种模式?

hash模式、history模式以及两者的区别


VUE.js常问考点

vue的基本原理是什么?(出自:https://cn.vuejs.org/v2/guide/reactivity.html

当你把一个普通的 JavaScript 对象传入 Vue 实例作为 data 选项,Vue 将遍历此对象所有的 property,并使用 Object.defineProperty 把这些 property 全部转为 getter/setter。Object.defineProperty 是 ES5 中一个无法 shim 的特性,这也就是 Vue 不支持 IE8 以及更低版本浏览器的原因。

这些 getter/setter 对用户来说是不可见的,但是在内部它们让 Vue 能够追踪依赖,在 property 被访问和修改时通知变更。这里需要注意的是不同浏览器在控制台打印数据对象时对 getter/setter 的格式化并不同,所以建议安装 vue-devtools 来获取对检查数据更加友好的用户界面。

每个组件实例都对应一个 watcher 实例,它会在组件渲染的过程中把“接触”过的数据 property 记录为依赖。之后当依赖项的 setter 触发时,会通知 watcher,从而使它关联的组件重新渲染。

1、vue页面传递参数有几种方式?

方式1:query传参的方式 (特点:刷新页面参数不丢失)
方式2:params传参的方式 (特点:刷新页面参数会丢失)解决方法:在route.js中增加参数名

 {path: '/intergral/addresslist/:id', component: AddressList, meta: {title: '收货地址',}}

2、vue组件通信有哪几种

1.父传子
父组件中传递:

<sec-kill :objDetails="objDetails"></sec-kill>

子组件中通过props接收:

  props: {
    //商品或者课程详情
    objDetails: {
      type: Object,
      default: function () {
        return {}
      }
    }
  }

2.子传父
子组件中用thi.$emit()触发一个方法

	  //关闭弹窗 
      closeDown() {
      	//第一个参数为触发的方法名 
      	//第二个为要传递的参数
        this.$emit('hideDownload',false)
      }

父组件中监听这个方法

<!-- 子组件触发的什么方法父组件就用@监听 -->
<downApp @hideDownload='hideDownload'></downApp>
    methods: {
      // 判断下载APP是否显示 msg: true 显示 false不显示
      hideDownload(msg){
        msg?this.addSize=true:this.addSize=false
      }
    }

3.兄弟组件
通过一个bus.js的js文件
js文件内容:

import Vue from 'vue'
//定义空的vue实例,作为实现非父子组件之间的通信
var goBackEntity = new Vue({});
export default goBackEntity;

使用方法:
1.在需要的页面引入bus.js 我这里叫whitePage.js随便什么都行
引入方式
2.这里我理解为跟子组件往父组件传值类似 fromRelease为要触发的方法名 第二个参数是要传递的参数

eventBus.$emit('fromRelease',true);

3.然后就是接收的问题了,在需要接收的文件中同样引入这个bus.js紧接着使用:

eventBus.$on('fromRelease', (e) => {
    //这个e就是传递过来的那个true
   console.log(e)
})

3、什么是 mvvm?

MVVM 是 Model-View-ViewModel 的缩写。mvvm 是一种设计思想。Model 层代表数据模型,也可以在 Model 中定义数据修改和操作的业务逻辑;View 代表 UI 组件,它负责将数据模型转化成 UI 展现出来,ViewModel 是一个同步 View 和 Model 的对象。

在 MVVM 架构下,View 和 Model 之间并没有直接的联系,而是通过 ViewModel 进行交互,Model 和 ViewModel 之间的交互是双向的, 因此 View 数据的变化会同步到 Model 中,而 Model 数据的变化也会立即反应到 View 上。

ViewModel 通过双向数据绑定把 View 层和 Model 层连接了起来,而 View 和 Model 之间的同步工作完全是自动的,无需人为干涉,因此开发者只需关注业务逻辑,不需要手动操作 DOM, 不需要关注数据状态的同步问题,复杂的数据状态维护完全由 MVVM 来统一管理。

4、mvvm 和 mvc 区别?

mvc 和 mvvm 其实区别并不大。都是一种设计思想。主要就是 mvc 中 Controller 演变成 mvvm 中的 viewModel。mvvm 主要解决了 mvc 中大量的 DOM 操作使页面渲染性能降低,加载速度变慢,影响用户体验。和当 Model 频繁发生变化,开发者需要主动更新到 View 。

5、vue 的优点是什么?

  1. 低耦合。视图(View)可以独立于 Model 变化和修改,一个 ViewModel 可以绑定到不同的"View"上,当 View 变化的时候 Model 可以不变,当 Model 变化的时候 View 也可以不变。
  2. 可重用性。你可以把一些视图逻辑放在一个 ViewModel 里面,让很多 view 重用这段视图逻辑。
  3. 独立开发。开发人员可以专注于业务逻辑和数据的开发(ViewModel),设计人员可以专注于页面设计,使用 Expression Blend 可以很容易设计界面并生成 xml 代码。
  4. 可测试。界面素来是比较难于测试的,而现在测试可以针对 ViewModel 来写。

6、vue生命周期的理解?

总共分为 8 个阶段创建前/后,载入前/后,更新前/后,销毁前/后。

  1. 创建前/后: 在 beforeCreate 阶段,vue 实例的挂载元素 el 还没有。
  2. 载入前/后:在 beforeMount 阶段,vue 实例的$el 和 data 都初始化了,但还是挂载之前为虚拟的 dom 节点,data.message 还未替换。在 mounted 阶段,vue 实例挂载完成,data.message 成功渲染。
  3. 更新前/后:当 data 变化时,会触发 beforeUpdate 和 updated 方法。
  4. 销毁前/后:在执行 destroy 方法后,对 data 的改变不会再触发周期函数,说明此时 vue 实例已经解除了事件监听以及和 dom 的绑定,但是 dom 结构依然存在

7、active-class 是哪个组件的属性

参考文献:active-class的用法
vue-router 模块的 router-link 组件。

8、嵌套路由怎么定义?

在实际项目中我们会碰到多层嵌套的组件组合而成,但是我们如何实现嵌套路由呢?因此我们需要在 VueRouter 的参数中使用 children 配置,这样就可以很好的实现路由嵌套。
index.html,只有一个路由出口

<div id="app">
    <!-- router-view 路由出口, 路由匹配到的组件将渲染在这里 -->
    <router-view></router-view>
</div>

main.js,路由的重定向,就会在页面一加载的时候,就会将 home 组件显示出来,因为重定向指向了 home 组件,redirect 的指向与 path 的必须一致。children 里面是子路由,当然子路由里面还可以继续嵌套子路由。

import Vue from 'vue'
import VueRouter from 'vue-router'
Vue.use(VueRouter)

//引入两个组件

import home from "./home.vue"
import game from "./game.vue"
//定义路由
const routes = [
    { path: "/", redirect: "/home" },//重定向,指向了home组件
    {
        path: "/home", component: home,
        children: [
            { path: "/home/game", component: game }
        ]
    }
]
//创建路由实例
const router = new VueRouter({routes})

new Vue({
    el: '#app',
    data: {
    },
    methods: {
    },
    router
})

home.vue,点击显示就会将子路由显示在出来,子路由的出口必须在父路由里面,否则子路由无法显示。

9、路由之间跳转?

声明式(标签跳转)
编程式( js 跳转) router.push(‘index’)

10、懒加载(按需加载路由)?

webpack 中提供了 require.ensure()来实现按需加载。以前引入路由是通过 import 这样的方式引入,改为 const 定义的方式进行引入。

  • 不进行页面按需加载引入方式:
import  home   from '../../common/home.vue'
  • 进行页面按需加载的引入方式:
const  home = r => require.ensure( [], () => r (require('../../common/home.vue')))

11、vuex 是什么?怎么使用?哪种功能场景使用它?

vue 框架中状态管理。在 main.js 引入 store,注入。新建了一个目录 store,…… export 。场景有:单页应用中,组件之间的状态。音乐播放、登录状态、加入购物车

// 新建 store.js
import vue from 'vue'
import vuex form 'vuex'
vue.use(vuex)
export default new vuex.store({
    //...code
})

//main.js
import store from './store'
...

12、vue-router 有哪几种导航钩子?

  • 全局导航钩子
    router.beforeEach(to, from, next)
    router.beforeResolve(to, from, next)
    router.afterEach(to, from ,next)

  • 组件内钩子
    beforeRouteEnter
    beforeRouteUpdate
    beforeRouteLeave

  • 单独路由独享组件
    beforeEnter

13、自定义指令(v-check, v-focus) 的方法有哪些? 它有哪些钩子函数? 还有哪些钩子函数参数?

  • 全局定义指令:在 vue 对象的 directive 方法里面有两个参数, 一个是指令名称, 另一个是函数。
  • 组件内定义指令:directives(vue中directives的用法
  • 钩子函数: bind(绑定事件出发)、inserted(节点插入时候触发)、update(组件内相关更新)
  • 钩子函数参数: el、binding

14、说出至少 4 种 vue 当中的指令和它的用法

v-if(判断是否隐藏)、v-for(把数据遍历出来)、v-bind(绑定属性)、v-model(实现双向绑定)

15、vue 的双向绑定的原理是什么

vue.js 是采用数据劫持结合发布者-订阅者模式的方式,通过 Object.defineProperty()来劫持各个属性的 setter,getter,在数据变动时发布消息给订阅者,触发相应的监听回调。

具体步骤:
第一步:需要 observe 的数据对象进行递归遍历,包括子属性对象的属性,都加上 setter 和 getter 这样的话,给这个对象的某个值赋值,就会触发 setter,那么就能监听到了数据变化

第二步:compile 解析模板指令,将模板中的变量替换成数据,然后初始化渲染页面视图,并将每个指令对应的节点绑定更新函数,添加监听数据的订阅者,一旦数据有变动,收到通知,更新视图

第三步:Watcher 订阅者是 Observer 和 Compile 之间通信的桥梁,主要做的事情是:

  • 在自身实例化时往属性订阅器(dep)里面添加自己

  • 自身必须有一个 update()方法

  • 待属性变动 dep.notice()通知时,能调用自身的 update() 方法,并触发 Compile 中绑定的回调,则功成身退。

第四步:MVVM 作为数据绑定的入口,整合 Observer、Compile 和 Watcher 三者,通过 Observer 来监听自己的 model 数据变化,通过 Compile 来解析编译模板指令,最终利用 Watcher 搭起 Observer 和 Compile 之间的通信桥梁,达到数据变化 -> 视图更新;视图交互变化(input) -> 数据 model 变更的双向绑定效果。

16、vuex 有哪几种属性

有 5 种,分别是 state、getter、mutation、action、module

17、vuex 的 store 特性是什么

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

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

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

18、vuex 的 getter 特性是什么

  • getter 可以对 state 进行计算操作,它就是 store 的计算属性

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

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

19、vuex 的 mutation 特性是什么

  • action 类似于 muation, 不同在于:action 提交的是 mutation,而不是直接变更状态

  • action 可以包含任意异步操作

20、vue 中 ajax 请求代码应该写在组件的 methods 中还是 vuex 的 action 中

  • 如果请求来的数据不是要被其他组件公用,仅仅在请求的组件内使用,就不需要放入 vuex 的 state 里

  • 如果被其他地方复用,请将请求放入 action 里,方便复用,并包装成 promise 返回

21、vuex 原理

  • vuex 仅仅是作为 vue 的一个插件而存在,不像 Redux,MobX 等库可以应用于所有框架,vuex 只能使用在 vue 上,很大的程度是因为其高度依赖于 vue 的 computed 依赖检测系统以及其插件系统,

  • vuex 整体思想诞生于 flux,可其的实现方式完完全全的使用了 vue 自身的响应式设计,依赖监听、依赖收集都属于 vue 对对象 Property set get 方法的代理劫持。最后一句话结束 vuex 工作原理,vuex 中的 store 本质就是没有 template 的隐藏着的 vue 组件;

22、使用 Vuex 只需执行 Vue.use(Vuex),并在 Vue 的配置中传入一个 store 对象的示例,store 是如何实现注入的?

Vue.use(Vuex) 方法执行的是 install 方法,它实现了 Vue 实例对象的 init 方法封装和注入,使传入的 store 对象被设置到 Vue 上下文环境的store中。因此在VueComponent任意地方都能够通过this.store 访问到该 store。

23、state 内部支持模块配置和模块嵌套,如何实现的?

在 store 构造方法中有 makeLocalContext 方法,所有 module 都会有一个 local context,根据配置时的 path 进行匹配。所以执行如 dispatch(‘submitOrder’, payload)这类 action 时,默认的拿到都是 module 的 local state,如果要访问最外层或者是其他 module 的 state,只能从 rootState 按照 path 路径逐步进行访问。

24、在执行 dispatch 触发 action(commit 同理)的时候,只需传入(type, payload),action 执行函数中第一个参数 store 从哪里获取的?

store 初始化时,所有配置的 action 和 mutation 以及 getters 均被封装过。在执行如 dispatch(‘submitOrder’, payload)的时候,actions 中 type 为 submitOrder 的所有处理方法都是被封装后的,其第一个参数为当前的 store 对象,所以能够获取到 { dispatch, commit, state, rootState } 等数据。

25、Vuex 如何区分 state 是外部直接修改,还是通过 mutation 方法修改的?

Vuex 中修改 state 的唯一渠道就是执行 commit(‘xx’, payload) 方法,其底层通过执行 this._withCommit(fn) 设置_committing 标志变量为 true,然后才能修改 state,修改完毕还需要还原_committing 变量。外部修改虽然能够直接修改 state,但是并没有修改_committing 标志位,所以只要 watch 一下 state,state change 时判断是否_committing 值为 true,即可判断修改的合法性。

26、调试时的"时空穿梭"功能是如何实现的?

devtoolPlugin 中提供了此功能。因为 dev 模式下所有的 state change 都会被记录下来,‘时空穿梭’ 功能其实就是将当前的 state 替换为记录中某个时刻的 state 状态,利用 store.replaceState(targetState) 方法将执行 this._vm.state = state 实现。

27、axios 是什么?怎么使用?描述使用它实现登录功能的流程

axios 是请求后台资源的模块。 npm i axios -S
如果发送的是跨域请求,需在配置文件中 config/index.js 进行配置

28、不用 vuex 会带来什么问题

  • 可维护性会下降,你要修改数据,你得维护 3 个地方

  • 可读性下降,因为一个组件里的数据,你根本就看不出来是从哪里来的

  • 增加耦合,大量的上传派发,会让耦合性大大的增加,本来 Vue 用 Component 就是为了减少耦合,现在这么用,和组件化的初衷相背

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值