vue系列之面试总结

什么是vue生命周期

答: Vue 实例从创建到销毁的过程,就是生命周期。也就是从开始创建、初始化数据、编译模板、挂载Dom→渲染、更新→渲染、卸载等一系列过程,我们称这是 Vue 的生命周期。
它的生命周期中有多个事件钩子,让我们在控制整个Vue实例的过程时更容易形成好的逻辑。

Vue生命周期总共有几个阶段

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

第一次页面加载会触发哪几个钩子

答:第一次页面加载时会触发 beforeCreate, created, beforeMount, mounted 这几个钩子

Vue的双向数据绑定原理是什么

答:vue.js 是采用数据劫持结合发布者-订阅者模式的方式,通过Object.defineProperty()来劫持各个属性的setter,getter,在数据变动时发布消息给订阅者,触发相应的监听回调。
具体步骤:
第一步:需要observe的数据对象进行递归遍历,包括子属性对象的属性,都加上 setter和getter
这样的话,给这个对象的某个值赋值,就会触发setter,那么就能监听到了数据变化
第二步:compile解析模板指令,将模板中的变量替换成数据,然后初始化渲染页面视图,并将每个指令对应的节点绑定更新函数,添加监听数据的订阅者,一旦数据有变动,收到通知,更新视图
第三步:Watcher订阅者是Observer和Compile之间通信的桥梁,主要做的事情是:
1、在自身实例化时往属性订阅器(dep)里面添加自己
2、自身必须有一个update()方法
3、待属性变动dep.notice()通知时,能调用自身的update()方法,并触发Compile中绑定的回调,则功成身退。
第四步:MVVM作为数据绑定的入口,整合Observer、Compile和Watcher三者,通过Observer来监听自己的model数据变化,通过Compile来解析编译模板指令,最终利用Watcher搭起Observer和Compile之间的通信桥梁,达到数据变化 -> 视图更新;视图交互变化(input) -> 数据model变更的双向绑定效果。

axios的特点有哪些

答:
一、Axios 是一个基于 promise 的 HTTP 库,支持promise所有的API
二、它可以拦截请求和响应
三、它可以转换请求数据和响应数据,并对响应回来的内容自动转换成 JSON类型的数据
四、安全性更高,客户端支持防御 XSRF

对于MVVM的理解

MVVM 是 Model-View-ViewModel 的缩写。
Model代表数据模型,也可以在Model中定义数据修改和操作的业务逻辑。
View 代表UI 组件,它负责将数据模型转化成UI 展现出来。
ViewModel 监听模型数据的改变和控制视图行为、处理用户交互,简单理解就是一个同步View 和 Model的对象,连接Model和View。
在MVVM架构下,View 和 Model 之间并没有直接的联系,而是通过ViewModel进行交互,Model 和 ViewModel 之间的交互是双向的, 因此View 数据的变化会同步到Model中,而Model 数据的变化也会立即反应到View 上。
ViewModel 通过双向数据绑定把 View 层和 Model 层连接了起来,而View 和 Model 之间的同步工作完全是自动的,无需人为干涉,因此开发者只需关注业务逻辑,不需要手动操作DOM, 不需要关注数据状态的同步问题,复杂的数据状态维护完全由 MVVM 来统一管理。

什么是MVC

MVC允许在不改变视图的情况下改变视图对用户输入的响应方式,用户把对View的操作交给了Controller处理,在Controller中响应View的事件调用Model的接口对数据进行操作,一旦Model发生变化便通知相关视图进行更新。
如果前端没有框架,只使用原生的html+js,MVC模式可以这样理解。将html看成view;js看成controller,负责处理用户与应用的交互,响应对view的操作(对事件的监听),调用Model对数据进行操作,完成model与view的同步(根据model的改变,通过选择器对view进行操作);将js的ajax当做Model,也就是数据层,通过ajax从服务器获取数据。

MVVM与MVC区别

MVVM与MVC两者之间最大的区别就是:MVVM实现了对View和Model的自动同步,也就是当Model的属性改变时,我们不用再自己手动操作Dom元素来改变View的变化,而是改变其属性后,该属性对应的View层数据会自动改变。
以Vue为例:

 <div id="vueDemo">
  <p>{{ title }}</p>
  <button v-on:click="clickEvent">hello word</button>
</div>
var vueDemo = new Vue({  
    el: '#vueDemo',  
    data: {    
        title: 'Hello Vue!'  
    },  
    methods: {    
        clickEvent: function () {      
            this.title = "hello word!"  
        }  
    }
})

复制代码这里的html => View层,可以看到这里的View通过模板语法来声明式的将数据渲染进DOM元素,当ViewModel对Model进行更新时,通过数据绑定更新到View。
Vue实例中的data相当于Model层,而ViewModel层的核心是Vue中的双向数据绑定,当Model发生变化时View也可以跟着实时更新,同理,View变化也能让Model发生变化。
总的看来,MVVM比MVC精简很多,不仅简化了业务与界面的依赖,还解决了数据频繁更新的问题,不用再用选择器操作DOM元素。因为在MVVM中,View不知道Model的存在,Model和ViewModel也观察不到View,这种低耦合模式提高代码的可重用性。

Vue组件间的参数传递

https://juejin.im/post/5c776e…
1) 父子通信
1.props和emit
父组件通过props传递数据给子组件,子组件通过emit发送事件传递给父组件。

// 父组件
<div>
    <child :data="child" @send="getFromChild"></child>
</div>

data(){
    return{
        toChild: '大儿子',
        fromChild: ''
    }
},
methods: {
    getFromChild(val){
        this.fromChild=val
    }
}
// 子组件
<div @click="toParent">{{data}}</div>

props:[data],
methods: {
    toParent(){
        this.$emit('send', '给父亲')
    }
}

2.v-model
v-model其实是props,emit的语法糖,v-model默认会解析成名为value的prop和名为input的事件。

// 父组件
<children v-model="msg"></children>
<p>{{msg}}</p>

data(){
    return{
        msg:'model'
    }
}
// 子组件
<input :value="value" @input="toInput" />

props: ['value'],
methods: {
    toInput(e){
        this.$emit('input', e.target.value)
    }
}

3.在父组件使用$children访问子组件,在子组件中使用$parent访问父组件

// 父组件
<child />

data(){
    return {
        msg: '父组件数据'
    }
},
methods: {
    test(){
        console.log('我是父组件的方法,被执行')
    }
},
mounted(){
    console.log(this.$children[0].child_msg); // 执行子组件方法
}
// 子组件
<div>{{$parent.msg}}</div>

data(){
    return{
        child_msg: '子组件数据'
    }
},
mounted(){
    // 子组件执行父组件方法
    this.$parent.test(); 
}

$listeners和$attrs
$attrs–继承所有父组件属性(除了prop传递的属性)
inheritAttrs–默认值true,继承所有父组件属性(除props),为true会将attrs中的属性当做html的data属性渲染到dom根节点上
$listeners–属性,包含了作用在这个组件上所有监听器,v-on=”$listeners”将所有事件监听器指向这个组件的某个特定子元素

// 父组件
<children :child1="child1" :child2="child2" @test1="onTest1"
@test2="onTest2"></children>

data(){
    return {
        child1: 'childOne',
        child2: 'childTwo'
    }
},
methods: {
    onTest1(){
        console.log('test1 running')
    },
    onTest2(){
        console.log('test2 running')
    }
}

// 子组件
<p>{{child1}}</p>
<child v-bind="$attrs" v-on="$listeners"></child>

props: ['child1'],
mounted(){
    this.$emit('test1')
}

// 孙组件
<p>{{child2}</p>
<p>{{$attrs}}</p>

props: ['child2'],
mounted(){
    this.$emit('test2')
}

.sync方式
在vue1.x中是对prop进行双向绑定,在vue2只允许单向数据流,也是一个语法糖

// 父组件
<child :count.sync="num" />

data(){
    return {
        num: 0
    }
}
// 子组件
<div @click="handleAdd">add</div>

data(){
    return {
        counter: this.count
    }
},
props: ["count"],
methods: {
    handleAdd(){
        this.$emit('update:count', ++this.counter)
    }
}

2) 兄弟组件通信
可以通过查找父组件中的子组件实现,
this.$parent.$children
在$children中可以通过组件name查询到需要的组件实例,然后进行通信
跨多层次组件通信
可以使用provide/inject,虽然文档中不推荐直接使用在业务中。
假设有父组件A,然后有一个跨多层次的子组件B

// 父组件A
export default{
    provide: {
        data: 1
    }
}
// 子组件B
export default{
    inject: ['data'],
    mounted(){
        // 无论跨几层都能获取父组件的data属性
        console.log(this.data); // 1
    }
}

3) 任意组件
可以用Vuex或Event Bus解决
eventBus的使用
1.新建一个bus.js文件

import Vue from 'vue';
export default new Vue();

2.使用它

<div @click="addCart">添加</div>
import Bus from 'bus.js';
export default{
    methods: {
        addCart(event){
            Bus.$emit('getTarget', event.target)
        }
    }
}
// 另一组件
export default{
    created(){
        Bus.$on('getTarget', target =>{
            console.log(target)
        })
    }
}

Vuex方式
https://segmentfault.com/a/11…

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

hash模式:在浏览器中符号“#”,#以及#后面的字符称之为hash,用window.location.hash读取;
特点:hash虽然在URL中,但不被包括在HTTP请求中;用来指导浏览器动作,对服务端安全无用,hash不会重加载页面。
hash 模式下,仅 hash 符号之前的内容会被包含在请求中,如 http://www.xxx.com,因此对于后端来说,即使没有做到对路由的全覆盖,也不会返回 404 错误。

history模式:history采用HTML5的新特性;且提供了两个新方法:pushState(),replaceState()可以对浏览器历史记录栈进行修改,以及popState事件的监听到状态变更。
history 模式下,前端的 URL 必须和实际向后端发起请求的 URL 一致,如 http://www.xxx.com/items/id。后端如果缺少对 /items/id 的路由处理,将返回 404 错误。Vue-Router 官网里如此描述:“不过这种模式要玩好,还需要后台配置支持……所以呢,你要在服务端增加一个覆盖所有情况的候选资源:如果 URL 匹配不到任何静态资源,则应该返回同一个 index.html 页面,这个页面就是你 app 依赖的页面。”

Vue与Angular以及React的区别

1.与AngularJS的区别

相同点:
都支持指令:内置指令和自定义指令;都支持过滤器:内置过滤器和自定义过滤器;都支持双向数据绑定;都不支持低端浏览器。

不同点:
AngularJS的学习成本高,比如增加了Dependency Injection特性,而Vue.js本身提供的API都比较简单、直观;在性能上,AngularJS依赖对数据做脏检查,所以Watcher越多越慢;Vue.js使用基于依赖追踪的观察并且使用异步队列更新,所有的数据都是独立触发的。

2.与React的区别

相同点:
React采用特殊的JSX语法,Vue.js在组件开发中也推崇编写.vue特殊文件格式,对文件内容都有一些约定,两者都需要编译后使用;中心思想相同:一切都是组件,组件实例之间可以嵌套;都提供合理的钩子函数,可以让开发者定制化地去处理需求;都不内置列数AJAX,Route等功能到核心包,而是以插件的方式加载;在组件开发中都支持mixins的特性。
不同点:
React采用的Virtual DOM会对渲染出来的结果做脏检查;Vue.js在模板中提供了指令,过滤器等,可以非常方便,快捷地操作Virtual DOM。

vue路由的钩子函数

首页可以控制导航跳转,beforeEach,afterEach等,一般用于页面title的修改。一些需要登录才能调整页面的重定向功能。

beforeEach主要有3个参数to,from,next:
to:route即将进入的目标路由对象,
from:route当前导航正要离开的路由
next:function一定要调用该方法resolve这个钩子。执行效果依赖next方法的调用参数。可以控制网页的跳转。

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

只用来读取的状态集中放在store中; 改变状态的方式是提交mutations,这是个同步的事物; 异步逻辑应该封装在action中。
在main.js引入store,注入。新建了一个目录store,….. export 。
场景有:单页应用中,组件之间的状态、音乐播放、登录状态、加入购物车
state
Vuex 使用单一状态树,即每个应用将仅仅包含一个store 实例,但单一状态树和模块化并不冲突。存放的数据状态,不可以直接修改里面的数据。
mutations
mutations定义的方法动态修改Vuex 的 store 中的状态或数据。
getters
类似vue的计算属性,主要用来过滤一些数据。
action
actions可以理解为通过将mutations里面处里数据的方法变成可异步的处理数据的方法,简单的说就是异步操作数据。view 层通过 store.dispath 来分发 action。
modules
项目特别复杂的时候,可以让每一个模块拥有自己的state、mutation、action、getters,使得结构非常清晰,方便管理。

vue中 key 值的作用

答:当 Vue.js 用 v-for 正在更新已渲染过的元素列表时,它默认用“就地复用”策略。如果数据项的顺序被改变,Vue 将不会移动 DOM 元素来匹配数据项的顺序, 而是简单复用此处每个元素,并且确保它在特定索引下显示已被渲染过的每个元素。key的作用主要是为了高效的更新虚拟DOM。
为什么使用v-for时必须添加唯一的key?
key 的特殊属性主要用在 Vue 的虚拟 DOM 算法,在新旧 nodes 对比时辨识 VNodes。如果不使用 key,Vue 会使用一种最大限度减少动态元素并且尽可能的尝试修复/再利用相同类型元素的算法。使用 key,它会基于 key 的变化重新排列元素顺序,并且会移除 key 不存在的元素。

有相同父元素的子元素必须有独特的 key。重复的 key 会造成渲染错误。

$route和$router的区别

答:$route是“路由信息对象”,包括path,params,hash,query,fullPath,matched,name等路由信息参数。而$router是“路由实例”对象包括了路由的跳转方法,钩子函数等。

什么是vue的计算属性

答:在模板中放入太多的逻辑会让模板过重且难以维护,在需要对数据进行复杂处理,且可能多次使用的情况下,尽量采取计算属性的方式。
好处:
①使得数据处理结构清晰;
②依赖于数据,数据更新,处理结果自动更新;
③计算属性内部this指向vm实例;
④在template调用时,直接写计算属性名即可;
⑤常用的是getter方法,获取数据,也可以使用set方法改变数据;
⑥相较于methods,不管依赖的数据变不变,methods都会重新计算,但是依赖数据不变的时候computed从缓存中获取,不会重新计算。

组件中data什么时候可以适用对象

组件复用时所有组件实例都会共享data,如果data是对象就会造成一个组件修改data以后会影响到其他所有组件,所以需要将data写成函数,每次用到就调用一次函数获得新的数据
当我们使用new Vue()的方式的时候,无论我们将data设置为对象还是函数都是可以的,因为new Vue()的方式是生成一个根组件,该组件不会复用,也就不存在共享data的情况

v-if与v-show的用法与区别

https://www.jianshu.com/p/2d3…

    原文作者:前端
    原文地址: https://segmentfault.com/a/1190000018060680
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞