【问题标题】:BootstrapVue table-template inside Vue slotVue插槽内的BootstrapVue表模板
【发布时间】:2018-12-05 00:30:41
【问题描述】:

我想为带有自定义数据呈现(模板)的 bootstrap-vue 表创建一个父组件。

现在,有点像这样:

<b-table
     :items="result"
     :fields="fields"
     :current-page="currentPage"
     :per-page="perPage">
    <template slot="Index" slot-scope="data">
        {{ data.index + 1 }}
    </template>
    <!-- more templates for various columns here -->
</b-table>
<b-pagination 
     align="center" 
     :total-rows="result.length" 
     v-model="currentPage" 
     :per-page="perPage"
/>

我想将它包装在一个组件中的原因是因为我多次使用这个表格布局,包括分页及其所有属性(如条纹、边框等)。

唯一改变的是列模板。

我知道,Vue 的做法是创建一个类似&lt;slot name="x"&gt;&lt;/slot&gt; 的槽并用&lt;template slot="x"&gt;...&lt;/template&gt; 填充它。一方面,这与 bootstrap-vue template 一致,另一方面,bootstrap-vue 似乎只能正确呈现模板,前提是它们正好放置在 b-table 内。

基本上,我想要实现的是这样一个组件:

<b-table>
    <slot name="templates"/>
</b-table>
<b-pagination stuff.../>

并在这样的子组件中使用它:

<TemplateTable>
    <template slot="templates">
        <template slot="Index" slot-scope="data">
            {{ data.index + 1 }}
        </template>
        <!-- more templates -->
    </template>
</TableTemplate>

有没有人做过类似的事情并想出了解决办法?

【问题讨论】:

    标签: vue.js vuejs2 vue-component bootstrap-vue


    【解决方案1】:

    只需构建您的自定义组件并传递您需要的任何自定义道具,如下所示:

    <template>
      <b-table v-bind="$attrs" v-on="$listeners" custom-prop="any">
        <slot v-for="(_, name) in $slots" :name="name" :slot="name" />
        <template
          v-for="(_, name) in $scopedSlots"
          :slot="name"
          slot-scope="slotData"
          ><slot :name="name" v-bind="slotData"
        /></template>
      </b-table>
    </template>
    
    <script>
    export default {
      name: 'AppTable',
    }
    </script>
    
    <style scoped></style>
    
    
    

    这就像一个魅力!

    【讨论】:

      【解决方案2】:

      感谢@nardnob,这是我在.vue 组件中使用的。所有b-table 组件都已加载到我的app.js 文件中。因此缺少导入语句。

      首先是TableWrapper.vue。我添加了Object.assign(this.$attrs, this.$props) 以确保CustomTable 中的任何未定义props 仍将通过组合$attrs$props 继续传递到b-table

      <script>
          export default {
              components: {},
      
              props: [
                'items',
                'fields'
              ],
      
              mixins: [],
      
              data: function () {
                  return {
                      //
                  }
              },
      
              render(h) {
                  return h('b-table', {
                      props: Object.assign(this.$attrs, this.$props),
                      slots: this.$parent.$slots,
                      scopedSlots: this.$parent.$scopedSlots,
                      on: {
                          // 'row-clicked': (item, index, event) => alert('clicked ' + index)
                      }
                  });
              },
      
              computed: {
                  //
              },
      
              created() {
                  //
              },
      
              mounted() {
                  //
              },
      
              methods: {
                  //
              },
      
              watch: {
                  //
              }
          }
      </script>
      

      然后CustomTable.vue

      <template>
          <table-wrapper
                  :items="items"
                  :fields="fields"
                  :striped="true"
          ></table-wrapper>
      </template>
      
      <script>
          export default {
              components: {},
      
              props: [
                'fields',
                'items',
              ],
      
              mixins: [],
      
              data: function () {
                  return {
                      //
                  }
              },
      
              computed: {
                  //
              },
      
              created() {
                  //
              },
      
              mounted() {
                  //
              },
      
              methods: {
                  //
              },
      
              watch: {
                  //
              }
          }
      </script>
      

      最后:

      <custom-table
          :fields="[
              {
                  key: 'code',
                  label: 'Code',
              },
              {
                  key: 'title',
                  label: 'Titel',
              },
              {
                  key: 'start_date',
                  label: 'Start',
              },
              {
                  key: 'end_date',
                  label: 'End',
              },
              {
                  key: 'log',
                  label: 'Log'
              }
          ]"
          :items="episodes"
      >
          <template v-slot:cell(log)="data">
              <i class="fa-icon fa-search ml-1 is-hoverable" @click="test"></i>
          </template>
      
      </custom-table>
      

      【讨论】:

        【解决方案3】:

        You can use a component's render function 将 slot 和 scopedSlots 传递给另一个组件(如 b-table)。但是你不能使用模板。为了让您拥有一个模板(带有分页、搜索等),您可以将呈现组件包装到另一个确实具有模板的组件中。那么你将拥有一个包含分页的custom-table 组件和一个table-wrapper 组件,而table-wrapper 组件将呈现一个b-table

        这是一个非常具体的例子..

        const constItems = [{
            index: 0,
            isActive: true,
            age: 40,
            first_name: 'Dickerson',
            last_name: 'Macdonald'
          },
          {
            index: 1,
            isActive: false,
            age: 21,
            first_name: 'Larsen',
            last_name: 'Shaw'
          },
          {
            index: 2,
            isActive: false,
            age: 89,
            first_name: 'Geneva',
            last_name: 'Wilson'
          },
          {
            index: 3,
            isActive: true,
            age: 38,
            first_name: 'Jami',
            last_name: 'Carney'
          }
        ];
        
        const bTableProps = {
          items: {
            type: [Array, Function],
            default: undefined
          },
          fields: {
            type: [Object, Array],
            default: undefined
          }
        };
        
        const constFields = [
          'index',
          'isActive',
          'age',
          'first_name',
          'last_name'
        ];
        
        Vue.component('table-wrapper', {
          props: Object.assign({}, bTableProps),
          render(h) {
            return h('b-table', {
              props: this.$props,
              slots: this.$parent.$slots,
              scopedSlots: this.$parent.$scopedSlots,
              on: {
                'row-clicked': (item, index, event) => alert('clicked ' + index)
              }
            });
          }
        });
        
        Vue.component('custom-table', {
          template: '<div><h3>hello table</h3><table-wrapper :items="items" :fields="fields"></table-wrapper></div>',
          props: Object.assign({}, bTableProps)
        });
        
        new Vue({
          el: "#app",
          data: {
            items: constItems,
            fields: constFields
          }
        });
        <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
        <link href="https://unpkg.com/bootstrap@4.1.3/dist/css/bootstrap.min.css" rel="stylesheet" />
        <link href="https://unpkg.com/bootstrap-vue@2.0.0-rc.11/dist/bootstrap-vue.css" rel="stylesheet" />
        <script src="https://unpkg.com/babel-polyfill@6.26.0/dist/polyfill.min.js"></script>
        <script src="https://unpkg.com/bootstrap-vue@2.0.0-rc.11/dist/bootstrap-vue.js"></script>
        
        <div id="app">
          <custom-table :items="items" :fields="fields">
            <template slot="index" slot-scope="data">
        			{{ data.index + 1 }}
        		</template>
          </custom-table>
          <custom-table :items="items" :fields="fields">
            <template slot="index" slot-scope="data">
        			{{ data.index + 2 }}
        		</template>
          </custom-table>
          <custom-table :items="items" :fields="fields">
            <template slot="index" slot-scope="data">
        			{{ data.index + 3 }}
        		</template>
          </custom-table>
        </div>

        【讨论】:

        • 感谢分享!它让我完全陷入困境,试图弄清楚。我也会发布我的.vue 解决方案以供将来参考:)
        • 很高兴它可以提供帮助。我将其发布为我自己的未来参考和其他所有人一样=)
        猜你喜欢
        • 2020-08-05
        • 1970-01-01
        • 2017-08-19
        • 2021-01-15
        • 1970-01-01
        • 2018-10-24
        • 2021-04-04
        • 1970-01-01
        • 2019-06-08
        相关资源
        最近更新 更多