如何實現 Vue 自定義組件中 hover 事件以及 v-model


在css中,很容易在鼠標hover時進行更改,只需:

.item { background: blue; } .item:hover { background: green; } 

在vue中,它會變得更復雜一些,因為我們沒有內置這個功能。我們必須自己實現這些。不過別擔心,工作量不是很大。

 

監聽正確的事件

那么,我們需要監聽哪些事件?

我們想知道什么時候鼠標懸停在元素上,這可以通過跟蹤鼠標何時進入元素以及何時離開元素來確定。為了跟蹤鼠標何時離開,可以使用mouseleave事件。

檢測鼠標何時進入可以通過相應的mouseenter事件來完成,但是我們不使用這個。

原因是在深度嵌套 DOM 樹上使用mouseenter時可能會出現嚴重的性能問題。這是因為mouseenter向輸入的元素以及每個單獨的祖先元素觸發一個唯一的事件。

那我們會用什么來代替呢?

我們使用mouseover事件。

二者的本質區別在於,mouseenter不會冒泡,簡單的說,它不會被它本身的子元素的狀態影響到.但是mouseover就會被它的子元素影響到,在觸發子元素的時候,mouseover會冒泡觸發它的父元素.(想要阻止mouseover的冒泡事件就用mouseenter)

為了把知識點串聯起來,我們使用vue 事件偵聽鼠標進入和離開時的狀態,並相應地更新狀態。

<template>
  <div @mouseover="hover = true" @mouseleave="hover = false" /> </template> ---------------------------------- export default { data() { return { hover: false, }; } } 

現在通過變量 hover 就可以響應鼠標的進入和移出。

 

在鼠標懸停時顯示一個元素

如果希望顯示基於懸停狀態的元素,可以將其與v-if指令配對

<template> <div> <span @mouseover="hover = true" @mouseleave="hover = false" > 鼠標懸停時顯示該內容 </span> <span v-if="hover">這里是秘密消息</span> </div> </template> ------------------------------------------------- export default { data() { return { hover: false, }; } }

 

鼠標懸停時切換樣式類

還可以做類似的事情來切換類

<template> <div> <span @mouseover="hover = true" @mouseleave="hover = false" :hljs-string">{ active: hover }" > Hover me to change the background! </span> </div> </template> ------------------------------------------- export default { data() { return { hover: false, }; } } ------------------------------------------- .active { background: green; } 

雖然這是可行的,但不是最好的解決方案。

對於這種情況,最好使用css

<template> <span> Hover me to change the background! </span> </template> ---------------------------------------- span:hover { background: green; }

 

將鼠標懸停在一個Vue組件上

如果你想要使用一個Vue組件來實現這種行為,那么我們需要做一些輕微的修改。我們不能像以前那樣聽mouseover和mouseleave事件。

如果Vue組件不發出那些事件,那么我們就不能監聽它們。

相反,我們可以添加.native事件修飾符來直接監聽定制Vue組件上的DOM事件。

<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事件。

 

基礎事例

假設有一個日期選擇器組件,該組件在一個對象中接受month和year的值,格式為:{month:1,year:2017}。 該組件需要傳入兩個屬性值 month 和 year,,並通過v-model更新綁定對象。

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

使用方式:

// 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事件,一點也不復雜

PPT模板下載大全https://www.wode007.com

高級用法

通過使用一個或多個計算屬性,我們可以將輸入數據(如字符串)反規范化為輸入元素更容易處理的格式。這通常與更高級的定制組件一起使用,這些組件必須處理各種可能的輸入格式,比如顏色選擇器。

對於日期選擇器示例,假設日期傳遞的格式是m/yyyy結構的字符串。 通過使用計算屬性(在本例中為splitDate),我們可以將輸入字符串拆分為具有month和year屬性的對象,同時僅對日期選擇器組件進行最少的修改。

// 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。這是在自己的自定義組件中添加雙向數據綁定支持的一種非常簡單但功能強大的方法。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM