如果在 vue 组件上单击 link,如何使子组件仅 运行?
How do I make a child component just run if click a link on the vue component?
我有两个组件
我的第一个组件(父组件)是这样的:
<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>
如果父组件执行,子组件也会自动执行
我想如果父组件执行,子组件不执行
我希望在用户单击显示时执行子组件 link
我该怎么做?
如何创建一个 属性 (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>
推荐哪种方法?归结为品味。如果您 can/don 不介意将 displayed
道具附加到每个项目,我认为这是最简单的解决方案。否则我会选择第一个(displayedIds
作为一个对象),除非它给了你 yikes,在这种情况下我会选择数组解决方案。
我有两个组件
我的第一个组件(父组件)是这样的:
<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>
如果父组件执行,子组件也会自动执行
我想如果父组件执行,子组件不执行
我希望在用户单击显示时执行子组件 link
我该怎么做?
如何创建一个 属性 (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>
推荐哪种方法?归结为品味。如果您 can/don 不介意将 displayed
道具附加到每个项目,我认为这是最简单的解决方案。否则我会选择第一个(displayedIds
作为一个对象),除非它给了你 yikes,在这种情况下我会选择数组解决方案。