前端高频面试题---VUE篇(五)

89 阅读5分钟

1. Vue中的$nextTick有什么作用?底层如何实现?

在Vue中,nextTick方法用于在DOM更新完成后执行回调函数。由于DOM更新是异步进行的,使用nextTick方法用于在DOM更新完成后执行回调函数。由于DOM更新是异步进行的,使用nextTick可以确保在DOM更新后才执行回调函数,从而避免一些问题。

底层实现上,Vue使用虚拟DOM diff算法来计算DOM的变化,并在浏览器绘制每一帧时进行DOM的更新。$nextTick方法会等待当前帧的DOM更新结束,并在下一帧开始时执行回调函数。在回调函数中,可以获取到更新后的DOM元素并进行操作。

具体实现上,Vue底层使用JavaScript的Promise对象来实现nextTick方法。当调用nextTick方法。当调用nextTick方法时,Vue会将回调函数存储在Promise对象的then方法中,并使用MutationObserver来观察DOM的变化。当DOM更新完成之后,MutationObserver会触发Promise对象的then方法,并执行存储的回调函数。回调函数中可以获取到更新后的DOM元素并进行操作。

总之,Vue中的$nextTick方法底层使用JavaScript的Promise对象和MutationObserver来实现。通过等待当前帧的DOM更新结束,并在下一帧开始时执行回调函数,可以实现在DOM更新后进行操作的目的。

2. Vue组件通信的方式有哪些?

Vue组件通信的方式有以下几种:

  1. props:父组件通过props将数据传递给子组件。
  2. emit:子组件通过emit:子组件通过emit触发事件,父组件监听该事件并传递数据。
  3. event bus:通过全局的event bus进行组件间通信。
  4. vue-router:通过vue-router进行路由配置,实现组件间的通信。
  5. vuex:通过vuex进行组件间状态管理,实现组件间的通信。
  6. provide/inject:通过provide将数据传递给所有子组件,子组件通过inject获取数据。
  7. 插槽作用域:通过作用域插槽将数据传递给子组件,子组件通过作用域插槽获取数据。

这些通信方式适用于不同的场景,可以根据需求选择合适的方式。

3. vue中为什么data属性是一个函数而不是一个对象,具体原因是什么?

在Vue中,data属性被设计为一个函数而不是一个对象,主要是为了解决在多个组件实例之间共享数据的问题。

当我们在一个Vue组件中定义data属性时,我们期望的是每个组件实例都有自己独立的数据对象,这样每个组件都可以独立地修改和操作自己的数据。

如果data属性是一个对象,那么多个组件实例之间会共享相同的数据对象。这意味着当一个组件实例修改了数据对象,其他组件实例也会受到影响,这显然不是我们期望的行为。

为了解决这个问题,Vue将data属性设计为一个返回对象的数据获取函数。当我们在组件中调用data函数时,会返回一个新的数据对象。这样,每个组件实例都有自己的数据对象,互不干扰。

此外,将data属性设计为函数还有一个好处,就是可以在组件实例化时进行参数化,从而允许我们在创建组件实例时传入初始数据。

总结起来,将data属性设计为函数是为了保证每个Vue组件实例都有自己独立的数据对象,避免多个组件实例之间共享数据,同时允许在创建组件实例时传入初始数据。

4. 在Vue项目中你是如何做的SSR渲染

在Vue项目中,可以使用Vue官方提供的服务器端渲染(SSR)功能来实现服务端渲染。下面是一些基本的步骤:

  1. 安装Vue SSR插件

使用npm或yarn安装Vue SSR插件,命令如下:

npm install vue-server-renderer --save
  1. 创建服务器端渲染函数

在Vue项目中,可以创建一个服务器端渲染函数,用于渲染Vue组件并返回HTML字符串。这个函数可以使用Vue SSR插件来渲染组件。

例如,可以创建一个名为ssr.js的文件,其中包含以下代码:

import Vue from 'vue';
import { createRenderer } from 'vue-server-renderer';
import App from './App.vue';

const renderer = createRenderer();

export default (req, res) => {
  const app = new Vue({
    el: '#app',
    render: h => h(App),
  });
  renderer.renderToString(app, (err, html) => {
    if (err) {
      res.status(500).send(err.message);
    } else {
      res.send(html);
    }
  });
};
  1. 配置服务器端路由

在Vue项目中,可以使用Express等Web服务器框架来配置服务器端路由。可以将SSR函数作为路由处理程序,并将路径与请求匹配到该处理程序。这样,当用户请求该路径时,服务器将渲染Vue组件并返回HTML字符串。

例如,在Express中,可以使用以下代码配置路由:

const express = require('express');
const path = require('path');
const fs = require('fs');
const app = express();
const ssr = require('./ssr');

app.get('/', (req, res) => {
  const html = fs.readFileSync(path.resolve(__dirname, './index.html'), 'utf-8');
  res.send(html);
});

app.get('/ssr', ssr);

5. Vue2.x对数组常用方法进行重写有哪些原因?

Vue2.x对数组常用方法进行重写的原因主要是为了实现响应式系统。由于JavaScript中的数组是引用类型,常规的引用跟踪机制不能捕获数组内部的变化。而Vue的响应式是通过Object.defineProperty()实现的,这个api没办法监听数组长度的变化,也就没办法监听数组的新增。因此,为了更友好的操作数组并触发响应式检测,Vue对改变原数组(数组本身)的方法进行了重写。具体地说,Vue中对数组进行方法重写是指重写数组的一些常用方法,例如push、pop、shift、unshift、splice、sort和reverse等。

  1. push:在向数组添加元素时,除了添加元素本身,还会更新数组的长度,并触发数组的更新。
  2. pop:在从数组中移除元素时,除了返回被移除的元素,还会更新数组的长度,并触发数组的更新。
  3. shift:在从数组的第一个位置开始移除元素时,除了返回被移除的元素,还会更新数组的长度,并触发数组的更新。
  4. unshift:在向数组的开头添加元素时,除了添加元素本身,还会更新数组的长度,并触发数组的更新。
  5. splice:在向数组的特定位置添加或移除元素时,除了修改数组本身,还会更新数组的长度,并触发数组的更新。

这些重写方法的存在使得Vue能够监听到我们对数组的操作,并在这些操作发生时触发对应的更新,从而实现响应式系统。

然而需要注意的是,Vue 3.x对这个系统进行了优化。在Vue 3.x中,由于使用了Proxy来代替Object.defineProperty()进行数据劫持,因此不再需要对数组的常用方法进行重写。相反,我们只需要在创建Vue实例时传入一个包含响应式属性的对象即可。