vue2.0面试题整理

1.vue中MVVM的理解

M:模型(Model):数据模型;负责数据存储。泛指后端进行的各种业务逻辑处理和数据操控,主要围绕数据库系统展开。
V:View 视图: 负责页面展示,也就是用户界面。主要由 HTML 和 CSS 来构建
VM:视图模型(View-Model): 负责业务逻辑处理(比如Ajax请求等),对数据进行加工后交给视图展示
通过vue类创建的对象叫Vue实例化对象,这个对象就是MVVM模式中的VM层,模型通过它可以将数据绑定到页面上,视图可以通过它将数据映射到模型上

优点
1.低耦合。视图(View)可以独立于Model变化和修改,
2.可重用性。你可以把一些视图逻辑放在一个ViewModel里面,让很多view重用这段视图逻辑
3.前后端分离,开发人员可以专注于业务逻辑(ViewModel)和数据的开发,设计人员可以专注于页面设计

目前三大框架vue、react、angular基本都是mvvm模式了,之前老的项目可能会用到mvc,例如angular.js,不过现在用angular.js开发的基本很少了。

2.为什么说VUE是一个渐进式的javascript框架, 渐进式是什么意思?

VUE允许你将一个网页分割成可复用的组件,每个组件都包含属于自己的HTML、CSS、JAVASCRIPT以用来渲染网页中相应的地方。对于VUE的使用可大可小,它都会有相应的方式来整合到你的项目中。所以说它是一个渐进式的框架。VUE是响应式的(reactive)这是VUE最独特的特性,也就是说当我们的数据变更时,VUE会帮你更新所有网页中用到它的地方。

3.vue生命周期

Vue 实例从创建到销毁的过程,就是生命周期。从开始创建、初始化数据、编译模板、挂载Dom→渲染、更新→渲染、销毁等一系列过程,称之为 Vue 的生命周期。

beforeCreate(创建前) :组件实例被创建之初,组件的属性生效之前
// beforeCreate生命周期执行的时候,data和methods中的数据都还没有初始化。不能在这个阶段使用data中的数据和methods中的方法

created(创建后) :组件实例已经完全创建,属性也绑定,但真实 dom 还没有生成,$el 还不可用
// data 和 methods都已经被初始化好了,如果要调用 methods 中的方法,或者操作 data 中的数据,最早可以在这个阶段中操作

beforeMount(挂载前) :在挂载开始之前被调用:相关的 render 函数首次被调用
// 执行到这个钩子的时候,在内存中已经编译好了模板了,但是还没有挂载到页面中,此时,页面还是旧的

mounted(挂载后) :在el 被新创建的 vm.$el 替换,并挂载到实例上去之后调用该钩子
// 到mounted周期的时候,Vue实例已经初始化完成了。此时组件脱离了创建阶段,进入到了运行阶段。 如果我们想要通过插件操作页面上的DOM节点,最早可以在和这个阶段中进行

beforeUpdate(更新前) :组件数据更新之前调用,真实DOM还没被渲染
// 当执行这个钩子时,页面中的显示的数据还是旧的,data中的数据是更新后的,页面还没有和最新的数据保持同步

update(更新后) :组件数据更新之后
// 页面显示的数据和data中的数据已经保持同步了,都是最新的

activated(激活前) :keep-alive专属,组件被激活时调用
// 当组件被切回来时,再去缓存里找这个组件、触发 activated钩子函数。

deactivated(激活后) :keep-alive专属,组件被销毁时调用
// 当组件被换掉时,会被缓存到内存中、触发 deactivated 生命周期

beforeDestory(销毁前) :组件销毁前调用
// Vue实例从运行阶段进入到了销毁阶段,这个时候上所有的 data 和 methods , 指令, 过滤器 ……都是处于可用状态。还没有真正被销毁

destoryed(销毁后) :组件销毁前调用
// 这个时候上所有的 data 和 methods , 指令, 过滤器 ……都是处于不可用状态。组件已经被销毁了。

4.Vue子组件和父组件执行顺序

加载渲染过程:beforeCreate(父) —> created(父)—>beforeMount(父)—>beforeCreate(子)—>created(子)—>beforeMount(子)—>mounted(子)—>mounted(父)
更新过程:beforeUpdate(父) —> beforeUpdate(子) —> update(子) —> update(父)
父组件更新:beforeUpdate(父) —> updated(父)
销毁过程:beforeDestory(父) —> beforeDestory(子) —> destoryed(子) —> destoryed(父)

5.v-el 作用

提供一个在页面上已存在的 DOM 元素作为 Vue 实例的挂载目标。可以是 CSS 选择器,也可以是一个 HTMLElement 实例。

6.Vue的el属性和$mount优先级?

new Vue({
  router,
  store,
  el: '#app',
  render: h => h(App)
}).$mount('#div')
/*当出现上面的情况就需要对el和$mount优先级进行判断,从下面的官方图片我们可以看出来,
el的优先级是高于$mount的,因此以el挂载节点为准*/

7.Vue实现数据双向绑定的原理:Object.defineProperty()

vue实现数据双向绑定主要是:采用数据劫持结合发布者-订阅者模式的方式,通过Object.defineProperty()来劫持各个属性的setter,getter,在数据变动时发布消息给订阅者,触发相应监听回调。
vue的数据双向绑定 将MVVM作为数据绑定的入口,整合Observer,Compile和Watcher三者,通过Observer来监听自己的model的数据变化,通过Compile来解析编译模板指令(vue中是用来解析 {{}}),最终利用watcher搭起observer和Compile之间的通信桥梁,达到数据变化 —>视图更新;视图交互变化(input)—>数据model变更双向绑定效果。

<script type="text/javascript">
    var obj = {}
    Object.defineProperty(obj, 'txt', {
        get: function () {
            return obj
        },
        set: function (newValue) {
            document.getElementById('txt').value = newValue
            document.getElementById('show').innerHTML = newValue
        }
    })
    document.addEventListener('keyup', function (e) {
        obj.txt = e.target.value
    })
</script>

8.假如data里面的数据不想做响应式,该怎么做

1.数据放在vue实例外(vue template中访问不到数据)
2.created, mounted钩子函数中定义(注意data中不要声明该变量名)
3.自定义Options
4.Object.freeze()

9.如何将获取data中某一个数据的初始状态?

data() {
   return {
     num: 10
    }
 },
mounted() {
   this.num = 1000
 },
methods: {
   countNum() {
   	// 可以通过this.$options.data().keyname来获取初始值
       // 计算出num增加了多少
       console.log(1000 - this.$options.data().num)
   }
 }

10.动态给vue的data添加一个新的属性时为什么不刷新?怎样解决?

原因:
一开始data里面的obj的属性会被设成了响应式数据,而后面新增的属性,并没有通过Object.defineProperty设置成响应式数据,所以当我们动态添加的时候并不会刷新。

解决方法:

1、Vue.set()
/*参数
{Object | Array} target
{string | number} propertyName/index
{any} value*/
Vue.set(this.list, 0, {name: 'zhangsan', age: 18})
this.$set(this.list, 0, {name: 'zhangsan', age: 18})
//如果是在组件中使用,就不能直接使用Vue实例来调用,但是可以使用this

2、Object.assign()
//直接使用Object.assign()添加到对象的新属性不会触发更新, 应创建一个新的对象,合并原对象和混入对象的属性
this.someObject = Object.assign({},this.someObject,{newProperty1:1,newProperty2:2 ...})

3、$forceUpdate()
//$forceUpdate迫使Vue 实例重新渲染,且仅仅影响实例本身和插入插槽内容的子组件,而不是所有子组件。

总结:
如果为对象添加少量的新属性,可以直接采用Vue.set()
如果需要为新对象添加大量的新属性,则通过Object.assign()创建新对象
如果你实在不知道怎么操作时,可采取$forceUpdate()进行强制刷新 (不建议)

PS:vue3是用过proxy实现数据响应式的,直接动态添加新属性仍可以实现数据响应式

11.Vue.observable

Vue.observable,让一个对象变成响应式数据。Vue 内部会用它来处理 data 函数返回的对象返回的对象可以直接用于渲染函数和计算属性内,并且会在发生变更时触发相应的更新。也可以作为最小化的跨组件状态存储器

使用场景:

/*在非父子组件通信时,可以使用通常的bus或者使用vuex,但是一些小项目上功能不是太复杂,
而使用上面两个又有点繁琐。这时,observable就是一个很好的选择*/

// 先新建一个js文件,引入vue
import Vue from 'vue
// 创建state对象,使用observable让state对象可响应
export let state = Vue.observable({
  name: '张三',
  age: 18
})
// 创建对应的方法
export let mutations = {
  changeName(name) {
    state.name = name
  },
  setAge(age) {
    state.age = age
  }
}

//在需要使用的文件中获取
<template>
  <div>
    <p>姓名:{{ name }}</p>
    <p>年龄:{{ age }}</p>
    <button @click="changeName('李四')">改变姓名</button>
    <button @click="setAge(20)">改变年龄</button>
  </div>
</template>
import { state, mutations } from '@/store
export default {
  // 在计算属性中拿到值
  computed: {
    name() {
      return state.name
    },
    age() {
      return state.age
    }
  },
  // 调用mutations里面的方法,更新数据
  methods: {
    changeName: mutations.changeName,
    setAge: mutations.setAge
  }
}

12.动态指令设置及动态传参

<template>
    ...
    <child @[someEvent]="handleSomeEvent()" :[someProps]="1000" />...
</template>
<script>
  ...
  data(){
    return{
      ...
      someEvent: type ? "click" : "dbclick",
      someProps: type ? "num" : "price"
    }
  },
  methods: {
    handleSomeEvent(){
      // do some
    }
  }  
</script>
//应用场景:用于页面中根据不同的返回值进行事件的触发和值的传参

13.Vue组件间的参数传递

1.父子间传值: props/$emit、 v-model:xxxx与update:xxxx、 ref、v-slot
2.非父子组件间的数据传递: vuex、 provide与inject、借用eventBus(就是创建一个事件中心,相当于中转站,可以用它来传递事件和接收事件。发送数据使用 $emit方法,使用 $on 接收)

provide和inject使用(响应式)是用来实现父组件向深层的子组件传值和接收的语法

// 祖先组件
provide(){
    return {
   	  // keyName: { name: this.name }, // value 是对象才能实现响应式,也就是引用类型
      keyName: this.changeValue // 通过函数的方式也可以[注意,这里是把函数作为value,而不是this.changeValue()]
     // keyName: 'test' value 如果是基本类型,就无法实现响应式
    }
},
data(){
	  return {
		msg:'初始mesg'
	}
},
methods: {
  	changeValue(){
  		this.msg= '改变后的msg'
  	}
}  
  
// 后代组件
inject:['keyName']
create(){
	console.log(this.keyName) // 改变后的msg
}

14.Vue的路由实现:hash模式 和 history模式

hash模式: 在浏览器中符号“#”,#以及#后面的字符称之为hash,用window.location.hash读取;

特点:hash虽然在URL中,但不被包括在HTTP请求中;用来指导浏览器动作,对服务端安全无用,hash不会重加载页面。
history模式: history 模式下,前端的 URL 必须和实际向后端发起请求的 URL 一致,history采用HTML5的新特性;且提供了两个新方法:pushState(),replaceState()可以对浏览器历史记录栈进行修改,以及popState事件的监听到状态变更。

15.$nextTick原理及运用(高薪问题)

1.Vue.nextTick( [callback, context] ):在下次 DOM 更新循环结束之后执行延迟回调。在修改数据之后立即使用这个方法,获取更新后的 DOM。

2.为什么需要它呢?

Vue 是异步修改 DOM 的并且不鼓励开发者直接接触 DOM,但有时候业务需要必须对数据更改–刷新后的 DOM 
做相应的处理,这时候就可以使用 Vue.nextTick(callback)这个api 了

解释:Vue是异步执行dom更新的,一旦观察到数据变化,Vue就会开启一个队列,然后把在同一个
事件循环 (event loop)当中观察到数据变化的 watcher 推送进这个队列。如果这个watcher被触发多次,
只会被推送到队列一次。这种缓冲行为可以有效的去掉重复数据造成的不必要的计算和DOm操作。
而在下一个事件循环时,Vue会清空队列,并进行必要的DOM更新。

3.理解原理前的准备
首先需要知道事件循环中宏任务和微任务这两个概念

1.常见的宏任务有:script, setTimeout, setInterval, setImmediate, I/O, UI rendering
2.常见的微任务有:process.nextTick(nodejs),Promise.then(), MutationObserver

4.理解 nextTick 的原理
正是 vue 通过异步队列控制 DOM 更新和 nextTick 回调函数先后执行的方式。如果
大家看过这部分的源码,会发现其中做了很多 isNative()的判断,因为这里还存在兼容性
优雅降级的问题

5.我在什么地方用它呢?

1.在Vue生命周期的created()钩子函数进行的DOM操作一定要放在Vue.nextTick()的回调函数中。
原因是在created()钩子函数执行的时候DOM 其实并未进行任何渲染,而此时进行DOM操作无异于徒劳,
所以此处一定要将DOM操作的js代码放进Vue.nextTick()的回调函数中。与之对应的就是mounted钩子函数,
因为该钩子函数执行时所有的DOM挂载和渲染都已完成,此时在该钩子函数中进行任何DOM操作都不会有问题 。
2.在数据变化后要执行的某个操作,而这个操作需要使用随数据改变而改变的DOM结构的时候
(譬如v-if/v-show根据字段变化显隐),这个操作都应该放进Vue.nextTick()的回调函数中。

16.Computed和watch区别和应用场景

Computed

//计算属性中的属性不需要在data中定义,而且必须有return
data(){
	return{
    	firstname:"张",
        lastname:"三"
    }
}
computehd(){
	fullname(){
    	return this.firstname+this.lastname
    }
}
/*计算属性具有缓存,计算属性是基于它们的依赖进行缓存的,只有在它的相关依赖发生改变时才会重新求值。
只要计算属性的依赖没有改变,那么调用它就会直接返回之前的缓存。 同时computed对于其中变量的依赖时
多个的时候,只要其中一个发生了变化都会触发这个函数*/

//应用场景:当一个变量的值受多个变量的值影响

watch

//监听器watch中的值需要在data中定义,且函数有参数,newval和oldval
data: {
  firstName: '张',
  lastName: '三',
  fullName: '张三r'
},
watch: {
  firstName: function (oval,nval) {
    this.fullName = nval + ' ' + this.lastName
  },
  lastName: function (oval,nval) {
    this.fullName = this.firstName + ' ' + nval
  },
  immediate: true,// 代表在wacth里声明了firstName之后立即先去执行其函数方法
  deep: true //深度监听
}
//watch的依赖是单个的,它每次只可以对一个变量进行监控,并且区别于computed属性,
监听器watch可以是异步的而computed则不行

//应用场景:当一个变量的值影响着多个变量的值

watch和computed都是以Vue的依赖追踪机制为基础的,它们都试图处理这样一件事情:当某一个数据(称它为依赖数据)发生变化的时候,所有依赖这个数据的“相关”数据“自动”发生变化,也就是自动调用相关的函数去实现数据的变动。

computed:计算属性是依赖的值改变会重新执行函数,计算属性是取返回值作为最新结果,所以里面不能异步的返回结果。不能写异步逻辑。计算属性基于响应式依赖进行缓存。如其中的任意一个值未发生变化,它调用的就是上一次计算缓存的数据,因此提高了程序的性能。

watch:computed和watch都是依赖数据发生变化后而执行的操作,但是计算属性初始化的时候就可以被监听到并且计算, 但是watch是发生改变的时候才会触发。当你有一些数据需要随着其它数据变动而变动时,或者当需要在数据变化时执行异步或开销较大的操作时,你可以使用 watch。
侦听属性是侦听的值改变会重新执行函数,将一个值重新赋值作为最新结果,所以赋值的时候可以进行一些异步操作。

watch和computed各自处理的数据关系场景不同

1.watch擅长处理的场景:一个数据影响多个数据
2.computed擅长处理的场景:一个数据受多个数据影响

17.vuex是什么?怎么使用?哪种功能场景使用它?

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

属性:
State、 Getter、Mutation 、Action、 Module

State
state是数据源存放地,对应于一般Vue对象里面的data。state里面存放的数据是响应式的,
Vue组件从store中读取数据,若是store中的数据发生改变,依赖这个数据的组件也会发生更新
需要通过mapState把全局 state 和 getters 映射到当前组件的 computed 计算属性中。

Getter
getters 可以对State进行计算操作,在多个组件间复用

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

Module
Vuex允许我们将store分隔成模块(module),每个模块拥有自己的state,mutation,action,getter,甚至是嵌套子模块

使用场景
一句话,不要为了使用vuex而去使用vuex,推荐组件间数据复用,记录登录及其它状态值数据,一些需要缓存的数据使用vuex都能达到很好的管理

18.v-show 与 v-if 的区别,两者的优先级

1.相同点:

v-show 和 v-if 都能控制元素的显示和隐藏。

2.不同点:

1.实现本质方法不同
	v-show 本质就是通过设置 css 中的 display 设置为 none,控制隐藏
	v-if 是动态的向 DOM 树内添加或者删除 DOM 元素
2.编译的区别
	v-show 其实就是在控制 css
	v-if 切换有一个局部编译/卸载的过程,切换过程中合适地销毁和重建内部的事件监听和子组件
3.编译的条件
	v-show 都会编译,初始值为 false,只是将 display 设为 none,但它也编译了
	v-if 初始值为 false,就不会编译了
4.性能比较
v-show 只编译一次,后面其实就是控制 css,而 v-if 不停的销毁和创建,故 v-show 性能更好一。

注意点:

因为 v-show 实际是操作 display:" "或者 none,当 css 本身有 display:none 时,v-show 无法让显示

适用场景:

如果要频繁切换某节点时,使用 v-show(无论 true 或者 false 初始都会进行渲染,
此后通过 css 来控制显示隐藏,因此切换开销比较小,初始开销较大),如果不需要频繁切换某节点时,
使用 v-if(因为懒加载,初始为 false 时,不会渲染,但是因为它是通过添加和删除dom元素来
控制显示和隐藏的,因此初始渲染开销较小,切换开销比较大)

优先级
v-for优先级比v-if高(vue2.x中)

注意事项
不要把 v-if 和 v-for 同时用在同一个元素上,带来性能方面的浪费(每次渲染都会先循环再进行条件判断)正确的做法应该是再v-for的外面新增一个模板标签template,在template上使用v-if也能结合filters或者是computed属性对数据进行加工,避免v-if判断,更好的渲染

注意:
在vue2.x中,v-for的优先级会比v-if的优先高,但在vue3.x中这一判断优先级被换了过来,在3.x的环境下v-if优先级更高,除此之外v-for和v-if在同一标签中使用也会报错,解决办法可以在外面套一个template标签,或者使用computed来对数组进行过滤然后渲染

18.vue中key的原理及其必要性以

vue中key作用:key是给每一个vnode的唯一id,也是diff的一种优化策略,可以根据key,更准确, 更快的找到对应的vnode节点(主要是为了高效的更新虚拟 DOM)

key是每一个节点的唯一标识

必要性:当我们对数据进行更新的时候,譬如在数组中插入、移除数据时,设置的key值能让vue底层高效的对新旧vnode进行diff,然后将比对出的结果用来更新真实的DOM。

19.vue路由的钩子函数及路由守卫

全局的路由钩子函数:beforeEach、afterEach

单个的路由钩子函数:beforeEnter

组件内的路由钩子函数:beforeRouteEnter、beforeRouteUpdate、beforeRouteLeave

路由守卫为:

	全局守卫:beforeEach
	后置守卫:afterEach
	全局解析守卫:beforeResolve
	路由独享守卫:beforeEnter

全局导航钩子

全局前置守卫:beforeEach

const router = new VueRouter({ ... })
router.beforeEach((to, from, next) => {
     	// ...
})
to: Route: 即将要进入的目标 路由对象
from: Route: 当前导航正要离开的路由
next: Function: 一定要调用该方法不然会阻塞路由。执行效果依赖 next 方法的调用参数。
next()方法接收的参数:

全局后置钩子:afterEach

router.afterEach((to, from) => {
     // do someting
});

//后置钩子并没有 next 函数

路由独享的钩子:
路由独享的导航钩子,它是在路由配置上直接进行定义的,参数的使用,和全局前置守卫是一样的
使用的钩子函数与全局路由守卫一致,为beforeEnter,不同的是,路由独享守卫是定义在路由记录中,全局路由守卫是定义在入口文件中,路由独享守卫只在路由进入时有效,全局路由守卫是所有路由跳转都会被拦截。

组件内的导航钩子:
beforeRouteEnter:在渲染该组件的对应路由前调用
beforeRouteUpdate:在当前路由改变,但是该组件被复用时调用
beforeRouteLeave:导航离开该组件的对应路由时调用

注意:
beforeRouteEnter 不能获取组件实例 this,因为当守卫执行前,组件实例被没有被创建出来,剩下两个钩子则可以正常获取组件实例 this

20.共享组件将不会重新渲染问题

我们有时候开发中会把多个路由解析为同一个Vue组件。问题是,Vue默认情况下共享组件将不会重新渲染,如果你尝试在使用相同组件的路由之间进行切换,则不会发生任何变化,此时我们需要传递key来区分,达到刷新的目的

const routes = [
  {
    path: "/a",
    component: MyComponent
  },
  {
    path: "/b",
    component: MyComponent
  },
];
<template>
    <router-view :key="$route.path"></router-view>
</template>

21.mixins

mixins是一种分发Vue组件中可复用功能的一种灵活方式。混入对象可以包含任意组件选项。当组件使用混入对象时,所有混入对象的选项将被混入该组件本身的选项。
mixins是一个JavaScript对象,可以包含组件中的任意选项,比如Vue实例中生命周期的各个钩子函数,也可以是data、components、methods或directives等

混入的优点:可以将一些组件通用的属性,方法,生命周期事件抽离出来,通过混入的方式来使用,使代码复用性更高;

缺点:容易被滥用

运用:

//mixin文件
export const myMixin={
    data(){
        return{
            msg:1
        }
    },
    created(){
        console.log('myMixin')
    },
    methods:{
        Fn(){
            console.log('myMixin')
        }
    }
}

//引入
<template>
	<div>运用mixin的组件</div>
</template>
<script>
    import {myMixin} from'目标文件路径'
    export default{
        mixins:[myMixin]
    }
</script>

特点:
1.在组件A对混入的数据做出更改后组件B获取到的仍是混入初始设置的数据,组件间操作互不污染。
2.值为对象的如methods,components等,选项会被合并,组件会覆盖混入对象的方法。比如混入对象里有个方法A,组件里也有方法A,这时候在组件里调用的话,执行的是组件里的A方法。
3.created,mounted等,就会被合并调用,混合对象里的钩子函数在组件里的钩子函数之前调用,
同一个钩子函数里,会先执行混入对象的东西,再执行本组件的。
4.在mixins里面包含异步请求函数的时候,通过直接调用异步函数获取返回数据

运用场景区别:

vuex:用来做状态管理,可以看做全局变量,里面定义的变量在每个组件中均可以使用和修改,
在任一组件中修改此变量的值之后,其他组件中此变量的值也会随之修改。

mixins:可以定义共用的变量,在每个组件中使用,引入组件中之后,各个变量是相互独立的,
值的修改在组件中不会相互影响。

父子组件:父子组件相对来说比较独立,只是父组件将一部分使用子组件,而mixins更像是对于组件的拓展,并且组件可以对于混入的数据和方法进行多样化操作。

22.vue自定义组件添加事件

使用修饰符.native 监听组件根元素的原生事件

<my-button  @click.native="alert()" names="点击触发"></my-button>

23.SSR

什么是ssr:Server-Side Rendering 我们称其为SSR,意为服务端渲染,展开说就是通过服务侧完成页面的 HTML 结构拼接的页面处理技术,发送到浏览器,然后为其绑定状态与事件,成为完全可交互页面的过程

ssr作用:
seo:搜索引擎优先爬取页面HTML结构,使用ssr时,服务端已经生成了和业务想关联的HTML,有利于seo
首屏呈现渲染:用户无需等待页面所有js加载完成就可以看到页面视图(压力来到了服务器,所以需要权衡哪些用服务端渲染,哪些交给客户端)

缺点:
1.项目复杂度高
2.需要库的支持性,代码兼容
3.服务器负载变大,相对于前后端分离务器只需要提供静态资源来说,服务器负载更大

24.setTimeout是在生命周期的什么阶段销毁的?如果不销毁会怎么样?

setTimeout是beforeDestroy 销毁的,不销毁内存、占用空间、最终导致浏览器崩溃

25.vue的修饰符有哪些?

1.事件修饰符

.stop 阻止事件继续传播
.prevent 阻止标签默认行为
.capture 使用事件捕获模式,即元素自身触发的事件先在此处处理,然后才交由内部元素进行处理
.self 只当在 event.target 是当前元素自身时触发处理函数
.once 事件将只会触发一次
.passive 告诉浏览器你不想阻止事件的默认行为

2.v-model的修饰符

.lazy    默认情况下,v-model同步输入框的值和数据。可以通过这个修饰符,转变为在change事件再同步。
.number   自动将用户的输入值转化为数值类型
.trim     自动过滤用户输入的首尾空格

3.键盘事件的修饰符

.enter 回车键
.tab 制表键
.esc 返回键
.space 空格键
.up 向上键
.down 向下键
.left 向左建
 .right 向右键

修饰键:(也叫系统修饰符)

.ctrl
.alt
.shift
.meta (就是ctrl旁边的window图标键)

v-bind修饰符

.sync

.sync修饰符,它只是作为一个编译时的语法糖存在。它会被扩展为一个自动更新父组件属性的 v-on 监听器

扩展为:

<comp :foo="bar" @update:foo="val => bar = val"></comp>

当子组件需要更新foo的值时,它需要显式的触发更新事件,如下:

this.emit('update:foo', newValue)

26.vuex中mutation和actions的区别和联系

actions
1.用于通过提交mutation改变数据
2.会默认将自身封装为一个Promise
3.可以包含任意的异步操作

mutation
1.通过提交commit改变数据
2.只是一个单纯的函数
3.不要使用异步操作,异步操作会导致变量不能追踪

27.npm的package.json中,版本号前面的^和~
波浪号〜匹配最新补丁版本号,也就是版本号的第三个数字。比如~1.2.3将匹配所有1.2.x版本,但将在1.3.0上停止。

插入符号^ 更宽松。 它匹配的是最新次要版本号,也就是第二个数字。比如:^ 1.2.3将匹配任何1.x.x版本,包括1.3.0,但将在2.0.0上停止。

星号*匹配任意版本,一般不用
latest意思安装的永远是最新的版本
还可以1.2.x形式匹配1.2z之后的任意版本1.2.1 1.2.2,不能是1.3.0

28.Eventloop事件循环机制

(1)将"执行栈"最开始的同步代码(宏任务)执行完成;
(2)检查是否有微任务。如有则执行所有的微任务;
(3)取出"任务队列"中事件所对应的回调函数(宏任务)进入”执行栈“并执行完成;
(4)再检查是否有微任务,如有则执行所有的微任务;
(5)主线程不断重复上面的(3)(4)步骤;

宏任务:同步代码,setTimeout,setInterval,requestAnimationFrame,I/O,UI rendering
微任务:process.nextTick,promise callback,MutationObserver

29.Vue的axios

axios 是一个基于Promise 用于浏览器和 nodejs 的 HTTP 客户端,它本身具有以下特征:

1.从浏览器中创建 XMLHttpRequest
2.从 node.js 发出 http 请求
3.支持 Promise API
4.拦截请求和响应
5.转换请求和响应数据
6.取消请求
7.自动转换JSON数据
8.客户端支持防止 CSRF/XSRF

30.说出至少4种vue指令和它的用法?

1.v-model 多用于表单元素实现双向数据绑定(同 angular 中的 ng-model)
2.v-for 格式: v-for=“字段名 in(of) 数组 json” 循环数组或 json(同 angular 中的 ng-repeat),需要注意从 vue2 开始取消了$index
3.v-show 显示内容 (同 angular 中的 ng-show)
4.v-hide 隐藏内容(同 angular 中的 ng-hide)
5.v-if 显示与隐藏 (dom 元素的删除添加 同 angular 中的 ng-if 默认值为 false)v-else-if 必须和 v-if 连用 v-else 必须和 v-if 连用 不能单独使用 否则报错 模板编译错误
6.v-bind 动态绑定 作用: 及时对页面的数据进行更改
7.v-on:click 给标签绑定函数,可以缩写为@,例如绑定一个点击函数 函数必须写在methods 里面
8.v-text 解析文本
9.v-html 解析 html 标签
10.v-bind:class 三种绑定方法 
	对象型 ‘{red:isred}’ 
	三元型 ‘isred?“red”:“blue”’ 
	数组型 ‘[{red:“isred”},{blue:“isblue”}]’
11.v-once 进入页面时 只渲染一次 不在进行渲染
12.v-cloak 防止闪烁
13.v-pre 把标签内部的元素原位输出

31.Vue如何创建自定义指令?

vue指令也分全局自定义指令和局部自定义指令。

全局的直接Vue.directive(‘指令名’,方法) 方法包括:

bind:只调用一次,指令第一次绑定到元素时调用。在这里可以进行一次性的初始化设置

inserted:被绑定元素插入父节点时调用 (仅保证父节点存在,但不一定已被插入文档中)

update:所在组件的 VNode 更新时调用,但是可能发生在其子 VNode更新之前。指令的值可能发生了改变,也可能没有。但是你可以通过比较更新前后的值来忽略不必要的模板更新

componentUpdated:指令所在组件的 VNode 及其子 VNode 全部更新后调用

unbind:只调用一次,指令与元素解绑时调用

32.vue-loader是什么?用途有哪些?

解析.vue文件的一个加载器。

用途:js可以写es6、style样式可以scss或less、template可以加jade等

33.scss 是什么?在 Vue-cli 中的安装使用步骤是?有哪几大特性?(高薪问题)

1.基本定义
SCSS 即是 SASS 的新语法,是 Sassy CSS 的简写,是 CSS3 语法的超集,也就是说
所有有效的 CSS3 样式也同样适合于 SASS,SASS 是 CSS3 的一个扩展,增加了规则嵌套、
变量、混合、选择器继承等等,通过使用命令行的工具或 WEB 框架插件把它转换成标准
的、格式良好的 CSS 代码

2.使用步骤:

	1.先装 css-loader、node-loader、sass-loader 等加载器模块
	2.在 build 目录找到 webpack.base.config.js,在那个 extends 属性中加一个拓展.scss
	3.在同一个文件,配置一个 module 属性
	4.然后在组件的 style 标签加上 lang 属性 ,例如:lang=”scss”

3.特性:

	1.可以用变量,例如($变量名称=值)
	2.可以用混合器,例如()
	3.可以嵌套

34.动态绑定 Class 有几种方式?

凡是有-的style属性名都要变成驼峰式,比如font-size要变成fontSize;
除了绑定值,其他的属性值要用引号括起来,比如backgroundColor:'#00a2ff’而不是 backgroundColor:#00a2ff;

对象

:style="{ color: activeColor, fontSize: fontSize + 'px' }"
:style="{color:(index==0?conFontColor:'#000')}"

数组

:style="[baseStyles, overridingStyles]"
:style="[{color:(index==0?conFontColor:'#000')},{fontSize:'20px'}]

三目运算符

:style="{color:(index==0?conFontColor:'#000')}"
:style="[{color:(index==0?conFontColor:'#000')},{fontSize:'20px'}]"

多重值

:style="{ display: ['-webkit-box', '-ms-flexbox', 'flex'] }"

绑定data对象

:style="styleObject"
data() {
    return{
      styleObject: {
        color: 'red',
        fontSize: '13px'
      }  
    }
}

35.如何定义 vue-router 动态路由以及如何获取传过来的动态参数?

1.动态路由:动态配置路由参数,页面刷新,数据不丢失

this.$router.push({
  path: `/particulars/${id}`,
})

接收页面通过 this.$route.params.id 接收

2.路由传参两种实现方式:

路由 name 匹配,通过 params 传参

 this.$router.push({
   name: 'particulars',
   params: {
     id: id
   }
 })

通过 this.$route.params.id 接收参数

路由 path 路径匹配,通过 query 传参

this.$router.push({
   path: '/particulars',
   query: {
     id: id
   }
})

通过 this.$route.query.id 接收参数

区别:
1.query要用path来引入,params要用name来引入,接收参数都是类似的,分别是this.$route.query.name 和 this.$route.params.name
2.query更加类似于ajax中get传参,params则类似于post,说的再简单一点,前者在浏览器地址栏中显示参数,后者则不显示。

36.VNode 是什么?虚拟 DOM 是什么?(高薪问题)

Vue在页面上渲染的节点,及其子节点称为“虚拟节点 (Virtual Node)”,简写为“VNode”。“虚拟 DOM”是由 Vue 组件树建立起来的整个 VNode 树的称呼。

1.Vnode 是什么
Vnode 是 JavaScript 对象,Vnode 表示 Virtual DOM,用 JavaScript 对象来描述真实的DOM 把 DOM 标签,属性,内容都变成对象的属性。就像使用 JavaScript 对象对一种动物进行说明一样{name: ‘Hello Kitty’, age: 1, children: null}。

1.Vnode 的作用
	通过 render 将 template 模版描述成 Vnode,然后进行一系列操作之后形成真实的 DOM 进行挂载。
2.Vnode 的优点
	1) 兼容性强,不受执行环境的影响。Vnode 因为是 JS 对象,不管 node 还是浏览器,都可以统一操作,
	从而获得了服务端渲染、原生渲染、手写渲染函数等能力。
	2) 减少操作 DOM,任何页面的变化,都只使用 Vnode 进行操作对比,只需要在最后一步挂载更新 DOM,
	不需要频繁操作 DOM,从而提高页面性能。

2.什么是虚拟 DOM?

1.文档对象模型或 DOM 定义了一个接口,该接口允许 JavaScript 之类的语言访问和操作 HTML 文档。
元素由树中的节点表示,并且接口允许我们操纵它们。但是此接口需要付出代价,
大量非常频繁的 DOM 操作会使页面速度变的非常缓慢
2.Vue 通过在内存中实现文档结构的虚拟表示来解决此问题,其中虚拟节点(Vnode)表示 DOM 树中的节点。
当需要操纵时,可以在虚拟 DOM 的 内存中执行计算和操作,而不是在真实 DOM 上进行操纵。
这自然会更快,并且允许虚拟 DOM 算法计算出最优化的方式来更新实际 DOM 结构,一旦计算出,
就将其应用于实际的 DOM 树,这就提高了性能,
这就是为什么基于虚拟 DOM 的框架(例如 Vue 和 react)如此突出的原因。

3.Vue 中如何实现一个虚拟 DOM?说说你的思路

首先要构建一个 Vnode 的类,DOM 元素上的所有属性在 Vnode 类实例化出来的对象上都存在对应的属性。
例如 tag 表示一个元素节点的名称,text 表示一个文本节点的文本,chlidren表示子节点等。
将 Vnode 类实例化出来的对象进行分类,例如注释节点、文本节点、元素节点、组件节点、函数式节点、
克隆节点。然后通过编译将模板转成渲染函数 render,执行渲染函数 render,
在其中创建不同类型的Vnode 类,最后整合就可以得到一个虚拟 DOM(vnode),
最后通过 patch 将 vnode 和oldVnode 进行比较后,生成真实 DOM

37.使用虚拟DOM的好处

web界面由DOM树来构建,当其中一部分发生变化时,其实就是对应某个节点发生了变化。
虚拟DOM就是为了解决浏览器性能问题而被设计出来的。若一次操作DOM中有十次更新DOM的动作,虚拟DOM不会立即操作DOM,而是将这十次更新的diff内容保存到本地一个js中,最终将这个js对象一次性attach 到DOM树上,在进行后续操作。避免大量无谓的计算量。所以,用js对象模拟DOM节点的好处是,页面的更新可以先全部反应在js对象(虚拟DOM)上,操作内存中的js对象的速度显然要更快,等更新完成之后,再将最终的js对象映射成真实的DOM,交由浏览器去绘制。因此使用虚拟 DOM 速度快,减小了页面渲染过程的次数。

38.动态组件的使用场景

可以让组件根据需求动态显示,一般用于需要根据数据动态渲染的场景或类似tab切换栏,即组件类型不确定。使用起来也特别简单,一般用于tab系列的组件。

39.vue中有处理过内存泄露问题吗

1.意外的全局变量
函数中意外的定义了全局变量,每次执行该函数都会生成该变量,且不会随着函数执行结束而释放。

2.未清除的定时器
定时器没有清除,它内部引用的变量,不会被释放。

3.脱离DOM的元素引用
一个dom容器删除之后,变量未置为null,则其内部的dom元素则不会释放。

4.持续绑定的事件
函数中addEventListener绑定事件,函数多次执行,绑定便会产生多次,产生内存泄漏。

5.绑在EventBus的事件没有解绑

6.闭包引起内存泄漏
比如事件处理回调,导致DOM对象和脚本中对象双向引用。

7.使用第三方库创建,没有调用正确的销毁函数

8.单页应用时,页面路由切换后,内存未释放

40.React和vue区别

1、监听数据变化的实现原理不同

2、数据流的不同react没有双向数据绑定,是单向数据流,react中通过将state(Model层)
与View层数据进行双向绑定达数据的实时更新变化,具体来说就是在View层直接写JS代码Model层中
的数据拿过来渲染,一旦像表单操作、触发事件、ajax请求等触发数据变化,则进行双同步

3、HoC和mixins
    Vue组合不同功能的方式是通过mixin,React组合不同功能的方式是通过HoC(高阶组件)

4、组件通信的区别;而Vue中子组件向父组件传递消息有两种方式:事件和回调函数,但Vue更倾向于使用事件。
在React中不支持自定义事件,我们都是使用回调函数的,这可能是他们二者最大的区别

5、模板渲染方式的不同
在表层上,模板的语法不同,React是通过JSX渲染模板。而Vue是通过一种拓展的HTML语法进行渲染,
但其实这只是表面现象,毕竟React并不必须依赖JSX。

6、渲染过程不同
Vue可以更快地计算出Virtual DOM的差异,这是由于它在渲染过程中,会跟踪每一个组件的依赖关系,
不需要重新渲染整个组件树。React在应用的状态被改变时,全部子组件都会重新渲染。
通过shouldComponentUpdate这个生命周期方法可以进行控制,但Vue将此视为默认的优化。
如果应用中交互复杂,需要处理大量的UI变化,那么使用Virtual DOM是一个好主意。
如果更新元素并不频繁,那么Virtual DOM并不一定适用,性能很可能还不如直接操控DOM。

7.框架本质不同
Vue本质是MVVM框架,由MVC发展而来;React是前端组件化框架,由后端组件化发展而来。

8.Vuex和Redux的区别
Redux使用的是不可变数据,而Vuex的数据是可变的,因此,Redux每次都是用新state替换旧state,
而Vuex是直接修改。Redux在检测数据变化的时候,是通过diff的方式比较差异的,而Vuex其实和Vue的原理一样,
是通过getter/setter来比较的,这两点的区别,也是因为React和Vue的设计理念不同。
React更偏向于构建稳定大型的应用,非常的科班化。相比之下,Vue更偏向于简单迅速的解决问题,更灵活,
不那么严格遵循条条框框。因此也会给人一种大型项目用React,小型项目用Vue的感觉。

41.实现观察者模式

vue中的双向数据绑定就是实现了观察者模式

42.Vue 的最大的优势是什么?

Vue 作为一款轻量级框架、简单易学、双向数据绑定、组件化、数据和结构的分离、虚拟
DOM、运行速度快,并且作者是中国人尤雨溪,对应的 API 文档对国内开发者优化,作为前端
开发人员的首选入门框架

Vue 的优势:

1.Vue.js 可以进行组件化开发,使代码编写量大大减少,读者更加易于理解。
2.Vue.js 最突出的优势在于可以对数据进行双向绑定。
3.使用 Vue.js 编写出来的界面效果本身就是响应式的,这使网页在各种设备上都能
显示出非常好看的效果。
4.相比传统的页面通过超链接实现页面的切换和跳转,Vue 使用路由不会刷新页
面。
5.vue 是单页面应用,使页面局部刷新,不用每次跳转页面都要请求所有数据和
dom,这样大大加快了访问速度和提升用户体验。
6.而且他的第三方 UI 组件库使用起来节省很多开发时间,从而提升开发效率。

43.Vue 和 jQuery 两者之间的区别是什么?

1.vue 和 jQuery 对比 jQuery 是使用选择器()选取 DOM 对象,对其进行赋值、取值、事件绑定等操作,
其实和原生的 HTML 的区别只在于可以更方便的选取和操作 DOM 对象,而数据和界面是在一起的

2.比如需要获取 label 标签的内容:)选取 DOM 对象,对其进行赋值、取值、事件绑定等操作,
其实和原生的 HTML 的区别只在于可以更方便的选取和操作 DOM 对象,而数据和界面是在一起的

3.比如需要获取 label 标签的内容:(“lable”).val();,它还是依赖 DOM 元素的值。
Vue 则是通过 Vue 对象将数据和 View 完全分离开来了

4.对数据进行操作不再需要引用相应的 DOM 对象,可以说数据和 View 是分离的,
他们通过 Vue 对象这个 vm 实现相互的绑定,这就是传说中的 MVVM

44.MVVM 和 MVC 区别是什么?哪些场景适合?

基本定义
1.MVVM 基本定义

MVVM 即 Model-View-ViewModel 的简写,即模型-视图-视图模型,模型(Model)指的是后端传递的数据,
视图(View)指的是所看到的页面,视图模型(ViewModel)是 mvvm 模式的核心,它是连接 view 和 model 的桥梁。
它有两个方向:
一是将模型(Model)转化成视图(View),即将后端传递的数据转化成所看到的页面,实现的方式是:数据绑定,
二是将视图(View)转化成模型(Model),即将所看到的页面转化成后端的数据。实现的方式是:
DOM 事件监听,这两个方向都实现的,我们称之为数据的双向绑定

2.MVC 基本定义

MVC 是 Model-View- Controller 的简写。即模型-视图-控制器。M 和 V 指的意思和
MVVM 中的 M 和 V 意思一样。C 即 Controller 指的是页面业务逻辑,使用 MVC 的目的就是
将M 和 V 的代码分离。MVC 是单向通信。也就是 View 跟 Model,必须通过 Controller 来承上启下

使用场景:

主要就是 MVC 中 Controller 演变成 MVVM 中的 viewModel,MVVM 主要解决了 MVC中大量的 DOM 操作
使页面渲染性能降低,加载速度变慢,影响用户体验,vue 数据驱动,通过数据来显示视图层而不是节点操作,
 场景:数据操作比较多的场景,需要大量操作 DOM 元素时,采用 MVVM 的开发方式,会更加便捷,
 让开发者更多的精力放在数据的变化上,解放繁琐的操作 DOM 元素

两者之间的区别:

MVC 和 MVVM 其实区别并不大,都是一种设计思想, MVC 和 MVVM 的区别并不是
VM 完全取代了 C,只是在 MVC 的基础上增加了一层 VM,只不过是弱化了 C 的概念,
ViewModel 存在目的在于抽离 Controller 中展示的业务逻辑,而不是替代 Controller,其它视图
操作业务等还是应该放在 Controller 中实现,也就是说 MVVM 实现的是业务逻辑组件的重用,
使开发更高效,结构更清晰,增加代码的复用性

45.请说下封装 Vue 组件的过程?

首先,组件可以提升整个项目的开发效率。能够把页面抽象成多个相对独立的模块,解决
了我们传统项目开发:效率低、难维护、复用性等问题

1.分析需求:确定业务需求,把页面中可以服用的结构,样式以及功能,单独抽离成一个文件,实现复用
2.具体步骤:使用 Vue.extend 方法创建一个组件,然后使用 Vue.component 方法注册组
件,子组件需要数据,可以在 props 中接受定义,而子组件修改好数据后,想把数据传递给父
组件,可以采用$emit 方法

46.组件中写 name 选项有什么作用?

1.项目使用 keep-alive 时,可搭配组件 name 进行缓存过滤
2.DOM 做递归组件时需要调用自身 name
3.vue-devtools 调试工具里显示的组见名称是由 vue 中组件 name 决定的

47.Vue 组件 data 为什么必须是函数

1.个组件都是 Vue 的实例
2.组件共享 data 属性,当 data 的值是同一个引用类型的值时,改变其中一个会影响其他
3.组件中的 data 写成一个函数,数据以函数返回值形式定义,这样每复用一次组件,就会返回一份新的 data,
类似于给每个组件实例创建一个私有的数据空间,让各个组件实例维护各自的数据。而单纯的写成对象形式,
就使得所有组件实例共用了一份 data,就会造成一个变了全都会变的结果

48.讲一下组件的命名规范

组件命名有两种方式,一种是使用链式命名 my-component,一种是使用大驼峰命名

MyComponent 在字符串模板中 和都可以使用,在非字符串模板中最好使用,因为要遵循 W3C 规范中的自定义组件名 (字母全小写且必须包含一个连字符),避免和当前以及未来的 HTML 元素相冲突

49.怎么在组件中监听路由参数的变化?

有两种方法可以监听路由参数的变化,但是只能用在包含的组件内。

第一种

watch: {
	‘$route’(to, from) {
		// 在此处监听
	}
}

第二种

beforeRouteUpdate (to, from, next) {
	//这里监听
}

50.怎么捕获 Vue 组件的错误信息?

1.errorCaptured 是组件内部钩子,当捕获一个来自子孙组件的错误时被调用,接收error、vm、info 三个参数,
return false 后可以阻止错误继续向上抛出
2.errorHandler 为全局钩子,使用 Vue.config.errorHandler 配置,接收参数与errorCaptured 一致,2.6 后
可捕捉 v-on 与 promise 链的错误,可用于统一错误处理与错误兜底

51.Vue 组件里的定时器要怎么销毁?

如果页面上有很多定时器,可以在 data 选项中创建一个对象 timer,给每个定时器取个名
字一一映射在对象 timer 中, 在 beforeDestroy 构造函数中

for(let k in this.timer){
	clearInterval(k)
};

如果页面只有单个定时器,可以这么做

const timer = setInterval(() =>{}, 500);
this.$once(‘hook:beforeDestroy’, () => {
	clearInterval(timer);
})

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

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

53.watch、methods 和 computed 的区别?

1.基本说明

1.computed:
计算属性将被混入到 Vue 实例中,所有 getter 和 setter 的 this 上下文自动地绑定为 Vue 实例
2.methods:
methods 将被混入到 Vue 实例中。可以直接通过 VM 实例访问这些方法,或者在指令表达式中使用。
方法中的 this 自动绑定为 Vue 实例。
3.watch:
观察和响应 Vue 实例上的数据变动,一个对象,键是需要观察的表达式,值是对应回调函数,值也可以是方法名,
或者包含选项的对象,Vue 实例将会在实例化时调,$watch(),遍历 watch 对象的每一个属性

2.三者的加载顺序

1.computed 是在 HTML DOM 加载后马上执行的,如赋值;(属性将被混入到 Vue 实例)
2.methods 则必须要有一定的触发条件才能执行,如点击事件,watch 呢?它用于观察 Vue 实例上的数据变动,
3.默认加载的时候先 computed 再 watch,不执行 methods;
4.触发某一事件后先 computed 再 methods 再到 watch,computed 属性 vs method 方,computed 计算属性
是基于它们的依赖进行缓存的

54.Vue-cli 用自定义的组件?有遇到过哪些问题吗?

1.在 components 目录新建你的组件文件(indexPage.vue),script 一定要 export default {}
2.在需要用的页面(组件)中导入:import indexPage from ‘@/components/indexPage.vue’
3.注入到 vue 的子组件的 components 属性上面,components:{indexPage}
4.在 template 视图 view 中使用,例如有 indexPage 命名,使用的时候则 index-page

55.Vue 中 solt 的使用方式,以及 solt 作用域插槽的用法

使用方式
当组件当做标签进行使用的时候,用 slot 可以用来接受组件标签包裹的内容,当给solt 标签添加 name 属性的 时候,可以调换响应的位置

插槽作用域
作用域插槽其实就是带数据的插槽,父组件接收来自子组件的 slot 标签上通过 v-bind绑定进而传递过来的数 据,父组件通过 scope 来进行接受子组件传递过来的数据

56.什么是 Vue 的计算属性

在模板中放入太多的逻辑会让模板过重且难以维护,在需要对数据进行复杂处理,且可能多次使用的情况下,尽量采取计算属性的方式,好处:使得数据处理结构清晰;依赖于数据,数据更新,处理结果自动更新;

1.计算属性内部 this 指向 vm 实例
2.在 template 调用时,直接写计算属性名即可
3.常用的是 getter 方法,获取数据,也可以使用 set 方法改变数据
4.相较于 methods,不管依赖的数据变不变,methods 都会重新计算,
但是依赖数据不变的时候 computed 从缓存中获取,不会重新计算

57.你是怎么认识 Vuex 的?

vuex 可以理解为一种开发模式或框架。比如 PHP 有 thinkphp,java 有 spring 等,通过状态(数据源)集中管理驱动组件的变化(好比 spring 的 IOC 容器对 bean 进行集中管理)

1.应用级的状态集中放在 store 中
2.改变状态的方式是提交 mutations,这是个同步的事物
3.异步逻辑应该封装在 action 中

58.Vuex 的 5 个核心属性是什么?

分别是 State、 Getter、Mutation 、Action、 Module
1.state
state 为单一状态树,在 state 中需要定义我们所需要管理的数组、对象、字符串等等,
只有在这里定义了,在 vue.js 的组件中才能获取你定义的这个对象的状态

2.getter
getter 有点类似 vue.js 的计算属性,当我们需要从 store 的 state 中派生出一些状态,那么我们就需要使用 getter,getter 会接收 state 作为第一个参数,而且 getter 的返回值会根据它的依赖被缓存起来,只有 getter 中的依赖值(state 中的某个需要派生状态的值)发生改变的时候才会被重新计算

3.mutation
更改 store 中 state 状态的唯一方法就是提交 mutation,就很类似事件。每个 mutation都有一个字符串类型的事件类型和一个回调函数,我们需要改变 state 的值就要在回调函数中改变。我们要执行这个回调函数,那么我们需要执行一个相应的调用方法store.commit

4.action
action 可以提交 mutation,在 action 中可以执行 store.commit,而且 action 中可以有任何的异步操作。在页面中如果我们要嗲用这个 action,则需要执行 store.dispatch

5.module
module 其实只是解决了当 state 中很复杂臃肿的时候,module 可以将 store 分割成模块,每个模块中拥有自己的 state、mutation、action 和 getter

59.Vuex 的出现解决了什么问题?

主要解决了以下两个问题
1.多个组件依赖于同一状态时,对于多层嵌套的组件的传参将会非常繁琐,并且对于兄弟组件间的状态传递无能为力
2.来自不同组件的行为需要变更同一状态。以往采用父子组件直接引用或者通过事件来变更和同步状态的多份拷贝。以上的这些模式非常脆弱,通常会导致无法维护的代码

60.简述 Vuex 的数据传递流程

当组件进行数据修改的时候我们需要调用 dispatch 来触发 actions 里面的方法。actions 里
面的每个方法中都会 有一个:
1.commit 方法,当方法执行的时候会通过 commit 来触 mutations 里面的方法进行数据的修改
2.mutations 里面的每个函数都会有一个 state 参数,这样就可以在 mutations 里面进行state 的数据修改 ,当数据修改完毕后,会传导给页面,页面的数据也会发生改变

61.Vuex 的 Mutation 和 Action 之间的区别是什么?

1.流程顺序
“相应视图—>修改 State”拆分成两部分,视图触发 Action,Action 再触发 Mutation
2.角色定位
基于流程顺序,二者扮演不同的角色

1.Mutation:专注于修改 State,理论上是修改 State 的唯一途径
2.Action:业务代码、异步请求
3.限制
	1)角色不同,二者有不同的限制
	2)Mutation:必须同步执行
	3)Action:可以异步,但不能直接操作 State

62.route和router 的区别是什么?

$route 是“路由信息对象”,包括 path,params,hash,query,fullPath,matched,
name 等路由信息参数
router为 vueRouter的实例,相当于一个全局的路由器对象,里面含有很多属性和子对象 ,
例如:history对象 , 经常用的跳转链接就可以用this.$router.push 会往history栈中添加一个新的记录 
返回上一个history也是使用router为 VueRouter的实例,相当于一个全局的路由器对象,
里面含有很多属性和子对 象,例如 history 对象,经常用的跳转链接就可以用 this.$router.push 
会往 history 栈中添加一个 新的记录。返回上一个 history 也是使用router为VueRouter的实例,
相当于一个全局的路由器对象,里面含有很多属性和子对象,例如history对象,
经常用的跳转链接就可以用this.$router.push会往history栈中添加一个新的记录。
返回上一个history也是使用router.go 方法

63.active-class 属于哪个组件中的属性?该如何使用?

active-class 是 vue-router 模块中 router-link 组件中的属性,主要作用是用来实现选
中样式的切换,在 vue-router 中要使用 active-class 有两种方式:
1.在 router-link 中写入 active-class
active-class 选择样式时根据路由中的路径(to=“/home”)去匹配,然后显示首页
2.直接在路由 js 文件中配置 linkActiveClass

export default new Router({
	linkActiveClass: ‘active’,
})
<div class="menu-btn">
	<router-link to="/" class="menu-home" active-class="active">首页</router-link >
</div>   
<div class="menu-btn">
	<router-link to="/my" class="menu-my" active-class="active">我的</router-link>
</div>

3.引起的问题
因为 to=“/” 引起的,active-class 选择样式时根据路由中的路径去匹配,然后显示,例如在 my 页面中,路由为 localhost:8081/#/my,那么 to=“/”和 to=”/my"都可以匹配到,所有都会激活选中样式

4、解决方法
1.在 router-link 中写入 exact
2.在路由中加入重定向

<router-link to="/" class="menu-home" active-class="active" exact>首页</router-link>

{
	path: '/',
	redirect: '/home'
}

64.请说出路由配置项常用的属性及作用

路由配置参数:

1.path: 跳转路径
2.component: 路径相对于的组件
3.name: 命名路由
4.children: 子路由的配置参数(路由嵌套)
5.props: 路由解耦
6.redirect: 重定向路由

65.编程式导航使用的方法以及常用的方法

1.路由跳转:this.$router.push() 
2.路由替换: this.$router.replace()
3.后退:this.$router.back()
4.前进:this.$router.forward()

66.Vue 怎么实现跨域

1.什么是跨域
跨域指浏览器不允许当前页面的所在的源去请求另一个源的数据。源指协议,端口,域名。只要这个 3 个中有一个不同就是跨域

2.使用 vue-cli 脚手架搭建项目时 proxyTable 解决跨域问题
打开 config/index.js,在 proxyTable 中添写如下代码:

proxyTable: {
	'/api': {  // 使用"/api"来代替"http://f.apiplus.c"
	target: 'http://f.apiplus.cn', //源地址
	changeOrigin: true, //改变源
	pathRewrite: {
	'^/api': ‘http://f.apiplus.cn’ //路径重写
}

3.使用 CORS(跨域资源共享)

1.前端设置,vue 设置 axios 允许跨域携带 cookie(默认是不带 cookie) axios.defaults.withCredentials = true;

2.后端设置:

	1.跨域请求后的响应头中需要设置
	2.Access-Control-Allow-Origin 为发起请求的主机地址
	3.Access-Control-Allow-Credentials,当它被设置为 true 时,允许跨域带 cookie,
	但此时 Access-Control- Allow-Origin 不能为通配符*
	4.Access-Control-Allow-Headers,设置跨域请求允许的请求头
	5.Access-Control-Allow-Methods,设置跨域请求允许的请求方式

67.Vue 中动画如何实现

1.哪个元素需要动画就给那个元素加 transition 标签
2.进入时 class 的类型分为以下几种
-enter -enter-active -enter-to
3.离开时 class 的类型分为以下几种
-leave -leave-active -leave-to

68.你对 Vue.js 的 template 编译的理解?

简而言之,就是先转化成 AST 树,再得到的 render 函数返回 Vnode(Vue 的虚拟 DOM 节点)
1.首先通过 compile 编译器把 template 编译成 AST 语法树(abstract syntax tree 即 源代码的抽象语法结构的树状表现形式),compile 是 createCompiler 的返回值,createCompiler 是用以创建编译器的,另外 compile 还负责合并 option
2.然后 AST 会经过 generate(将 AST 语法树转化成 render funtion 字符串的过程)得到render 函数,render 的返回值是 Vnode,Vnode 是 Vue 的虚拟 DOM 节点,里面有(标签名、子节点、文本等等)

69.Vue 渲染模板时怎么保留模板中的 HTML 注释呢?

在组件中将 comments 选项设置为 true

<template comments> ... <template>

70.Vue2.0 兼容 IE 哪个版本以上吗?

不支持 ie8 及以下,部分兼容 ie9 ,完全兼容 10 以上,因为 vue 的响应式原理是基于 es5
的 Object.defineProperty(),而这个方法不支持 ie8 及以下

71.Vue 如何去除 URL 中的#

vue-router 默认使用 hash 模式,所以在路由加载的时候,项目中的 URL 会自带 “#”,
如果不想使用 “#”, 可以使用 vue-router 的另一种模式 history:new Router ({ mode :
‘history’, routes: [ ]})
需要注意的是,当我们启用 history 模式的时候,由于我们的项目是一个单页面应用,所
以在路由跳转的时候,就会出现访问不到静态资源而出现 “404” 的情况,这时候就需要服
务端增加一个覆盖所有情况的候选资源:如果 URL 匹配不到任何静态资源,则应该返回同一
个 “index.html” 页面

72.说一下你在 Vue 中踩过的坑

1.给对象添加属性的时候,直接通过给 data 里面的对象添加属性然后赋值,新添加的属性不是响应式的
解决办法:通过 Vue.set(对象,属性,值)这种方式就可以达到,对象新添加的属性是响应式的

2.在 created 操作 dom 的时候,是报错的,获取不到 dom,这个时候实例 vue 实例没有挂载
解决办法:通过:Vue.nextTick(回调函数进行获取)

73.在 Vue 中使用插件的步骤

采用 ES6 的 import … from …语法或 CommonJS 的 require()方法引入插件
使用全局方法 Vue.use( plugin )使用插件,可以传入一个选项对象 Vue.use(MyPlugin,
{ someOption: true })

74.Vue 项目优化的解决方案都有哪些?

1. 使用 mini-css-extract-plugin 插件抽离 css
2. 配置 optimization 把公共的 js 代码抽离出来
3. 通过 webpack 处理文件压缩
4. 不打包框架、库文件,通过 cdn 的方式引入
5. 小图片使用 base64
6.  配置项目文件懒加载
7.  UI 库配置按需加载
8.  开启 Gzip 压缩

75.使用 Vue 的时候一下加载造成页面卡顿,该如何解决?

vue-router 解决首次加载缓慢的问题。
懒加载简单来说就是按需加载
1.像 vue 这种单页面应用,如果没有应用懒加载,运用 webpack 打包后的文件将会异常的大,造成进入首页时, 需要加载的内容过多,时间过长,会出现长时间的白屏,即使做了 loading 也是不利于用户体验,
2.而运用懒加载 则可以将页面进行划分,需要的时候加载页面,可以有效的分担首页所承担的加载压力,减少首页加载用时。
3.用法:在配置路由时使用:component:resolve=>require([“@components/路由的路径”],resolve)。 就是用了懒加载后打完包直接运行那个 index.html 会报错,报文件引用错误其实是打包时候路径配置有点问 题,找到 build 下面的webpack.prod.conf.js 添加 publicPath:“./”

76.请说出 Vue.cli 项目中 src 目录每个文件夹和文件的用法?

1.assets 文件夹是放静态资源
2.components 是放组件
3.router 是定义路由相关的配置
4.view 视图
5.app.vue 是一个应用主组件
6.main.js 是入口文件

77.你知道 style 上加 scoped 属性的原理吗?

1.什么是 scoped
在 Vue 组件中,为了使样式私有化(模块化),不对全局造成污染,可以在 style 标
签上添加 scoped 属性以表示它的只属于当下的模块,局部有效。如果一个项目中的所有 vue
组件 style 标签全部加上了 scoped,相当于实现了样式的私有化。如果引用了第三方组件,需
要在当前组件中局部修改第三方组件的样式,而又不想去除 scoped 属性造成组件之间的样式
污染。此时只能通过穿透 scoped 的方式来解决,选择器。

2.scoped 的实现原理:
Vue 中的 scoped 属性的效果主要通过 PostCSS 转译实现,如下是转译前的 Vue 代码:

<style scoped></style>

浏览器渲染后的代码:

<div data-v-fed36922>Vue.js scoped</div>

.scoped[data-v-fed36922]{font-size:14px;}
即:PostCSS 给所有 dom 添加了一个唯一不重复的动态属性,然后,给 CSS 选择器额外添加一
个对应的属性选择器来选择该组件中 dom,这种做法使得样式私有化

78.说说你对 SPA 单页面的理解,它的优缺点分别是什么?

单页 Web 应用 (single-page application 简称为 SPA) 是一种特殊的 Web 应用,它将所有的活动局限于一个 Web 页面中,仅在该 Web 页面初始化时加载相应的 HTML、JavaScript和 CSS,一旦页面加载完成了,SPA 不会因为用户的操作而进行页面的重新加载或跳转,取而代之的是利用 JavaScript 动态的变换 HTML 的内容,从而实现 UI 与用户的交互,由于避免了页面的重新加载,SPA 可以提供较为流畅的用户体验,得益于 ajax,我们可以实现无跳转刷新,又多亏了浏览器的 histroy 机制,我们用 hash 的变化从而可以实现推动界面变化,从而模拟元素客户端的单页面切换效果。
SPA 的优缺点:
1.优点:

1.无刷新界面,给用户体验原生的应用感觉
2.节省原生(android 和 ios)app 开发成本
3.提高发布效率,无需每次安装更新包
4.容易借助其他知名平台更有利于营销和推
5.符合 web2.0 的趋势

2.缺点:

1.效果和性能确实和原生的有较大差距
2.各个浏览器的版本兼容性不一样
3.业务随着代码量增加而增加,不利于首屏优化
4.某些平台对 hash 有偏见,有些甚至不支持 pushstate
5.不利于搜索引擎抓取

79.怎样理解 Vue 的单向数据流?

1.数据从父级组件传递给子组件,只能单向绑定
2.子组件内部不能直接修改从父级传递过来的数据
3.所有的 prop 都使得其父子 prop 之间形成了一个单向下行绑定:父级 prop 的更新会向下流动到子组件中,但是反过来则不行,这样会防止从子组件意外改变父级组件的状态,从而导致你的应用的数据流向难以理解。
4.每次父级组件发生更新时,子组件中所有的 prop 都将会刷新为最新的值,这意味着你不应该在一个子组件内部改变 prop。如果你这样做了,Vue 会在浏览器的控制台中发出警告
5.子组件想修改时,只能通过 $emit 派发一个自定义事件,父组件接收到后,由父组件修改

80.Vue 中操作 data 中数组的方法中哪些可以触发视图更新,哪些不可以,不可以的话有什么解决办法?(高新问题)

1.可以被改变的
push()、pop()、shift()、unshift()、splice()、sort()、reverse()这些方法会改变被操作的数组;

2.不可以改变的
filter()、concat()、 slice()这些方法不会改变被操作的数组,并且返回一个新的数组,以上方法都可以触发视图更新

3、解决方案

1.利用索引直接设置一个数组项,例:this.array[index] = newValue,直接修改数组的长度,
例:this.array.length = newLength
2.以上两种方法不可以触发视图更新
	1)可以使用 this.$set(this.array,index,newValue),this.array.splice(index,1,newValue)
	2)可以使用 this.array.splice(newLength)

81.Vue 中如何重置 data? (高薪问题)

要初始化 data 中的数据,可以使用 Object.assign()方法,实现重置 data 中的数据

1.Object.assign()方法基本定义

1.Object.assign() 方法用于将所有可枚举属性的值从一个或多个源对象复制到目标对象。它将返回目标对象。
2.用法: Object.assign(target, …sources),第一个参数是目标对象,第二个参数是源对象,
就是将源对象属性复制到目标对象,返回目标对象

2.具体使用方式

使用 Object.assign(),vm.data可 以 获 取 当 前 状 态 下 的 data, vm .data 可以获取当前状态下的 data,
vm.data可以获取当前状态下的data,vm.options.data(this)可以获取到组件初始化状态下的 data,
复制 Object.assign(this.data, this.data, this.data,this.options.data(this))
// 注意加 this,不然取不到 data() { a: this.methodA } 中的 this.methodA

82.如何对 Vue 首屏加载实现优化? (高薪问题)

1.把不常改变的库放到 index.html 中,通过 cdn 引入
2.vue 路由的懒加载
3.不生成 map 文件
4.vue 组件尽量不要全局引入
5.使用更轻量级的工具库
6.开启 gzip 压缩
7.首页单独做服务端渲染

83.在 Vue 实例中编写生命周期 hook 或其他option/propertie 时,为什么不使用箭头函数?(高薪问题)

箭头函数自己没有定义 this 上下文,而是绑定到其父函数的上下文中,当你在 Vue 程序
中使用箭头函数(=>)时,this 关键字病不会绑定到 Vue 实例,因此会引发错误,所以强烈
建议改用标准函数声明

84.is 这个特性你有用过吗?主要用在哪些方面?(高薪问题)

1.动态组件

<component :is="componentName"></component>, componentName 可以是在本页面已经注册的局部组件名
和全局组件名,也可以是一个组件的选项对象。 当控制 componentName改变时就可以动态切换选择组件

2.is 的用法
只能出现在其它某些特定的元素内部

 <ul>
	<li is="cardList"></li>
</ul>

85.vue常用属性方法执行顺序props、data、computed、watch、methods
根据vue.js源码可以看出执行顺序为:props=>methods=>data=>computed=>watch
在这里插入图片描述

  • 11
    点赞
  • 63
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值