Как я могу использовать динамические компоненты в ListView

Я пытаюсь заполнить NativeScript-Vue ListView шаблонами, которые содержат компоненты, типы которых неизвестны заранее. Например, этот код не работает, так как в NativeScript нет элемента 'component', но это говорит о том, что я пытаюсь выполнить:

<ListView for="component in components">
    <v-template>
        <component :is="component" />
    </v-template>
</ListView>

computed: {
    components () {
        return ['Label', 'Button'];
    }
}

Да, я знаю, что вы можете использовать if="" в v-шаблоне, но в этом случае я не знаю заранее, какие компоненты необходимо загрузить в ListView. В моем случае я загружаю глобальные компоненты в плагин, и на эти компоненты будет ссылаться в ListView.

2 ответа

Спасибо @Manoj. Эти мудрые слова заставили меня задуматься, шаблон не может быть динамическим, но содержимое v-шаблона может быть. Может быть, не для всех, но этот код работает для меня:

// App.vue

<template>
    <Page>
        <ActionBar title="Welcome to NativeScript-Vue!"/>
        <GridLayout columns="*" rows="400,*">
            <ListView ref="lv" for="item in items">
              <v-template>
                <v-component :type="item.type" :options="item.options" />
              </v-template>
            </ListView>
        </GridLayout>
    </Page>
</template>

<script lang="ts">
  import Vue from 'nativescript-vue'
  import { Component } from 'vue-property-decorator'
  import VComponent from './VComponent.vue'

  @Component({
    components: {
      VComponent
    }
  })
  export default class App extends Vue {
      get items () {
      return [
        {type: 'Label', options: [{key: 'text', value: 'I am a Label'}, {key: 'color', value:'red'}] },
        {type: 'Button', options: [{key: 'text', value:'I am a Button!'}]}
      ]
    }
  }
</script>


// VComponent.vue

<template>
  <StackLayout ref="myLayout">
  </StackLayout>
</template>

<script lang="ts">
  import Vue from 'nativescript-vue'
  import { Component, Prop } from 'vue-property-decorator'
  import { StackLayout } from 'tns-core-modules/ui/layouts/stack-layout'
  import { Label } from 'tns-core-modules/ui/label'
  import { Button } from 'tns-core-modules/ui/button'

  const classByClassName = {
    'Label': Label,
    'Button': Button
  }

  @Component
  export default class CoolTemplate extends Vue {
    @Prop() type!: string;
    @Prop() options;

    mounted () {
      if (this.type) {
        const myLayout = <StackLayout>((<Vue>this.$refs.myLayout).nativeView)
        const component = new classByClassName[this.type]
        for (var i = 0; i< this.options.length; i++) {
          const option = this.options[i];
          component[option.key] = option.value 
        }
        myLayout.addChild(component)
      }
    }

  } 
</script>

Ваш шаблон не может быть динамическим, вот и весь смысл использования ListView - сохранять их статичными, чтобы их можно было использовать по мере необходимости. Если вы хотите видеть различные компоненты на основе данных, вы должны использовать несколько шаблонов.

Читайте больше на документах.

Другие вопросы по тегам