[英]vuejs ref is undefined when importing component with lazy loading
I'm trying to import a component like this for lazy loading:我正在尝试导入这样的组件以进行延迟加载:
components: {SizeChartForm:() => import("@/core/components/size/SizeChartForm/SizeChartForm")},
I'm having a ref to SizeChartForm
component:我有一个
SizeChartForm
组件的参考:
<SizeChartForm ref="sizeChart" v-model="value" />
and trying to use it in the mounted:并尝试在安装中使用它:
mounted() {
this.$refs.sizeChart.setDisabled(false)
}
but it says sizeChart
is undefined.但它说
sizeChart
未定义。 Even $nextTick
is not working.甚至
$nextTick
也不起作用。
But when I use normal import it works:但是当我使用正常导入时,它可以工作:
import SizeChartForm from "@/core/components/size/SizeChartForm/SizeChartForm";
components: {SizeChartForm}
Vue version: 2.6.11 Vue版本:2.6.11
$nextTick
is not enough - it takes much longer to load an async component. $nextTick
是不够的 - 加载异步组件需要更长的时间。
Generally if you need to do some work when the child component is mounted, you should do it in child's mounted hook, not in parent's ( docs - "Note that mounted
does not guarantee that all child components have also been mounted." ).一般来说,如果你需要在子组件挂载时做一些工作,你应该在子组件的挂载钩子中做,而不是在父组件中(文档- “注意,
mounted
并不能保证所有子组件也已被挂载。” )。
If moving the code to the child is not an option, you can use the (little documented) fact that Vue 2 lifecycle emits special events like hook:mounted
for each lifecycle stage and those events can be listened in the parent: <child ref="child" @hook:mounted="onAsyncComponentMounted"></child>
如果将代码移动到子级不是一个选项,您可以使用 Vue 2 生命周期为每个生命周期阶段发出特殊事件(如
hook:mounted
)的(很少记录)事实,并且可以在父级中监听这些事件: <child ref="child" @hook:mounted="onAsyncComponentMounted"></child>
Those events were removed in Vue 3 (I'm unable to find any documentation or anything in themigration guide but I'v tested and it doesn't work) so the best approach seems to emit some custom event from the child's mounted
hook and listen for it in the parent (see second example)这些事件在 Vue 3 中被删除(我无法在迁移指南中找到任何文档或任何内容,但我已经测试过但它不起作用)所以最好的方法似乎是从孩子的
mounted
钩子中发出一些自定义事件和在父母那里听(见第二个例子)
Update更新
I found this tweet from the Vue core team member Damian Dulisz explaining (see the replies) that hook:xxx
events are not considered public API and are not documented intentionally.我发现这条来自 Vue 核心团队成员 Damian Dulisz 的推文解释说(参见回复)
hook:xxx
事件不被视为公共 API,也没有刻意记录。 So from this POV and also considering it's removal in Vue 3, use the second solution...因此,从这个 POV 并考虑到它在 Vue 3 中被删除,使用第二种解决方案......
Vue 2
// NOTE: this works only in Vue 2, not in Vue 3! const child = { template: ` <div> <input ref="input" type="text" /> </div> ` } // to simulate component async loading in browser env. const loadComponentAsync = function() { return new Promise(function(resolve, reject) { setTimeout(() => resolve(child), 2000); }) } const app = new Vue({ el: '#app', components: { 'child': () => loadComponentAsync() }, methods: { onAsyncComponentMounted() { console.log(this.$refs.child.$refs.input) } } })
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.6.14/vue.js"></script> <div id='app'> <child ref="child" @hook:mounted="onAsyncComponentMounted"></child> </div>
Vue 3
const child = { template: ` <div> <input ref="input" type="text" /> </div> `, mounted() { this.$emit('child-mounted') } } const loadComponentAsync = function() { return new Promise(function(resolve, reject) { setTimeout(() => resolve(child), 2000); }) } const app = Vue.createApp({ components: { 'child': Vue.defineAsyncComponent(() => loadComponentAsync()) }, methods: { onAsyncComponentMounted() { console.log(this.$refs.child.$refs.input) } } }).mount('#app')
<script src="https://unpkg.com/vue@3.1.5/dist/vue.global.js"></script> <div id='app'> <child ref="child" @child-mounted="onAsyncComponentMounted"></child> </div>
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.