简体   繁体   English

vue.js 2 带动态模板的单文件组件

[英]vue.js 2 single file component with dynamic template

I need a single file component to load its template via AJAX.我需要一个文件组件来通过 AJAX 加载其模板。 I search a while for a solution and found some hints about dynamic components.我搜索了一段时间的解决方案,发现了一些关于动态组件的提示。 I crafted a combination of a parent component which imports a child component and renders the child with a dynamic template.我制作了一个父组件的组合,它导入一个子组件并使用动态模板呈现子组件。

Child component is this:子组件是这样的:

<template>
  <div>placeholder</div>
</template>

<script>
import SomeOtherComponent from './some-other-component.vue';

export default {
  name: 'child-component',
  components: {
    'some-other-component': SomeOtherComponent,
  },
};
</script>

Parent component is this父组件是这个

<template>
  <component v-if='componentTemplate' :is="dynamicComponent && {template: componentTemplate}"></component>
</template>

<script>
import Axios from 'axios';
import ChildComponent from './child-component.vue';

export default {
  name: 'parent-component',
  components: {
    'child-component': ChildComponent,
  },
  data() {
    return {
      dynamicComponent: 'child-component',
      componentTemplate: null,
    };
  },
  created() {
    const self = this;
    this.fetchTemplate().done((htmlCode) => {
      self.componentTemplate = htmlCode;
    }).fail((error) => {
      self.componentTemplate = '<div>error</div>';
    });
  },
  methods: {
    fetchTemplate() {
      const formLoaded = $.Deferred();
      const url = '/get-dynamic-template';
      Axios.get(url).then((response) => {
        formLoaded.resolve(response.data);
      }).catch((error) => {
        formLoaded.reject(error);
      }).then(() => {
        formLoaded.reject();
      });
      return formLoaded;
    },
  },
};
</script>

The dynamic template code fetched is this:获取的动态模板代码是这样的:

<div>
<h1>My dynamic template</h1>
<some-other-component></some-other-component>
</div>

In general the component gets its template as expected and binds to it.通常,组件按预期获取其模板并绑定到它。 But when there are other components used in this dynamic template (some-other-component) they are not recognized, even if they are correctly registered inside the child component and of course correctly named as 'some-other-component'.但是,当此动态模板中使用了其他组件(some-other-component)时,即使它们在子组件中正确注册并且当然正确命名为“some-other-component”,它们也无法识别。

I get this error: [Vue warn]: Unknown custom element: some-other-component - did you register the component correctly?我收到此错误:[Vue warn]: Unknown custom element: some-other-component - 您是否正确注册了该组件? For recursive components, make sure to provide the "name" option.对于递归组件,请确保提供“名称”选项。

Do I miss something or is it some kind of issue/bug?我错过了什么还是某种问题/错误?

I answer my question myself, because I found an alternative solution after reading a little bit further here https://forum.vuejs.org/t/load-html-code-that-uses-some-vue-js-code-in-it-via-ajax-request/25006/3 .我自己回答我的问题,因为我在这里进一步阅读https://forum.vuejs.org/t/load-html-code-that-uses-some-vue-js-code-in后找到了一个替代解决方案-it-via-ajax-request/25006/3

The problem in my code seems to be this logical expression :is="dynamicComponent && {template: componentTemplate}" .我的代码中的问题似乎是这个逻辑表达式:is="dynamicComponent && {template: componentTemplate}" I found this approach somewhere in the internet.我在互联网的某个地方找到了这种方法。 The original poster propably assumed that this causes the component "dynamicComponent" to be merged with {template: componentTemplate} which should override the template option only, leaving other component options as defined in the imported child-component.vue .原始海报可能假设这会导致组件“dynamicComponent”与{template: componentTemplate}合并,后者应该只覆盖模板选项,而保留导入的child-component.vue中定义的其他组件选项。 But it seems not to work as expected since && is a boolean operator and not a "object merge" operator.但它似乎没有按预期工作,因为&&是 boolean 运算符而不是“对象合并”运算符。 Please somebody prove me wrong, I am not a JavaScript expert after all.请有人证明我错了,毕竟我不是 JavaScript 专家。

Anyway the following approach works fine:无论如何,以下方法可以正常工作:

<template>
  <component v-if='componentTemplate' :is="childComponent"></component>
</template>

<script>
import Axios from 'axios';
import SomeOtherComponent from "./some-other-component.vue";

export default {
  name: 'parent-component',
  components: {
    'some-other-component': SomeOtherComponent,
  },
  data() {
    return {
      componentTemplate: null,
    };
  },
  computed: {
    childComponent() {
      return {
        template: this.componentTemplate,
        components: this.$options.components,
      };
    },
  },
  created() {
    const self = this;
    this.fetchTemplate().done((htmlCode) => {
      self.componentTemplate = htmlCode;
    }).fail((error) => {
      self.componentTemplate = '<div>error</div>';
    });
  },
  methods: {
    fetchTemplate() {
      const formLoaded = $.Deferred();
      const url = '/get-dynamic-template';
      Axios.get(url).then((response) => {
        formLoaded.resolve(response.data);
      }).catch((error) => {
        formLoaded.reject(error);
      }).then(() => {
        formLoaded.reject();
      });
      return formLoaded;
    },
  },
};
</script>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM