首页 > 解决方案 > 将 b-icon 传递给 VueJS 中的元素

问题描述

我想使用 VueJS 将一段 HTML 传递给 table-data-element。下面演示了我的场景:

    <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 单文件组件的最小示例。但是,通过这种方式,我在表格中得到了空字段,而不是实际的图标。难道没有一种简单而干净的方法来实现这一目标吗?

标签: vue.jsbootstrap-vue

解决方案


它不起作用的原因是你不能v-html用来渲染自定义组件。

相反,这里有两种不同的方法可以做到这一点。

首先是预先定义你的b-icon-*和使用的v-ifv-else-ifv-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>


推荐阅读