Передача b-icon в элемент <td>в VueJS - PullRequest
0 голосов
/ 18 марта 2020

Я хочу передать кусок HTML элементу данных таблицы, используя VueJS. Следующий пример демонстрирует мой сценарий:

    <template>
      <div>
        <div v-if="someObject.properties" style="margin-top: 20px;" class="table-responsive-md">
          <table class="table table-striped">
            <thead>
            <tr>
              <th style="text-align: left" scope="col">Some icons</th>
            </tr>
            </thead>
            <tbody v-for="(property, index) in someObject.properties" :key="index">
            <tr>
              <td style="text-align: center" v-html="getIconWhenSomeRequirementIsMet(property)"/>
            </tr>
            </tbody>
          </table>
        </div>
      </div>
    </template>

    <script lang="ts">
      ...
      getIconWhenSomeRequirementIsMet (property: any): string {
        if (property.type === 'animal') return '<b-icon-check class="h3 mb-0" style="color:green;"/>'
        if (property.type === 'human') return '<b-icon-check class="h3 mb-0" style="color:yellow;"/>'
        return '<b-icon-x class="h3 mb-0" style="color:red;"/>'
      }
    </script>

Приведенный выше код является минимальным примером моего Vue отдельного файлового компонента. Тем не менее, таким образом, я получаю пустые поля в моей таблице вместо реальных значков. Нет ли простого и понятного подхода для достижения этой цели?

1 Ответ

2 голосов
/ 18 марта 2020

Причина, по которой это не работает, заключается в том, что вы не можете использовать v-html для визуализации пользовательских компонентов.

Вместо этого есть два различных способа сделать это.

Первый это предварительно определить ваши b-icon-* и использовать v-if, v-else-if и v-else для соответствия значку, который нужно показать.

Второй - динамическое связывание свойств с использованием v-bind, таким образом вы можно использовать метод, чтобы сделать это, как вы сейчас, но вместо этого вернуть свойства, основанные на типе.

new Vue({
  el: "#app",
  data() {
    return {
      items: [
        { type: "animal" },
        { type: "human" },
        { type: "alien" },
      ],
      fields: ['Type', 'Icon 1', 'Icon 2']
    }
  },
  methods: {
    getIconWhenSomeRequirementIsMet (type) {
      /* Default properties */
      const properties = {
        icon: 'x',
        style: 'color: red',
        class: 'h3 mb-0'
      };
      
      if (type === 'animal') {
        properties.icon = 'check';
        properties.style = 'color: green;';
      }
      else if (type === 'human') {
        properties.icon = 'check';
        properties.style = 'color: yellow;';
      }
      
      return properties;
    }
  }
})
<link href="//unpkg.com/bootstrap/dist/css/bootstrap.min.css" rel="stylesheet" />
<link href="//unpkg.com/bootstrap-vue@2.7.0/dist/bootstrap-vue.min.css" rel="stylesheet" />

<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.6.11/vue.js"></script>
<script src="//unpkg.com/bootstrap-vue@latest/dist/bootstrap-vue.min.js"></script>
<script src="//unpkg.com/bootstrap-vue@latest/dist/bootstrap-vue-icons.min.js"></script>

<div id="app">
  <div class="table-responsive-md">
    <table class="table table-striped">
      <thead>
        <tr>
          <th v-for="field in fields" >{{ field }}</th>
        </tr>
      </thead>
      <tbody>
        <tr v-for="{ type } in items">
          <td>
            {{ type }}
          </td>
          <td>
            <b-icon-check v-if="type === 'animal'" variant="success" class="h3 mb-0">
            </b-icon-check>
            <b-icon-check v-else-if="type === 'human'" variant="warning" class="h3 mb-0">
            </b-icon-check>
            <b-icon-x v-else variant="danger" class="h3 mb-0">
            </b-icon-x>
          </td>
          <td>
            <b-icon v-bind="getIconWhenSomeRequirementIsMet(type)"></b-icon>
          </td>
        </tr>
      </tbody>
    </table>
  </div>
</div>
...