如今Vue佔據了國內前端市場的大壁江山,在前端求職過程中,Vue的相關面試題也是越來越多。之所以Vue如此火熱,很大部分原因就是它的漸進式、元件化、指令式等思想,讓普通開發人員非常好上手。【相關推薦:】
指令是一個Vue專案用的最多的東西之一了,今天我們就來講解Vue指令中的一個分支:自定義指令。
想要使用自定義指令,首先我們得搞清楚什麼是自定義指令?
自定義指令非常好理解,我們使用的v-for、v-if、v-model等等稱之為指令,也被稱之為Vue的內建指令。這些指令都是我們可以直接使用的。
為了更好的滿足需求,最大化的讓開發者個性化開發,Vue暴漏了自定義指令的API給我們,讓我們除了使用內建指令外,我們還可以自己定義指令,定義好後和內建指令的方式非常類似。
比如我們看面的程式碼:
<p v-pin="200">我是一段話</p>
上面那段程式碼中v-pin可能很多小夥伴不知道是什麼,看起來像是指令,但是有沒有遇到過。其實v-pin就是一個自定義指令,只是我們這兒省略註冊它的程式碼。
我們為了房間,直接使用Vue2.x的腳手架工具快速搭建一個專案。
搭建命令:
vue create 專案名稱
執行起來:
要想使用自定義指令,我們必須先提前把它註冊好,就好比我們的元件一樣,得先註冊,才能使用。
註冊指令也分為全域性註冊和區域性註冊,和全域性註冊元件和區域性註冊元件一個道理。全域性註冊的指令可以在任何元件中直接使用,區域性註冊的指令只能在註冊的地方使用。
3.1 全域性註冊
全域性註冊顧名思義,自定義指令註冊好後,在專案的所有元件內都可以直接使用。
Vue提供了一個directive方法給我們註冊自定義指令,我們在main.js中註冊一個全域性的自定義指令。
程式碼如下:
// src/main.js import Vue from "vue"; import App from "./App.vue"; Vue.config.productionTip = false; Vue.directive("resize", { bind() {}, inserted() {}, update() {}, componentUpdated() {}, unbind() {}, }); new Vue({ render: (h) => h(App), }).$mount("#app");
上段程式碼中我們就直接呼叫了Vue提供的directive方法來註冊全域性的自定義指令,該方法接收兩個引數:指令名稱、包含指令勾點函數的物件。
指令註冊完畢後,我們就可以在專案中任意元件中的元素上使用「v-指令名稱」的形式使用指令了。
需要注意的是,指令勾點函數不是必須的,大家可以把它與vue的生命週期勾點函數做類比,它們的作用就是用來讓指令在不同的過程中做不同的事情。
3.2 區域性註冊
通常來說,如果自定義指令不是每個元件都會用到的話,我們一般局註冊自定義指令就好了。
我們改造一下APP.vue檔案,在其內部註冊自定義指令,程式碼如下:
<script> export default { name: "App", components: {}, directives: { resize: { bind() {}, inserted() {}, update() {}, componentUpdated() {}, unbind() {}, }, }, }; </script>
如上所示,Vue提供了一個directives選項供我們註冊自定義指令,它與data、methods同級別,上段程式碼中我們註冊了一個名叫resize的自定義指令,該指令只允許在元件內部使用。
注意:全域性註冊指令使用的是directive,區域性註冊指令使用的是directives,很好理解,區域性指令一次性注意註冊很多個,全域性指令依次只能註冊一個。
上一節簡單介紹了區域性註冊自定義指令和全域性註冊自定義指令,可以看到指令裡面有幾個勾點函數,我們的操作邏輯主要在這幾個勾點函數當中,所以我們有必要介紹下這幾個勾點函數。
4.1 勾點函數介紹
bind:
只呼叫一次,指令第一次繫結到元素時呼叫。在這裡可以進行一次性的初始化設定。
inserted:
被繫結元素插入父節點時呼叫 (僅保證父節點存在,但不一定已被插入檔案中)。
update:
所在元件的 VNode 更新時呼叫,但是可能發生在其子 VNode 更新之前。指令的值可能發生了改變,也可能沒有。但是你可以通過比較更新前後的值來忽略不必要的模板更新
componentUpdated:
指令所在元件的 VNode及其子 VNode全部更新後呼叫。
unbind:
只呼叫一次,指令與元素解綁時呼叫。
上面5個就是自定義指令的全部勾點函數,每個勾點函數都是可選的,視情況而定。大家可以簡單理解勾點函數順序:指令繫結到元素時(bind)、元素插入時(inserted)、元件更新時(update)、元件更新後(componentUpdated)、指令與元素解綁時(unbind)。這些和元件的生命週期函數有點類似。
4.2 勾點函數引數介紹
為了方便我們的邏輯操作,每個勾點函數都會接收引數,我們可以用這些引數做我們想做的事。
el:
指令所繫結的元素,可以用來直接操作 DOM。
binding:
一個物件,包含以下屬性:
name
:指令名,不包括 v-
字首。value
:指令的繫結值,例如:v-my-directive="1 + 1"
中,繫結值為 2
。oldValue
:指令繫結的前一個值,僅在 update
和 componentUpdated
勾點中可用。無論值是否改變都可用。expression
:字串形式的指令表示式。例如 v-my-directive="1 + 1"
中,表示式為 "1 + 1"
。arg
:傳給指令的引數,可選。例如 v-my-directive:foo
中,引數為 "foo"
。modifiers
:一個包含修飾符的物件。例如:v-my-directive.foo.bar
中,修飾符物件為 { foo: true, bar: true }
。vnode:
Vue 編譯生成的虛擬節點。
oldVnode:
上一個虛擬節點,僅在
update
和componentUpdated
勾點中可用。
在使用的時候,el和binding引數是我們使用得最平凡的,有了這些引數,我們的操作就變得簡單起來。
上面兩節介紹瞭如何註冊自定義指令以及相關引數,接下來就該實戰了,我們在APPVue中定義一個自定義指令,先來驗證一下勾點函數的執行情況。
程式碼如下:
<template> <div id="app"> <img alt="Vue logo" src="./assets/logo.png" /> <div v-resize></div> </div> </template> <script> export default { name: "App", components: {}, directives: { resize: { bind() { console.log("bind") }, inserted() { console.log("inserted") }, update() { console.log("update") }, componentUpdated() { console.log("componentUpdated") }, unbind() { console.log("unbind") }, }, }, }; </script>
效果如下:
上面程式碼中我們將自定義指令resize繫結到了div元素上面,當我們重新整理頁面時,執行了自定義指令中的bind和inserted勾點函數,其餘函數均要元素有更新才會執行。
5.1 實現v-resize指令
需求背景:
在做資料大屏或者自適應開發的時候,我們通常需要根據瀏覽器視窗大小的變化重新渲染頁面,比如重新繪製echarts圖表等功能。
需求描述:
實現自定義指令v-resize指令,視窗大小發生變化時,實時列印最新的視窗寬高。
程式碼實現:
// src/APP.vue <template> <div id="app"> <h1>視窗寬度:{{ innerWidth }}</h1> <h1>視窗高度:{{ innerHeight }}</h1> <div style="height: 300px; width: 80%; background: blue" v-resize></div> </div> </template> <script> export default { name: "App", data() { return { innerHeight: window.innerHeight, innerWidth: window.innerWidth, }; }, components: {}, directives: { resize: { bind() { console.log("bind"); }, inserted(el, binding, vnode) { console.log("inserted"); console.log(el, binding); let that = vnode.context; // 監聽瀏覽器的resize事件 window.addEventListener("resize", () => { that.innerHeight = window.innerHeight; that.innerWidth = window.innerWidth; }); }, update() { console.log("VNode更新了"); }, componentUpdated() { console.log("componentUpdated"); }, unbind() { console.log("unbind"); window.removeEventListener("resize"); }, }, }, }; </script>
效果如下:
當我們更改瀏覽器視窗大小時,頁面上會實時列印出最新的高度和寬度,當然這兒只是一個最簡單的案例,實際專案中我們通常會在視窗大小發生變化後去呼叫自定義的一些方法。
5.2 指令傳參和傳值
我們使用v-bind、v-model等內建指令時,都是可以傳參和傳值的,我們自定義指令也一樣。
範例程式碼:
<template> <div id="app"> <h1>視窗寬度:{{ innerWidth }}</h1> <h1>視窗高度:{{ innerHeight }}</h1> <div style="height: 300px; width: 80%; background: blue" v-resize:[args]="value" ></div> </div> </template> <script> export default { name: "App", data() { return { innerHeight: window.innerHeight, innerWidth: window.innerWidth, args: "我是引數", value: "我是傳的值", }; }, components: {}, directives: { resize: { bind(el, binding) { console.log("bind"); console.log("值", binding.value); console.log("引數", binding.arg); }, }, }, }; </script>
效果如下:
args和value就是我們傳給指令的引數和值,需要注意的是value接收變數或者表示式,arg接收字串或者變數,具體解釋可以參上引數詳解那一節。
5.3 指令簡寫
很多時候我們不需要用到自定義指令中的所有勾點函數,常用的就那麼幾個,所以官方給我們提供了一種簡寫的方式。
程式碼如下:
resize(el, binding) { console.log("我是簡寫的自定義指令", binding.value); },
上面程式碼的寫法讓我們的指令變得很簡潔,上段程式碼的意思就是把bind和update勾點函數合二為一了,通常我們想要這兩個勾點函數做同樣的事的時候使用。
知道了自定義指令如何使用,我們可以擴充一下使用場景,加深一下大家對自定義指令的理解。
6.1 v-copy
實現一鍵複製文字內容,用於滑鼠右鍵貼上。
6.2 v-longpress
實現長按,使用者需要按下並按住按鈕幾秒鐘,觸發相應的事件。
6.3 v-debounce
防止按鈕在短時間內被多次點選,使用防抖函數限制規定時間內只能點選一次。
6.4 v-LazyLoad
實現一個圖片懶載入指令,只載入瀏覽器可見區域的圖片。
6.5 v-draggable
實現一個拖拽指令,可在頁面可視區域任意拖拽元素。
上面的一些自定義指令都是需求中非常常見的,對應的指令程式碼網上也有很多,但是我建議大家自己下去實踐一下。
自定義指令的語法規則和用法很簡單,複雜的是我們要用來解決什麼問題。在合適的場景下使用合適的解決辦法才是最重要的。
(學習視訊分享:、)
以上就是vue中什麼是自定義指令?怎麼使用?的詳細內容,更多請關注TW511.COM其它相關文章!