Skip to content

Vue 面试题精选

汇总 Vue 必知必会知识点

看题之前建议先看过一遍官方文档 https://cn.vuejs.org/guide/introduction.html

面试题大纲

    1. Vue2 和 Vue3 的区别?
    1. Vue 的响应式原理是什么?
    1. Vue 的生命周期是什么?
    1. Vue 的组件之间如何通信?
    1. Vuex 和 Vue 组件的区别是什么?
    1. Vue 的路由是如何实现的?
    1. Vue 的指令有哪些?
    1. Vue 的过渡效果是如何实现的?
    1. Vue 的单向数据流是什么?
    1. Vue 的自定义指令是如何实现的?
    1. Vue 的错误处理机制是什么?
    1. Vue 的插件是如何实现的?
    1. Vue 的高阶组件是什么?
    1. Vue 的渲染函数是什么?
    1. Vue 的 $nextTick 方法是干什么用的?
    1. Vue 的 $set 和 $delete 方法是干什么用的?
    1. Vue 的 keep-alive 是什么?
    1. Vue 的计算属性和侦听器的区别是什么?
    1. Vue 的 $emit 和 $on 方法是干什么用的?
    1. Vue 的 $watch 和 $computed 方法有什么区别?
    1. Vue 的 $attrs 和 $listeners 是什么?
    1. Vue 的 Virtual DOM 是什么?
    1. Vue 的模板语法有哪些?
    1. Vue 的动态组件是如何实现的?
    1. Vue 的路由守卫是什么?
    1. Vue 的异步组件是如何实现的?
    1. Vue 的父子组件之间的通信方式有哪些?
    1. Vue 的路由懒加载是如何实现的?
    1. Vue 的自定义过渡类名是如何实现的?
    1. Vue 的插槽是什么?
    1. Vue 的深度监听是如何实现的?
    1. Vue 的组件递归是如何实现的?
    1. Vue 的响应式设计思想是什么?
    1. Vue 的路由懒加载和异步组件有什么区别?
    1. Vue 的组件内部通信和全局通信有什么区别?
    1. Vue 的组件内部状态和全局状态有什么区别?
    1. Vue 的组件化和模块化的区别是什么?
    1. Vue 的组件缓存和异步组件有什么区别?
    1. Vue 的组件通信和状态管理有什么关系?
    1. Vue 的组件内部状态管理和全局状态管理有什么区别?
    1. Vue 的组件间通信有哪些常用的方式?
    1. Vue computed watch 是不是异步?

1. Vue2 和 Vue3 的区别

Vue 2 和 Vue 3 之间有许多不同之处,主要包括:

  • 性能提升: Vue 3 通过重构其内部实现,带来了显著的性能提升。
  • Composition API: Vue 3 新增了 Composition API,这是一种全新的组件编写方式,可以更好地管理组件内部状态和逻辑。
  • Fragments: Vue 3 支持 Fragments,可以在渲染多个元素时不需要使用额外的包裹元素。
  • Teleport: Vue 3 新增了 Teleport,可以让你在不同位置渲染组件。
  • Suspense: Vue 3 支持 Suspense,可以在异步组件加载时显示 loading 状态。
  • 代码结构变化: Vue 3 重构了其内部代码结构,使得组件的实现更加清晰明了。
  • 其他新特性: Vue 3 还新增了一些其他新特性,如错误处理,异步组件,持久化状态,更好的 TypeScript 支持

总之, Vue 3 是一个更先进、更快捷的版本,带来了更好的开发体验和性能。

Portals 是 Vue 3 中的一个新特性,它允许组件将其内容呈现到任意 DOM 节点上,而不仅仅限于组件的根元素。当您想在组件根元素外显示内容时(例如在模态框或工具提示中),这在某些情况下非常有用。

以下是 Vue3 的例子:

javascript
<template>
  <div>
    <p>This is the component content</p>
    <portal to="#modal">
      <p>This content will be rendered in the #modal element</p>
    </portal>
  </div>
</template>

<script>
export default {
  name: 'MyComponent'
}
</script>

<!-- This is the HTML where the component is used -->
<div id="app">
  <MyComponent />
  <div id="modal"></div>
</div>

在上面的代码中,组件中的 <p>This content will be rendered in the #modal element</p> 将被呈现在页面的 <div id="modal"></div> 元素中。

2.Vue 的响应式原理是什么?

Vue 的响应式原理是通过 Object.defineProperty() 来实现的。

在 Vue 2 中,Vue 会在创建 Vue 实例时将数据对象的每个属性都使用 Object.defineProperty() 定义为 getter 和 setter。当数据发生改变时,会触发 setter 方法,在其中进行依赖收集和视图更新。

在 Vue 3 中,Vue 使用了 "Proxy" 代替了 Object.defineProperty() ,来更简单高效地实现响应式。Proxy 可以直接拦截对象属性的读写操作,而不需要通过定义 getter 和 setter。这样可以更简单地实现响应式,并且带来了性能提升。

可以通过 Object.defineProperty()和"Proxy" 分别写一个例子来说明 他们的区别

通过 Object.defineProperty() 实现响应式

js
const data = {
  name: 'John Doe'
};

Object.keys(data).forEach((key) => {
  let internalValue = data[key];
  Object.defineProperty(data, key, {
    get() {
      console.log(`Getting ${key}: ${internalValue}`);
      return internalValue;
    },
    set(newValue) {
      console.log(`Setting ${key} to ${newValue}`);
      internalValue = newValue;
    }
  });
});

data.name = 'Jane Doe';
// Setting name to Jane Doe
console.log(data.name);
// Getting name: Jane Doe

通过 "Proxy" 实现响应式

js
const data = {
  name: 'John Doe'
};

const handler = {
  get(target, key) {
    console.log(`Getting ${key}: ${target[key]}`);
    return target[key];
  },
  set(target, key, value) {
    console.log(`Setting ${key} to ${value}`);
    target[key] = value;
  }
};

const proxy = new Proxy(data, handler);

proxy.name = 'Jane Doe';
// Setting name to Jane Doe
console.log(proxy.name);
// Getting name: Jane Doe

我们可以发现,在使用 Object.defineProperty() 时,我们需要手动遍历对象的每个属性,并为每个属性分别定义 getter 和 setter。而在使用 Proxy 时,我们只需要定义一个通用的 handler 对象,就可以对整个对象进行拦截。

另外,在使用 Object.defineProperty() 实现响应式时,需要手动维护内部状态来存储属性值,这会增加代码的复杂度;而在使用 Proxy 实现响应式时,我们可以直接在 handler 中操作 target 对象,这样可以减少代码复杂度。

3. Vue 的生命周期是什么?

Vue 的生命周期指的是组件在从创建到销毁的过程中会经历的各个阶段,Vue 在每个阶段都提供了对应的钩子函数,允许我们在特定时间点执行特定的操作。

Vue2 的生命周期阶段及钩子函数如下:

  • beforeCreate: 组件实例刚被创建,但是还没有初始化。
  • created: 组件实例已经创建完成,并且已经初始化完成。
  • beforeMount: 组件实例即将被挂载到页面上。
  • mounted: 组件实例已经被挂载到页面上。
  • beforeUpdate: 组件实例即将更新。
  • updated: 组件实例已经更新完成。
  • beforeDestroy: 组件实例即将被销毁。
  • destroyed: 组件实例已经被销毁。

Vue3 的生命周期阶段与 Vue2 一样,只是增加了一个钩子函数:

  • unmounted:组件实例从页面上被移除

总结:Vue3 的生命周期钩子函数与 Vue2 相同,只是增加了一个 unmounted 钩子函数。

4. Vue 的组件之间如何通信?

Vue2 和 Vue3 中组件之间的通信方式基本相同,都可以通过 props$emit$on$off$onceprovide/inject 等方式来实现。

    1. props: 父组件可以通过在组件标签上定义属性来向子组件传递数据,如 <my-component v-bind:my-prop="someData"></my-component>。子组件可以通过 props 选项来定义接收的属性,如 props: ['myProp'],然后在组件的 template 中使用这些数据。
    1. $emit: 子组件可以通过 $emit 方法触发事件,如 this.$emit('myEvent', someData)。父组件可以通过在组件标签上监听事件来接收这些数据,如 <my-component v-on:my-event="handleMyEvent"></my-component>
    1. $on, $off, $once: 组件之间可以通过 $on 方法监听事件,通过 $off 方法取消监听,通过 $once 方法监听一次性事件。
    1. provide/inject: Vue2.3 中新增的 provide 和 inject 主要用于祖先组件向后代组件传递数据。祖先组件可以在组件的选项中定义 provide 选项,并提供需要传递的数据,如 provide: { myData: this.myData }。后代组件可以在组件的选项中定义 inject 选项,来声明需要接收的数据,如 inject: ['myData']。
    1. EventBus Api: Vue3 中新增的 EventBus Api 可以在全局范围内监听和触发事件。可以通过 Vue.createEventBus() 创建一个全局的 EventBus 实例,然后在任意位置监听和触发事件。在组件中使用 EventBus 可以通过在组件的 mounted 钩子函数中绑定事件监听,在组件的 beforeDestroy 钩子函数中移除事件监听。
    1. vuex : Vuex 是一个专门管理 Vue 应用状态的库,它提供了一个全局的 store 对象来存储数据,通过 actions 来更新数据。

区别: Vue 组件之间的通信主要是通过 props 和 $emit 来实现,而 Vuex 的作用是管理全局状态,并不是用来在组件之间传递数据的。

    1. Vue3 的 Composition API : Vue3 中新增的 Composition API 主要是为了解决组件逻辑复杂,代码可维护性差的问题。Composition API 可以让我们通过函数式编程的思想来定义组件逻辑,并且可以将公共逻辑抽离出来,使组件之间可以共享。

5. Vuex 和 Vue 组件的区别是什么?

Vuex 和 Vue 组件都是 Vue 框架的重要部分,但是它们有着不同的功能和用途。

  • Vuex 是一个状态管理库,主要用于管理应用中所有组件的共享状态。它提供了一个集中式的存储,让不同组件之间的状态变化可以被追踪和管理。

  • Vue 组件是 Vue 的基本构造块,用于构建用户界面。组件可以被复用,每个组件都有自己的状态和模板。组件之间可以通过 props 传递数据,通过 $emit 触发事件。

总结:Vuex 主要用来管理应用中所有组件的共享状态,Vue 组件是 Vue 框架的基本构造块,用于构建用户界面。

6. Vue 的路由是如何实现的?

Vue 的路由是通过 vue-router 库来实现的。vue-router 是 Vue 官方提供的路由管理库,它可以将 URL 与组件进行映射,根据不同的 URL 展示不同的组件。

实现步骤如下:

  • 安装 vue-router 库
  • 创建一个路由对象,并配置路由规则
  • 将路由对象挂载到 Vue 根实例中
  • 在组件中使用 <router-view> 标签来渲染路由对应的组件

例如:

js
//main.js
import Vue from 'vue';
import VueRouter from 'vue-router';
Vue.use(VueRouter);

const router = new VueRouter({
  routes: [
    {path: '/', component: Home},
    {path: '/about', component: About}
  ]
});

new Vue({
  router,
  render: (h) => h(App)
}).$mount('#app');

在组件中使用 <router-view> 标签来渲染路由对应的组件

js
//App.vue
<template>
  <div id="app">
    <router-view />
  </div>
</template>

这样就完成了一个简单的路由配置,可以根据不同的 URL 展示不同的组件。

原理呢

Vue 的路由原理主要有两部分组成:

  • HTML5 History API:这是一个浏览器自带的功能,可以在不刷新页面的情况下改变 URL,并且可以在返回和前进按钮中使用。
  • Vue-router 库:它是一个 Vue 插件,用来管理路由和与组件之间的映射关系。

在 Vue-router 中,使用了 Vue 的响应式系统来监听 URL 的变化,并在发生变化时动态渲染组件,这样就可以在不刷新页面的情况下实现路由的功能。

当用户在浏览器中点击链接或者在应用中调用路由导航函数时,Vue-router 会监听到 URL 的变化,并将 URL 与配置的路由映射规则进行匹配。如果匹配成功,Vue-router 会在 <router-view> 标签中渲染对应的组件。这样就可以在不刷新页面的情况下实现路由的功能。

在 Vue3 和 Vue2 中路由实现原理是一样的,只不过 Vue3 中使用了更加高效的 Proxy 对象来实现响应式。

7. Vue 的指令有哪些?

Vue 的指令有以下几种:

  • v-bind:用来绑定属性。
  • v-on:用来绑定事件监听器。
  • v-if:用来判断是否渲染元素。
  • v-for:用来遍历数组或者对象。
  • v-model:用来实现双向数据绑定。
  • v-text:用来更新元素的文本内容。
  • v-html:用来更新元素的 html 内容。
  • v-show:用来切换元素的显示和隐藏。
  • v-else:用来和 v-if 一起使用,表示当 v-if 条件不成立时的元素。
  • v-else-if:用来和 v-if 一起使用,表示当 v-if 条件不成立时可以接着判断其他条件。

Vue2 和 Vue3 中指令是相同的,没有新增或者删除指令。

8. Vue 的过渡效果是如何实现的?

Vue 的过渡效果是通过 Vue 的 <transition> 组件和 CSS 类实现的。

  • 在 Vue2 中,我们可以在 <transition> 组件中定义 enter/leave 的 CSS 类,来实现进入/离开时的动画效果。
  • 在 Vue3 中,我们可以使用 transition 函数来实现过渡效果。

在 Vue3 中,我们可以使用 onBeforeEnter、onEnter、onAfterEnter 等 hooks 来实现过渡效果。

Vue 2 和 Vue 3 的过渡效果实现方式有些不同。

Vue 2 中,过渡效果通过 CSS 类和 JavaScript 钩子函数来实现。使用者可以在组件中添加过渡类名,Vue 会自动在进入/离开过程中添加/删除这些类名。还可以在组件中添加 JavaScript 钩子函数,在进入/离开过程中触发。

Vue 3 中,过渡效果通过使用新的 <transition><transition-group> 组件实现。与 Vue 2 不同的是,Vue 3 中的过渡效果是基于 JavaScript 而不是 CSS 实现的。这意味着,Vue 3 中的过渡效果可以更灵活地控制,并且可以在 JavaScript 中添加额外的逻辑。

总结来说,Vue 2 中的过渡效果更依赖于 CSS,Vue 3 中的过渡效果更加灵活,可以在 JavaScript 中添加额外的逻辑。

9. Vue 的单向数据流是什么?

Vue 遵循单向数据流的原则,即数据的流动只能在父组件到子组件的单向流动,而不能在子组件到父组件的流动。这样做可以让组件之间的关系更加清晰易懂,并且在组件之间传递数据时不会出现意外情况。

单向数据流的实现主要通过 props$emit 来实现。父组件可以通过 props 将数据传递给子组件,子组件可以通过 $emit 来触发事件给父组件。这样做可以让父组件对子组件的数据进行控制,并且可以在子组件触发事件时做出相应的反应。

10. Vue 的自定义指令是如何实现的?

Vue 的自定义指令是通过 Vue.directive() 方法来实现的。可以在 Vue 实例或者 Vue 的全局配置中进行自定义指令的注册。

在 Vue2 中,自定义指令需要提供一个对象,其中包含 bind、update、unbind 三个钩子函数。

  • bind:只调用一次,指令第一次绑定到元素时调用。
  • update:被绑定元素所在的模板更新时调用,而不论绑定值是否变化。
  • unbind:只调用一次,指令与元素解绑时调用。

在 Vue3 中,自定义指令需要提供一个函数,该函数接收一个 DirectiveArgs 对象。 DirectiveArgs 对象包含一组属性和方法,用于访问和控制元素和指令绑定的数据。

在 Vue3 中,自定义指令是更为简单的,更加易用,更加灵活的。

通过自定义指令,可以实现更加复杂的操作,比如实现自定义事件、属性绑定等等。

11. Vue 的错误处理机制是什么?

Vue 2 中,错误处理机制主要是通过配置 Vue 实例的 errorCaptured 钩子函数来实现的。这个钩子函数可以捕获组件内的所有错误,并且可以在组件树的任何层级上被调用。

Vue 3 中,错误处理机制和 Vue 2 相似,但是有所增强。首先 Vue 3 支持了 Error Handling API,可以在组件实例上配置 onError 钩子函数来处理错误。同时,Vue 3 也提供了 ErrorCaptured 声明式组件,可以在组件树上捕获错误,并且可以在任何层级上被调用

12. Vue 的插件是如何实现的?

Vue 插件是通过 Vue.use() 方法来实现的。Vue.use() 方法接受一个插件对象,该对象需要定义一个 install 方法,该方法会在 Vue.use() 被调用时执行。

在 Vue2 中,install 方法接收 Vue 构造函数作为参数,通过该参数可以访问 Vue.prototype 上的方法,进而实现插件的功能。

在 Vue3 中,install 方法接收 createApp 函数作为参数,通过该参数可以访问 app.config 上的方法,进而实现插件的功能。

举个例子,假设有一个自定义插件 myPlugin,它在 Vue2 中的实现可能长这样:

javascript
const myPlugin = {
  install(Vue) {
    Vue.prototype.$myMethod = function () {
      // 自定义的方法
    };
  }
};
Vue.use(myPlugin);

而在 Vue3 中的实现可能长这样:

javascript
const myPlugin = {
  install(app) {
    app.config.globalProperties.$myMethod = function () {
      // 自定义的方法
    };
  }
};
createApp(App).use(myPlugin);

总结一下,Vue2 和 Vue3 中的插件实现方式类似,都是通过在 Vue 构造函数或 app.config 上添加自定义方法来实现插件功能。但是 Vue3 中,我们需要使用 createApp 创建应用然后使用 use 来注册插件,并且 Vue3 中,我们需要操作 app.config 来实现插件的功能。

13. Vue 的高阶组件是什么?

Vue 的高阶组件是一种可复用组件逻辑的方式。它是一个函数,接收一个组件作为参数,并返回一个新的组件。高阶组件可以在不修改原始组件的情况下,为组件提供额外的功能,如添加 props、监听器等。

在 Vue2 中,高阶组件可以通过 Vue.extend() 方法实现,例如:

javascript
const ComponentWithExtraProps = Vue.extend({
  props: {
    extraProp: String
  },
  render(h) {
    return h(WrappedComponent, {
      props: {
        extraProp: this.extraProp
      }
    });
  }
});

在 Vue3 中,高阶组件可以通过 createComponent() 函数实现,例如:

javascript
import {createComponent} from 'vue';
const ComponentWithExtraProps = createComponent({
  props: {
    extraProp: String
  },
  render() {
    return () =>
      createVNode(WrappedComponent, {
        props: {
          extraProp: this.extraProp
        }
      });
  }
});

这两种方式的实现方式基本一致,只是在 Vue3 中,高阶组件使用 createComponent() 来创建,并且需要通过 render 函数来渲染组件。

14. Vue 的渲染函数是什么?

Vue 的渲染函数是用来在 JavaScript 中声明组件的渲染逻辑的函数。在 Vue 2 中,渲染函数通过 template 选项或者 render 选项来定义。在 Vue 3 中,渲染函数是在 setup() 函数中返回的。渲染函数使用 JSX 语法,而不是模板语言,因此可以在 JavaScript 中操作组件的渲染。 渲染函数的优点是更加灵活,可以通过 JavaScript 来控制渲染逻辑,提升性能。 渲染函数是通过 JSX 产生的虚拟 DOM 来渲染组件,渲染函数和组件的生命周期钩子配合使用可以更好地控制组件的渲染。

15. Vue 的 $nextTick 方法是干什么用的?

Vue 的 $nextTick 方法是用来在下一个 DOM 更新周期中使用的。当你在组件中更新了数据并希望立即更新视图,但是还没有到下一个 DOM 更新周期时,可以使用 $nextTick 方法。该方法接受一个回调函数作为参数,该回调函数在下一次 DOM 更新周期中被调用。在 Vue 2 和 Vue 3 中都支持 $nextTick 方法。

示例:

js
this.message = 'Hello';
this.$nextTick(() => {
  console.log(this.$el.textContent); // "Hello"
});

这个示例中,我们改变了 message 的值,但是在下一个 DOM 更新周期才能看到最终的结果,我们可以用 nextTick 来保证在真正的 DOM 更新之后再执行代码。

nextTick 的原理

$nextTick 方法是 Vue.js 中的一个实例方法,它允许在下一次 DOM 更新循环结束之后执行延迟回调。这个方法的原理是在下一个 tick(即下一次 DOM 更新循环结束)中执行回调,主要用于在更新 DOM 之后操作 DOM。

实现原理是在 Vue 的更新队列中添加回调函数,在下一次 DOM 更新循环结束后调用这些回调函数。

在 vue2 和 vue3 中都有这个方法。

16. Vue 的 $set 和 $delete 方法是干什么用的?

17. Vue 的 keep-alive 是什么?

Vue 的 keep-alive 是一个 Vue 内置组件,它可以用来缓存组件实例,避免重复渲染和重新创建组件实例。当组件在进入/离开路由时,keep-alive 会将组件实例缓存在内存中,当组件再次进入该路由时,会直接使用缓存的组件实例,而不是重新创建。

在 Vue2 中,使用 <keep-alive> 标签包裹需要缓存的组件即可使用。在 Vue3 中,使用 vue.component 方法和 setup 函数来实现。

需要注意的是,使用 keep-alive 时,组件的 created、mounted 钩子函数只会在第一次创建时触发,而 activated 和 deactivated 钩子函数会在组件进入/离开缓存时触发。

18. Vue 的计算属性和侦听器的区别是什么?

Vue 的计算属性和侦听器都可以用来响应数据变化,但是它们有一些显著的不同:

计算属性是基于它们的依赖进行缓存的。这意味着如果依赖没有发生变化,那么计算属性只会在第一次访问时计算一次。 侦听器不会缓存结果,并且在依赖发生变化时每次都会被调用。 总体而言,计算属性更适用于需要在模板中使用的复杂计算,而侦听器更适用于需要在数据变化时执行异步或开销较大的操作。

Vue2 和 Vue3 都支持计算属性和侦听器。在 vue2 中通过 computed 和 watch 来实现,在 vue3 中通过 computed 和 watchEffect 来实现。

计算属性是一种基于它们的依赖进行缓存的 getter 函数。

当依赖更改时,计算属性会重新求值。而侦听器是在数据变化时被调用的函数。 计算属性适用于需要在模板中展示计算结果的场景,而侦听器适用于需要在数据变化时执行异步或开销较大的操作的场景。

19. Vue 的 $emit 和 $on 方法是干什么用的?

20. Vue 的 $watch 和 $computed 方法有什么区别?

21. Vue 的 $attrs 和 $listeners 是什么?

22. Vue 的 Virtual DOM 是什么?

https://cn.vuejs.org/guide/extras/rendering-mechanism.html#virtual-dom

Vue 的 Virtual DOM 是一种 JavaScript 实现的虚拟 DOM,它可以在浏览器端帮助我们更高效地更新页面。 Vue 在渲染组件时会将组件的视图渲染成一棵 JavaScript 对象树,这棵树就是 Virtual DOM。 在每次组件状态变化时,Vue 会比较新旧 Virtual DOM 的差异并只更新需要更新的部分。 这样就可以避免不必要的 DOM 操作,从而提高性能。 Vue2 和 Vue3 使用的 Virtual DOM 实现方式是一致的。

23. Vue 的模板语法有哪些?

24. Vue 的动态组件是如何实现的?

25. Vue 的路由守卫是什么?

26. Vue 的异步组件是如何实现的?

27. Vue 的父子组件之间的通信方式有哪些?

28. Vue 的路由懒加载是如何实现的?

29. Vue 的自定义过渡类名是如何实现的?

30. Vue 的插槽是什么?

31. Vue 的深度监听是如何实现的?

在 Vue 2 中,可以通过在 $watch 函数中设置 deep: true 来实现深度监听。Vue3 中没有提供 $watch 函数,但可以使用 computed 代替。

Vue 2 在源码中使用了 Object.defineProperty 和 Observer 类来实现对数据的深度监听,在调用 vm.$watch() 方法时,会在 Observer 类中遍历整个对象,使用 Object.defineProperty 为对象的每一个属性设置 getter 和 setter,以便在属性发生变化时触发回调函数。

Vue 3 中, 通过 Proxy 代替了 Object.defineProperty, 实现数据监听。在调用 setup()函数的时候,会调用内部的 reactive 函数来处理数据,并返回一个代理对象,在代理对象上的操作就会触发数据变化,进而触发视图更新。

32. Vue 的组件递归是如何实现的?

Vue 的组件递归是通过在组件中使用自己来实现的。在组件定义中加入 name 选项,然后在组件模板中使用该组件即可实现递归。可以使用 props 传递参数给递归组件来实现更多复杂的递归结构。

比如在组件中使用:

vue
<template>
  <div>
    <my-component :item="item"></my-component>
  </div>
</template>

<script>
export default {
  name: 'my-component',
  props: ['item'],
  template: `
    <div>
      <p>{{ item.name }}</p>
      <my-component v-if="item.children" v-for="child in item.children" :key="child.id" :item="child"></my-component>
    </div>
  `
};
</script>

在上述代码中,我们在 my-component 中使用了自己,并使用 v-for 指令来循环遍历子组件,实现了组件的递归。

注意在组件递归中,需要使用 key 来区分每个子组件,避免组件重复渲染。

33. Vue 的响应式设计思想是什么?

Vue 的响应式设计思想是在 Vue 实例创建时通过 Object.defineProperty() 方法劫持对象的 getter 和 setter 来实现。当绑定的数据变化时,Vue 会自动更新视图。这种机制称为响应式系统。

34. Vue 的路由懒加载和异步组件有什么区别?

Vue 的路由懒加载和异步组件主要的区别在于实现方式和使用场景上。

  • 路由懒加载:是指在路由被访问时才加载对应的组件,而不是一次性全部加载。它是通过使用 Vue Router 的异步组件和 Webpack 的 code splitting 功能来实现的。
  • 异步组件:是指将组件定义为一个工厂函数,在需要时才加载对应的组件。它主要用于在运行时动态加载组件。

总的来说,路由懒加载更适用于路由层面的代码分割,而异步组件则更适用于组件层面的动态加载。

35. Vue 的组件内部通信和全局通信有什么区别?

36. Vue 的组件内部状态和全局状态有什么区别?

37. Vue 的组件化和模块化的区别是什么?

38. Vue 的组件缓存和异步组件有什么区别?

39. Vue 的组件通信和状态管理有什么关系?

40. Vue 的组件内部状态管理和全局状态管理有什么区别?

41. Vue 的组件间通信有哪些常用的方式?

Vue 的组件间通信有多种常用的方式,如:

  • props 和``$emit`:父组件可以通过 props 传递数据给子组件,子组件可以通过$emit 触发事件给父组件
  • $parent$children:父子组件可以通过$parent$children直接访问对方
  • $refs:组件可以通过$refs来访问其它组件
  • vuex:组件可以通过 vuex 来进行全局状态管理
  • eventBus:组件可以通过 eventBus 来进行组件间通信
  • provide/inject:在 Vue 2.3.0+ 中新增的 provide/inject API,可以用来在父子组件间传递数据。

不同的场景使用不同的方式来进行组件间通信,需要根据项目需求进行选择。

Vue computed watch 是不是异步?

在 Vue.js 中,computed 和 watch 是不同的东西,它们的行为也有所不同。

computed 计算属性是同步执行的,它依赖于响应式数据,只有当其依赖的数据发生变化时才会重新计算。computed 计算属性的值是缓存的,只有在其依赖的数据发生变化时才会重新计算,并且计算属性的值会被缓存起来,当多次读取计算属性时,会直接返回缓存的值,而不会重新计算。

watch 监听属性是异步执行的,它用于监听某个特定的数据的变化,一旦监听到数据变化就会触发回调函数,这个回调函数是异步执行的。当数据发生变化时,Vue.js 会将这个回调函数放到下一个事件循环中执行,以避免阻塞页面的渲染。

总的来说,computed 计算属性是同步执行的,而 watch 监听属性是异步执行的。这也是它们的区别之一。