第 94 题:vue 在 v-for 时给每项元素绑定事件需要用事件代理吗?为什么?

发布于 2022-07-01 11:21:41 字数 68 浏览 1076 评论 19

这是一个很常见的功能,主要是用在列表页的绑定,一遍我们需要遍历才能输出我们的数组,同时我们有需要绑定一个点击事件,点击后跳转到详情页面。

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(19

单挑你×的.吻 2022-05-04 13:55:46

react 是委托到 document 上, 然后自己生成了合成事件, 冒泡到 document 的时候进入合成事件, 然后他通过 getParent() 获取该事件源的所有合成事件, 触发完毕之后继续冒泡
vue 是怎么做的我就不清楚了, 但是尤大应该会意识到合成事件带来的好处, 跨端跨浏览器

每个dom都有的事件都代理到document上,但是一些特殊的比如focus这种必须放在input这些dom上。

爱本泡沫多脆弱 2022-05-04 13:55:46

react 是委托到 document 上, 然后自己生成了合成事件, 冒泡到 document 的时候进入合成事件, 然后他通过 getParent() 获取该事件源的所有合成事件, 触发完毕之后继续冒泡
vue 是怎么做的我就不清楚了, 但是尤大应该会意识到合成事件带来的好处, 跨端跨浏览器

每个dom都有的事件都代理到document上,但是一些特殊的比如focus这种必须放在input这些dom上。

https://juejin.im/post/5d0af976e51d454fbf540a0f

血之狂魔 2022-05-04 13:55:45

react好像跟vue不一样,react好像所有事件都委托到 document 上了吧,然后进行派发

React 中的事件是合成事件,所有事件都委托到 document 了,最后通过addEventListener来监听事件,react-dom 中 合成事件的处理源码:

// react-dom/src/events/EventListener.js 
export function addEventBubbleListener(
  element: Document | Element,
  eventType: string,
  listener: Function,
): void {
  element.addEventListener(eventType, listener, false);
}

// 调用处
addEventBubbleListener(element, getRawEventName(topLevelType)
疑心病 2022-05-04 13:55:45

首先我们需要知道事件代理主要有什么作用?

  • 事件代理能够避免我们逐个的去给元素新增和删除事件
  • 事件代理比每一个元素都绑定一个事件性能要更好

从vue的角度上来看上面两点

  • 在v-for中,我们直接用一个for循环就能在模板中将每个元素都绑定上事件,并且当组件销毁时,vue也会自动给我们将所有的事件处理器都移除掉。所以事件代理能做到的第一点vue已经给我们做到了
  • 在v-for中,给元素绑定的都是相同的事件,所以除非上千行的元素需要加上事件,其实和使用事件代理的性能差别不大,所以也没必要用事件代理
无声静候 2022-05-04 13:55:44

说一下我个人理解,先说结论,可以使用

事件代理作用主要是 2 个

  1. 将事件处理程序代理到父节点,减少内存占用率
  2. 动态生成子节点时能自动绑定事件处理程序到父节点

这里我生成了十万个 span 节点,通过 performance monitor 来监控内存占用率和事件监听器的数量,对比以下 3 种情况

  1. 不使用事件代理,每个 span 节点绑定一个 click 事件,并指向同一个事件处理程序
  <div>
      <span 
        v-for="(item,index) of 100000" 
        :key="index" 
        @click="handleClick">
        {{item}}
      </span>
    </div>
  1. 不使用事件代理,每个 span 节点绑定一个 click 事件,并指向不同的事件处理程序
  <div>
      <span 
        v-for="(item,index) of 100000" 
        :key="index" 
        @click="function () {}">
        {{item}}
      </span>
    </div>
  1. 使用事件代理
<div  @click="handleClick">
      <span 
        v-for="(item,index) of 100000"  
        :key="index">
        {{item}}
      </span>
    </div>

可以看到使用事件代理无论是监听器数量和内存占用率都比前两者要少

同时对比 3 个图中监听器的数量以及我以往阅读 vue 源码的过程中,并没有发现 vue 会自动做事件代理,但是一般给 v-for 绑定事件时,都会让节点指向同一个事件处理程序(第二种情况可以运行,但是 eslint 会警告),一定程度上比每生成一个节点都绑定一个不同的事件处理程序性能好,但是监听器的数量仍不会变,所以使用事件代理会更好一点

上面有回答说react/vue框架已经帮我们实现了统一的事件代理,为何说这里的第1,2种写法属于非事件代理(vue中)?

北恋 2022-05-04 13:55:12

vue自身没有做事件代理,如果需要,则直接代理到父节点。对于mpvue写小程序来说,还是很有必要的,毕竟安卓机小程序性能太差。

    <ul @click="meths">
      <li v-for="(item,key) in 10" :key="key" :data-index="key">{{item}}</li>
    </ul>

    // vue
    meths(e) {
      if (e.target.nodeName.toLowerCase() === 'li') {
        console.log(e.target.dataset.index)
      }
    }

    // mpvue
    meths(e) {
        console.log(e.target.dataset.index)
    }  
伪装你 2022-05-04 13:54:57

react好像跟vue不一样,react好像所有事件都委托到document上了吧,然后进行派发

对的,react 代理到了 document 上

口干舌燥 2022-05-04 13:54:28

vue本身不做事件代理

  1. 普通html元素和在组件上挂了.native修饰符的事件。最终EventTarget.addEventListener()挂载事件
  2. 组件上的,vue组件实例上的自定义事件(不包括.native)会调用原型上的$on,$emit(包括一些其他api $off,$once等等)

参考:
https://segmentfault.com/a/1190000009750348

复古式 2022-05-04 13:10:31

react 是委托到 document 上, 然后自己生成了合成事件, 冒泡到 document 的时候进入合成事件, 然后他通过 getParent() 获取该事件源的所有合成事件, 触发完毕之后继续冒泡
vue 是怎么做的我就不清楚了, 但是尤大应该会意识到合成事件带来的好处, 跨端跨浏览器

方觉久 2022-05-04 11:50:10

react好像跟vue不一样,react好像所有事件都委托到document上了吧,然后进行派发

久光 2022-05-04 09:10:32
<ul>
      <li
        v-for="i in 10"
        :key="i"
        @click="c"
      >{{i}}</li>
    </ul>

屏幕快照 2019-07-09 下午2 48 57

一本正经胡说八道的,事件并没有被代理

痴情 2022-05-04 08:29:10

源码没有做事件代理

https://forum.vuejs.org/t/is-event-delegation-necessary/3701/2

快三年了,真的没有做优化吗?

往事风中埋 2022-05-04 05:45:09

嗯,看了楼上的那篇文章,和我的结论大致相同,只有在非常非常多的节点中,使用事件代理会提高一点性能,否则绑定在每个节点中几乎没有差别

小巷里的女流氓 2022-05-03 23:30:20

说一下我个人理解,先说结论,可以使用

事件代理作用主要是 2 个

  1. 将事件处理程序代理到父节点,减少内存占用率
  2. 动态生成子节点时能自动绑定事件处理程序到父节点

这里我生成了十万个 span 节点,通过 performance monitor 来监控内存占用率和事件监听器的数量,对比以下 3 种情况

  1. 不使用事件代理,每个 span 节点绑定一个 click 事件,并指向同一个事件处理程序
  <div>
      <span 
        v-for="(item,index) of 100000" 
        :key="index" 
        @click="handleClick">
        {{item}}
      </span>
    </div>
  1. 不使用事件代理,每个 span 节点绑定一个 click 事件,并指向不同的事件处理程序
  <div>
      <span 
        v-for="(item,index) of 100000" 
        :key="index" 
        @click="function () {}">
        {{item}}
      </span>
    </div>
  1. 使用事件代理
<div  @click="handleClick">
      <span 
        v-for="(item,index) of 100000"  
        :key="index">
        {{item}}
      </span>
    </div>

可以看到使用事件代理无论是监听器数量和内存占用率都比前两者要少

同时对比 3 个图中监听器的数量以及我以往阅读 vue 源码的过程中,并没有发现 vue 会自动做事件代理,但是一般给 v-for 绑定事件时,都会让节点指向同一个事件处理程序(第二种情况可以运行,但是 eslint 会警告),一定程度上比每生成一个节点都绑定一个不同的事件处理程序性能好,但是监听器的数量仍不会变,所以使用事件代理会更好一点

白首有我共你 2022-05-03 17:03:32

哪位大佬能给段代码 0.0

等风来 2022-05-03 00:58:35

之前好像看过 react / vue 这些框架都自己实现了一套事件,把事件都代理到document上面了,所以不需要自己手动再去代理了,如果不用框架需要代理到父级元素

浅黛梨妆こ 2022-05-02 01:32:13

在vue 中 vue 做了处理
如果我们自己在非vue 中需要对很多元素添加事件的时候,可以通过将事件添加到它们的父节点而将事件委托给父节点来触发处理函数

万劫不复 2022-05-01 06:38:19

不需要,因为vue源码里已经做了处理

~没有更多了~

关于作者

江心雾

暂无简介

0 文章
0 评论
22 人气
更多

推荐作者

玍銹的英雄夢

文章 0 评论 0

我不会写诗

文章 0 评论 0

十六岁半

文章 0 评论 0

浸婚纱

文章 0 评论 0

qq_kJ6XkX

文章 0 评论 0

    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文