Vue JS динамические компоненты - PullRequest
0 голосов
/ 28 апреля 2018

У меня есть структура данных элементов вроде:

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

и в моем шаблоне я делаю v-for с if внутри для отображения различных компонентов в зависимости от типа:

<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>

У меня вопрос, есть ли "чище", лучший способ сделать это?

1 Ответ

0 голосов
/ 28 апреля 2018

Я думаю, что я бы сделал замену компонентов на основе тега , например:

//  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>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...