前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >如何实现 Vue 自定义组件中 hover 事件以及 v-model

如何实现 Vue 自定义组件中 hover 事件以及 v-model

作者头像
前端小智@大迁世界
发布2020-05-11 17:27:37
18.9K0
发布2020-05-11 17:27:37
举报
文章被收录于专栏:终身学习者终身学习者

作者:Joshua Bemenderfer 译者:前端小智 来源:alligator

在CSS中,很容易在鼠标hover时进行更改,只需:

代码语言:javascript
复制
.item {
  background: blue;
}

.item:hover {
  background: green;
}

在Vue中,它会变得更复杂一些,因为我们没有内置这个功能。我们必须自己实现这些。不过别担心,工作量不是很大。

监听正确的事件

那么,我们需要监听哪些事件?

我们想知道什么时候鼠标悬停在元素上,这可以通过跟踪鼠标何时进入元素以及何时离开元素来确定。为了跟踪鼠标何时离开,可以使用mouseleave事件。

检测鼠标何时进入可以通过相应的mouseenter事件来完成,但是我们不使用这个。

原因是在深度嵌套 DOM 树上使用mouseenter时可能会出现严重的性能问题。这是因为mouseenter向输入的元素以及每个单独的祖先元素触发一个唯一的事件。

那我们会用什么来代替呢?

我们使用mouseover事件。

二者的本质区别在于,mouseenter不会冒泡,简单的说,它不会被它本身的子元素的状态影响到.但是mouseover就会被它的子元素影响到,在触发子元素的时候,mouseover会冒泡触发它的父元素.(想要阻止mouseover的冒泡事件就用mouseenter)

为了把知识点串联起来,我们使用Vue 事件侦听鼠标进入和离开时的状态,并相应地更新状态。

代码语言:javascript
复制
<template>
  <div
    @mouseover="hover = true"
    @mouseleave="hover = false"
  />
</template>
----------------------------------

export default {
  data() {
    return {
      hover: false,
    };
  }
}

现在通过变量 hover 就可以响应鼠标的进入和移出。

在鼠标悬停时显示一个元素

如果希望显示基于悬停状态的元素,可以将其与v-if指令配对

代码语言:javascript
复制
<template>
  <div>
    <span
      @mouseover="hover = true"
      @mouseleave="hover = false"
    >
      鼠标悬停时显示该内容
    </span>
    <span v-if="hover">这里是秘密消息</span>
  </div>
</template>

-------------------------------------------------

export default {
  data() {
    return {
      hover: false,
    };
  }
}

鼠标悬停时切换样式类

还可以做类似的事情来切换类

代码语言:javascript
复制
<template>
  <div>
    <span
      @mouseover="hover = true"
      @mouseleave="hover = false"
      :class="{ active: hover }"
    >
      Hover me to change the background!
    </span>
  </div>
</template>
-------------------------------------------

export default {
  data() {
    return {
      hover: false,
    };
  }
}
-------------------------------------------

.active {
  background: green;
}

虽然这是可行的,但不是最好的解决方案。

对于这种情况,最好使用CSS

代码语言:javascript
复制
<template>
  <span>
    Hover me to change the background!
  </span>
</template>

----------------------------------------

span:hover {
  background: green;
}

将鼠标悬停在一个Vue组件上

如果你想要使用一个Vue组件来实现这种行为,那么我们需要做一些轻微的修改。我们不能像以前那样听mouseovermouseleave事件。

如果Vue组件不发出那些事件,那么我们就不能监听它们。

相反,我们可以添加.native事件修饰符来直接监听定制Vue组件上的DOM事件。

代码语言:javascript
复制
<template>
  <my-custom-component
    @mouseover.native="hover = true"
    @mouseleave.native="hover = false"
  />
</template>
--------------------------------------
export default {
  data() {
    return {
      hover: false,
    };
  }
}

使用.native,我们侦听本地DOM事件,而不是从Vue组件发出的事件。

接着我们来看看如何在自定义组件中 实现 v-model

虽然v-model是向普通组件添加双向数据绑定的强大功能,但是如何向自己的自定义组件添加对v-model的支持并不总是那么容易,但其实很简单。

v-model 介绍

要了解如何在组件中实现v-model支持,需要了解它是如何工作的。虽然看起来很神奇,但v-model= syncedProp实际上是一个非常简单的简写:value= syncedProp @input= syncedProp = arguments[0] (或者 value= syncedProp @input= syncedProp = $event.target)。

因此,要与v-model兼容,你的组件需要做的就是接受:value属性,并在用户更改值时发出@input事件。

基础事例

假设有一个日期选择器组件,该组件在一个对象中接受monthyear的值,格式为:{month:1,year:2017}。 该组件需要传入两个属性值 monthyear,,并通过v-model更新绑定对象。

代码语言:javascript
复制
// DatePicker.vue
<template>
  <div class="date-picker">
    Month: <input type="number" ref="monthPicker" :value="value.month" @input="updateDate()"/>
    Year: <input type="number" ref="yearPicker" :value="value.year" @input="updateDate()"/>
  </div>
</template>

<script>
export default {
  props: ['value'],

  methods: {
    updateDate() {
      this.$emit('input', {
        month: +this.$refs.monthPicker.value,
        year: +this.$refs.yearPicker.value
      })
    }
  }
};
</script>

使用方式:

代码语言:javascript
复制
// WrapperComponent.vue

<template>
  <div class="wrapper">
    <date-picker v-model="date"></date-picker>
    <p>
      Month: {{date.month}}
      Year: {{date.year}}
    </p>
  </div>
</template>

<script>
import DatePicker from './DatePicker.vue';

export default {
  components: {
    DatePicker
  },

  data() {
    return {
      date: {
        month: 1,
        year: 2017
      }
    }
  }
})
</script>

如上所看到的,它只是接受一个:value属性并发出一个带有更新日期的@input事件,一点也不复杂

大家都说简历没项目写,我就帮大家找了一个项目,还附赠【搭建教程】

高级用法

通过使用一个或多个计算属性,我们可以将输入数据(如字符串)反规范化为输入元素更容易处理的格式。这通常与更高级的定制组件一起使用,这些组件必须处理各种可能的输入格式,比如颜色选择器。

对于日期选择器示例,假设日期传递的格式是m/yyyy结构的字符串。 通过使用计算属性(在本例中为splitDate),我们可以将输入字符串拆分为具有monthyear属性的对象,同时仅对日期选择器组件进行最少的修改。

代码语言:javascript
复制
// StringyDatePicker.vue
<template>
  <div class="date-picker">
    Month: <input type="number" ref="monthPicker" :value="splitDate.month" @input="updateDate()"/>
    Year: <input type="number" ref="yearPicker" :value="splitDate.year" @input="updateDate()"/>
  </div>
</template>

<script>
export default {
  props: ['value'],

  computed: {
    splitDate() {
      const splitValueString = this.value.split('/');

       return {
        month: splitValueString[0],
        year: splitValueString[1]
      }
    }
  },

  methods: {
    updateDate() {
      const monthValue = this.$refs.monthPicker.value;
      const yearValue = this.$refs.yearPicker.value;
      this.$emit('input', `${monthValue}/${yearValue}`);
    }
  }
};
</script>

一旦熟悉了这里介绍的概念,可能会发现自己对任何和每个我们创建的接受用户输入的组件都使用了v-model。这是在自己的自定义组件中添加双向数据绑定支持的一种非常简单但功能强大的方法。

代码部署后可能存在的BUG没法实时知道,事后为了解决这些BUG,花了大量的时间进行log 调试,这边顺便给大家推荐一个好用的BUG监控工具 Fundebug

原文:

https://alligator.io/vuejs/ad... https://michaelnthiessen.com/...

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 监听正确的事件
  • 在鼠标悬停时显示一个元素
  • 鼠标悬停时切换样式类
  • 将鼠标悬停在一个Vue组件上
  • v-model 介绍
  • 基础事例
  • 高级用法
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档