代码之家  ›  专栏  ›  技术社区  ›  moses toh

如果单击vue组件上的链接,如何使子组件仅运行?

  •  0
  • moses toh  · 技术社区  · 7 年前

    我有两个组件

    我的第一个组件(父组件)如下所示:

    <template>
        <ul class="list-group">
            <li v-for="item in invoices" class="list-group-item">
                <div class="row">
                    ...
                    <div class="col-md-7">
                        ...
                        <a href="javascript:"
                           class="toggle-show"
                           aria-expanded="false"
                           data-toggle="collapse"
                           :data-target="'#' + item.id"
                           @click="show(item.id)">
                            Show <span class="caret"></span>
                        </a>
                    </div>
                </div>
                <div class="collapse" :id="item.id">
                    <order-collapse/>
                </div>
            </li>
        </ul>
    </template>
    <script>
        import orderCollapse from './orderCollapse.vue'
        export default {
            ...
            components: {orderCollapse},
            data() {
                return {
                    invoices: [
                        {
                            id: 1,
                            ...
                        },
                        {
                            id: 2,
                            ...
                        },
                        {
                            id: 3,
                            ...
                        }
                    ]
                }
            },
            methods: {
                show(id) {
                    // orderCollapse executed if this method run
                }
            },
        }
    </script>
    

    我的第二个组件(子组件)如下所示:

    <template>
        <table class="table table-bordered table-collapse">
            <!-- this is used to display detail by id -->
        </table>
    </template>
    <script>
        export default {
            name: 'order-collapse',
            ...
        }
    </script>
    

    如果父组件已执行,则子组件也会自动执行

    如果父组件已执行,子组件未执行

    如果用户单击“显示链接”,我希望执行子组件

    我该怎么做?

    1 回复  |  直到 7 年前
        1
  •  1
  •   acdcjunior Mukul Kumar    7 年前

    创建一个属性怎么样( displayedIds )保持每个 order-collapse 然后使用 v-if :

    <div ... v-if="displayedIds[item.id]">
        <order-collapse :id="item.id"></order-collapse>
    </div>
    

    而且,考虑到 显示EDID 最初声明为 {} ,您将拥有 show() 方法为:

      methods: {
        show(id) {
            // orderCollapse executed if this method run
            this.$set(this.displayedIds, id, true); // use $set to be reactive
        }
      },
    

    演示:

    Vue.component('order-collapse', {
      template: "#oc",
      name: 'order-collapse',
      props: ['id'],
      mounted() {
        console.log('order-collapsed mounted for id', this.id);
      }
    });
    
    new Vue({
      el: '#app',
      data() {
        return {
          displayedIds: {},
          invoices: [{id: 1},{id: 2},{id: 3}]
        }
      },
      methods: {
        show(id) {
          // orderCollapse executed if this method run
          this.$set(this.displayedIds, id, true);
        }
      },
    })
    <script src="https://unpkg.com/vue/dist/vue.min.js"></script>
    
    <div id="app">
        <ul class="list-group">
            <li v-for="item in invoices" class="list-group-item">
                <div class="row">
                    ...
                    <div class="col-md-7">
                        ...
                        <a href="javascript:"
                           class="toggle-show"
                           aria-expanded="false"
                           data-toggle="collapse"
                           :data-target="'#' + item.id"
                           @click="show(item.id)">
                            Show <span class="caret"></span>
                        </a>
                    </div>
                </div>
                <div class="collapse" :id="item.id" v-if="displayedIds[item.id]">
                    <order-collapse :id="item.id"></order-collapse>
                </div>
            </li>
        </ul>
    </div>
    
    <template id="oc">
        <table class="table table-bordered table-collapse">
            <!-- this is used to display detail by id -->
            <tr>
              <td>ID: {{ id }}</td>
            </tr>
        </table>
    </template>


    另一种可能性是 显示EDID 作为 大堆 而不是对象。这样你就无法使用 $set ,只是普通的 .push() :

    methods: {
      show(id) {
        // orderCollapse executed if this method run
        this.displayedIds.push(id);
      }
    },
    

    并使用 .includes() :

    <div ... v-if="displayedIds.includes(item.id)">
        <order-collapse :id="item.id"></order-collapse>
    </div>
    

    演示:

    Vue.component('order-collapse', {
      template: "#oc",
      name: 'order-collapse',
      props: ['id'],
      mounted() {
        console.log('order-collapsed mounted for id', this.id);
      }
    });
    
    new Vue({
      el: '#app',
      data() {
        return {
          displayedIds: [],
          invoices: [{id: 1},{id: 2},{id: 3}]
        }
      },
      methods: {
        show(id) {
          // orderCollapse executed if this method run
          this.displayedIds.push(id);
        }
      },
    })
    <script src="https://unpkg.com/vue/dist/vue.min.js"></script>
    
    <div id="app">
        <ul class="list-group">
            <li v-for="item in invoices" class="list-group-item">
                <div class="row">
                    ...
                    <div class="col-md-7">
                        ...
                        <a href="javascript:"
                           class="toggle-show"
                           aria-expanded="false"
                           data-toggle="collapse"
                           :data-target="'#' + item.id"
                           @click="show(item.id)">
                            Show <span class="caret"></span>
                        </a>
                    </div>
                </div>
                <div class="collapse" :id="item.id" v-if="displayedIds.includes(item.id)">
                    <order-collapse :id="item.id"></order-collapse>
                </div>
            </li>
        </ul>
    </div>
    
    <template id="oc">
        <table class="table table-bordered table-collapse">
            <!-- this is used to display detail by id -->
            <tr>
              <td>ID: {{ id }}</td>
            </tr>
        </table>
    </template>


    最后,如果你发现更容易推理 display 标志可能是 在每个 item 本身,作为属性

    在这种情况下 show 应接收全部 项目 (不仅仅是 item.id ):

    <a ... @click="show(item)">
    

    显示器将使用 item.displayed :

    <div ... v-if="item.displayed">
        <order-collapse :id="item.id"></order-collapse>
    </div>
    

    以及方法:

    methods: {
      show(item) {
        // orderCollapse executed if this method run
        this.$set(item, 'displayed', true);
      }
    },
    

    演示:

    Vue.component('order-collapse', {
      template: "#oc",
      name: 'order-collapse',
      props: ['id'],
      mounted() {
        console.log('order-collapsed mounted for id', this.id);
      }
    });
    
    new Vue({
      el: '#app',
      data() {
        return {
          invoices: [{id: 1},{id: 2},{id: 3}]
        }
      },
      methods: {
        show(item) {
          // orderCollapse executed if this method run
          this.$set(item, 'displayed', true);
          // you could use `item.displayed = true` if you declared `displayed: false` in each item at data
        }
      },
    })
    <script src="https://unpkg.com/vue/dist/vue.min.js"></script>
    
    <div id="app">
        <ul class="list-group">
            <li v-for="item in invoices" class="list-group-item">
                <div class="row">
                    ...
                    <div class="col-md-7">
                        ...
                        <a href="javascript:"
                           class="toggle-show"
                           aria-expanded="false"
                           data-toggle="collapse"
                           :data-target="'#' + item.id"
                           @click="show(item)">
                            Show <span class="caret"></span>
                        </a>
                    </div>
                </div>
                <div class="collapse" :id="item.id" v-if="item.displayed">
                    <order-collapse :id="item.id"></order-collapse>
                </div>
            </li>
        </ul>
    </div>
    
    <template id="oc">
        <table class="table table-bordered table-collapse">
            <!-- this is used to display detail by id -->
            <tr>
              <td>ID: {{ id }}</td>
            </tr>
        </table>
    </template>

    建议采用哪种方法? 归结起来就是味道。如果您可以/不介意附加 displayed 支持每一项,我认为这是最简单的解决方案。否则我会选择第一个( 显示EDID 作为一个对象),除非它给出了yikes,在这种情况下,我会选择数组解决方案。