资讯专栏INFORMATION COLUMN

组件(3):自定义事件

Yangyang / 2998人阅读

摘要:自定义事件自定义事件有能力使子组件事件触发父组件中的动作。它所做的只是报告自己的内部事件,因为父组件可能会关心这些事件。只是这里父组件上的事件功效没有双向绑定中事件那么强大。

自定义事件

自定义事件有能力使子组件事件触发父组件中的动作。
那么父组件如何监听事件呢?可以使用指令v-on:event-name="callback"监听。
而子组件又是如何触发事件的呢? 很简单,调用this.$emit(eventName)
先来个简单例子

new Vue({
    el:"#app-1",
    methods:{
        callback:function(){
            alert("父组件监听到事件触发,执行回调。")
        }
    },
    components: {
        "component-1":{
            template:"",
            methods:{
                emitor:function(){
                    console.log("111")
                    this.$emit("alert-event")
                }
            }
        }
    }
})

根据以上代码,可以得出个事件执行流程,基本上不管什么自定义事件都是这个流程

子组件某方法

this.$emit("event")

DOM上v-on监听event

父组件methods中的callback

子组件已经和它外部完全解耦了。它所做的只是报告自己的内部事件,因为父组件可能会关心这些事件。
事件负载

在事件执行的同时,子组件还可以在触发事件的同时挂上一些负载的数据,随着事件传递给父组件。
使用API的第二个参数this.$emit(event, payload),具体如下。

new Vue({
    el: "#app-2",
    data: {
        message: ""
    },
    methods: {
        handleMessage: function (payload) {
            this.message = payload.message
        }
    },
    components: {
        "component-2": {
            data: function () {
                return { message: "" }
            },
            template: "
            
", methods: { sendMsg: function () { this.$emit("message", { message: this.message }) } } } } })

点击发送按钮触发事件并把信息传递给父组件,可以看到还是这里同样遵循自定义事件流程,其他都是烟雾,之多了个负载this.$emit("message", { message: this.message })

原生事件

通过.native后缀还可以在子组件元素根节点上绑定原生事件的监听。

new Vue({
    el:"#app-3",
    methods:{
        todo:function(){
            alert("事件回调方法是父组件中的")
        }
    },
    components:{
        "component-3":{
            template:""
        }
    }
})

还是要千万注意,回调方法在父组件作用域上。

双向绑定(.sync修饰符与update事件)

可以通过以下步骤实现一个双向绑定:

在子组件VirtualDOM节点上,通过v-bind:prop.sync="foo"进行数据下发,这里以.sync修饰符标注,通知父组件子组件需要进行props的更新。

子组件通过this.$emit("update:prop",newValue)通知父组件自己需要把prop更新为一个新值newValue以子组件的data选项作为过渡变量

父组件会监听这个更新事件,从而在负载上拿到newValue,更新foo的数据,并把新数据重新下发给子组件的prop

注意:这里并不是子组件props值的改变引发父组件数据的改变,而是利用子组件的data做桥梁,通过事件及其负载引起父组件的变动。
new Vue({
    el: "#app-4",
    data: { parentMsg: "parent"s message" },
    components: {
        "component-4": {
            props: ["child_msg"],
            data: function () {
                return { inputText: this.child_msg }
            },
            template: "
                
", watch: { child_msg: function (val) { this.inputText = val }, inputText: function (val) { this.$emit("update:child_msg", val) } } } } })

父、子组件各包含一个输入框,并且将它们绑定到自己的某data属性上。watch子组件的该data属性,一有输入就触发事件通知父组件,并payload新值。父组件通过payload更新自己的data,并通过prop将新值下发给子组件,子组件watch自己的propprop一旦变动,将新变动赋给data

理解v-model 在input元素上使用

我们在用输入框时,会用v-model进行双向绑定。


等价于

具体行为:① 在inputvalue属性上引用组件的data ② 发生oninput事件时,更新组件data,从而更新value

new Vue({
    el:"#app-6",
    data:{
        message:"Hello"
    }
})
{{message}}
在自定义事件的表单输入组件上使用
前提:

等价于
new Vue({
    el: "#app-7",
    data: {
        price: 100
    },
    components: {
        "component-7": {
            props: ["value"],
            template: "
                
子组件Prop:【{{value}}】
", methods:{ updateValue:function(value){ value = value+"-" this.$emit("input",value) } } } }, })
父组件数据:【{{price}}】

这里的流程,输入框输入时,触发子组件上input事件并执行updateValue方法,方法参数为输入框中的value(通过$emit.target.value获取),方法可以先对value进行一系列加工处理形成super_value,最后使用this.$emit("input",super_value)触发父组件在子组件节点上监听的input事件,并将加工过的super_value负载在事件上。父组件@input="price = arguments[0]"中的arguments[0]即是这个super_value,父组件通过input的回调更新自己的data,在将data下发给子组件的value特性。

这里如果使用v-model指令,那么子组件特性value、父组件监听的事件input及其回调price = arguments[0], 这些都是固定的,不能变化。

此示例的执行流程其实与双向绑定(.sync修饰符与update事件)中的例子是一样的。
只是这里父组件上的input事件功效没有双向绑定中update事件那么强大。

在组件上使用

在输入框组件中已经说过v-model的种种限制,其中最主要的两点,下发的组件特性必须命名为value和父组件监听的只能绑定事件input,不灵活, 例如在checkbox中,我要给下发的特性取名为checked代替value,并且父组件不想监听@input事件,而是@change事件。

为了解决这个不灵活的问题,可以在组件model选项设置propevent,如下

new Vue({
    el: "#app-9",
    data: {
        isChecked: false,
        message:"please choose this box"
    },
    components: {
        "component-9": {
            model: {
                prop: "checked",
                event: "change"
            },
            props:{
                checked:Boolean,
                value:String
            },
            template: "
", methods:{ choose:function(checked){ this.$emit("change",checked) } } } } })
特性`value`现在从v-model绑定中解放出来了,可自定义使用

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/93443.html

相关文章

  • 组件(3):定义事件

    摘要:自定义事件自定义事件有能力使子组件事件触发父组件中的动作。它所做的只是报告自己的内部事件,因为父组件可能会关心这些事件。只是这里父组件上的事件功效没有双向绑定中事件那么强大。 自定义事件 自定义事件有能力使子组件事件触发父组件中的动作。那么父组件如何监听事件呢?可以使用指令v-on:event-name=callback监听。而子组件又是如何触发事件的呢? 很简单,调用this.$em...

    RebeccaZhong 评论0 收藏0
  • 【Vue原理】Event - 源码版 之 绑定组件定义事件

    摘要:写文章不容易,点个赞呗兄弟专注源码分享,文章分为白话版和源码版,白话版助于理解工作原理,源码版助于了解内部详情,让我们一起学习吧研究基于版本如果你觉得排版难看,请点击下面链接或者拉到下面关注公众号也可以吧原理源码版之绑定组件自定义事件组件 写文章不容易,点个赞呗兄弟专注 Vue 源码分享,文章分为白话版和 源码版,白话版助于理解工作原理,源码版助于了解内部详情,让我们一起学习吧研究基于...

    amuqiao 评论0 收藏0
  • 微信小程序(新)必备知识

    摘要:组件化开发小程序在未出现组件之前,要重用的话,只能简单复制粗暴黏贴组件化开发的优势可复用代码分离,可维护更重要定义组件先创建文件夹用于存放组件,然后再创建组件文件夹注意组件的文件名并不是组件名,而页面文件名是页面名,组件名是引用时才确定的引 组件化开发 小程序在未出现组件之前,要重用的话,只能简单(复制)粗暴(黏贴) 组件化开发的优势: 1、可复用(wxml/wxss/js) 2、代...

    mengera88 评论0 收藏0
  • 微信小程序定义组件(一)

    摘要:自定义组件触发的时候。使用外部样式表在最上方引入文件,微信小程序的路径一个大坑,接着在引入即可。 好吧,突然发现学不完了,一下子,那就分开吧,由于时间太久,直接重新大致复习了一下 微信小程序自定义组件微信小程序支持自定义组件下方的目录showImg(https://melovemingming-1253878077.cos.ap-chengdu.myqcloud.com/blog-im...

    Guakin_Huang 评论0 收藏0
  • 【Vue原理】Event - 白话版

    摘要:写文章不容易,点个赞呗兄弟专注源码分享,文章分为白话版和源码版,白话版助于理解工作原理,源码版助于了解内部详情,让我们一起学习吧研究基于版本如果你觉得排版难看,请点击下面链接或者拉到下面关注公众号也可以吧原理白话版事件是我最感兴趣的东西之 写文章不容易,点个赞呗兄弟专注 Vue 源码分享,文章分为白话版和 源码版,白话版助于理解工作原理,源码版助于了解内部详情,让我们一起学习吧研究基于...

    kumfo 评论0 收藏0

发表评论

0条评论

Yangyang

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<