詳解Vue用自定義指令完成一個下拉菜單(select組件)
這次分享的是關(guān)于Vue自定義指令的使用方法,學(xué)習(xí)完基礎(chǔ)后我們再來實戰(zhàn)完成一個下拉列表,廢話不多說,直接上干貨
基本用法
//全局注冊 Vue.directive('my-directive', { // 指令選項 }) // 局部注冊 var app = new Vue({ el: '#app' directives: { 'my-directive': { // 指令選項 } })
相信對Vue比較熟悉的人看完都知道,directive的寫法與組件 基本類似,只是方法名由component改為了directive。上例只是注冊了自定義指令v-my-directive,還沒實現(xiàn)具體功能,下面具體介紹 自定義指令的各個選項。
指令定義函數(shù)提供了幾個鉤子函數(shù) (可選):
- bind:只調(diào)用一次,指令第一次綁定到元素時調(diào)用,用這個鉤子函數(shù)可以定義一個在綁定時執(zhí)行一次的初始化動作。
- inserted:被綁定元素插入父節(jié)點(diǎn)時調(diào)用 (父節(jié)點(diǎn)存在即可調(diào)用,不必存在于 document 中)。
- update:所在組件的 VNode 更新時調(diào)用,但是可能發(fā)生在其孩子的 VNode 更新之前。指令的值可能發(fā)生了改變也可能沒有。但是你可以通過比較更新前后的值來忽略不必要的模板更新 (詳細(xì)的鉤子函數(shù)參數(shù)見下)。
- componentUpdated:所在組件的 VNode 及其孩子的 VNode 全部更新時調(diào)用。
- unbind:只調(diào)用一次,指令與元素解綁時調(diào)用。
可根據(jù)需求在不同的鉤子函數(shù) 內(nèi)完成邏輯代碼,如下面v-focus,我們希望在元素插入父節(jié)點(diǎn)時就調(diào)用,那用到的最好的就是inserted了。示例代碼如下
// html部分 <div id="app" v-focus> // js部分 Vue.directive('focus', { // 當(dāng)綁定元素插入到 DOM 中。 inserted: function (el) { // 聚焦元素 el.focus() } })
效果如下圖所示
自定義指令 v-focus.png
可以看到,打開這個頁面,input輸入框就自動獲取焦點(diǎn)了,成為可輸入狀態(tài)。
每個鉤子函數(shù) 都可以有幾個參數(shù)可用,比如我們上面用到了el。它們 的含義如下:
- el:指令所綁定的元素,可以用來直接操作 DOM 。
- binding:一個對象,包含以下屬性:
- name:指令名,不包括 v-前綴。
- value:指令的綁定值,例如:v-my-directive="1 + 1", value 的值是 2。
- oldValue:指令綁定的前一個值,僅在 update和 componentUpdated鉤子中可用。無論值是否改變都可用。
- expression:綁定值的字符串形式。例如 v-my-directive="1 + 1" ,expression 的值是 "1 + 1"。
- arg:傳給指令的參數(shù)。例如 v-my-directive:foo,arg 的值是 "foo"。
- modifiers:一個包含修飾符的對象。例如:v-my-directive.foo.bar, 修飾符對象 modifiers 的值是 { foo: true, bar: true }。
- vnode:Vue 編譯生成的虛擬節(jié)點(diǎn),查閱 VNode API 了解更多詳情。
- oldVnode:上一個虛擬節(jié)點(diǎn),僅在 update和 componentUpdated鉤子中可用。
下面是結(jié)合了以上參數(shù) 的一些具體示例,代碼如下
// HTML部分 <div id="app" v-demo:msg.a.b="message"> <div v-text:msg.a.b="message"></div> </div> // JS部分 Vue.directive('demo', { bind: function (el, binding, vnode) { var s = JSON.stringify el.innerHTML = 'name: ' + binding.name + '<br>' + 'value: ' + binding.value + '<br>' + 'expression: ' + binding.expression + '<br>' + 'argument: ' + binding.arg + '<br>' + 'modifiers: ' + JSON.stringify(binding.modifiers).modifiers + '<br>' + 'vnode keys: ' + Object.keys(vnode).join(',') } }) new Vue({ el: '#app', data: { message: 'some text' } })
執(zhí)行后,<div>的內(nèi)容會使用innerHTML重置,結(jié)果為
name: "test" value: "some text" expression: "message" argument: "msg" modifiers: {"a":true,"b":true} vnode keys: tag, data, children, text, elm, ns, context, functionalContext, functionalOptions, functionalScopeId, key, componentOptions, componentInstance, parent, raw, isStatic, isRootInsert, isComment, isCloned, isOnce, asyncFactory, asyncMeta, isAsyncPlaceholder
在多數(shù)使用場景,我們會在bind鉤子里綁定一些事件,比如在document上用addEventListerer綁定,在unbind里有
removeEventListener 解綁,比較典型的示例就是讓這個元素隨著鼠標(biāo)拖拽。
如果需要更多個值,自定義指令也可以傳入一個JavaScript對象字面量, 只要是合法類型的JavaScript表達(dá)式都是可以的。示例代碼如下:
// HTML部分 <div id="app" v-demo:msg.a.b="message"> <div v-test="{msg: 'hello', name: 'Aresn'}"></div> </div> //JS部分 Vue.directive('test', { bind: function (el, binding, vnode) { console.log(binding.value.msg) console.log(binding.value.name) } }) var app = new Vue({ el: '#app' })
Vue 2.x很移除大量Vue 1.x自定義指令的配置。在使用自定義指令時,應(yīng)該充分解業(yè)務(wù)需求,因為很多時候你需要的可能并不是自定義指令,而是組件。
基礎(chǔ)的東西講完了,我們來根據(jù)directive提供的API來寫一個點(diǎn)擊外部區(qū)域可以讓其下拉列表消失的菜單
// HTML部分 <div id="app" v-clock> <div class="main" v-clickoutside="handleClose"> <button @click="show = !show">點(diǎn)擊顯示下拉菜單</button> <div class="dropdown" v-show="show"> <p>下拉框內(nèi)容,點(diǎn)擊外面區(qū)域可以關(guān)閉</p> </div> </div> // JS部分 var app = new Vue({ el: '#app', data: { show: false }, methods: { handleClose() { this.show = false; } } }) Vue.directive('clickoutside', { bind: function(el, binding, vode) { function documentHandler (e) { if (el.contains(e.target)) { return false } if (binding.expression) { binding.value(e) } } el.__vueClickOutSide__ = documentHandler document.addEventListener('click', documentHandler) }, unbind: function(el, binding) { document.removeEventListener('click', el.__vueClickOutSide__) delete el.__vueClickOutSide__ } })
要在document上綁定click事件,所以在bind鉤子內(nèi)聲明了一個函數(shù)documentHandler,并將它作為句柄定在document的click事件上。documentHandler函數(shù)做了兩個判斷,第一個是判斷點(diǎn)擊的區(qū)域是否是指令所在的元素內(nèi)部,如果是,就跑出函數(shù),不信下繼續(xù)執(zhí)行
contains方法是用來判斷元素A是否包含了元素 B,包含返回true,不包含返回false
// HTML <div id="parent"> 父元素 <div id="children">子元素</div> </div> // JS var a = doucment.getElemengById('parent') var b = doucment.getElemengById('children') console.log(A.contains(B)) // true console.log(B.contains(A)) // false
第二個判斷是當(dāng)前 的指令v-clickoutside有沒有寫表達(dá)式,在該自定義指令中,表達(dá) 式應(yīng)該是第一個函數(shù) ,在過濾了內(nèi)部元素后,點(diǎn)擊外面任何區(qū)域應(yīng)該招待用戶表達(dá) 式中的函數(shù) ,所以binding.value就用來執(zhí)行上下文methods中指定的函數(shù)的
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
Vue中computed和watch的區(qū)別小結(jié)
watch和computed都是以Vue的依賴追蹤機(jī)制為基礎(chǔ)的,當(dāng)某一個依賴型數(shù)據(jù)發(fā)生變化的時候,所有依賴這個數(shù)據(jù)的相關(guān)數(shù)據(jù)會自動發(fā)生變化,即自動調(diào)用相關(guān)的函數(shù),來實現(xiàn)數(shù)據(jù)的變動,這篇文章簡單介紹下Vue中computed和watch的區(qū)別異同,感興趣的朋友一起看看吧2022-12-12詳解Vue webapp項目通過HBulider打包原生APP
這篇文章主要介紹了詳解Vue webapp項目通過HBulider打包原生APP,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2018-06-06詳解Vue的computed(計算屬性)使用實例之TodoList
本篇文章主要介紹了詳解Vue的computed(計算屬性)使用實例之TodoList,具有一定的參考價值,有興趣的可以了解一下2017-08-08一文搞懂Vue3中toRef和toRefs函數(shù)的使用
這篇文章主要為大家介紹了Vue3中toRef和toRefs函數(shù)的使用方法,文中通過示例為大家進(jìn)行了詳細(xì)的講解,感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下2022-07-07