【问题标题】:Meaning of v-slot:activator="{ on }"v-slot 的含义:activator="{ on }"
【发布时间】:2019-08-06 21:07:26
【问题描述】:

看Vuetify example code for v-toolbar,v-slot:activator="{ on }"的目的是什么?例如:

<template v-slot:activator="{ on }">
  <v-toolbar-title v-on="on">
    <span>All</span>
    <v-icon dark>arrow_drop_down</v-icon>
  </v-toolbar-title>
</template>

<script>
  export default {
    data: () => ({
      items: [
        'All', 'Family', 'Friends', 'Coworkers'
      ]
    })
  }
</script>

据我所知,on 在任何地方都没有定义变量,所以我看不出它是如何工作的。当我在我的项目中尝试它时,Internet Explorer 在&lt;template v-slot:activator="{ on }"&gt; 上抛出一个错误,但如果我删除它,页面就会呈现。

【问题讨论】:

标签: vue.js vuejs2 vuetify.js


【解决方案1】:

您可能指的是这个例子:

<v-toolbar color="grey darken-1" dark>
  <v-menu :nudge-width="100">
    <template v-slot:activator="{ on }">
      <v-toolbar-title v-on="on">
        <span>All</span>
        <v-icon dark>arrow_drop_down</v-icon>
      </v-toolbar-title>
    </template>

    ...
  </v-menu>
</v-toolbar>

以下行声明了一个名为activator 的scoped slot,并提供了一个范围对象(来自VMenu),其中包含一个名为on 的属性:

<template v-slot:activator="{ on }">

这在作用域对象上使用destructuring syntax,即IE does not support。

对于 IE,您必须从作用域对象本身取消引用 on:

<template v-slot:activator="scope">
  <v-toolbar-title v-on="scope.on">

但理想解决方案 IMO 是使用 Vue CLI 生成的项目,其中包括 Babel 预设 (@vue/babel-preset-app) 以自动包含 target 浏览器所需的转换/polyfills。在这种情况下,babel-plugin-transform-es2015-destructuring 将在构建期间自动应用。

activator 槽的详细信息

VMenu 允许用户指定一个名为activator 的开槽模板,其中包含在某些事件时激活/打开菜单的组件(例如,click)。 VMenu 为这些事件 via an object 提供侦听器,传递给 activator 插槽:

<v-menu>
  <template v-slot:activator="scopeDataFromVMenu">
    <!-- slot content goes here -->
  </template>
</v-menu>

槽内容可以像这样访问VMenu的事件监听器:

<v-menu>
  <template v-slot:activator="scopeDataFromVMenu">
    <button v-on="scopeDataFromVMenu.on">Click</button>
  </template>
</v-menu>

为了提高可读性,范围内的数据也可以是模板中的destructured:

<!-- equivalent to above -->
<v-menu>
  <template v-slot:activator="{ on }">
    <button v-on="on">Click</button>
  </template>
</v-menu>

范围对象中的侦听器使用v-on 的对象语法传递给&lt;button&gt;,该语法将一个或多个事件/侦听器对绑定到元素。对于on这个值:

{
  click: activatorClickHandler // activatorClickHandler is an internal VMenu mixin
}

...按钮的点击处理程序绑定到VMenu 方法。

【讨论】:

    【解决方案2】:

    我认为最初的问题是关于理解“on”对象。最好在这里解释:

    https://github.com/vuetifyjs/vuetify/issues/6866

    本质上,“on”是从激活器传入的道具。 v-on="on" 所做的是将 on prop 绑定到组件。 “on”本身就是所有从激活器传递过来的事件监听器。

    【讨论】:

      【解决方案3】:

      要提出可读性提示,可以使用以下语法:

      <v-menu>
          <template v-slot:activator="{ on: activationEvents }">
              <v-btn v-on="activationEvents">
                  I like turtles ?
              </v-btn>
          </template>
      </v-menu>
      

      在我的大脑中,这比v-on="on" 具有更流畅的可读性,对我来说,这就像观察一个仅包含以下内容的对话:

      • 第一个人:“嘿”
      • 第 2 个人:“是的”

      明白吗? ;)

      顺便说一句,activationEvents 可以是任何alias,如“slotEvents”、“listeners”、“anyOldEvent”,或者对读者更有意义的任何对神秘的on 的重命名。

      【讨论】:

      • 这与仅在元素上使用 v-if="show" 来显示/隐藏和在按钮上使用 @click="show=!show" 来控制它有什么不同?
      • 我相信来自插槽的事件可能不仅仅是点击,例如悬停或聚焦等。这特别适用于集成到具有激活内部行为的特定 Vuetify 组件中。
      • 好吧,没有什么能阻止你使用@@hover 或@@focus :) 我会理解激活器可能有用的一些极端情况,但99% 的时间,一个简单的显示变量似乎只是很好。
      【解决方案4】:

      运行下面的代码,你就会知道 v-menu 中的 'attrs' 和 'on' 是什么。

      <v-menu>
          <template v-slot:activator="{ on, attrs }">
              <div v-bind="attrs" v-on="on">
                  v-menu slot activator:
                  <br />
                  attrs == {{ JSON.stringify(attrs) }}
                  <br />
                  on == {{ '{' + Object.keys(on).map(k => k + " : " + on[k]).join(',') + '}' }}
              </div>
          </template>
      </v-menu>
      

      结果:

      v-menu slot activator:
      attrs == {"role":"button","aria-haspopup":true,"aria-expanded":"false"}
      on == {
      click:function (e) {if (_this.openOnClick) {onClick && onClick(e);}_this.absoluteX = e.clientX;_this.absoluteY = e.clientY;},
      keydown:function () { [native code] }
      }
      

      解释:

      &lt;div v-bind="attrs" v-on="on"&gt; 等于

      <div 
          v-bind="{role:'button',aria-haspopup:true,aria-expanded:'false'}" 
          v-on="{click:function (e) {/*implement by v-menu*/},keydown:function () {/*implement by v-menu*/}}"
      >
      

      从 vue 2.4.0+ 开始,v-on 还支持绑定到不带参数的事件/侦听器对的对象。请注意,使用对象语法时,它不支持任何修饰符。 示例:

      <!-- v-on's object syntax (vue 2.4.0+) -->
      <button v-on="{ mousedown: doThis, mouseup: doThat }"></button>
      

      关于 Internet Explorer 中的&lt;template&gt; 标签抛出错误:

      正如 vuetify 文档所说:

      Template caveat

      由于 Internet Explorer 对 &lt;template&gt; 标记的支持有限,您必须将完全编译的 dom 元素发送到浏览器。这可以通过提前构建您的 Vue 代码或通过创建帮助组件来替换 dom 元素来完成。例如,如果直接发送到 IE,这将失败:

      <!-- Vue Component -->
      <template v-slot:items="props">
        <td>{‌{ props.item.name }‌}</td>
      </template>
      

      【讨论】:

      • 嗨@HaoQiRen,您的回答似乎没有提供有关“on”含义的信息,您能否提供有关您的示例的更多信息?你读过this吗?尝试修改您的答案并添加详细信息,以使其对未来的观点有价值:)
      猜你喜欢
      • 2021-02-27
      • 1970-01-01
      • 1970-01-01
      • 2020-10-24
      • 2022-11-01
      • 1970-01-01
      • 1970-01-01
      • 2020-02-05
      • 2022-12-10
      相关资源
      最近更新 更多