繁体   English   中英

Vue 事件 - 无法从子组件监听 $emit 事件

[英]Vue Events - Can't listen to $emit event from child component

我有一个简单的问题,我就是不知道为什么它不起作用。 我有一个子组件“app-buttons”,我有一个输入字段,我想听,所以我可以根据输入值过滤一个列表。

如果我将输入放在我有列表的根组件中,一切正常。 但是我想将它拆分,然后将搜索输入值 $emit 给父 en 然后使用它。

 // THIS IS THE COMPONENT WHERE I WAN'T TO LISTEN TO THE SEARCH INPUT import Buttons from './app-buttons.js'; import Event from './vue-event.js'; export default Vue.component('post-item', { template: ` <section class="posts flex" v-if="posts"> <app-buttons :posts="posts"></app-buttons> <transition-group name="posts" tag="section" class="posts flex"> <article class="postitem" :class="{ 'danger': !post.published }" v-for="post in posts" :key="post.id"> <p v-if="post.published">Post is published</p> <p v-else>Post is <em><strong>not</strong></em> published</p> <h4>{{ post.title }}</h4> <button type="submit" @click="post.published = !post.published">Change status</button> </article> </transition-group> </section> `, data() { return { }; }, components: { Buttons, }, props: { posts: Array, filterdList: [], }, created() { console.log('%c Post items', 'font-weight: bold;color:blue;', 'created'); }, computed: { //filteredList() { // return this.posts.filter(post => { // return post.title.toLowerCase().includes(this.search.toLowerCase()); // }); //}, }, methods: { update() { console.log('test'); } } }); // THIS IS THE COMPONENT IM TRIGGERING THE $EVENT FROM import Event from './vue-event.js'; export default Vue.component('app-buttons', { template: ` <div class="postswrapper flex flex--center flex--column"> <section :class="className" class="flex flex--center"> <button type="button" @click="showUnpublished">Unpublish</button> <button type="button" @click="shufflePosts">Shuffle</button> </section> <section :class="className"> <input type="text" v-model="search" v-on:input="updateValue" placeholder="Search..." /> </section> </div> `, data() { return { className: 'buttons', search: '', } }, props: { posts: Array, }, created() { //console.log(this); console.log('%c Buttons', 'font-weight: bold;color:blue;', 'created'); }, methods: { updateValue() { //console.log(this.search); this.$emit('searchquery', this.search); }, showUnpublished() { this.posts.forEach(item => { item.published = true; }) }, shufflePosts() { this.$emit('postshuffled', 'Fisher-Yates to the rescue'); for (var i = this.posts.length - 1; i >= 0; i--) { let random = Math.floor(Math.random() * i); let temp = this.posts[i]; Vue.set(this.posts, i, this.posts[random]); Vue.set(this.posts, random, temp); } }, } });
 <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Vue JS</title> <script src="https://cdn.jsdelivr.net/npm/vue@2.6.6/dist/vue.js"></script> <link rel="stylesheet" type="text/css" href="style.css"> </head> <body> <div id="app"> <app-header :logo="logo" :name="name"></app-header> <post-item :posts="posts" v-on:searchquery="update" v-on:sq="update" v-on:postshuffled="update"></post-item> </div> <script type="module"> import AppHeader from './components/app-header.js'; import PostItem from './components/post-item.js'; const app = new Vue({ el: '#app', data: { name: 'Vue App', logo: { class: 'vue-logo', src: 'https://vuejs.org/images/logo.png', }, components: { AppHeader, PostItem, }, posts: [ {id: 1, title: 'Test', published: true}, {id: 2, title: 'New post', published: true}, {id: 3, title: 'Added', published: true}, {id: 4, title: 'Another post', published: true}, {id: 5, title: 'In the future', published: false}, {id: 6, title: 'Last post', published: true}, ], }, created() { console.log('Created'); }, mounted() { console.log('Mounted'); }, methods: { update() { console.log('updated'); } }, }); </script> </body> </html>

你说:

我有一个子组件“app-buttons”,我有一个输入字段,我想听,所以我可以根据输入值过滤一个列表。

你有:

<div id="app">
    <app-header :logo="logo" :name="name"></app-header>
    <post-item :posts="posts" v-on:searchquery="update" v-on:sq="update" v-on:postshuffled="update"></post-item>
</div>

这表示您希望post-item发出searchquery事件。 它不是。

post-item ,您有:

    <app-buttons :posts="posts"></app-buttons>

所以你希望app-buttons发出一个事件并且post-item隐式冒泡它,但 Vue 事件不会冒泡。 如果你想要这种行为,你需要让post-item处理事件:

    <app-buttons :posts="posts" v-on:searchquery="$emit('searchquery', $event)"></app-buttons>

好的,我已经更改了标记,并且可以正常工作。 但这会是最好的方法吗? :) 并感谢Roy J的帮助。

 import Event from './vue-event.js'; import Buttons from './app-buttons.js'; export default Vue.component('post-item', { template: ` <section class="posts flex" v-if="posts"> <app-buttons :posts="posts" v-on:searchquery="update($event)"></app-buttons> <transition-group name="posts" tag="section" class="posts flex"> <article class="postitem" :class="{ 'danger': !post.published }" v-for="post in filteredItems" :key="post.id"> <p v-if="post.published">Post is published</p> <p v-else>Post is <em><strong>not</strong></em> published</p> <h4>{{ post.title }}</h4> <button type="submit" @click="post.published = !post.published">Change status</button> </article> </transition-group> </section> `, data() { return { search: '', }; }, components: { Buttons, }, props: { posts: Array, }, created() { console.log('%c Post items', 'font-weight: bold;color:blue;', 'created'); }, computed: { filteredItems(search) { return this.posts.filter(post => { return post.title.toLowerCase().indexOf(this.search.toLowerCase()) > -1 }); } }, methods: { update(event) { this.search = event; } } }); // Child component import Event from './vue-event.js'; export default Vue.component('app-buttons', { template: ` <div class="postswrapper flex flex--center flex--column"> <section :class="className" class="flex flex--center"> <button type="button" @click="showUnpublished">Unpublish</button> <button type="button" @click="shufflePosts">Shuffle</button> </section> <section :class="className"> <input type="text" v-model="search" v-on:input="updateValue" placeholder="Search..." /> </section> </div> `, data() { return { className: 'buttons', search: '', } }, props: { posts: Array, }, created() { console.log('%c Buttons', 'font-weight: bold;color:blue;', 'created'); }, methods: { updateValue() { this.$emit('searchquery', this.search); }, showUnpublished() { this.posts.forEach(item => { item.published = true; }) }, shufflePosts() { for (var i = this.posts.length - 1; i >= 0; i--) { let random = Math.floor(Math.random() * i); let temp = this.posts[i]; Vue.set(this.posts, i, this.posts[random]); Vue.set(this.posts, random, temp); } }, } });
 Index same as before, just without alle the events on the components.

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM