动态组件有两种常用场景: 一是动态路由:动态路由exportconstasyncRouterMap:ArrayRouteRecordRaw〔{path:,name:index,meta:{title:首页},component:BasicLayout,引用了BasicLayout组件redirect:welcome,children:〔{path:welcome,name:Welcome,meta:{title:引导页},component:()import(viewswelcome。vue)},。。。〕}〕 二是动态渲染组件,比如在Tabs中切换:eltabs:modelvaluecopyTabNametypecardtemplatevforitemintabList:keyitem。keyitem。nameeltabpane:nameitem。key:labelitem。name:disableditem。disabled:lazyitem。lazytruetemplatelabelspancomponentvifitem。icon:isitem。icon{{item。name}}spantemplate关键在这里component:keyitem。keyitem。name:isitem。componentvbinditem。propseltabpanetemplateeltabs 在vue2中使用并不会引发什么其他的问题,但是当你将组件包装成一个响应式对象时,在vue3中,会出现一个警告: VuereceivedaComponentwhichwasmadeareactiveobject。Thiscanleadtounnecessaryperformanceoverhead,andshouldbeavoidedbymarkingthecomponentwithmarkRaworusingshallowRefinsteadofref。 出现这个警告是因为:使用reactive或ref(在data函数中声明也是一样的)声明变量会做proxy代理,而我们组件代理之后并没有其他用处,为了节省性能开销,vue推荐我们使用shallowRef或者markRaw跳过proxy代理。 解决方法如上所说,需要使用shallowRef或markRaw进行处理: 对于Tabs的处理:import{markRaw,ref}fromvueimportAfrom。componentsA。vueimportBfrom。componentsB。vueinterfaceComponentList{name:Stringcomponent:Component}consttabrefComponentList〔〕(〔{name:组件A,component:markRaw(A)},{name:组件B,component:markRaw(B)}〕) 对于动态路由的处理:import{markRaw}fromvue动态路由exportconstasyncRouterMap:ArrayRouteRecordRaw〔{path:,name:index,meta:{title:首页},component:markRaw(BasicLayout),使用markRawredirect:welcome,。。。}〕 而对于shallowRef和markRaw,2者的区别在于shallowRef只会对value的修改做出反应,比如:conststateshallowRef({count:1})不会触发更改state。value。count2会触发更改state。value{count:2} 而markRaw,是将一个对象标记为不可被转为代理。然后返回该对象本身。constfoomarkRaw({})console。log(isReactive(reactive(foo)))false也适用于嵌套在其他响应性对象constbarreactive({foo})console。log(isReactive(bar。foo))false 可看到,被markRaw处理过的对象已经不少一个响应式对象了。 对于组件来说,它不应该是一个响应式对象,对于shallowRef和markRaw推荐在使用动态组件用markRaw进行处理。