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

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

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

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

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


person CAJazzer    schedule 09.02.2019    source источник


Ответы (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>
person CAJazzer    schedule 10.02.2019

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

Прочитать подробнее о документах.

person Manoj    schedule 09.02.2019