我有两个组件
我的第一个组件(父组件)是这样的:
<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/