Vue 组件上的类似 DOM 事件那点事儿

click 是事件.

事件是基本的 DOM 元素都具备的一个特性.

一个 DOM 元素不管是否绑定了事件响应函数.

只要我们点击了(或者触摸了)这个 DOM 元素.那么在其内部一定就会发出一个对应的事件信号.

<div></div>
<button></button>
<p></p>
<span></span>
.....

div.onclick = function () {}
button.onclick = function () {}
p.onclick = function () {}
span.onclick = funciton () {}
....

组件上的 click

首先组件是一个 js 对象.

里面包含了一堆和当前组件相关的数据和函数.

HelloWorld.vue

- data () {}
- methods: {}
- watch: {}
- computed: {}
- components: {}
....

当在语法级别,我们给定一个第三方组件绑定 click 事件时.

<cube-button @click="hanlderClick"><cube-button>

并在当前组件内部定义事件响应函数

HelloWorld.vue

methods: {
    hanlderClick () {
        console.log('点击 cube-button 事件将被触发.')
    }
}

点击 cube-button 时,事件将被触发,乍看之下,感觉这很符合直觉.

(本来就是写的一堆跑浏览器下的玩意,click 事件不是很常见吗?)

但是稍微深入思考一下,就会发现问题所在了.


往组件上绑定事件到底是在干什么?

已经知道了,组件本身是一个 js 对象.

我们在组件上绑定 @click 事件,翻译一下就是: 往组件上绑定 click 事件.

现在的问题是,一个普通的 js 对象 Object.

它是不具备 click 事件特性的.

它不可见,它是数据,用户根本就不可能想普通的 HTML 元素那样用肉眼看到它.

看不到它,怎么可能去点击它.就更不可能有 click 这个存在于肉眼可见的 DOM 元素上了.

所以,能够触发 click 事件的,肯定是组件内部以某种方式向外发布了 click 事件.$emit

1. 直接在组件上绑定 click 事件.

<div id='app'>
    <!--直接在组件上绑定 click 事件,并没有任何效果.-->
    <comp-one @click="handlerClick" content="Hello Click"></comp-one>
</div>
const CompOne = {
    template:`<div :style="styleObj" >{{content}}</div>`,
    props:['content']
}
 var app = new Vue({
    el: '#app',
    data: {},
    methods: {
      handlerClick () {
        console.log('写在组件上的 click')
      }
    }
}

点击组件发现并没有任何效果:

组件直接绑定事件没有任何结果

2.当组件内部任意一个可以被用户点击到的 DOM 元素发布一个 click 事件

const CompOne = {
    template:`<div :style="styleObj" @click="hanlderClick">{{content}}</div>`,
    props:['content'],
    methods: {
      hanlderClick () {
        this.$emit('click') // 最外层 DIV 元素看的到,用户点击这个 div,手动的向外部发送 click 事件.
      }
    }
}

结果:

内部手动的给组件的某个 HTML 元素绑定 click,然后在 clickhanlder 内向外发布 click 事件

结论:在组件上监听click事件的本质是,被监听事件的组件内部,无论以何种方式,必须想外部$emit 出 click 事件信号才可以.

  • 常规方式是,利用组件内模板用户可视可操作的某个 DOM 元素点击的时候触发 $emit('click')
  • 不常规做法是,不利用上述这种的任意其他方式.比如定时器.

3.@click.native

如果,我们直接在组件上使用 @click 就必须手动的在被监听了 click 的组件内部调用 $emit.

而 @click.native 修饰符则就是帮我们做了一件事情而已.

在被监听了 @click 的组件内部的 DOM 根元素上自动的注册 click 事件.

并定义 clickHanlder .

在此 clickHanlder 内,触发 this.$emit('click')

<div 420123456='app'>
    <!-- 组件内部 根元素 click=>{this.$emit('click')} -->
    <comp-one @click.native="handlerClick" content="Hello Click"></comp-one>
  </div>
  
 const CompOne = {
    // template:`<div :style="styleObj" @click="hanlderClick">{{content}}</div>`, // @cilck.native 等价 @click = clickhanlder
    template:`<div :style="styleObj">{{content}}</div>`, // 内部不需要在手动的注册并调用 click 事件响应函数了
    props:['content'],
    methods: {
      // hanlderClick () { // @cilck.native 等价 @click = clickhanlder
      //   this.$emit('click')
      // }
    }
}

 var app = new Vue({
    el: '#app',
    data: {},
    methods: {
      handlerClick () {
        console.log('写在组件上的 click')
      }
    }
}

结果

@click.native 默认就是帮我们做了:组件根元素绑定 click,提供 clickhandler,在 clickhandler 内部发布 click 仅此而已

关于组件上定义 DOM 事件说明

  • 和在组件上定义任意事件本质上一样的.(不管是 DOM.click, 还是 whateverEvent). 都是需要组件内部去触发.
  • 例子里定义的 click ,对于组件来说,不存在这样的事件,组件本身是一个 Object 对象,不可视元素,是数据,用户根本无法操作它,更加不会有 click 事件了.所以需要靠内部的不管是 DOM 也好,其他方式也罢,在某个时刻触发 click 事件 (this.$emit('click'))
  • 对于原生的 DOM 事件来说,@click.native 的 native 修饰符,Vue 默认值是帮我们在组件的根模板元素上绑定了 click 函数,就是DOM元素本身可以发布click事件的机制.
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容