【问题标题】:Vue js dynamic componentsVue js 动态组件
【发布时间】:2018-04-28 09:13:39
【问题描述】:

我有如下元素的数据结构:

[
  {
    type: 'text',
    content: 'some text'
  },
  {
    type: 'image',
    content: {
      name: 'filename.jpg',
      url: 'http://example.com/filename.jpg'
    }
  }
]

在我的模板中,我使用 if's inside 执行 v-for,以根据类型呈现不同的组件:

<div v-for="element in elements">
  <div v-if="element.type === 'text'">
    <p>{{ element.content }}</p>
  </div>
  <div v-if="element.type === 'image'">
    <some-component :image="element.content"></some-component>
  </div>
</div>

我的问题是,有没有“更清洁”、更好的方法?

【问题讨论】:

    标签: vuejs2 vue-component


    【解决方案1】:

    我想我会根据<component> 标签制作一个组件交换器——比如:

    //  template swapper based on the <component> tag
    //  :is     - string value pointing to the component to be used
    //  :value  - data to be used in the selected component 
    Vue.component('vue-html-tag', {
      props: ['value'],
      template: `<component :is="'vue-' + value.tag + '-tag'" :value="value"></component>`
    });
    
    
    //  tag components 
    Vue.component('vue-p-tag', {
      props: ['value'],
      template: `<p :class="value.class">
            {{ value.text }}
            <vue-html-tag v-for="item in value.content" :key="item.id" :value="item"></vue-html-tag>
        </p>`
    });
    
    Vue.component('vue-img-tag', {
      props: ['value'],
      template: `<img :src="value.src" />`
    });
    
    Vue.component('vue-a-tag', {
      props: ['value'],
      template: `<a :href="value.href" :target="value.target">{{ value.text}}</a>`
    });
    
    Vue.component('vue-span-tag', {
      props: ['value'],
      template: `<span :class="value.class">
            {{ value.text }}
            <vue-html-tag v-for="item in value.content" :key="item.id" :value="item"></vue-html-tag>
        </span>`
    });
    
    
    
    //  app instance
    new Vue({
      el: '#app',
      data: {
        html: [
          { id: 1, tag: 'p', text: 'Lorem ipsum', class: 'foo',
            content: [
              { id: 11, tag: 'span', text: 'Nested span:', class: 'foo-span',
                content: [
                  { id: 111, tag: 'a', text: 'Link 1 inside span inside p', href: 'http://example.com' },
                  { id: 112, tag: 'a', text: 'Link 2 inside span inside p', href: 'http://example.com' },
              ]
            }]
          },
          { id: 2, tag: 'img', src: 'http://via.placeholder.com/350x150' },
          { id: 3, tag: 'a', text: 'Link', href: 'http://example.com' }
        ]
      }
    })
    .foo {
      padding: 10px;
      border: 1px solid olive
    }
    
    .foo-span {
      padding: 20px;
      display: block;
      border: 1px solid orange
    }
    
    .foo-span a {
      display: block;
      padding: 10px;
      margin-bottom: 5px;
      border: 1px solid tomato
    }
    <script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.3/vue.js"></script>
    
    <div id="app">
      <vue-html-tag v-for="item in html" :key="item.id" :value="item"></vue-html-tag>
    </div>

    【讨论】:

      猜你喜欢
      • 2015-09-06
      • 2018-11-22
      • 2020-01-24
      • 2019-03-31
      • 2017-11-20
      • 1970-01-01
      • 2018-09-27
      • 2018-07-02
      • 1970-01-01
      相关资源
      最近更新 更多