我正在为我正在编写的UI库实现一个组合的select下拉列表和搜索框组件,使用Vue.js来驱动交互,但我遇到了一个问题,Vue.js似乎如何处理父组件和子组件之间的通信。
基本上,我的目标是允许库的用户使用以下内容定义HTML中的搜索选择元素:
<search-select>
<search-option value="foo">Foo</search-option>
<search-option value="bar">Bar</search-option>
<search-option value="baz">Baz</search-option>
<search-option value="foobar">Foobar</search-option>
</search-select>我的search-select组件模板如下所示:
<template>
<div class="search-select">
<div class="placeholder" ref="placeholder"></div>
<ul class="dropdown">
<input
type="text"
placeholder="Type to filter..."
v-on:input="updateFilter"
>
<slot></slot>
</ul>
</div>
</template>其思想是,search-select组件将在指定输入的基础上添加一个文本输入框,用户可以输入该输入框来筛选可以选择的选项。完成的组件看起来类似于这。
但是,从文档中可以看出,Vue.js没有为我提供任何直接的方式来从父级访问子组件的属性,也没有提供任何方式从父级<slot>中侦听click事件或类似的子组件。
这意味着我无法根据用户的输入筛选子组件的可见性,或者在用户单击其中一个子组件时更新search-select组件的值。
Vue.js文档提到了将事件从子组件传递给父组件的方法,但似乎没有一种方法适用于在插槽中定义的元素--似乎父母只能监听在其中显式定义的组件中的事件。
如何实现此用例所需的父组件和子组件之间的双向通信类型,而不违反与组件之间共享信息有关的任何Vue.js最佳实践?
发布于 2017-08-23 09:46:27
您可以使用事件总线来解决这个问题。只需让每个选项侦听输入事件,然后让它根据传递的参数决定是否隐藏自己。
请参阅下面的小提琴或演示。
const bus = new Vue();
Vue.component('search-option', {
template: `
<option v-if="show" :value="this.$attrs.value"><slot></slot></option>
`,
created() {
bus.$on('filter', (input) => {
this.show = this.$attrs.value.includes(input);
});
},
beforeDestory() {
bus.$off('filter');
},
data() {
return {
show: true,
};
},
});
Vue.component('search-select', {
template: `
<div class="search-select">
<div class="placeholder" ref="placeholder"></div>
<ul class="dropdown">
<input
type="text"
placeholder="Type to filter..."
v-on:input="updateFilter"
v-model="myinput"
>
<slot></slot>
</ul>
</div>
`,
methods: {
updateFilter() {
console.log('update filter');
bus.$emit('filter', this.myinput);
},
},
data() {
return {
myinput: undefined,
};
},
});
Vue.component('parent', {
template: `
<div class="parent">
<search-select>
<search-option value="foo">Foo</search-option>
<search-option value="bar">Bar</search-option>
<search-option value="baz">Baz</search-option>
<search-option value="foobar">Foobar</search-option>
</search-select>
</div>
`,
});
new Vue({
el: '#app',
})<script src="https://unpkg.com/vue/dist/vue.min.js"></script>
<div id="app">
<parent></parent>
</div>
https://stackoverflow.com/questions/45835400
复制相似问题