上抛出一个错误,但如果我删除......" /> 上抛出一个错误,但如果我删除......"> 上抛出一个错误,但如果我删除......" />
ChatGPT解决这个技术问题 Extra ChatGPT

Meaning of v-slot:activator="{ on }"

Looking at the Vuetify example code for v-toolbar, what is the purpose of v-slot:activator="{ on }"? For example:

<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>

As far as I can see, on is not a defined variable anywhere, so I don't see how this is working. When I try it in my project, Internet Explorer throws an error on the <template v-slot:activator="{ on }">, but if I remove it, the page renders.


t
tony19

You're likely referring to this example:

<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>

The following line declares a scoped slot named activator, and it is provided a scope object (from VMenu), which contains a property named on:

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

This uses destructuring syntax on the scope object, which IE does not support.

For IE, you'd have to dereference on from the scope object itself:

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

But the ideal solution IMO is to use a Vue CLI generated project, which includes a Babel preset (@vue/babel-preset-app) to automatically include the transforms/polyfills needed for the target browsers. In this case, babel-plugin-transform-es2015-destructuring would be automatically applied during the build.

Details on the activator slot

VMenu allows users to specify a slotted template named activator, containing component(s) that activate/open the menu upon certain events (e.g., click). VMenu provides listeners for those events via an object, passed to the activator slot:

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

The slot content can access VMenu's event listeners like this:

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

For improved readability, the scoped data can also be destructured in the template:

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

The listeners from the scope object are passed to the <button> with v-on's object syntax, which binds one or more event/listener pairs to the element. For this value of on:

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

...the button's click handler is bound to a VMenu method.


P
PropertyWebBuilder

I think the original question is about understanding the "on" object. It is best explained here:

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

Essentially "on" is a prop passed in from the activator. What v-on="on" does is bind that on prop to the component. "on" itself is all of the event listeners passed from the activator.


t
tony19

To call out a readability tip, it's possible to use this syntax:

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

In my brain this has a more fluent readability than v-on="on", which to me is like observing a conversation consisting solely of:

Person 1: "Hey"

Person 2: "Yep"

Understand? ;)

By the way, activationEvents could be any alias, like "slotEvents", "listeners", "anyOldEvent", or whatever makes more sense to the reader as a renaming of the mysterious on.


In what way is this different from just using a v-if="show" on the element to show/hide and @click="show=!show" on the button to control it?
I believe the events from the slot could be more than just click, for example hover or focus, etc. This is particular for integrating into specific Vuetify components that have internal behavior around activation.
Well, nothing is preventing you from using @@hover or @@focus :) I would understand some edge cases where activators could be useful, but 99% of the times, a simple show variable seems just fine.
H
HaoQiRen

Run the below code,you will know what is 'attrs' an 'on' in v-menu.

<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>

Result:

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] }
}

Explanation:

<div v-bind="attrs" v-on="on"> equals

<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*/}}"
>

Starting in vue 2.4.0+, v-on also supports binding to an object of event/listener pairs without an argument. Note when using the object syntax, it does not support any modifiers. Example:

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

About <template> tags in Internet Explorer throws an error :

as vuetify docs say:

Template caveat

Due to Internet Explorer’s limited support for <template> tags, you must send fully compiled dom elements to the browser. This can be done by either building your Vue code in advance or by creating helper components to replace the dom elements. For instance, if sent directly to IE, this will fail:

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

Hi @HaoQiRen, your answer seems to give little information about the meaning of "on", can you give more information about your example? Have you read this? Try to modify your answer and add details in order to make it valuable for future views :)

关注公众号,不定期副业成功案例分享
Follow WeChat

Success story sharing

Want to stay one step ahead of the latest teleworks?

Subscribe Now