失眠网,内容丰富有趣,生活中的好帮手!
失眠网 > Vue.js 之 组件-监听子组件事件

Vue.js 之 组件-监听子组件事件

时间:2019-05-28 14:20:11

相关推荐

Vue.js 之 组件-监听子组件事件

1、监听子组件事件

前面介绍了父组件如何通过 prop 向子组件传递数据,反过来,子组件如何向父组件通信呢?

在 Vue.js 中,这是通过自定义事件来实现的,子组件使用$emit()方法触发事件,父组件使用v-on指令监听子组件的自定义事件。

// evenName: 事件名// args: 事件传递的参数vm.$emit( evenName, [...args] )

<div id="app"><child @greet="sayHello"></child></div><script src="vue.js"></script><script>ponent('child', {props: [],data() {return {name: '张三'}},methods: {handleChick() {this.$emit('greet', this.name)}},template: `<button @click="handleChick">开始欢迎</button>`});new Vue({el: '#app',methods: {sayHello(name) {alert("Hello, " + name)}}});</script>

1.1、案例:点赞

<div id="app"><post-list></post-list></div><script src="vue.js"></script><script>// 父组件ponent('PostList', {data() {return {posts: [{id: 1, title: '《Spring Boot实践》', author: '张三', date: '-10-21 20:10:15', vote: 0},{id: 2, title: '《Vue.js入门》', author: '李四', date: '-10-10 09:15:11', vote: 0},{id: 3, title: '《Python数据分析》', author: '王五', date: '-11-11 15:22:03', vote: 0}]}},methods: {// 自定义事件vote的事件处理器方法handleVote(post) {post.vote = ++post.votereturn post}},template: `<div><ul><PostListItemv-for="post in posts":key="post.id":post="post"@vote="handleVote(post)"/></ul></div>`});// 子组件ponent('PostListItem', {methods: {handleVote() {// 触发自定义事件this.$emit('vote');}},props: ['post'],template: `<li><p><span>标题:{{ post.title }} | 发帖人:{{ post.author }} | 发帖时间:{{ post.date }} | 点赞数:{{ post.vote }}</span><button @click="handleVote">赞</button></p></li>`});let vm = new Vue({el: '#app'});</script>

2、将原生事件绑定到组件

在组件上也可以监听原生事件,在使用v-on命令时,添加一个.native修饰符即可。如:

<base-input @focus.native="onFocus"></base-input>

这种方式最终是在组件的根元素上添加了focus(聚焦)事件的监听,如果组件模板的根元素是<input>,那没有问题,但是如果不是,就有问题了。如:

ponent('MyInput', {template: `<label>{{ label }}<input class="child"></lavel>`})

根元素是<label>,相当于在<label>上添加了focus事件监听器,这时,父级的.native监听器将静默失败,它不会报错,但是 onFocus 处理函数不会被如期被调用

为了解决这个问题,Vue.js 提供了一个$listeners属性,它是一个对象,里面包含了作用在这个组件上的所有监听器,如:

{focus(event) {...},input(value) {...},...}

有了$listeners属性,就可以使用 v-on="$listeners" 将组件上的所有事件监听器发送到特定的子元素。对于需要那些使用 v-model 的元素(如<input>)来说,可以为这些监听器创建一个新的计算属性,如下面:

<div id="app"><my-input :label="title" v-model="msg" @focus="onFocus"></my-input><p>{{ msg }}</p></div><script src="vue.js"></script><script>ponent('MyInput', {inheritAttrs: false,// 父级传入数据:title -> label;msg -> valueprops: ['label', 'value'],data() {return {}},computed: {inputListeners() {let vm = this// 将所有的对象合并为一个新对象return Object.assign({},// 从父级添加的所有监控this.$listeners,// 添加自定义监控器或覆写一些监听器的行为{// 确保组件和 v-model 一起工作input(event) {vm.$emit('input', event.target.value)}})}},template: `<label>{{ label }}<inputv-bind="$attrs":value="value"v-on="inputListeners"></label>`});new Vue({el: '#app',data: {title: '输入框:',msg: '请输入'},methods: {onFocus() {console.log("不要摸人家么,好痒,臭流氓!")}}});</script>

2.1、.sync 修饰符

在某些情况下,可能需要对一个组件的 prop 进行双向绑定,Vue.js 推进以 update: myPropName 模式触发事件来实现。例如:

<div id="app"><span>父组件计数值:{{counter }}</span><!-- <child :val="counter" @update:val="addCounter"></child>--><!-- $event:自定义事件的附加参数 --><child :val="counter" @update:val="counter = $event"></child></div><script src="vue.js"></script><script>ponent('child', {props: {val: {type: Number,default: 0}},data() {return {count: this.val}},methods: {handleChick() {this.$emit('update:val', ++this.count)}},template: `<div><span>子组件计数值:{{ val }}</span><button @click="handleChick">增加计数</button></div>`});new Vue({el: '#app',data: {counter: 0},methods: {addCounter(val) {return this.counter = val;}}});</script>

为了方便起见,Vue.js 为了上述这种模式提供了一个缩写,即.sync修饰符(在 v-bind 指令上使用),修改如下:

<child :val="counter" @update:val="counter = $event"></child>

<child :val.sync="counter"></child>

当用一个对象同时设置多个 prop 的时候,也可以将.sync修饰符和v-bind一起使用:

<text-document v-bind.sync="doc"></text-document>

这里会把doc对象中的每一个属性作为一个单独的 prop 传进去,然后为每个属性添加 v-on:update 监听器。

<body><div id="app"><span>父组件 post:{{ post.title }} | {{ post.author }} | {{ post.time }} | {{ post.vote }} | {{ post.price }}</span><child v-bind.sync="post"></child></div><script src="vue.js"></script><script>ponent('child', {props: {title: {type: String },author: {type: String },time: {type: String },vote: {type: Number },price: {type: Number },},data() {return {title: this.vote,author: this.vote,time: this.vote,vote: this.vote,price: this.price}},methods: {handleChick() {this.$emit('update:vote', this.vote += 1)this.$emit('update:price', this.price += 4)}},template: `<div><span>子组件 post:{{ title }} | {{ author }} | {{ time }} | {{ vote }} | {{ price }}</span><br><button @click="handleChick">增加计数</button></div>`});new Vue({el: '#app',data: {post: {title: '《Spring Boot 从入门到入土》',author: '张三',time: '05月16日00:05:50',vote: 0,price: 0}},methods: {}});</script>

注:本篇主要来源:《Vue.js 从入门到实践》第十一章 组件,作者:孙鑫,出版社:中国水利水电出版社

如果觉得《Vue.js 之 组件-监听子组件事件》对你有帮助,请点赞、收藏,并留下你的观点哦!

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。