javascript - 如何让子组件在单击 vue 组件上的链接时运行?

标签 javascript vue.js vuejs2 vue-component vuex

我有两个组件

我的第一个组件(父组件)是这样的:

<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>

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

我想如果父组件执行,子组件不执行

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

我该怎么做?

最佳答案

如何创建一个属性 (displayedIds) 来保存每个 order-collapse 的显示状态,然后使用 v-if 调节其显示>:

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

而且,考虑到 displayedIds 最初声明为 {},您的 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>


另一种可能性是将 displayedIds 作为数组而不是对象。这样你就不能使用 $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(而不仅仅是 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 属性附加到每个项目,我认为这是最简单的解决方案。否则我会选择第一个(displayedIds 作为一个对象),除非它让你感到奇怪,在这种情况下我会选择数组解决方案。

关于javascript - 如何让子组件在单击 vue 组件上的链接时运行?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49642415/

相关文章:

javascript - 在 JavaScript 中检测点击与触摸

javascript - 欧拉计划 8 JavaScript

vue.js - 在提交时获取表单数据?

html - Vue.js 图像映射单击后禁用区域

javascript - Vue Element Ui 拖放传输 Element

javascript - Vue 路由器 beforeEnter 与 beforeEach

javascript - JavaScript 中的命名空间 : do I need to rewrite all my variable and function references?

javascript - 为什么 Function.x 在声明 Function.prototype.x 后工作?

vue.js - 为什么 filter() 中的 `this` 在 VueJS 中未定义?

vue.js - vuejs : router-link params is empty