在 Vuetify 中创建日历时,方法参数意味着什么?

What do the method arguments mean when creating a calendar in Vuetify?

我想解决的问题

我正在使用 Vuetify 创建日历。 Vuetify 代码中有一些我不明白的地方。我试图通过查看官方网站上的示例代码来理解它,但看起来 Vuetify 方法在脚本方法中传递了唯一的参数,我还检查了 API,参数是从 Vuetify 获取时间和其他事件?

代码

模板

<template>
  <v-row class="fill-height">
    <v-col>
      <v-sheet height="600">
        <v-calendar
          ref="calendar"
          v-model="value"
          color="primary"
          type="4day"
          :events="events"
          :event-color="getEventColor"
          :event-ripple="false"
          @change="getEvents"
          @mousedown:event="startDrag"
          @mousedown:time="startTime"
          @mousemove:time="mouseMove"
          @mouseup:time="endDrag"
          @mouseleave.native="cancelDrag"
        >
          <template v-slot:event="{ event, timed, eventSummary }">
            <div
              class="v-event-draggable"
              v-html="eventSummary()"
            ></div>
            <div
              v-if="timed"
              class="v-event-drag-bottom"
              @mousedown.stop="extendBottom(event)"
            ></div>
          </template>
        </v-calendar>
      </v-sheet>
    </v-col>
  </v-row>
</template>

脚本

<script>
  export default {
    data: () => ({
      value: '',
      events: [],
      colors: ['#2196F3', '#3F51B5', '#673AB7', '#00BCD4', '#4CAF50', '#FF9800', '#757575'],
      names: ['Meeting', 'Holiday', 'PTO', 'Travel', 'Event', 'Birthday', 'Conference', 'Party'],
      dragEvent: null,
      dragStart: null,
      createEvent: null,
      createStart: null,
      extendOriginal: null,
    }),
    methods: {
      startDrag ({ event, timed }) {
        if (event && timed) {
          this.dragEvent = event
          this.dragTime = null
          this.extendOriginal = null
        }
      },
      startTime (tms) {
        const mouse = this.toTime(tms)

        if (this.dragEvent && this.dragTime === null) {
          const start = this.dragEvent.start

          this.dragTime = mouse - start
        } else {
          this.createStart = this.roundTime(mouse)
          this.createEvent = {
            name: `Event #${this.events.length}`,
            color: this.rndElement(this.colors),
            start: this.createStart,
            end: this.createStart,
            timed: true,
          }

          this.events.push(this.createEvent)
        }
      },
      extendBottom (event) {
        this.createEvent = event
        this.createStart = event.start
        this.extendOriginal = event.end
      },
      mouseMove (tms) {
        const mouse = this.toTime(tms)

        if (this.dragEvent && this.dragTime !== null) {
          const start = this.dragEvent.start
          const end = this.dragEvent.end
          const duration = end - start
          const newStartTime = mouse - this.dragTime
          const newStart = this.roundTime(newStartTime)
          const newEnd = newStart + duration

          this.dragEvent.start = newStart
          this.dragEvent.end = newEnd
        } else if (this.createEvent && this.createStart !== null) {
          const mouseRounded = this.roundTime(mouse, false)
          const min = Math.min(mouseRounded, this.createStart)
          const max = Math.max(mouseRounded, this.createStart)

          this.createEvent.start = min
          this.createEvent.end = max
        }
      },
      endDrag () {
        this.dragTime = null
        this.dragEvent = null
        this.createEvent = null
        this.createStart = null
        this.extendOriginal = null
      },
      cancelDrag () {
        if (this.createEvent) {
          if (this.extendOriginal) {
            this.createEvent.end = this.extendOriginal
          } else {
            const i = this.events.indexOf(this.createEvent)
            if (i !== -1) {
              this.events.splice(i, 1)
            }
          }
        }

        this.createEvent = null
        this.createStart = null
        this.dragTime = null
        this.dragEvent = null
      },
      roundTime (time, down = true) {
        const roundTo = 15 // minutes
        const roundDownTime = roundTo * 60 * 1000

        return down
          ? time - time % roundDownTime
          : time + (roundDownTime - (time % roundDownTime))
      },
      toTime (tms) {
        return new Date(tms.year, tms.month - 1, tms.day, tms.hour, tms.minute).getTime()
      },
      getEventColor (event) {
        const rgb = parseInt(event.color.substring(1), 16)
        const r = (rgb >> 16) & 0xFF
        const g = (rgb >> 8) & 0xFF
        const b = (rgb >> 0) & 0xFF

        return event === this.dragEvent
          ? `rgba(${r}, ${g}, ${b}, 0.7)`
          : event === this.createEvent
            ? `rgba(${r}, ${g}, ${b}, 0.7)`
            : event.color
      },
      getEvents ({ start, end }) {
        const events = []

        const min = new Date(`${start.date}T00:00:00`).getTime()
        const max = new Date(`${end.date}T23:59:59`).getTime()
        const days = (max - min) / 86400000
        const eventCount = this.rnd(days, days + 20)

        for (let i = 0; i < eventCount; i++) {
          const timed = this.rnd(0, 3) !== 0
          const firstTimestamp = this.rnd(min, max)
          const secondTimestamp = this.rnd(2, timed ? 8 : 288) * 900000
          const start = firstTimestamp - (firstTimestamp % 900000)
          const end = start + secondTimestamp

          events.push({
            name: this.rndElement(this.names),
            color: this.rndElement(this.colors),
            start,
            end,
            timed,
          })
        }

        this.events = events
      },
      rnd (a, b) {
        return Math.floor((b - a + 1) * Math.random()) + a
      },
      rndElement (arr) {
        return arr[this.rnd(0, arr.length - 1)]
      },
    },
  }
</script>

例如,方法中的startDrag以事件和时间为参数。另外,在我查看示例时所指的点击部分中,它是 showEvent ({ nativeEvent, event }),我认为 nativeEvent 和 event 的参数也是错误的。还有另一种称为 updateRange ({ start, end }) 的方法。此外,它还接受参数 (tms) 和 (event),但模板中没有传递任何值,所以我想知道它为什么起作用。 下面是Vuetify的官网。 https://vuetifyjs.com/en/components/calendars/#click

Vue 中的事件处理

v-on directive@ for shorthand)的值为函数名时,模板编译器将其转换为包含事件参数的函数调用。

例如,这个标记:

<CustomButton @submit="upload">Submit</CustomButton>

...等同于:

<CustomButton @submit="(e) => upload(e)">Submit</CustomButton>

事件参数 (e) 是 CustomButton 在发出 submit 事件时传递的数据。假设 CustomButtondoSomething() 在这里被调用:

// CustomButton.vue
export default {
  methods: {
    doSomething() {
      const eventData = { name: 'product 1', quantity: 100 }
      this.$emit('submit', eventData) 
    }
  }
}

注意事件参数的类型是:

{
  name: string,
  quantity: number,
}

鉴于上面的 @submit 处理设置,父级会收到 submit 事件,并使用该事件参数调用 upload()

// Parent.vue
export default {
  methods: {
    upload(eventData) {
      console.log({ name: eventData.name, quantity: eventData.quantity })
    }
  }
}

在参数列表中使用 object destructuring,该代码可以重写为:

// Parent.vue
export default {
  methods: {
    upload({ name, quantity }) {
      console.log({ name, quantity })
    }
  }
}

这就是您在示例代码中看到的模式

活动

每个组件的 Vuetify API 文档列出了所有事件及其参数 (v-calendar's API / events)。

鉴于下面的事件参数,查看以下方法签名是有意义的...

@mousedown:event="startDrag"

mousedown:event 的事件参数:

{
  event: any,
  ⋮
  timed: boolean,
  ⋮
}

方法签名:

export default {
  methods: {
    startDrag({ event, timed }) {⋯}
  }
}

@click:event="showEvent"

click:event 的事件参数:

{
  event: any,
  ⋮
  nativeEvent: MouseEvent | TouchEvent
}

方法签名:

export default {
  methods: {
    showEvent({ event, nativeEvent }) {⋯}
  }
}

@change="updateRange"

change 的事件参数:

{
  start: {⋯},
  end: {⋯}
}

方法签名:

export default {
  methods: {
    updateRange({ start, end }) {⋯}
  }
}