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

时间:2018-11-09 21:12:07

标签: vue.js components

this tutorial之后,我试图以编程方式在页面上创建组件的实例。

主要代码段是这样:

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)),出现以下错误:“未捕获的TypeError:无法读取未定义的属性'容器'”

    < / li>

我真的不确定如何解决此问题,如果有Vue.js的强者可以给我一些提示,说明为什么我会遇到这些错误并解决这些问题,这将是非常棒的。

3 个答案:

答案 0 :(得分:2)

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 Single File Component (SFC)中,默认导出this之外没有引用Vue实例,因此您无权访问$refs或任何其他Vue实例属性/方法。要访问Vue实例,您需要将此行this.$refs.container.appendChild(instance.$el)移动到默认导出中的某个位置,例如,在mounted挂钩中或您的methods之一中。

请参见此CodeSandbox,以获取有关如何进行此操作的示例。

答案 1 :(得分:0)

通过将“ this”分配给属性“ parent”来工作。通过设置父级,您还可以访问新实例中的$ store。 (当然,“ this”是另一个Vue实例/组件,并且已经可以访问商店)

let newItem = new Vue(Object.assign({}, YourNewComponent, {
    parent: this,
    propsData: {
        whatever: 'some value',
    },
}));
newItem.$mount(document.getElementById(('some-id'));

如果您不需要引用父项,则可以不添加“父项:此”。

重要提示:以这种方式在页面上安装许多(例如500多个)项目时,您会获得巨大的性能影响。最好只通过props给新的Component必要的东西,而不是给它整个“ this”对象。

答案 2 :(得分:0)

这是在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');