怎么在Vue中通過自定義指令實現(xiàn)一個Select組件?針對這個問題,這篇文章詳細(xì)介紹了相對應(yīng)的分析和解答,希望可以幫助更多想解決這個問題的小伙伴找到更簡單易行的方法。
一、首先,我們簡單布局一下:
<template> <div class="select"> <div class="inner"> <div class="inputWrapper"> <input type="text" readonly placeholder="請選擇菜品"> <span class="iconfont icon-zhankaishangxia"></span> </div> <ul class="options"> <li v-for="(item, index) in options" :key="index">{{item.value}}</li> </ul> </div> </div> </template> ...... data() { return { options: [ { value: '西紅柿雞蛋' }, { value: '青椒抱雞蛋' }, { value: '回鍋肉' }, { value: '宮保雞丁' }, { value: '地三鮮' } ], } }
效果是這樣:
下面可供選擇的options用的是絕對定位;同時input設(shè)置了readonly,使input變的不可輸入,整體布局很簡單。
二、開始添加功能
接下來,我們要添加兩個功能:
點擊上面的input框,可以切換顯示下面的options
選擇options里的某個選項后讓它展示在input里,同時讓選項部分消失
這兩項目功能都挺簡單,先來完成第一個,點擊input框切換顯示options,借助v-show就好。
<div class="inputWrapper" @click="showOptions = !showOptions"> <input type="text" readonly placeholder="請選擇菜品"> <span class="iconfont icon-zhankaishangxia"></span> </div> <ul class="options" v-show="showOptions" v-show="showOptions"> //添加v-show <li v-for="(item, index) in options" :key="index">{{item.value}}</li> </ul> ...... data() { showOptions: false }
如上所示,在選項里添加 v-show="showOptions"
并將 showOptions 初始化為 false 。同時,在包裹 input 的 div 上添加 click 事件來回切換 showOptions 的布爾值。
效果如下:
第二個,點擊下面的選項,將被選擇的展示到input里,同時讓options消失,也不難。
<div class="inputWrapper" @click="showOptions = !showOptions"> <input type="text" readonly placeholder="請選擇菜品" :value="selected"> //這里用value綁定一個data值selected <span class="iconfont icon-zhankaishangxia"></span> </div> <ul class="options" v-show="showOptions"> <li v-for="(item, index) in options" :key="index" @click="choose(item.value)">{{item.value}}</li> </ul> ...... data() { return { ...... showOptions: false selected: '' } }, methods: { choose(value) { this.showOptions = false if (value !== this.selected) { this.selected = value } } }
邏輯很簡單,在input里用value綁定一個data值,點擊選擇某個選項后,將選項的內(nèi)容賦給這個data值即可,同時,隱藏整個選項內(nèi)容。
效果如下:
從上面的效果圖中可以看到,已經(jīng)可以正常選擇了,但是有一個問題,就是它選項內(nèi)容展示的時候,我們希望點擊其它空白的地方也可以讓選擇內(nèi)容隱藏,但是上面的代碼并沒有解決這個問題,接下來我們來用兩種辦法來解決它。
3、常規(guī)的DOM操作 VS Vue自定義指令
其實,實現(xiàn)這個功能并不難,只是要想解決它就需要操作DOM
<div class="inputWrapper" @click.stop="showOptions = !showOptions"> //注意這里的stop修飾器 <input type="text" readonly placeholder="請選擇菜品" :value="selected"> <span class="iconfont icon-zhankaishangxia"></span> </div> <ul class="options" v-show="showOptions"> <li v-for="(item, index) in options" :key="index" @click.stop="choose(item.value)">{{item.value}}</li> //還有這里的stop修飾器 </ul> ... data() { return { ...... showOptions: false } } mounted() { let that = this document.addEventListener('click', function() { that.showOptions = false }) }
上面的代碼有兩點:一個是在mounted后面給整個document添加了點擊事件,這樣在點擊時候就可以將options隱藏,但是,我們在點擊輸入框部分和選項內(nèi)容時,我們不希望它觸發(fā),而是讓它走我們之前寫好的邏輯,所以給兩個 click 事件都添加了 stop 修飾器來阻止冒泡,這樣,點擊到它們的時候就不會冒泡到 document 上面了。效果如下:
到這里基本功能都寫完了,可以通過添加 $emit 和 props 來進行數(shù)據(jù)傳遞,讓它更加通用些。但是最后關(guān)于點擊其它地方讓選項部分消失的功能,我們還可以再完善下,可以考慮使用Vue指令的方式實現(xiàn)。
關(guān)于Vue指令,官方文檔里有比較清楚的說明,如果不是特別明白可以點擊這里先看看!
關(guān)于Vue自定義指令,在這個例子中需要明白以下基本知識點:
它是用來操作DOM的,所以所有Vue指令都會掛在 template 里的某個元素上
它有4個鉤子函數(shù),一是 bind ,它在指令第一次綁定到元素上調(diào)用而且只調(diào)用一次,這個鉤子很重要,我們在這個例子里會用到;第二個是 inserted ,它在元素插入到父元素的時候調(diào)用,官方文檔里給了一個 v-focus 的例子就用到了它;第三個和第四個分別是 update 和 componentUpdated ,前者是在 vNode 更新時調(diào)用,后者是在更新完成后調(diào)用;最后是 unbind ,在指令和元素解綁時調(diào)用。
這4個鉤子函數(shù)可以 都至少可以傳3個參數(shù) ,第一是 el 就是被綁定指令的元素,第二個 binding , 它是個對象 ,而且 它的一些屬性特別有用 ,它的屬性包括 name , expression 和 value 等,當(dāng)然不只這三個,但是我們這個例子要用。舉個例子: 假如我寫一個自定義指令 v-example="test" ,而這個 test 是我在 methods 里寫的一個方法,那么就可以通過 binding.name 拿到 example 字符串,可以通過 binding.value 拿到 test 函數(shù)本身并且執(zhí)行。如果這里不明白沒關(guān)系接下來我們會說到。
如果仔細(xì)觀察,它們非常像 Vue 本身的生命周期鉤子函數(shù),只是它們是作用在指令上與元素的上的。從 bind 最開始綁定到最后 unbind 解綁完成了一個完整的周期。
好了,我們把之前 mounted 寫的DOM操作相關(guān)的東西都刪掉,開始動手寫一個自定義指令。
<ul class="options" v-show="showOptions" v-clickOut="test"> //這里使用了下面的自定義指令,并將一個test方法傳遞進去了 <li v-for="(item, index) in options" :key="index" @click.stop="choose(item.value)">{{item.value}}</li> </ul> ... methods: { ...... test() { //test函數(shù),它作為參數(shù)傳遞給了指令 console.log('這是一個測試函數(shù)') } }, directives: { //這里是自定義指令 clickOut: { // 這里是自定義的v-clickOut指令 bind: function(el, binding) { // bind鉤子函數(shù),當(dāng)它與元素綁定的時候就會執(zhí)行 console.log('el===>', el) console.log('binding.name===>', binding.name) console.log('binding.expression===>', binding.expression) console.log('binding.value===>', binding.value) } } }
上面的代碼都有清楚的注釋說明,我們自定義了一個 clickOut 的指令,并且把它掛到了一個元素上,而且給它傳了一個 test 方法,我們來看看 console.log 出的東西都是些啥。
從上面的圖片可以看出當(dāng)指令和元素綁定的時候即 bind 的時候,它會執(zhí)行bind函數(shù)獲得很多有用的東西,上面我們講了 bind 函數(shù)里有幾個重要的參數(shù),從打印出的結(jié)果里我們非常清楚地看到,el就是指令綁定的元素本身,binding是一個對象,它獲得了很多有用的東西,包括傳遞進來的函數(shù)。
明白了它的基本構(gòu)造,我們就來繼續(xù)完善這個指令。
<ul class="options" v-show="showOptions" v-clickOut="test"> <li v-for="(item, index) in options" :key="index" @click.stop="choose(item.value)">{{item.value}}</li> </ul> ... methods: { test() { this.showOptions = false } }, directives: { clickOut: { bind: function(el, binding) { document.addEventListener('click', function(e) { if (el.contains(e.target)) return false if (binding.expression) { binding.value() } }) } }
看下上面改寫過的代碼做了些啥? 說下邏輯:當(dāng)我們自定的 v-clickOut 與選項部分的ul元素綁定的時候,我們監(jiān)聽document的click事件,如果點擊的元素是被指令綁定的元素的子元素或是被綁定元素本身,那就什么都不做;如果不是,那就執(zhí)行傳遞進來的test函數(shù)。而test函數(shù)執(zhí)行的結(jié)果就是把選項部分隱藏。
邏輯很清楚。
當(dāng)然我們可以繼續(xù)完善它。我們給 document.addEventListener
了,也可以在 合適的時候 removeEventListener
,這個合適的時候就是 unbind 鉤子函數(shù)。
所以我們可以完善下:
...... directives : { clickOut: { bind: function(el, binding) { function handler(e) { if (el.contains(el.target)) return false if (binding.expression) { binding.value() } } el.handler = handler document.addEventListener('click', el.handler) }, unbind: function(el) { document.removeEventListener('click', el.handler) } } }
關(guān)于怎么在Vue中通過自定義指令實現(xiàn)一個Select組件問題的解答就分享到這里了,希望以上內(nèi)容可以對大家有一定的幫助,如果你還有很多疑惑沒有解開,可以關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道了解更多相關(guān)知識。
網(wǎng)頁標(biāo)題:怎么在Vue中通過自定義指令實現(xiàn)一個Select組件-創(chuàng)新互聯(lián)
標(biāo)題路徑:http://jinyejixie.com/article0/dsecio.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供網(wǎng)站收錄、網(wǎng)站建設(shè)、營銷型網(wǎng)站建設(shè)、關(guān)鍵詞優(yōu)化、網(wǎng)站策劃、移動網(wǎng)站建設(shè)
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)