Javascript 如何以编程方式间接创建Vue组件

Javascript 如何以编程方式间接创建Vue组件,javascript,vue.js,Javascript,Vue.js,我正在尝试以编程方式将组件添加到我的Vue单文件组件中的一个页面中,如果您提前知道要做什么,该组件的工作效果会非常好。在我的例子中,组件及其布局将通过JSON接收,我正在尝试动态创建它们。下面你可以看到,我想做一些类似eval的事情,但不幸的是,这不适用于未实例化的对象。下面的代码使用硬编码值进行简化,以获得点 <template> <div id="app"> <h2>Static template:</h2> <Inp

我正在尝试以编程方式将组件添加到我的Vue单文件组件中的一个页面中,如果您提前知道要做什么,该组件的工作效果会非常好。在我的例子中,组件及其布局将通过JSON接收,我正在尝试动态创建它们。下面你可以看到,我想做一些类似eval的事情,但不幸的是,这不适用于未实例化的对象。下面的代码使用硬编码值进行简化,以获得点

<template>
  <div id="app">
    <h2>Static template:</h2>
    <InputTemplate type="text"></InputTemplate>
    <h2>Dynamically inserted:</h2>
    <div ref="container">
      <button @click="onClick">Click to insert</button>
      <br/>
    </div>
  </div>
</template>  

<script>
import Vue from 'vue'
//the component I'd like to create
import InputTemplate from './components/InputTemplate.vue'

export default {
  name: 'app',
  components: { InputTemplate },
  methods: {
    onClick() {
      //I'd like to do something like this, but eval doesn't work like this
      var ComponentClass = Vue.extend(eval('InputTemplate'))
      var instance = new ComponentClass({
        propsData: {type: 'text' }
      })
      instance.$mount()
      this.$refs.container.appendChild(instance.$el)
    }
  }
}
</script>
您可以使用通过API检索组件

我已经通过Axios使用GraphQL进行了测试,但它应该可以与任何REST服务一起使用

主要组件如下所示:

<template>
  <div>
    <h1>Test page</h1>
    <div><button @click="clicked = true">Load component</button></div>
    <async-component v-if="clicked" />
  </div>
</template>

<script>
import axios from 'axios';

export default {
  data() {
    return {
      clicked: false,
    };
  },
  components: {
    'async-component': () => axios.post('http://localhost:5000/graphql', { query: `
      {
        asyncComponentByRowId(rowId: 1) {
          component
          content
        }
      }
    `,
    }).then((response) => {
      const comp = response.data.data.asyncComponentByRowId.content;
      // eval can be harmful
      return eval(`(${comp})`);
    }),
  },
};
</script>
当按下按钮时,从API异步下载后将显示组件

唯一的问题是我正在使用
eval
解码对象

结果:


事实证明,Vue有
,如果您将它放入
v-for
循环,它正是我希望实现的

你试过了吗?如果我理解正确,使用异步组件将允许我根据需要动态导入组件,方法是使用类似于
myComponent:()=>import(myComponent)
?我自己没有试过,但这也是我的理解方式。我认为可以用另一个函数替换
import
函数,该函数返回一个Promise中的组件对象。
<template>
  <div>
    <h1>Test page</h1>
    <div><button @click="clicked = true">Load component</button></div>
    <async-component v-if="clicked" />
  </div>
</template>

<script>
import axios from 'axios';

export default {
  data() {
    return {
      clicked: false,
    };
  },
  components: {
    'async-component': () => axios.post('http://localhost:5000/graphql', { query: `
      {
        asyncComponentByRowId(rowId: 1) {
          component
          content
        }
      }
    `,
    }).then((response) => {
      const comp = response.data.data.asyncComponentByRowId.content;
      // eval can be harmful
      return eval(`(${comp})`);
    }),
  },
};
</script>
{
  "data": {
    "asyncComponentByRowId": {
      "component": "my-async-component",
      "content": "{\r\n\ttemplate: '<div>{{ msg }}</div>',\r\n\tdata: function() {\r\n\t\treturn {\r\n\t\t\tmsg: 'Async component works!'\r\n\t\t};\r\n\t}\r\n}"
    }
  }
}
{
  template: '<div>{{ msg }}</div>',
  data: function() {
    return {
      msg: 'Async component works!'
    };
  }
}