淺談Vue.js中如何實(shí)現(xiàn)自定義下拉菜單指令
我們利用 Vue.js 的自定義指令能力,來(lái)實(shí)現(xiàn)一個(gè)自定義下拉菜單功能。描述如下:
- 點(diǎn)擊按鈕,彈出下拉菜單。
- 點(diǎn)擊下拉菜單之外的區(qū)域,關(guān)閉下拉菜單。
1基礎(chǔ)版
html:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<link rel="stylesheet" type="text/css" href="style.css" rel="external nofollow" >
</head>
<body>
<div id="app" v-cloak>
<div class="main" v-outside-click="close">
<button @click="isShow=!isShow">點(diǎn)擊</button>
<div class="dropDown" v-show="isShow">
<p>零售新物種:藥店和便利店合體之后</p>
</div>
</div>
</div>
<script src="https://cdn.bootcss.com/vue/2.2.2/vue.min.js"></script>
<script src="index.js"></script>
</body>
</html>
我們?yōu)榘粹o綁定了 isShow 變量,當(dāng)點(diǎn)擊按鈕時(shí),顯示 class="dropDown" 的 div 元素。
js:
Vue.directive('outside-click', {
bind: function (el, binding, vnode) {
//定義點(diǎn)擊函數(shù)
function clickHandler(e) {
if (el.contains(e.target)) {//如果點(diǎn)擊區(qū)域在所在指令元素內(nèi)部,則直接返回
return false;
}
if (binding.expression) {//如果定義了表達(dá)式,則執(zhí)行表達(dá)式中的函數(shù)
binding.value(e);
}
}
el.vueOutsideClick = clickHandler;
document.addEventListener('click', clickHandler);//綁定到 document 的點(diǎn)擊事件
},
unbind: function (el, binding, vnode) {
document.removeEventListener('click', el.vueOutsideClick);//解綁
delete el.vueOutsideClick;//銷(xiāo)毀
}
});
var app = new Vue({
el: '#app',
data: {
isShow: false
},
methods: {
close: function () {
this.isShow = false;
}
}
});
bind 中:
- 首先在定義了點(diǎn)擊函數(shù),內(nèi)部邏輯為:如果點(diǎn)擊區(qū)域在所在指令元素內(nèi)部,則直接返回;如果定義了表達(dá)式,則執(zhí)行表達(dá)式中的函數(shù)(示例中是 close)。
- 這里用到了 contains 函數(shù), A.contains(B) 是判斷元素 A 是否包含了元素 B。
- 接著在 el 中定義了一個(gè)變量,用于存放剛才定義的點(diǎn)擊函數(shù)。bind() 與 unbind() 通過(guò) el 變量進(jìn)行參數(shù)傳遞。
- 然后綁定到 document 的點(diǎn)擊事件。
unbind 中:
- 解綁在 bind 中綁定的點(diǎn)擊事件。
- 銷(xiāo)毀該變量。
css:
[v-cloak] {
display: none;
}
.main {
width: 125px;
}
button {
display: block;
width: 100%;
color: #ffffff;
background-color: #99CC66;
border: 0;
padding: 6px;
text-align: center;
font-size: 12px;
border-radius: 4px;
cursor: pointer;
position: relative;
outline: none;
}
button:active {
top: 1px;
left: 1px;
}
.dropDown {
width: 100%;
height: 150px;
margin: 5px 0;
font-size: 12px;
background-color: #ffffff;
border-radius: 4px;
box-shadow: 0 1px 6px rgba(0, 0, 0, .2);
}
.dropDown p {
display: inline-block;
padding: 6px;
}
效果:

2 ESC 關(guān)閉
現(xiàn)在讓我們做個(gè)優(yōu)化,即在按下鍵盤(pán)的 ESC 鍵時(shí),也能關(guān)閉下拉菜單。
js:
bind: function (el, binding, vnode) {
function clickHandler(e) {
if (el.contains(e.target) && e.keyCode !== 27) {
return false;
}
...
}
...
document.addEventListener('keyup', clickHandler, false);//綁定鍵盤(pán)事件
},
unbind: function (el, binding, vnode) {
...
document.removeEventListener('keyup', el.vueOutsideClick);//解綁
...
}
在 bind 函數(shù)中,強(qiáng)化了判斷,如果點(diǎn)擊區(qū)域在所在指令元素內(nèi)部并且沒(méi)有按下 ESC 鍵時(shí),才直接返回。即按下 ESC 鍵時(shí),會(huì)執(zhí)行后續(xù)操作(執(zhí)行表達(dá)式中的函數(shù))。
在 unbind 函數(shù)中,也解綁了 keyup 事件。
效果:

3 ESC 為可選項(xiàng)
我們可以把 ESC 作為可選項(xiàng),而這可以通過(guò)修飾符來(lái)實(shí)現(xiàn)。
js:
bind: function (el, binding, vnode) {
//定義點(diǎn)擊函數(shù)
function clickHandler(e) {
//是否開(kāi)啟開(kāi)關(guān)
var escSwitch = (binding.modifiers && binding.modifiers.esc);
if (el.contains(e.target)) {//如果點(diǎn)擊區(qū)域在所在指令元素內(nèi)部時(shí)
if (escSwitch && e.keyCode === 27) {//帶有了 esc 修飾符,則讓程序往下執(zhí)行
} else {//直接返回
return false;
}
}
if (binding.expression) {//如果定義了表達(dá)式,則執(zhí)行表達(dá)式中的函數(shù)
binding.value(e);
}
}
...
}
我們通過(guò) binding.modifiers 來(lái)判斷自定義指令是否設(shè)置了 esc 修飾符,然后以此為基礎(chǔ),來(lái)編寫(xiě)后續(xù)邏輯。
html:
<div id="app" v-cloak>
<div class="main" v-outside-click.esc="close">
...
</div>
</div>
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
- Vue+Element UI實(shí)現(xiàn)下拉菜單的封裝
- vue+element實(shí)現(xiàn)下拉菜單并帶本地搜索功能示例詳解
- vue實(shí)現(xiàn)下拉菜單樹(shù)
- 解決vue動(dòng)態(tài)下拉菜單 有數(shù)據(jù)未反應(yīng)的問(wèn)題
- vue實(shí)現(xiàn)帶過(guò)渡效果的下拉菜單功能
- Vue.js下拉菜單組件使用方法詳解
- vue下拉菜單組件(含搜索)的實(shí)現(xiàn)代碼
- Vue實(shí)現(xiàn)自定義下拉菜單功能
- 詳解Vue用自定義指令完成一個(gè)下拉菜單(select組件)
- vue實(shí)現(xiàn)下拉菜單效果
相關(guān)文章
vue-cli項(xiàng)目使用mock數(shù)據(jù)的方法(借助express)
現(xiàn)如今前后端分離開(kāi)發(fā)越來(lái)越普遍,前端人員寫(xiě)好頁(yè)面后可以自己模擬一些數(shù)據(jù)進(jìn)行代碼測(cè)試,這樣就不必等后端接口,提高了我們開(kāi)發(fā)效率。今天就來(lái)分析下前端常用的mock數(shù)據(jù)的方式是如何實(shí)現(xiàn)的,需要的朋友可以參考下2019-04-04
Vue頁(yè)面加載后和刷新后的樣式差異問(wèn)題的解決方案
在使用?Vue?構(gòu)建的單頁(yè)面應(yīng)用中,頁(yè)面的樣式可能因?yàn)槁酚汕袚Q、組件加載順序或樣式的動(dòng)態(tài)加載導(dǎo)致樣式混亂,尤其是在復(fù)雜的應(yīng)用中,隨著頁(yè)面的切換或者刷新,按鈕、文字、布局等可能表現(xiàn)出不同的樣式,所以本文給大家介紹了Vue頁(yè)面加載后和刷新后的樣式差異問(wèn)題的解決方案2025-01-01
基于vue+echarts實(shí)現(xiàn)柱狀圖漸變色效果(每個(gè)柱子顏色不同)
前段時(shí)間的vue項(xiàng)目中用到了echarts柱狀圖,由于UI設(shè)計(jì)稿中要求使用漸變色,并且每個(gè)柱子的顏色不同,于是做了一番研究,現(xiàn)將我的實(shí)現(xiàn)方案分享如下2024-05-05
基于Vue+ECharts實(shí)現(xiàn)地圖展示與交互
這篇文章中,我將逐步介紹如何使用 Vue 和 ECharts 實(shí)現(xiàn)一個(gè)互動(dòng)式的地圖展示組件,其中支持返回上一層地圖、點(diǎn)擊查看不同城市的詳細(xì)信息,以及根據(jù)數(shù)據(jù)動(dòng)態(tài)展示不同的統(tǒng)計(jì)信息,感興趣的小伙伴跟著小編一起來(lái)看看吧2025-02-02
vue3+echarts實(shí)現(xiàn)漸變色環(huán)形圖過(guò)程
這篇文章主要介紹了vue3+echarts實(shí)現(xiàn)漸變色環(huán)形圖過(guò)程,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-08-08
Vue3+TypeScript實(shí)現(xiàn)遞歸菜單組件的完整實(shí)例
Vue.js中的遞歸組件是一個(gè)可以調(diào)用自己的組件,遞歸組件一般用于博客上顯示評(píng)論,形菜單或者嵌套菜單,文章主要給大家介紹了關(guān)于Vue3+TypeScript實(shí)現(xiàn)遞歸菜單組件的相關(guān)資料,需要的朋友可以參考下2021-08-08
Vue動(dòng)態(tài)構(gòu)建混合數(shù)據(jù)Treeselect選擇樹(shù)及巨樹(shù)問(wèn)題的解決
這篇文章主要介紹了Vue動(dòng)態(tài)構(gòu)建混合數(shù)據(jù)Treeselect選擇樹(shù)及巨樹(shù)問(wèn)題的解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-07-07

