Vue.js:在页面中多次包含相同的组件实例
Posted
技术标签:
【中文标题】Vue.js:在页面中多次包含相同的组件实例【英文标题】:Vue.js: Including same instance of component multiple times in page 【发布时间】:2019-07-09 05:39:24 【问题描述】:我想要完成的工作: 我有一些显示在页面上的过滤器来过滤页面上显示的产品。在移动设备中,我想将这些过滤器隐藏在一个按钮后面,一旦按下该按钮,就会在侧面的滑出菜单中显示过滤器。
虽然我可以在页面上复制相同的组件两次,但这些组件并不是完全相同的实例,也就是说,单击过滤器会触发该功能来过滤页面上的产品,但它会设置自己的数据属性,我用它来表示“如果数据属性'selected'为真,则向组件添加一个'selected'类。当我调整窗口大小时,组件的另一个实例没有'selected'数据属性标记为'真实'。
我希望如此,因为来自文档:
请注意,单击按钮时,每个按钮都会保持自己的独立计数。这是因为每次使用组件时,都会创建它的一个新实例。
...但是最好的方法是什么?
我尝试了在组件上设置一个类“mobile”的想法,.mobile css 会以不同的方式设置组件的样式,但我需要它打破它的嵌套位置。
例如
<body>
<header>
<!-- desktop -->
<guitar-filters>
<header>
<!-- mobile -->
<guitar-filters>
</body
这是我的 Vue 组件“guitar-filters”,它显示了几个名为“instrument-filter”的组件:
Vue.component('guitar-filters',
data: function()
return
isMobile: false
,
mounted: function()
var comp = this;
this.setIsMobile();
window.addEventListener('resize', function()
comp.setIsMobile();
);
,
methods:
setIsMobile: function()
this.isMobile = (window.innerWidth <= 900) ? true : false;
,
template: `
<ul class="filters" :class="mobile: isMobile">
<li>
All
</il>
<li>
Series
<ul>
<instrument-filter filter-by="series" filter="All">All</instrument-filter>
<instrument-filter filter-by="series" filter="Frontier">Frontier</instrument-filter>
<instrument-filter filter-by="series" filter="Legacy">Legacy</instrument-filter>
<instrument-filter filter-by="series" filter="USA">USA</instrument-filter>
</ul>
</li>
<li>
Body Shape
<ul>
<instrument-filter filter-by="bodyType" filter="All">All</instrument-filter>
<instrument-filter filter-by="bodyType" filter="Concert">Concert</instrument-filter>
<instrument-filter filter-by="bodyType" filter="Concertina">Concertina</instrument-filter>
<instrument-filter filter-by="bodyType" filter="Concerto">Concerto</instrument-filter>
<instrument-filter filter-by="bodyType" filter="Orchestra">Orchestra</instrument-filter>
</ul>
</li>
</ul>
`
);
仪器过滤器组件:
Vue.component('instrument-filter',
data: function()
return
selected: false
,
props : [
'filterBy',
'filter'
],
methods:
addFilter: function()
this.$root.$emit('addFilter',filterBy: this.filterBy,filter: this.filter);
,
clearFilter: function()
this.$root.$emit('clearFilter',filterBy: this.filterBy,filter: this.filter);
,
template: `
<li :class=" 'selected' : selected " @click="selected = !selected; selected ? addFilter() : clearFilter()"><slot></slot></li>
`
);
.css:
ul.filters > li > ul > li.selected::before
content: "✔️";
...
目标是让过滤器在两个实例中都具有“选定”类。如果我单击“音乐会”主体形状,然后将窗口大小调整为移动断点,则该过滤器组件的另一个实例也将被选中。
编辑:我可以破解这个。我可以使用 javascript 移动组件的一个实例,但我正在学习 Vue,并希望以 Vue 的方式和最佳实践来做到这一点。
【问题讨论】:
【参考方案1】:您可以通过多种不同的方式来处理此问题。看起来您已经开始使用事件总线路径。另一种选择可能是使用共享应用状态(请参阅Vuex)。
我所做的类似于共享状态,但只是使用应用程序(同样适用于公共父组件)数据。共享对象被传递给组件的两个实例。如果选择了一个项目,则切换相应的条目。由于对象是共享的,因此两个组件保持同步。
如果没有共同的父组件,则必须查看事件或状态。
看看有没有帮助。
Vue.component('guitar-filters',
props: [ 'data' ],
data: function()
return
isMobile: false
,
mounted: function()
var comp = this;
this.setIsMobile();
window.addEventListener('resize', function()
comp.setIsMobile();
);
,
methods:
setIsMobile: function()
this.isMobile = (window.innerWidth <= 900) ? true : false;
,
template: `
<ul class="filters" :class="mobile: isMobile">
<li>
All
</il>
<li>
Series
<instrument-filters :list="data.seriesFilters"/>
</li>
<li>
Body Shape
<instrument-filters :list="data.bodyFilters"/>
</li>
</ul>
`
);
Vue.component('instrument-filters',
props : [ 'list', ],
methods:
toggle(toggleItem)
let itemInList = this.list.find((item) => item.value === toggleItem.value);
itemInList.selected = !itemInList.selected;
,
,
template: `
<ul>
<li v-for="item in list" :class=" 'selected' : item.selected " @click="toggle(item)"> item.label </li>
</ul>
`
);
new Vue(
el: "#app",
data:
filterData:
seriesFilters: [
label: 'All', value: 'All', selected: false ,
label: 'Frontier', value: 'Frontier', selected: false ,
label: 'Legacy', value: 'Legacy', selected: false ,
label: 'USA', value: 'USA', selected: false ,
],
bodyFilters: [
label: 'All', value: 'All', selected: false ,
label: 'Concert', value: 'Concert', selected: false ,
label: 'Concertina', value: 'Concertina', selected: false ,
label: 'Concerto', value: 'Concerto', selected: false ,
label: 'Orchestra', value: 'Orchestra', selected: false ,
],
,
);
ul
margin-left:20px;
ul > li
cursor: pointer;
ul.filters > li > ul > li.selected::before
content: "✔️";
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<header>
<!-- desktop -->
<guitar-filters :data="filterData" />
</header>
<!-- mobile -->
<guitar-filters :data="filterData" />
</div>
小提琴:https://jsfiddle.net/nigelw/jpasfkxb
【讨论】:
谢谢!这正是我需要做的,它帮助我更多地了解 Vue!道具!以上是关于Vue.js:在页面中多次包含相同的组件实例的主要内容,如果未能解决你的问题,请参考以下文章