在Vue.js中动态实例化组件



在本教程之后,我将尝试在页面上以编程方式创建组件实例。

主要片段如下:

import Button from 'Button.vue'
import Vue from 'vue'
var ComponentClass = Vue.extend(Button)
var instance = new ComponentClass()
instance.$mount()
this.$refs.container.appendChild(instance.$el)

但是我有两个错误:

  1. 我试图实例化的组件包含对存储的引用,但这些引用不起作用:"TypeError:无法读取未定义的属性'state'">

  2. 对于代码段(this.$refs.container.appendChild(instance.$el)(的最后一行,我得到了以下错误:"未捕获类型错误:无法读取未定义的属性'container'">

我真的不知道如何解决这个问题,如果Vue.js中的任何人都能给我一些提示,告诉我为什么会出现这些错误,并解决它们,那将是非常棒的。

1(由于您手动实例化该组件,而它不属于主应用程序的组件树,因此存储不会从根组件自动注入。在实例化组件时,您必须手动将存储提供给构造函数。。

import ProjectRow from "./ProjectRow.vue";
import Vue from "vue";
import store from "../store";
let ProjectRowClass = Vue.extend(ProjectRow);
let ProjectRowInstance = new ProjectRowClass({ store });

2( 在Vue单一文件组件(SFC(中,默认导出之外的this不引用Vue实例,因此您无权访问$refs或任何其他Vue实例属性/方法。要访问Vue实例,您需要将此行this.$refs.container.appendChild(instance.$el)移动到默认导出中的某个位置,例如mounted钩子或methods中的一个。

请参阅此CodeSandbox,了解如何进行此操作的示例。

这是在Vue.js中实例化组件的另一种方法,您可以使用两个不同的根元素。

// Instantiate you main app
var app = new Vue({
el: '#app',
data: {
message: 'Hello Vue!'
}
})
//
// Then instantiate your component dynamically
//
// Create a component or import it.
const Hello = {
props: ['text'],
template: '<div class="hello">{{ text }}</div>',
};
// Create a componentClass by Vue.
const HelloCtor = Vue.extend(Hello);
// Use componentClass to instantiate your component.
const vm = new HelloCtor({
propsData: {
text: 'HI :)'
}
})
// then mount it to an element.
.$mount('#mount');

它通过分配"这个";财产";"父";。通过设置父级,您还可以访问新实例中的$store。(当然,假设"this"是另一个Vue实例/组件,并且已经可以访问商店(

new (Vue.extend(YourNewComponent))({
parent: this,
propsData: {
whatever: 'some value',
},
}).$mount(el.querySelector('.some-id'))

如果你不需要引用父母,你可以直接离开"家长:这个;出来

重要提示:以这种方式在页面上装载许多(如500+(项目时,您将获得巨大的性能提升。最好只通过道具给新组件提供必要的东西,而不是给它整个"道具";这个";对象

我走上了这条路,遵循了上面的所有例子,甚至是这个例子:https://css-tricks.com/creating-vue-js-component-instances-programmatically/

虽然我走得很远,而且它很有效(我用这种方式制作了很多组件(,但至少在我的案例中,它有的缺点。例如,我同时使用Vuetify,并且动态添加的组件不属于外部表单,这意味着虽然本地(每个组件(验证有效,但表单没有收到整体状态。另一件不起作用的事情是禁用窗体。随着更多的工作,将窗体作为父属性传递,其中一些工作开始起作用,但删除组件呢。这并不顺利。虽然它们是不可见的,但它们并没有被真正删除(内存泄漏(。

所以我改为使用渲染函数。事实上,它要容易得多,有很好的文档记录(Vue 2和Vue 3(,而且一切都很正常。我也从这个项目中得到了很好的帮助:https://koumoul-dev.github.io/vuetify-jsonschema-form/latest/

基本上,要动态添加一个函数,只需实现render()函数,而不需要使用模板。工作方式有点像React。您可以在这里实现任何逻辑来选择标签、选项和所有内容。只要返回,Vue就会构建影子DOM并保持真实DOM的最新状态。

这里的方法似乎可以直接操作DOM,我很高兴我不再需要这样做了

最新更新