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>Vue.component('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>// 父组件Vue.component('PostList', {data() {return {posts: [{id: 1, title: '《Spring Boot实践》', author: '张三', date: '2019-10-21 20:10:15', vote: 0},{id: 2, title: '《Vue.js入门》', author: '李四', date: '2019-10-10 09:15:11', vote: 0},{id: 3, title: '《Python数据分析》', author: '王五', date: '2019-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>`});// 子组件Vue.component('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> ,那没有问题,但是如果不是,就有问题了。如:

Vue.component('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>Vue.component('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>Vue.component('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>Vue.component('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: '2021年05月16日00:05:50',vote: 0,price: 0}},methods: {}});
</script>

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

Vue.js 之 组件-监听子组件事件相关推荐

  1. Vue父组件监听子组件调用删除模块(个性化页面设置会使用到)

    子组件 <template><div><h4>Xiongdi</h4><button @click="aClick">删 ...

  2. vue关于监听子组件接收从父组件传过来的动态值的问题

    这几天开发时,发现了一个现象,当我想监听子组件接收的从父组件传过来的值得时候,watch不起作用,查了很多资料,大概的原因是因为watch监听得必须是第一次绑定得值,并且初始值发生了改变得时候才会监听 ...

  3. 【Flutter】监听滚动动作 控制组件 透明度渐变 ( 移除顶部状态栏空白 | 帧布局组件 | 透明度组件 | 监听滚动组件 )

    文章目录 前言 一.移除顶部状态栏空白 二.帧布局组件 三.透明度组件 四.监听滚动事件 五.完整代码示例 六.相关资源 前言 在上一篇博客 [Flutter]Banner 轮播组件 ( flutte ...

  4. js下载文件 监听下载完成事件

    <script src="xxx/layui/layui.js"></script> <script src="xxx/jquery.min ...

  5. vue --- 子组件监听点击事件,接收父组件参数.实现对应跳转

    开始 vue中子组件这一块,有点麻烦.不是说它很难,而是它的传送数据方式,以及和各种前端后端路由混在一起时,如果不清晰很容易就迷茫 下面假设: 路由配置文件为:router.js 父组件为 paren ...

  6. jquery 监听td点击事件_VUE @hook浅析(监听子组件的生命周期钩子) - 古兰精

    一.前言 接触hook是从webhook开始接触的,webhook是git的一个扩展服务,可以在仓库接收到push/commit事件并发送http request至一个开发者可以自定义的URL.通过这 ...

  7. window.open 打开vue路由,并监听页面关闭事件,监听子父页面消息传递

    name:路由 query:传递参数 const page2 = this.$router.resolve({name:'addHs',query:{hsCode:row.hsCode}}); var ...

  8. js取消键盘监听_JS键盘事件(非常详细)

    在 JavaScript 中,当用户操作键盘时,会触发键盘事件,键盘事件主要包括下面 3 种类型: keydown:在键盘上按下某个键时触发.如果按住某个键,会不断触发该事件,但是 Opera 浏览器 ...

  9. vue 点击事件传递多个参数_Vue子组件监听事件中传递参数的方法

    在子组件中,我们可以通过以下方式监听事件: v-on:click="$emit('funcName',a)" 如果需要传多个参数,可以通过以下方式: v-on:click=&quo ...

最新文章

  1. Docker 搭建elasticsearch 7.6.x集群
  2. 这些超级高效的人工神经元不使用电子?
  3. InnoDB O_DIRECT选项漫谈(一)【转】
  4. java代码输出伞_在伞中集成测试Web应用程序的问题
  5. SQLServer权限
  6. 如何在Golang中返回错误?
  7. java拖动图片拼图_求教,我的这个拼图程序中的移动图片的改怎么做
  8. STM32系列 STM32F4xx 独立看门狗(IWDG)
  9. 利用GPU实现大规模动画角色的渲染
  10. 精美Java 图书管理系统
  11. mcuisp下载程序
  12. nmap扫描端口命令详解linux网络探测之网络安全
  13. 学习《华为基本法》(大结局):法的修订与接班人
  14. 尺缩钟慢之动尺收缩——思想实验推导狭义相对论(六)
  15. WPS:WPS的论文使用技巧之成功解决如何在尾注设置的参考文献后添加致谢、附录等章节(图文教程)
  16. Usability: Rules and Principle
  17. 正则表达式在一个字符串上多次搜索、正则表达式匹配书名等
  18. 一剑走江湖---武汉
  19. 计算机网络交换机无法ping,无法Ping通路由器交换机提示request time out修复方法
  20. HTML5期末大作业:美食主题网站设计——美食零食官网响应式网页设计(6页) HTML+CSS+JavaScript

热门文章

  1. 将正方形图片变成圆形
  2. 微信小程序系列--之模板消息错误提示: errcode: 41028, errmsg: invalid form id hint:如何解决...
  3. Win10右下角通知中心打不开
  4. # 一个礼拜学习Ios7816协议 第二天
  5. CSS3 之实现超酷图片墙动画
  6. Zemax学习笔记(3)- Zemax中的序列模式和非序列模式
  7. AD10 层相关操作【视图从底层往顶层看】【层切换】【层切换的快捷键的使用】【 阻焊层solder与助悍层paste】【增加机械层】
  8. python入门书籍2018_Python语言新贵,2018涨薪技能,小编吐血为你整理的学习书单...
  9. AI大牛汤晓鸥:AlphaGo之后大家还能做点什么?| 演讲
  10. 文本相似度计算的简单实例超详细代码解释(附代码,文件)