自定义事件

通过prop属性,父组件可以向子组件传递数据,而子组件的自定义事件就是用来将内部的数据报告给父组件的。

<div id="app3">
<my-component2 v-on:myclick="onClick"></my-component2>
</div>
<script>
Vue.component('my-component2', {
template: `<div>
<button type="button" @click="childClick">点击我触发自定义事件</button>
</div>`,
methods: {
childClick () {
this.$emit('myclick', '这是我暴露出去的数据', '这是我暴露出去的数据2')
}
}
})
new Vue({
el: '#app3',
methods: {
onClick () {
console.log(arguments)
}
}
})
</script>

如上所示,共分为以下步骤:

1.子组件在自己的方法中将自定义事件以及需要发出的数据通过以下代码发送出去

this.$emit('myclick', '这是我暴露出去的数据', '这是我暴露出去的数据2')
  • 第一个参数是自定义事件的名字

  • 后面的参数是依次想要发送出去的数据

2.父组件利用v-on为事件绑定处理器

<my-component2 v-on:myclick="onClick"></my-component2>

这样,在Vue实例的methods方法中就可以调用传进来的参数了

注意: 在使用v-on绑定事件处理方法时,不应该传进任何参数,而是直接写v-on:myclick="onClick",不然,子组件暴露出来的数据就无法获取到了

举例:

Vue.component('button-counter', {
template: '<button v-on:click="increment">{{counter}}</button>',
data: function () {
return {
counter: 0
}
}, methods: {
increment: function () {
this.counter += 1
this.$emit('increment-event')
}
}
}) new Vue({
el: '#app',
data: {
totalCounter: 0
}, methods: {
total_increment: function () {
this.totalCounter += 1
}
}
})
<div id='app'>
<button>{{ totalCounter }}</button>
</br>
<button-counter v-on:increment-event='total_increment'></button-counter>
<button-counter v-on:increment-event='total_increment'></button-counter>
</div>

下面两个按钮是两个相同的子组件,并和上面那个按钮共同组成了父组件。

当点击任意一个子组件的按钮,使其加1,都会使得父组件+1,最终:父组件的数值 = 子组件的数值之和

点击下方左边button

点击下方右边button

自定义事件的原理

通过$emit(event)触发一个自定义事件

然后通过$on(event,callback) 去执行对应的callback(回调函数)

(两个event是字符串,且必须名称相同)

但$on不能在父组件中监听子组件抛出的事件,所以我们要做到这一点,可以在父组件的模板中使用到子组件的时候,直接用v-on绑定 (和$on作用效果一致) 就像上面那样:

<button-counter v-on:increment-event='total_increment'></button-counter>

这样一来,自定义事件的雏形就变得和原生事件一样了

即使这样,上面的代码可能还是有些难理解,我认为比较重要的是这一段:

increment: function () {
this.counter += 1
this.$emit('increment-event')
}

因为我们对于事件的运用主要是:利用事件和函数绑定,从而在事件触发的时候能执行相印的函数

所以! 对于自定义事件,我们要解决的问题就是,“这个事件在什么时候被触发” 在上面的代码中,触发事件的时间(执行 this.$emit('increment-event')的时间)

就恰恰是执行this.counter += 1 的时候

绑定原生事件

如果想在某个组件的根元素上监听一个原生事件。可以使用 .native 修饰 v-on

<my-component v-on:click.native="doTheThing"></my-component>

探究v-model

v-model可以对表单控件实现数据的双向绑定,它的原理就是利用了绑定属性和事件来实现的。比如input控件。不使用v-model,可以这样实现数据的双向绑定:

<div id="app4">
<input type="text" v-bind:value="text" v-on:input="changeValue($event.target.value)">
{{text}}
</div>
<script>
new Vue({
el: '#app4',
data: {
text: '444'
},
methods: {
changeValue (value) {
this.text = value
}
}
})
</script>

面的代码同样实现了数据的双向绑定。其本质就是:

  • inputvalue特性绑定到Vue实例的属性text上,text改变,input中的内容也会改变

  • 然后把表单的input事件处理函数设置为Vue实例的一个方法,这个方法会根据输入参数改变Vue中text`的值

  • 相应的,在input中输入内容时,触发了input事件,把event.target.value传给这个方法,最后就实现了改变绑定的数据的效果。

v-model就是上面这种方式的语法糖,也就是把上面的写法封装了一下,方便我们使用。

使用自定义事件创建自定义的表单输入组件

理解了v-model的内幕,也就可以把这个效果用在自定义表单组件上了。
来实现一个简单的只能输入hello的表单输入组件。

<div id="app5">
<my-component3 v-model="hello"></my-component3>
<div>{{hello}}</div>
</div>
<script>
Vue.component('my-component3', {
template: `<input ref="input" type="text" :value="value" @input="checkInput($event.target.value)">`,
props: ['value'],
methods: {
checkInput (value) {
var hello = 'hello'
if (!hello.includes(value)) {
this.$emit('input', hello)
this.$refs.input.value = hello
} else {
this.$emit('input', value)
}
}
}
})
new Vue({
el: '#app5',
data: {
hello: ''
}
})
</script>

定制组件的v-model

默认情况下,一个组件的 v-model 会使用 value 属性和 input 事件,但是诸如单选框、复选框之类的输入类型可能把 value 属性用作了别的目的。model 选项可以回避这样的冲突:

Vue.component('my-checkbox', {
model: {
prop: 'checked', // 将输入的特性改为checked
event: 'change' // 触发的自定义事件类型为change
},
props: {
checked: Boolean,
// this allows using the `value` prop for a different purpose
value: String
}
})

这样设置的话,

<my-checkbox v-model="foo" value="some value"></my-checkbox>

上面的代码就等同于

<my-checkbox :checked="foo" @change="val => { foo = val }" value="some value"></my-checkbox>

实际使用时,与之前不同的地方是:

  1. 把子组件中接收外部数据的prop属性改为checked

  2. 向父组件发出事件时,事件类型应改为change

Vue.component('my-component3', {
template: `<input ref="input" type="text" :value="checked" @input="checkInput($event.target.value)">`,
props: ['checked'], // 属性名改变
model: {
prop: 'checked',
event: 'change'
},
methods: {
checkInput (value) {
var hello = 'hello'
if (!hello.includes(value)) {
this.$emit('change', hello) // 事件类型改变
this.$refs.input.value = hello
} else {
this.$emit('change', value) // 事件类型改变
}
}
}
})

Vue组件-组件的事件的更多相关文章

  1. vue如何正确销毁当前组件的scroll事件?

    将方法写出来,销毁在beforeDestroy写. mounted(){ window.addEventListener("scroll",this.handleFun), }, ...

  2. 042——VUE中组件之子组件使用$on与$emit事件触发父组件实现购物车功能

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  3. Vue父组件与子组件传递事件/调用事件

    1.Vue父组件向子组件传递事件/调用事件 <div id="app"> <hello list="list" ref="child ...

  4. Vue组件绑定自定义事件

    Vue组件使用v-on绑定自定义事件: 可以分为3步理解: 1.在组件模板中按照正常事件机制绑定事件: template: '<button v-on:click="increment ...

  5. Vue 兄弟组件通过事件广播传递数据

    非父子组件传值 通过事件广播实现非父子组件传值1.新建js,引入并实例化Vue import Vue from 'vue' var VueEvent = new Vue(); export defau ...

  6. 深入理解Vue父子组件通讯的属性和事件

    在html中使用元素,会有一些属性,如class,id,还可以绑定事件,自定义组件也是可以的.当在一个组件中,使用了其他自定义组件时,就会利用子组件的属性和事件来和父组件进行数据交流. 父子组件之间的 ...

  7. vue -- 父子组件间的事件触发

    1.父组件触发子组件事件 Parent.vue <child ref="child"></child> <div @click="fn&qu ...

  8. vue怎么给自定义组件绑定原生事件

     下面主要以4个示例Demo演示(示例代码JS引用的Vue CDN),建议小伙伴直接复制示例代码运行查看, 赶时间的小伙伴可直接往下拉,看示例demo4 注:全局或局部注册的组件称为子组件,其中声明的 ...

  9. 怎样在 Vue 里面使用自定义事件将子组件的数据传回给父组件?

    首先, Vue 里面的组件之间的数据流动是 单向 的, 数据可以从父组件传递给子组件, 但不能从子组件传递给父组件, 因为组件和组件之间是 隔离 的. 就像两个嵌套的 黑盒子 . 能通过 props ...

随机推荐

  1. 使用gdb查看栈帧的情况, 没有ebp

    0x7fffffffdb58: 0x004005ba  0x00000000  0x00000000  0x00000000 <-----funcb的栈帧 [0x7fffffffdb60, 0x ...

  2. Linux面试题汇总答案(转)

    转自:小女生的Linux技术~~~Linux面试题汇总答案~~ 一.填空题:1. 在Linux系统中,以 文件 方式访问设备 .2. Linux内核引导时,从文件 /etc/fstab 中读取要加载的 ...

  3. [洛谷P1341]无序字母对

    题目大意:给一张无向图,找一条字典序最小的欧拉路径 题解:若图不连通或有两个以上的奇数点,则没有欧拉路径,可以$dfs$,在回溯时把这个节点加入答案 卡点:没有在回溯时加入答案,导致出现了欧拉路径没走 ...

  4. BZOJ5288 & 洛谷4436 & LOJ2508:[HNOI/AHOI2018]游戏——题解

    https://www.lydsy.com/JudgeOnline/problem.php?id=5288 https://www.luogu.org/problemnew/show/P4436 ht ...

  5. 洛谷 P1338 末日的传说 解题报告

    P1338 末日的传说 题目描述 只要是参加jsoi活动的同学一定都听说过Hanoi塔的传说:三根柱子上的金片每天被移动一次,当所有的金片都被移完之后,世界末日也就随之降临了. 在古老东方的幻想乡,人 ...

  6. IDEA中使用Docker: 图形化 or 命令行 ,你更稀罕那个??

    Docker简介: Docker 是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的容器中,然后发布到任何流行的 Linux 机器上,也可以实现虚拟化. 容器是完全使用沙箱机 ...

  7. android脱壳之DexExtractor原理分析[zhuan]

    http://www.cnblogs.com/jiaoxiake/p/6818786.html内容如下 导语: 上一篇我们分析android脱壳使用对dvmDexFileOpenPartial下断点的 ...

  8. Codeforces Round #345 (Div. 2) B

    B. Beautiful Paintings time limit per test 1 second memory limit per test 256 megabytes input standa ...

  9. [dhcpd]清除dhcp缓存

    修改了dhcp的default-lease-time && max-lease-time 清除缓存: rm /var/lib/dhcpd.leases~ echo "&quo ...

  10. stout代码分析之三:Option类

    为了安全表示NULL, stout实现了Option类.Option对象有两种状态: enum State { SOME, NONE, }; 其中SOME表示非空,NONE表示为空.可通过isSome ...