話不多說先看效果,這個效果是用在真實項目中的實際效果哈:

指令是啥?
按照慣例,先請出官方的解釋:
指令 (Directives) 是帶有 v- 字首的特殊特性。指令特性的值預期是單個 JavaScript 表達式 (v-for 是例外情況,稍後我們再讨論)。指令的職責是,當表達式的值改變時,将其産生的連帶影響,響應式地作用于 DOM。
再按照慣例,大家 ( 假裝 ) 看不懂,然後我來舉個栗子解釋一番。。。好,還是不知所雲,本文結束 (
Ctrl + F4
) ,下一篇。
為了避免上述情況出現,就不解釋了。實際上官方提供了很多内置指令,如:
v-if
、
v-for
、
v-bind
and so on。每一個指令都有自己特定的功能。
自定義指令
顧名思義就是自己定義的指令啦,可以實作我們想要的功能。下面就實作一個 一鍵
Copy
的功能吧。
生命周期
首先簡單瞟一下指令的文法,每個指令都有自己的生命周期,看到生命周期,肯定會想到鈎子函數,沒錯,指令也提供了鈎子函數:
-
:指令第一次綁定到元素時調用,此鈎子隻會調用一次。在這裡可以進行一次性的初始化設定。bind
-
:被綁定元素插入父節點時調用 (僅保證父節點存在,但不一定已被插入文檔中)。inserted
-
:所在元件的 VNode 更新時調用,但是可能發生在其子 VNode 更新之前。指令的值可能發生了改變,也可能沒有。update
-
:指令所在元件的 VNode 及其子 VNode 全部更新後調用。componentUpdated
-
:隻調用一次,指令與元素解綁時調用。unbind
下面再簡單瞟一眼上述鈎子函數的參數哈:
-
:指令所綁定的元素,可以用來直接操作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
來了解更多詳情。VNode API
-
:上一個虛拟節點,僅在oldVnode
和update
鈎子中可用。componentUpdated
看起來還挺多的,不過别方,其實常用的就幾個。好了下面要開始表演了:
等等,還是再捋一下思路吧:
- 怎麼
:實際上浏覽器提供了原生 api,但是隻能copy
選中的值(就是滑鼠選中的那種)。copy
- 那怎麼用代碼實作選中的效果呢?這就要用到輸入控件(input、textarea…)了,該控件提供了選中的
,選中的就是目前控件的api
值。value
- 那思路就有了:
- 動态建立
标簽input
- 把要複制的值賦給
input.value
- 調用
選中api
input.value
- 最後調用
複制選中的值api
- 動态建立
- 首先建一個
檔案(v-copy.js)。定義一個對象。( 指令實際就是一個對象 )js
import { Message } from 'ant-design-vue'; const vCopy = { // 名字愛取啥取啥 /* bind 鈎子函數,第一次綁定時調用,可以在這裡做初始化設定 el: 作用的 dom 對象 value: 傳給指令的值,也就是我們要 copy 的值 */ bind(el, { value }) { el.$value = value; // 用一個全局屬性來存傳進來的值,因為這個值在别的鈎子函數裡還會用到 el.handler = () => { if (!el.$value) { // 值為空的時候,給出提示,我這裡的提示是用的 ant-design-vue 的提示,你們随意 Message.warning('無複制内容'); return; } // 動态建立 textarea 标簽 const textarea = document.createElement('textarea'); // 将該 textarea 設為 readonly 防止 iOS 下自動喚起鍵盤,同時将 textarea 移出可視區域 textarea.readOnly = 'readonly'; textarea.style.position = 'absolute'; textarea.style.left = '-9999px'; // 将要 copy 的值賦給 textarea 标簽的 value 屬性 textarea.value = el.$value; // 将 textarea 插入到 body 中 document.body.appendChild(textarea); // 選中值并複制 textarea.select(); textarea.setSelectionRange(0, textarea.value.length); const result = document.execCommand('Copy'); if (result) { Message.success('複制成功'); } document.body.removeChild(textarea); }; // 綁定點選事件,就是所謂的一鍵 copy 啦 el.addEventListener('click', el.handler); }, // 當傳進來的值更新的時候觸發 componentUpdated(el, { value }) { el.$value = value; }, // 指令與元素解綁的時候,移除事件綁定 unbind(el) { el.removeEventListener('click', el.handler); }, }; export default vCopy;
- 到這裡,一鍵
的功能就實作了,最後再說一嘴怎麼将自定義指令注冊到全局:再建立一個Copy
( directives.js )檔案來注冊所有的全局指令。js
import copy from './v-copy'; // 自定義指令 const directives = { copy, }; // 這種寫法可以批量注冊指令 export default { install(Vue) { Object.keys(directives).forEach((key) => { Vue.directive(key, directives[key]); }); }, };
- 最後,在
中這樣引入:main.js
import Vue from 'vue'; import Directives from './directives'; Vue.use(Directives);
- 最後的最後,說一下怎麼用吧。。
<template> <button v-copy="copyText">copy</button> </template> <script> export default { data() { return { copyText: '要 Copy 的内容', }; }, }; </script>
OK 全部搞完了,撒花。