markRaw 包裹引入的组件,是为了什么?
markRaw
的作用:
在 Vue 中,markRaw
是一个函数,用于将一个对象标记为 “原始对象”,这意味着 Vue 将不会对该对象进行响应式转换。
使用场景:
- 当你有一些对象,不希望 Vue 将其变成响应式对象时,可以使用
markRaw
。例如,某些第三方库的实例或非常大的数据集,将其变成响应式对象会带来性能开销,此时可以使用markRaw
来避免这种情况。 - 在某些情况下,你可能需要在 Vue 组件中存储一些非响应式的数据,这些数据不会影响视图的渲染,也不需要触发 Vue 的响应式更新机制,那么
markRaw
是一个很好的选择。
示例代码:
<template>
<div>
<p>{{ rawObj.message }}</p>
<button @click="updateObj">Update</button>
</div>
</template>
<script>
import { markRaw, reactive } from 'vue';
export default {
setup() {
// 使用 markRaw 标记对象为原始对象
const rawObj = markRaw({ message: 'Hello, World' });
const reactiveObj = reactive({ message: 'Hello, Vue' });
const updateObj = () => {
// 修改原始对象的属性
rawObj.message = 'Updated raw message';
// 修改响应式对象的属性
reactiveObj.message = 'Updated reactive message';
};
return {
rawObj,
reactiveObj,
updateObj
};
}
};
</script>
代码解释:
- 首先,我们从 Vue 中导入
markRaw
和reactive
函数。 - 在
setup
函数中,使用markRaw({ message: 'Hello, World' })
创建了一个原始对象rawObj
。 - 同时,使用
reactive({ message: 'Hello, Vue' })
创建了一个响应式对象reactiveObj
。 -
updateObj
函数用于修改rawObj
和reactiveObj
的message
属性。 - 当点击按钮调用
updateObj
函数时,会发现修改reactiveObj
的属性会触发 Vue 的响应式更新,从而更新视图中显示的reactiveObj.message
的值;而修改rawObj
的属性不会触发 Vue 的响应式更新,因为它被标记为原始对象,所以视图中显示的rawObj.message
的值不会自动更新。
注意事项:
- 一旦一个对象被标记为
markRaw
,它将始终是非响应式的,不能再通过 Vue 的响应式 API 使其变为响应式。 - 对于大型数据集合或不需要响应式的对象,使用
markRaw
可以提高性能,但需要谨慎使用,确保不会在需要响应式的地方使用它,以免导致意外的行为。
markRaw
包裹引入的组件:
在 Vue 中,将引入的组件用 markRaw
包裹通常是为了避免 Vue 将该组件实例转换为响应式对象。这主要基于以下几个方面的考虑:
性能优化:
- Vue 的响应式系统会对数据对象进行代理,以实现数据的响应式更新。对于组件实例来说,将其变成响应式对象可能会带来额外的性能开销,特别是对于一些复杂的组件。使用
markRaw
包裹组件实例可以避免 Vue 对其进行响应式处理,从而提高性能。
避免不必要的响应式更新:
- 有些组件在使用过程中并不需要响应式更新。例如,某些静态组件,它们的状态不会发生改变,或者它们的状态改变不会影响到父组件或其他相关组件的渲染逻辑。将这样的组件用
markRaw
包裹可以确保 Vue 不会对其内部的状态变化进行监听和响应式处理,避免不必要的渲染和性能消耗。
使用场景示例:
假设你有一个自定义组件 MyComponent
,你可能会在某些情况下这样使用 markRaw
:
<template>
<div>
<component :is="componentInstance" />
</div>
</template>
<script>
import { markRaw, ref } from 'vue';
import MyComponent from './MyComponent.vue';
export default {
setup() {
// 将组件实例标记为原始对象,避免 Vue 对其进行响应式处理
const componentInstance = markRaw(MyComponent);
return {
componentInstance
};
}
};
</script>
代码解释:
- 从 Vue 中导入
markRaw
和ref
函数,并引入MyComponent.vue
组件。 - 在
setup
函数中,使用markRaw(MyComponent)
将MyComponent
组件实例标记为原始对象,得到componentInstance
。 - 在模板中使用动态组件
<component :is="componentInstance" />
来渲染这个组件。 - 因为
componentInstance
被标记为原始对象,Vue 不会对其进行响应式处理,所以在该组件实例的状态发生变化时,Vue 不会触发额外的响应式更新逻辑,这在一些场景下可以优化性能和避免不必要的更新。
注意事项:
- 要谨慎使用
markRaw
包裹组件,确保组件确实不需要 Vue 的响应式更新,否则可能会导致组件的状态改变无法正确反映在视图上。 - 对于大多数常规组件,通常不需要使用
markRaw
包裹,因为 Vue 的响应式系统可以很好地处理它们的状态更新和渲染。只有在明确知道组件的状态更新不应该触发响应式更新时,才考虑使用markRaw
包裹组件。