vue面试题

100 阅读5分钟

1.vue解决了哪些问题

①虚拟dom:dom操作时非常耗性能,不再使用原生的dom操作节点,极大的解放dom操作,但具体操作的还是dom,只是换了一种方式。

**②视图、数据、结构分离:**使数据的更改更为简单,不需要进行逻辑代码的修改,只需要操作数据就能完成相关操作。

③**组件化:**把一个单页应用中的各种模块拆分到单独的组件中,便于开发,以及后期的维护

2.MVVM的理解

MVVM就是Model-View-ViewModel的缩写,MVVM将视图和业务逻辑分开。

在MVVM框架下,View和Model之间没有直接的联系,而是通过ViewModel进行交互,

因此view数据的变化会同步到Model中,而Model数据的变化也会立即反映到View上

ViewModel通过双向数据绑定把View层和Model层连接了起来,因此开发者只需要关注业务逻辑,不需要手动操作DOM,也不需要关注数据状态的同步问题,这些都由MVVM统一管理。

3.如何实现一个自定义组件,不同组件之间是如何通信的

3-1. 自定义组件

在子组件中创建模版,使用props接收父组件中的数据,在父组件中引入子组件,中components写入子组件名称,最后挂载到父组件中的template。

3-2. props和$emit

父组件通过props在子组件中接收数据

子组件通过this.$emit向父组件中触发事件

3-3. childrenchildren 和 parent

this.$children[0].msg = "hello world" //父组件修改子组件data中的数据
this.$parent.mag //子组件拿到父组件data中的数据
$children的值是数组,$parent的值是个对象

3-4. refref 和 refs

ref:如果在普通的dom元素上使用,引用指向dom元素,如果在子组件上使用,引用指向组件的实例

//父组件
<template>
    <component-a ref="comA"></component-a>
</template>
<script>
    export default{
        mounted(){
            const comA = this.$refs.comA;
            console.log(comA.name)//Vue.js
            comA.sayHello() //hello
        }
    }
</script>

//子组件
export default{
    data(){
        return {
            name:"Vue.js"
        }
    },
    methods:{
        sayHello(){
            console.log("hello")
        }
    }
}

3-5. eventBus(Bus总线)

1. 在src中新建一个bus.js,导入空的vue实例

2.在传输数据的一方引入bus.js,然后通过Bus.emit(“事件名”,"参数")来来派发事件,数据是以emit(“事件名”,"参数")来来派发事件,数据是以emit()的参数形式来传递

3.在接受的数据的一方引入 Bus.js ,然后通过 Bus.$on("事件名",(data)=>{data是接受的数据})

3-6. attrs/attrs / listeners

 将数据挂在到子组件的标签上,在子组件中使用this.$attrs直接获取到所有挂载的数据,返回的是一个对象。 

4. nextTick的理解

**使用nextTick的原因:**Vue是异步修改DOM的,并且不鼓励开发者直接接触DOM,但是有时候需要必须对的DOM元素做相应的处理,这就需要this.$nextTick();

**原理:**Vue通过异步队列控制DOM更新的和nextTick回调函数先后的顺序。

//HTML
<button @click="change()">按钮</button><h1 ref="gss">{{msg}}</h1>
//JS
export default{
    name:"app",
    data(){
        return {
            msg:"123"
        }
    },
    methods:{
        change(){
            this.msg = "456";
            console.log(this.refs["gss"].innerHTML)//123
            this.$nextTick(function(){
                console.log(this.refs["gss"].innerHTML)//456
            })
        }
    }

}  

5. Vue的生命周期(11个钩子函数)

1. beforeCreate(创建前): 

在此生命周期函数执行的时候,data和methods中的数据都还没有初始化。

2. created(创建后): 

在此生命周期函数中,data和methods都已经被初始化好了,最早只能在created中操作。

3. beforeMount(载入前): 

在此生命周期函数执行的时候,模板已经在内存中编译好了,未挂载到页面中去,此时页面还是旧的。

4. mounted(载入后): 

此时页面和内存中都是最新的数据,最早可以操作dom节点的方法。

5. beforeUpdate(更新前):

此时页面中显示的数据还是旧的,但是data中的数据是最新的。

6. Updated(更新后):

此时页面显示数据和最新的data数据同步。

7. beforeDestroy(销毁前):

并没有真正执行销毁,数据还可以使用。

8.destroyed(销毁后):

数据已经销毁完毕

9. activated:

组件激活时

10. deactivated:

组件未激活时

11. errorCaptured(错误调用):

当捕获一个来自后代组件的错误时调用

6.虚拟dom原理

虚拟dom就是用对象的方式取代真实的DOM操作,把真实的DOM操作放在内存当中,

在内存中的对象里做模拟操作,打开时浏览器会解析HTML元素,构建一颗DOM树,

在内存当中模拟DOM操作,操作完后又会生成一颗dom树,两颗DOM树进行比较,根据diff算法比较两颗DOM树不同的地方,只渲染一次不同的地方。

diff核心:1,两个相同的组件产生类似的DOM结构,不同的组件产生不同的DOM结构;

                2,同一层级的一组节点,他们可以通过唯一的id进行区分。

链接:juejin.cn/post/684490…

7.双向绑定的原理?数据劫持?

 vue实现数据双向绑定主要是:采用数据劫持结合发布者-订阅者模式的方式。

  通过Object.defineProperty()来劫持属性的setter,getter,在数据变动时发布消息给订阅者,触发相应监听回调

数据劫持:****当我们访问或设置对象的属性的时候,都会触发相对应的函数,然后在这个函数里返回或设置属性的值。我们可以在触发函数的时候动一些手脚做点我们自己想做的事情,这也就是**“劫持”操作**。

8.Proxy相比于defineProperty的优势

Vue3.0摒弃了Object.defineProperty,改为基于Proxy的观察者机制探索

proxy相对于defineproperty的优点:

  • 可以劫持整个对象,并返回一个新对象。
  • 有多种劫持操作(13种)

Object.defineProperty的缺点

无法监控到数组下标的变化,使通过数组的下标的设置值,不能实时响应。

Object.defineProperty只能劫持对象的属性,因此我们需要对每个对象的每个属性进行遍历

如果能劫持一个完整的对象才是更好的选择。

补充:

Proxy是ES6新增的一个属性,意思就是代理,它来“代理”某些操作。Proxy让我们能够以简洁的控制外部对象的访问,类似于设计模式中的代理模式。

使用Proxy的核心优点是可以交由它来处理一些非核心逻辑(如:读取或设置对象的某些属性前记录日志)

9. watch、computed和methods的区别

watch 监听属性 没有缓存性,属性值发生变化时就会执行,可以利用它做一些异步操作

computed具有缓存性,依赖于属性值,只要属性发生变化时就会重新调用

methods 没有缓存性,只要调用就会执行

10. virtual-dom原理实现(虚拟dom)

virtual-dom(简称vdom)的概念大规模的使用于react相比于频繁的手动去操作dom而带来性能问题,virtual-dom也是react这个框架的非常重要的特性之一

vdom关于dom的创建节点,删除节点,添加节点等dom操作都放到vdom中,

通过操作vdom来提高直接操作的dom的效率和性能。

链接:juejin.cn/post/684490…