【面试题】Vue面试题整理

news2024/9/23 5:33:40

1. v-show 和 v-if 的区别?

  • v-if 指令用于条件渲染,它会根据表达式的值的真假来决定是否渲染元素。如果表达式的值为 false,则该元素不会被渲染并且也不会保留在 DOM 中。
  • v-show 指令用于条件展示,它不会从 DOM 中删除元素,只是简单地使用 CSS 属性 display 控制元素的显示和隐藏。
  • v-if 更适用于在运行时动态添加/删除元素,而 v-show 更适用于频繁切换显示和隐藏。

2. 为何在 v-for 使用 key?

  • 当 Vue 使用 v-for 指令更新被迭代的元素时,会通过 diff 算法检测哪些元素已经被添加、删除或移动,以便只更新需要更新的元素,而不是重新渲染整个列表。为了实现这个检测机制,Vue 使用每个元素的 key 作为跟踪它们的标识。
  • 在为元素指定 key 时,key 的值应该是一个字符串或数值类型。它的值应该是唯一的,且不会随着元素的重新排序而改变。如果没有为元素指定唯一的 key,Vue 会使用元素的索引作为默认 key,但是元素的索引可能会发生变化,因此使用索引作为 key 会导致潜在的渲染错误。

3. 描述Vue组件的生命周期

  • 在 Vue 中,组件生命周期指的是组件从创建到销毁的整个过程,包含了多个阶段和钩子函数。钩子函数在组件的不同阶段做出相应的处理,实现对组件的控制。Vue 组件的生命周期包含四个阶段:创建阶段、更新阶段、销毁阶段、激活\停用阶段。
  • 创建阶段的主要工作是创建组件实例并将组件实例渲染到页面中。该阶段会调用四个钩子函数,即 beforeCreate、created、beforeMount、mounted。beforeCreate 函数在组件实例初始化之后,数据观测和事件配置之前被调用,此时组件实例尚未创建,不能访问 data 和 methods 等数据和方法。created 函数在组件实例创建完后被立即调用,此时组件实例已经创建,可以访问 data 和 methods 等数据和方法,但此时组件尚未被挂载到 DOM 中。beforeMount 函数在组件挂载之前被调用,此时组件已经完成了模板编译,但尚未将其渲染到页面中。mounted 函数在组件挂载完成后被调用,此时组件已经被渲染到页面中,可以进行需要访问 DOM 的操作。
  • 更新阶段调用 beforeUpdate 和 updated 钩子函数。beforeUpdate 函数在组件更新之前被调用,此时组件的数据已经发生了变化,但是 DOM 尚未重新渲染,这个阶段可以进行组件数据更新前的处理工作,例如计算属性的更新、深度监听数据的变化等。updated 函数在组件更新之后被调用,此时组件的 DOM 已经重新渲染,数据观测(data observer)和 event/watcher 事件已经重新开始,可以进行一些需要访问更新后 DOM 元素的操作。
  • 销毁阶段调用 beforeDestroy 和 destroyed 钩子函数。beforeDestroy 函数在组件实例销毁之前被调用,此时组件实例仍然可以访问,该阶段可以进行一些组件销毁前的处理工作,比如清除定时器、取消事件监听等。destroyed 函数在组件销毁之后被调用,此时组件实例已经被销毁,无法再访问组件实例中的任何数据和方法。
  • 激活/停用阶段调用 activated 和 deactivated 钩子函数。activated 函数在 keep-alive 组件被激活时调用。deactivated 函数在 keep-alive 组件被停用时调用。

4. Vue父子组件生命周期执行顺序

在父组件中调用子组件时,组件的生命周期执行顺序如下:

  1. 父组件开始创建阶段,首先会调用父组件的 beforeCreate 和 created 函数。
  2. 父组件进入模板编译阶段,此时会先调用父组件的 beforeMount 函数,然后会递归遍历子组件的模板,创建子组件实例,并调用子组件的 beforeCreate 和 created 函数。
  3. 当子组件实例创建完成后,父组件会调用子组件的 beforeMount 函数,将子组件渲染到父组件的模板中,渲染完成会先调用子组件的 mounted 函数。当子组件全部渲染完成后,会调用父组件的 mounted 函数。此时父组件和子组件已经挂载完成。
  4. 当子组件的数据发生变化时,首先调用父组件的 beforeUpdate 函数,然后依次调用子组件的 beforeUpdate 和 updated 函数,当子组件全部更新完成后,会调用父组件的 updated 函数。当父组件的数据发生变化时,如果这些数据被传递给子组件作为 props 属性,那么会调用子组件的 beforeUpdate 和 updated 函数;如果父组件中的数据改变没有通过 props 属性传递给子组件,那么不会调用子组件的 beforeUpdate 和 updated 函数,只会调用父组件的 beforeUpdate 和 updated 函数。
  5. 当父组件被销毁时,子组件也会随之销毁,首先调用父组件的 beforeDestory 函数,然后依次调用子组件的 beforeDestory 和 destoryed 函数,当子组件全部销毁后,会调用父组件的 destoryed 函数。

5. Vue组件如何通讯?

  • 父到子传值:父到子的传值可以通过在子组件中添加 props 配置项来完成,props 配置项的值可以是一个数组,数组中的元素用于接收父组件传递过来的数据,在父组件中通过子组件的标签属性来传递这些数据。我们可以把父到子传值理解成函数的封装和调用,props 数组中的元素是函数的形参,在使用子组件的时候,传入父组件的数据作为实参。
  • 子到父传值:子到父的传值可以通过自定义事件完成。在子组件中,通过 $emit 方法触发自定义事件,$emit 方法的第一个参数是自定义事件的名称,之后的参数则是要传递的数据。在父组件中,使用 v-on 指令来监听这个自定义事件,v-on 指令的参数是自定义事件的名称,值是一个函数,这个函数会在自定义事件被触发时被执行,函数的参数就是子组件传递过来的数据。
  • Vuex:Vuex 是 Vue.js 的官方状态管理库,用于管理应用程序中的共享状态,可以解决应用程序中状态管理复杂性的问题。Vuex 中有四个核心概念:1. state,用于存放数据,通过 this.$store.state.xxx 来访问。2. getters,相当于组件的计算属性,里面的函数自带一个 state 参数,通过 this.$store.getters.xxx 来访问。3. mutations,在 mutations 中定义方法修改 state 中的数据,定义的方法必须的同步的,可以通过 this.$store.commit("xxx") 来调用。4. actions,用于处理异步操作,但是 actions 不能修改数据,需要在 actions 定义的函数中提交 mutations,因为只有 mutations 中定义的方法能够修改数据,通过 this.$store.dispatch("xxx") 来调用。

6. 描述Vue组件渲染和更新的过程

Vue组件渲染和更新的过程简单地概况为以下几个步骤:

  1. 初始化组件实例:在渲染一个组件之前,Vue会创建一个组件实例,并将组件的选项对象进行合并、处理,最终形成一个组件实例的配置对象。
  2. 渲染组件:Vue将组件实例的配置对象转化为一个渲染函数,并执行该渲染函数,生成一个虚拟DOM树。此时,Vue会对虚拟DOM树进行初次渲染,将组件显示在页面上。
  3. 监听数据变化:当组件实例中的响应式数据发生变化时,Vue中的渲染watcher会立即检测到这些变化,并重新计算组件的渲染函数,生成一个新的虚拟DOM树。
  4. 对比新旧虚拟DOM树:Vue会将新生成的虚拟DOM树和上一次渲染时生成的虚拟DOM树进行比较,找出需要更新的部分。
  5. 更新组件:Vue只会更新旧虚拟DOM树中有差异的部分,使组件达到更新的效果。

7. 双向数据绑定v-model的实现原理

  • v-model 是 Vue.js 中常用的指令,通过该指令可以将表单元素的值与 Vue 实例的属性进行双向绑定。当用户输入表单元素的值时,Vue 会自动更新实例的属性,反之亦然。
  • 使用 v-model 时,只需要在需要绑定的表单元素或组件上加上 v-model 指令,并把它的值设置为需要绑定的属性即可,代码如下:
`<input type="text" v-model="message">`
  • v-model 指令实际上是一个语法糖,它相当于同时使用了一个名为 value 的属性 和 一个名为 input 的事件。上面的代码等价于:
`<input 
	type="text"
	:value="message"
	@input="message = $event.target.value"
>`

其中,:value="message" 是将组件的 value 属性与组件实例的 message 属性绑定起来;@input="message = $event.target.value" 则是将组件的 input 事件与一个函数绑定起来,这个函数将当前表单元素的值赋给组件实例的 message 属性。

8. 如何理解MVVM模式?

  • 传统的组件渲染是静态渲染,数据更新需要操作DOM。Vue框架采用 MVVM(Model-View-ViewModel) 模式来管理应用程序的数据模型(Model)和视图界面(View)之间的交互,即数据驱动视图,达到减少DOM操作的目的。
  • MVVM的基本思想是将 Model 和 View 进行解耦(Decoupling),也就是将 Model 和 View 分离开来,使得它们之间的依赖关系降到最小。然后通过 ViewModel 来协调它们之间的通信。当 Model 变化时,我们不需要手动更新 View,而是可以通过 Vue 的响应式机制,让 Vue 自动更新 View。同样,当用户与 View 交互时,我们也不需要手动修改 Model,而是可以通过 Vue 的指令和事件机制,让 Vue 自动更新 Model。这种解耦机制使得我们可以更加专注于业务逻辑的实现,而不需要过多地关注 View 和 Model 之间的细节。
    在这里插入图片描述
  • Model:Vue应用程序中的数据模型,通常是一个JavaScript对象或数组。这些数据模型被存储在Vue实例的 data 属性中。
  • View:Vue应用程序中的视图界面,通常由 HTML模板 和 Vue指令 组成。Vue的模板语法允许开发人员在HTML中绑定数据以及表达式,从而实现视图的动态更新。
  • ViewModel:ViewModel 是Vue应用程序的核心,它是一个Vue实例,它充当 Model 和 View 之间的桥梁。ViewModel 负责业务逻辑以及管理数据,它可以将 Model数据 绑定到 View 上,同时也可以响应 View 上的事件和用户交互。ViewModel 通过 Vue的响应式机制监听 Model数据 的变化,并自动更新 View。

9. 计算属性computed有何特点?

在Vue实例中,计算属性 computed 是一种用于实时计算 Vue 组件属性值的便捷方式。它可以缓存计算结果,只有在计算属性依赖的响应式数据发生改变时才重新计算;当依赖的数据没有改变时,计算属性不再计算,直接返回缓存的结果,提高了组件渲染的性能。

10. 为何组件中的data必须是一个函数?

在Vue中,每个组件实例都拥有自己的作用域和状态。如果 data 选项是一个简单的对象,那么该组件的实例都会共享这个对象,这样就会出现一个实例更改数据后导致另一个实例中的数据被改变的问题。将 data 定义为一个函数,每个组件实例在创建时都会调用该函数来返回一个对象,从而确保每个实例都拥有自己的数据。同时,Vue 在内部会对这个函数进行封装,确保它只被调用一次,从而避免不必要的性能损失。

11. Ajax请求应该放在哪个生命周期?

  • Ajax(Asynchronous JavaScript and XML) 是一种网络请求方式,可以通过 JavaScript 和 XML 实现异步传输数据。Ajax 可以在不重新加载整个页面的情况下,通过异步请求服务器上的数据,并将数据局部更新到页面上,从而实现局部刷新的效果,提高用户的交互体验。
  • 一般 Ajax 请求会在页面加载完成后,由用户触发某个事件时执行,也就是 mounted 生命周期后执行。这种方式可以避免在页面加载时对服务器进行不必要的请求,提高页面加载速度和用户体验。

12. 如何将父组件所有props传给子组件?

在调用子组件时,绑定 $props 属性。

<child-component v-bind="$props"></child-component>

13. 如何自己实现v-model?

对于一个自定义组件,如果要实现 v-model 双向绑定,需要通过 自定义v-model 的方式实现。自定义v-model 需要在自定义组件中使用 model选项 来配置 value属性 和 input事件的名称。并在组件模板中使用v-bind 将 value属性 绑定到 input元素的value属性上,并通过 v-on 监听 input事件,当input事件触发时将表单元素的值通过 $emit 方法发送出去。这样就可以使用v-model语法糖来实现自定义组件的双向绑定了。

14. 多个组件有相同逻辑,如何抽离?

  • 在Vue中,mixin(混入)是一种将多个组件之间共享的逻辑抽象出来并进行重用的机制。通过定义一个mixin对象,可以将其应用于多个组件中,从而为这些组件提供相同的属性、方法、生命周期钩子等。
  • mixin 是一个普通的 JavaScript 对象,可以包含各种属性和方法,例如data、computed、methods、created等。在组件中,通过定义 mixins 选项来应用一个或多个 mixin。当组件引用了一个或多个 mixin 时,mixin 中定义的属性和方法会被混合到该组件中,这些属性和方法与组件自生定义的属性和方法会合并成一个新的对象。如果 mixin 中定义的属性或方法与组件自身定义的属性或方法名称冲突,则以组件自身的属性或方法为准。
  • 使用 mixin 可以将组件中相同的逻辑代码进行抽象和复用,避免了代码重复和冗余。但是,mixin 的使用也存在一些问题,比如,多个 mixin 可能会造成命名冲突。变量来源不明确,不利于代码阅读。mixin 和组件可能会出现多对多的关系,复杂度高。

15. 何时使用异步组件?

异步组件与常规组件的不同之处在于,异步组件只有在需要的时候才会被加载,而不是在应用程序初始化时就被全部加载。异步组件的应用场景是:当某个组件的体积比较大时,例如Echarts文件,如果应用初始化时就加载,会非常慢,严重影响性能。此时可以将该组件设置为异步组件,在需要使用该组件时,再加载该组件。异步组件通过 import() 函数引入。

16. 何时需要使用keep-alive?

  • keep-alive是Vue内置的一个组件,可以将其用于需要缓存的动态组件,避免每次重新渲染时都要执行组件的 created、mounted、destoryed等钩子函数,从而提高应用程序的性能。
  • keep-alive组件可以包裹动态组件,使其被缓存。被缓存的组件在组件切换时并不会被销毁,而是被保留在内存中,下次需要渲染时直接从缓存中读取组件实例,避免了组件的重新创建和重新渲染。

17. 何时需要使用beforeDestory?

beforeDestroy 函数在组件实例销毁之前被调用,此时组件实例仍然可以访问,该阶段可以进行一些组件销毁前的处理工作,比如清除定时器、取消事件监听 $off、解绑自定义事件 event.$off 等。

18. 什么是作用域插槽?

  • 作用域插槽(scoped slot)是Vue中的一种高级插槽技术。父组件希望使用子组件中的数据作为插槽中的内容,可以使用作用域插槽。
  • 在父组件中,使用<template>标签来声明一个作用域插槽,并在其中使用 v-slot 指令来指定作用域变量的名称。子组件可以使用<template>标签来包含作用域插槽<slot>
  • 下面是一个使用作用域插槽的示例:
<!--父组件-->
<template>
	<div>
		<child-component>
			<template v-slot="slotProps">
				{{slotProps.slotData.text}}
			</template>
		</child-component>
	</div>
</template>

<script>
import child-component from './ChildComponent'

export default{
	components: {
		child-component
	},
	data(){
		return{}
	}
}
<script>
<!--子组件-->
<template>
	<div>
		<slot :slotData="message"></slot>
	</div>
</template>

<script>
export default{
	data(){
		return {
			message: {text: '子组件数据'}
		}
	}
}
</script>

19. Vuex中的actions和mutations有什么区别?

  • mutations 中的函数用于处理 state 数据,函数执行的操作必须是同步的,这是为了保证对 state 的修改是可追溯和可控的。修改 state 数据的唯一方案是提交(commit) mutations。
  • actions 中的函数可以包含任意异步操作,例如 Ajax请求、定时器任务等。当异步操作完成后,actions 会通过 commit 方法触发相关的 mutations 来修改 state。

20. Vue-router有哪些路由模式?

Vue-router 中提供了两种路由模式,一种是hash模式,另一种是history模式。

  • hash模式是默认的路由模式。hash模式的URL中存在 #,例如http://www.baidu.com/#/abc#后面的内容就是路由地址。hash模式的优点是兼容性好,它不需要后端支持,只要在前端将URL中 #后面的内容进行解析,就能获取到路由信息。当URL的hash部分(#后面的内容)发生变化时,会触发 window.onhashchange 事件,该事件可以用来监听浏览器的返回\前进按钮、手动修改URL的hash部分等操作。
  • history模式的URL不会像hash模式那样带有 #,而是一个正常的URL,例如:http://www.baidu.com/path/to/page。history模式是通过利用 HTML5 History API 实现的,可以在不刷新整个页面的情况下,动态改变当前URL地址和页面内容。可以通过 window.onpopstate 来监听路由的变化。history模式需要后端的支持,因为它需要在服务器端进行配置。如果用户直接访问了一个history模式下的URL,而此时后端又没有相应的配置,就会出现404错误。Vue-router 提供了一个特殊的 fallback 选项,用于定义在服务器返回404错误页面时,应该返回什么样的页面。常见的做法是将 fallback 设为单页面应用的主页,以保证用户可以正确访问到页面。
  • 在选择路由模式的时候,如果是 to B 的系统,推荐使用 hash模式,该模式的路由简单易用,兼容性好,对URL规范不敏感。如果是 to C 的系统,推荐使用 history 模式,该模式需要后端支持。总之需要考虑成本和收益,尽量选择简单的路由模式。

21. 如何配置Vue-router异步加载?

  • Vue-rouer 的异步加载可以通过路由懒加载的方式实现,路由懒加载是指将路由对应的组件分开打包,只在需要的时候动态加载,而不是在页面初始化时全部加载。路由懒加载可以有效地减少初始页面加载的时间。
  • 在 Vue.js 中,通过以下代码实现路由懒加载:
export default new VueRouter({
	routes: [
		{
			path: '/foo', 
			component: ()=>import('./Foo.vue')
		},
		{
			path: '/bar',
			component: ()=>import('./Bar.vue')
		}
	]
})

22. 用vnode描述一个DOM结构

  • 给定一个DOM结构片段:
<div id="div" class="container">
	<p>abc</p>
	<ul style="font-size: 20px">
		<li>abc</li>
	</ul>
</div>
  • 使用vnode模拟该DOM结构:
{
	tag: 'div',
	props: {
		id: 'div1',
		className: 'container'
	},
	children: [
		{
			tag: 'p',
			children: 'abc'
		},
		{
			tag: 'ul',
			props: {style: 'font-size: 20px'},
			children: [
				{
					tag: 'li',
					children: 'abc'
				}
			]
		}
	]
}

23. data的监听是如何实现的?

在Vue中,data的监听是通过Vue响应式机制完成的。Vue的响应式机制使用 ES5 中的 Object.defineProperty() 方法来实现对数据的监听。在Vue实例初始化时,会对 data 属性中的每个属性进行监听,将属性转化为 getter 和 setter 函数。当数据发生变化时, setter 函数会被触发,Vue的响应式机制就会重新渲染组件,更新视图界面。

24. Vue如何监听数组的变化?

  • Vue的响应式机制通过在对象上使用 Object.defineProperty()方法来实现属性的劫持,从而监听对象的变化。然而,由于 Object.defineProperty() 只能劫持对象的属性,而不能劫持数组的变化,因此Vue对数组的监听需要做特殊处理。
  • Vue对数组的监听通过重写数组的原型方法来实现,常见的数组原型方法有 push、pop、shift、unshift 等。例如,在调用 push() 方法时,Vue会在数组末尾添加新元素,并触发数组的 length 属性的更新,从而触发更新视图。

25. 请描述Vue响应式原理

  • Vue框架采用了MVVM模式来管理应用程序的Model和View之间的交互,即数据驱动视图,减少了DOM操作。当Model发生变化时,通过Vue的响应式机制,自动更新View。Vue响应式原理是基于数据劫持实现的,其核心是使用 Object.defineProperty() 方法对数据对象的属性进行监听,当数据发生变化时,触发 getter 和 setter 方法,从而实现数据的响应式更新。

  • Vue响应式机制主要包含以下几个部分:

名称作用
Observer:数据观察者用于监听数据对象的属性变化,当属性发生变化时,通知订阅者进行更新
Watcher:数据订阅者用于订阅 Observer 发送的属性变化通知,当属性发生变化时,调用更新函数进行界面更新
Dep:消息订阅与发布中心用于存储订阅者和发送通知,当数据发生变化时,通知所有订阅者进行更新
Compiler:模板编译器用于解析模板,生成抽象语法树(AST),实现模板与数据的关联
Directive:指令用于将模板中的元素与数据绑定起来,实现数据的双向绑定,例如 v-if v-for v-bind 等
  • Vue响应式的实现流程如下:
  1. 在 Vue 实例化时,通过递归遍历 data 属性中的所有属性,为每个属性设置 getter 和 setter 方法,并在 getter 方法中为该属性收集依赖(即将该属性相关的 Watcher 添加到 Dep 中)。
  2. 当数据发生变化时,会触发 setter 方法,setter 方法会通知 Dep 中所有订阅该属性的 Watcher 进行更新。
  3. Watcher 接收到更新通知后触发更新函数,根据被修改的属性的值,重新计算视图中需要更新的部分,并将这部分更新到DOM上。

26. diff算法的时间复杂度

Vue中的diff算法是指在更新虚拟DOM时,对新旧虚拟DOM进行比较,并尽可能地减少DOM操作的算法。使用diff算法比较两棵树的时间复杂度为 O ( n 3 ) O(n^3) O(n3),如果一棵树有1000个节点,就要执行十亿次计算,那么算法是不可用的。Vue对diff算法进行了优化,使得算法的时间复杂度降到了 O ( n ) O(n) O(n)

Vue的diff算法的优化策略如下:

  • 只比较同一层级,不跨级比较。
    在这里插入图片描述

  • tag 和 key 都相同,则认为是相同节点,递归地进行子节点的比较。

  • tag 不相同,则直接删掉重建,不再深度比较。

在这里插入图片描述

27. 简述diff算法的过程

diff算法是用来比较新旧DOM树并完成DOM更新的算法。diff算法的核心包括四个函数,即h函数、patch函数、patchVnode函数、updateChildren函数。

  • h函数用于在diff算法初始化时,新建vnode节点。h函数是通过函数重载的方式定义的,即传入函数的参数个数、参数类型不同时,函数会执行不同的内容。h函数的返回结果是执行vnode函数,vnode函数返回一个JS对象,也就是虚拟DOM。
  • patch函数用于比较新旧虚拟DOM数据的根节点是否相同。patch函数接收两个参数,第一个参数可以是 vnode 也可以是 普通DOM元素,代表旧的 vnode;第二个参数是 vnode,代表新的 vnode。当第一个参数是DOM元素时,patch 函数会先创建一个空的 vnode,然后将这个空的 vnode 关联到该DOM元素上。如果传入的两个参数都是 vnode,且两个 vnode 相同(也就是 vnode 的 sel 和 key 一样),此时会调用 patchVnode 函数,用于比较这两个 vnode 的子集(text 和 children)。如果传入的两个 vnode 不相同,那么会删除旧的 vnode,然后根据新的 vnode,重建这个删除掉的 vnode。
  • patchVnode函数是用于比较两个 vnode 并更新 DOM 的核心函数,它会比较新旧 vnode 节点的 text 和 children,执行 addVnodes 和 removeVnodes 函数更新DOM元素。
  • updateChildren 函数是在 patchVnode 函数执行时,如果新旧 vnode 节点都存在 children 的情况执行的函数。该函数使用双端比较策略,对两个 vnode 的 children 进行对比。如果新旧节点的 children 存在 sel 和 key 相等的情况,那么就会在 updataChildren 函数中,递归调用 patchVnode 函数,比较子节点的 text 和 children。
  • 总之,diff算法的过程,就是 patch -> patchVnode ->updateChildren ->patchVnode -> updateChildren -> patchVnode … 的循环递归过程。

28. Vue为何是异步渲染,$nextTick有什么用?

  • Vue组件是异步渲染的,因为在组件的渲染过程中,涉及到数据的响应式更新、计算属性、侦听器等多个步骤,这些步骤可能会涉及到异步操作,例如异步获取数据,从而导致组件渲染时存在延迟。
  • 在Vue中,$nextTick 是一个实例方法,它用于在下次DOM更新循环结束之后执行延迟回调。当我们修改了Vue实例中的数据后,Vue异步执行DOM更新,更新完成之后我们可能需要进行一些DOM操作,但此时DOM还没有被更新,这时可以使用$nextTick来确保DOM已经更新完毕,从而进行DOM操作。$nextTick方法是异步执行的,因此回调函数不会立即执行,而是会在DOM更新后执行。这意味着,在回调函数中,我们可以访问到最新的DOM状态。

29. Vue有哪些性能优化方式?

  • 合理使用 v-show 和 v-if
  • 利用 computed 的缓存特性,合理利用计算属性。
  • 使用 v-for 时添加 key 属性,并且避免 v-if 和 v-for 的同时使用。
  • 在 beforeDestory 期间,及时销毁自定义事件,DOM事件等,避免内存泄漏。
  • 合理使用异步组件,keep-alive,路由懒加载。
  • data 层级不要太深。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/392616.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Windows openssl-1.1.1d vs2017编译

工具&#xff1a; 1. perl&#xff08;https://strawberryperl.com/&#xff09; 2. nasm&#xff08;https://nasm.us/&#xff09; 3. openssl源码&#xff08;https://www.openssl.org/&#xff09; 可以自己去下载 或者我的网盘提供下载&#xff1a; 链接&#xff1a;…

Redis List 底层三种数据结构原理剖析

1. Redis List 是什么作为 Java 开发者的你&#xff0c;看到这个词并不陌生。在 Java 开发中几乎每天都会使用这个数据结构。Redis 的 List 与 Java 中的 LinkedList 类似&#xff0c;是一种线性的有序结构&#xff0c;可以按照元素被推入列表中的顺序来存储元素&#xff0c;能…

2023年第九周总周结 | 开学第一周

为什么要做周总结&#xff1f; 1.避免跳相似的坑 2.客观了解上周学习进度并反思&#xff0c;制定可完成的下周规划 一、上周问题解决情况 不满却又喜欢“受害者”身份项目导向学习进展困难&#xff0c;进而产生挫败焦虑作息调整→学习时长变少and变碎 二、这周存在问题 and 反…

Tomcat 配置文件数据库密码加密

几年前研究过Tomcat context.xml 中数据库密码改为密文的内容&#xff0c;因为当时在客户云桌面代码没有留备份也没有文章记录&#xff0c;最近项目又提出了这个需求就又重新拾起来学习一下。在网上找了一些资料&#xff0c;自己也大概试了一下&#xff0c;目前功能是实现了。参…

SpringCloud系列(十五)[分布式搜索引擎篇] - 结合实际应用场景学习并使用 RestClient 客户端 API

前面的文章具体介绍了是索引库及文档的一些基本操作指令, 指令还是挺简单的; 那么实际应用场景下, 我们是如何操作 ElasticSearch 的呢?  其实 ElasticSearch 官方已经为我们提供了各种不同语言的客户端, 目的就是为了来操作 ElasticSearch, 这些客户端的本质就是组装 DSL 语…

vmware虚拟机与树莓派4B安装ubuntu1804 + ros遇到的问题

如题所示&#xff0c;本人在虚拟机上安装ubuntu1804&#xff0c;可以很容易安装&#xff0c;并且更换系统apt源和ros源&#xff0c;然后安装ros&#xff0c;非常顺利&#xff0c;但是在树莓派4B上安装raspiberry系统就遇到了好多问题。 树莓派我烧录的是这个镜像&#xff1a;ub…

ASO优化之选择最佳关键词

ASO的关键字排名是指针对特定的关键词在应用商店搜索结果中所形成的位置。虽然这看起来很简单&#xff0c;但应用商店排名不仅仅是位置&#xff0c;应用的排名统计数据都要考虑进去。 应用商店搜索结果因国家/地区而异&#xff0c;这就意味着如果我们从不同的国家或地区进行搜…

经典文献阅读之--Lifelong SLAM(变化环境中Lifelong定位建图)

0. 简介 商场、超市等大多数现实场景的环境随时都在变化。不考虑这些变化的预建地图很容易变得过时。因此&#xff0c;有必要拥有一个最新的环境模型&#xff0c;以促进机器人的长期运行。为此《A General Framework for Lifelong Localization and Mapping in Changing Envir…

Oracle技术分享 exp导数据时报错ORA-01578 ORA-01110

问题描述&#xff1a;exp导数据时报错ORA-01578 ORA-01110&#xff0c;如下所示&#xff1a; 数据库&#xff1a;oracle 19.12 多租户 1、异常重现 [oracledbserver ~]$ exp ora1/ora1orclpdbfileemp.dmp tablesemp logexp.log Export: Release 19.0.0.0.0 - Production onS…

OpenEuler20.03源码安装配置PostgreSQL13.4详细图文版

OpenEuler安装配置PostgreSQL 序号更新内容更新日期更新人1完成第一至三章内容编辑&#xff1b;2021年9月18日liupp2增加PostgreSQL服务开机自动启动&#xff1b;2021年10月25日liupp 一、准备条件 OpenEuler(Hyper-V虚拟机)&#xff1a; 版本&#xff1a;20.03 LTS SP2下载地…

推荐几个超实用的开源自动化测试框架

有什么好的开源自动化测试框架可以推荐&#xff1f;为了让大家看文章不蒙圈&#xff0c;文章我将围绕3个方面来阐述&#xff1a; 1、通用自动化测试框架介绍 2、Java语言下的自动化测试框架 3、Python语言下的自动化测试框架 随着计算机技术人员的大量增加&#xff0c;通过编写…

什么是MyBatis?无论是基础教学还是技术精进,你都应该看这篇MyBatis

文章目录学习之前&#xff0c;跟你们说点事情&#xff0c;有助于你能快速看完文章一、先应用再学习&#xff0c;代码示例1. 第一个MyBatis程序2. MyBatis整合Spring3. SpringBoot整合MyBatis二、MyBatis整体流程&#xff0c;各组件的作用域和生命周期三、说说MyBatis-config.xm…

流域土壤保持及GIS实现

流域土壤保持及GIS实现 流域水土过程模拟与生态调控 01 土壤保持模拟 土壤侵蚀不仅会引起耕地生产力下降、河床抬升、泥沙淤积阻塞河道等生态环境问题&#xff0c;也会对人们正常的生产生活产生威胁。生态系统的土壤保持量&#xff08;吨/公顷/年&#xff09;&#xff0c;是…

$3 : 水​​​​​项目实战 - 水果库存系统

javase知识点复习&#xff1a; final关键字&#xff1a;http://t.csdn.cn/bvFgu 接口的定义&#xff0c;特性&#xff0c;实现&#xff0c;继承&#xff1a;http://t.csdn.cn/tbXl3 异常&#xff1a;http://t.csdn.cn/VlS0Z DAO的概念和角色&#xff08;设计理念&#xff09;&a…

适配PyTorch FX,OneFlow让量化感知训练更简单

作者 | 刘耀辉审稿 | BBuf、许啸宇1背景近年来&#xff0c;量化感知训练是一个较为热点的问题&#xff0c;可以大大优化量化后训练造成精度损失的问题&#xff0c;使得训练过程更加高效。Torch.fx在这一问题上走在了前列&#xff0c;使用纯Python语言实现了对于Torch.nn.Module…

学习笔记:Java并发编程(补)CompletableFuture

学习视频&#xff1a;https://www.bilibili.com/video/BV1ar4y1x727 参考书籍&#xff1a;《实战 JAVA 高并发程序设计》 葛一鸣 著 系列目录 学习笔记&#xff1a;Java 并发编程①_基础知识入门学习笔记&#xff1a;Java 并发编程②_共享模型之管程学习笔记&#xff1a;Java 并…

win10开机黑屏只有鼠标怎么办?这里有4个妙招

真实案例&#xff1a;电脑开机黑屏&#xff0c;只出现鼠标箭头光标怎么办&#xff1f; “早上打开电脑&#xff0c;发现开不了机&#xff0c;屏幕上只有一个鼠标光标&#xff01;百度搜索了很长时间&#xff0c;但所有的方法都没有奏效。求教各位大神&#xff0c;有什么好方法…

中电金信源启小程序开发平台 赋能金融+业务生态共享共建

导语&#xff1a;源启小程序开发平台立足于“为金融业定制”&#xff0c;从小程序全生命周期的角度出发&#xff0c;助力银行、互联网金融、保险、证券客户实现一站式小程序开发、发布、运营与营销。企业可以通过源启小程序开发平台&#xff0c;低成本高效率开发一款定制化小程…

The 19th Zhejiang Provincial Collegiate Programming Contest vp

和队友冲了这场&#xff0c;极限6题&#xff0c;重罚时铁首怎么说&#xff0c;前面的A题我贡献了太多的罚时&#xff0c;然后我的G题最短路调了一万年&#xff0c;因为太久没写了&#xff0c;甚至把队列打成了优先队列&#xff0c;没把head数组清空完全&#xff0c;都是我的锅呜…

搭载英伟达Jetson Orin的Allspark 2全新亮相,算力高达100TOPS!

Allspark 2 系列AI边缘计算机 Allspark 2经过设计优化的铝合金外壳&#xff0c;内置静音涡轮风扇&#xff0c;散热优秀。尺寸102.5X62.5X31mm&#xff0c;整机重量188g。 相比Allspark 1&#xff0c;2代整机轻了25克&#xff0c;更加轻薄。 在机身更加轻薄的情况下&#xff0c…