javascript - Vue 两次导入相同的组件/ Vue 事件从子级只到根,而不是到父级
问题描述
我有的
我两次导入相同的组件。该组件用于显示带有集合的下拉列表。当下拉列表中的项目被选中时,将触发一个事件。该组件被导入到list.js
和 中BulkActions.vue
。
问题
选择下拉列表中的集合时会触发一个事件。然后它使用 触发事件$emit
。不知何故,此事件仅在list.blade.php
而不是在BulkActions.vue
. 对于两个下拉菜单(从同一个组件加载)应该有不同的行为。我不知道为什么会发生这种情况,也不知道为什么该事件只在我的根部被捕获。
我试过的
我试图prop
在 HTML 中传递一个额外的“变量事件名称”,但这没有用。我也尝试了各种导入组件的方法。
有谁知道如何解决这个问题?
文件
list.blade.php
:
<div class="media-list-navbar mt-3 mb-3">
<shown-results :text="resultText"></shown-results>
<search-bar @update-filters="updateFilters"></search-bar>
<document-types @update-filters="updateFilters"></document-types>
<collection-dropdown eventname="update-filters"
@update-filters="updateFilters"></collection-dropdown>
<div class="clearfix"></div>
</div>
<bulk-actions @select-all="selectAll"
@deselect-all="deselectAll"
:items="items"
:multiselect="multiSelect"></bulk-actions>
BulkActions.vue
<template>
<div class="multiselect-list-navbar mt-3 mb-3" v-if="multiselect">
<div class="float-left">
<button type="button"
class="btn btn-outline-secondary"
@click="$emit('deselect-all')">
<i class="fas fa-fw fa-times"></i> {{ Lang.get('media/item.index.list.multi-select.deselect-all') }}
</button>
<button type="button"
class="btn btn-outline-secondary"
@click="$emit('select-all')">
<i class="fas fa-fw fa-check"></i> {{ Lang.get('media/item.index.list.multi-select.select-all') }}
</button>
</div>
<bulk-collection
@update-filters="doSomething"></bulk-collection>
<div class="clearfix"></div>
</div>
</template>
<script>
export default {
name: "Bulk",
props: {
multiselect: Boolean,
items: Array
},
components: {
'bulk-collection': () => import('./Collections')
},
methods: {
doSomething() {
console.log(this.items)
}
}
}
</script>
<style scoped>
</style>
list.js
import MediaItem from '../components/MediaItem';
import UploadModal from '../components/media/UploadModal';
import ItemDetail from '../components/media/ItemDetail';
import ShownResults from '../components/media/list/ShownResults';
import SearchBar from '../components/media/list/SearchBar';
import DocumentTypes from '../components/media/list/DocumentTypes';
import {default as CollectionDropdown} from '../components/media/list/Collections';
import Order from '../components/media/list/Order';
import BulkActions from '../components/media/list/BulkActions';
if (document.getElementById('media-list')) {
const mediaList = new Vue({
el: '#media-list',
components: {
MediaItem,
ShownResults,
SearchBar,
UploadModal,
ItemDetail,
DocumentTypes,
CollectionDropdown,
Order,
BulkActions
},
[...]
Collections.vue
<template>
<div class="dropdown float-left">
<button class="btn btn-secondary dropdown-toggle"
type="button"
data-toggle="dropdown">
{{ Lang.get('media/item.index.list.filters.collections.title') }}
</button>
<div class="dropdown-menu" ref="collectionDropdown">
<div class="dropdown-item no-pseudo">
<input type="search"
class="form-control"
name="search"
:placeholder="Lang.get('media/item.index.list.filters.collections.filter')"
v-model="query"
@keyup="search">
</div>
<div class="dropdown-item last-item no-pseudo">
<alert type="warning">
<template v-slot:body>
{{ Lang.get('media/item.index.list.filters.collections.none-filter') }}
</template>
</alert>
</div>
<div v-for="item in list"
class="dropdown-item"
v-if="!item.hidden">
<span class="custom-control custom-checkbox">
<input type="checkbox"
class="custom-control-input"
name="collection[]"
:checked="item.checked"
:id="item.slug"
:value="item.id"
@change="selectItem">
<label class="custom-control-label" :for="item.slug">
{{ item.name }}
</label>
</span>
</div>
</div>
</div>
</template>
<script>
import Alert from '../../partials/Alert';
export default {
name: "Collections",
components: {
Alert
},
data() {
return {
displayAmount: 10, // amount of items displayed without search
list: [],
query: ''
}
},
computed: {
/**
* Return an array of selected items only
*/
checked() {
return this.list.filter(item => {
return item.checked === true;
})
}
},
methods: {
/**
* Mark an item as selected
*/
selectItem(e) {
let selectedId = e.target.value;
this.markItem(selectedId);
},
/**
* Mark an item from the list as selected
*
* @param {Number} itemId
*/
markItem(itemId) {
this.list.forEach(item => {
if (item.id === parseInt(itemId)) {
item.checked = !item.checked;
}
});
this.$emit('update-filters', {
props: this.checked.map(item => item.id).join(',')
});
},
/**
* Search in the current URL for collection ids
*/
markItemsFromUrl() {
let urlParams = new URLSearchParams(window.location.search);
if (urlParams.has('collection')) {
let urlFilters = urlParams.get('collection').split(','); // split url parameters
urlFilters.forEach(itemId => {
this.markItem(itemId);
});
}
},
},
mounted() {
this.fetchList();
this.markItemsFromUrl();
/**
* Prevent Bootstrap dropdown from closing after clicking inside it
*/
$(this.$refs.collectionDropdown).on('click.bs.dropdown', function (e) {
e.stopPropagation();
});
}
}
</script>
下面是一个 GIF 动画来演示这个问题。第一个下拉列表(顶部的那个)具有正常行为。第二个(稍后出现)没有。单击第二个时,将发生第一个事件。
解决方案
推荐阅读
- javascript - 无法在 Localhost 上启动 tui-image-editor
- firebase - 使用 Cloud run 而不是 Cloud Functions 会受益吗?它在 GCP 中的什么位置?
- intellij-idea - Intellij Idea Community Edition 2018.3.6 表现非常缓慢
- node.js - $in 的 MongoDB 性能
- node.js - 如何将 base64 字符串作为 Openssl 的输入证书传递?
- c# - 宏获取当前用户宏而不是联系人
- mongodb - 如何在mongodb中使用group by?
- java - 如何从字符串值中删除字符?
- javascript - 通过传递参数通过单击按钮来操作表格列宽
- java - 试图将数据库中的信息显示到终端