vue自定義指令使用~以仿寫v-show和實現v-copy為例講解
highlight: a11y-dark theme: simplicity-green
vue自定義指令產生的背景
- 我們知道前端程式設計師,寫的各種程式碼,最終是要作用於頁面上的DOM元素的。比如用HTML固定好DOM的基礎結構,用CSS設定DOM的樣式,用JS去做一些DOM的互動。因為DOM元素相當於“物理層”,要呈現給使用者看的。DOM相當於積木一樣,我們去操作這個積木,最終“搭建”成各式各樣的效果出來。 > 所以一切花裡胡哨的前端框架都是,基於前端三件套HTML、CSS、JS封裝出來的
- 所以jQuery中就通過
$
符,直接操作DOM就挺方便的,方便是方便了,但是直接操作DOM會引起頁面的迴流重繪,又會略為有點浪費瀏覽器的效能,容易出現頁面卡頓的情況,造成使用者體驗不太好。 > 萬事皆有利弊,直接操作DOM,有時候,也可能,會是一個簡單方便快捷的選擇。 - 所以vue和react就閃亮登場了,用資料驅動的思想,並不是直接操作DOM,通過虛擬DOM做一個緩衝,虛擬DOM會蒐集誰需要操作DOM,操作了DOM的哪些東西,統一先記錄好,最終全部一塊操作DOM。有點像js文件碎片的感覺。這樣的話,瀏覽器效能就會優化提升不少。所以,vue中並不提倡直接操作DOM,因為有虛擬DOM在呢,你還直接操作真實DOM幹啥啊。用vue指令啊 > 虛擬DOM確實是個好東西,給大佬點贊。我們知道vue提供的內建指令很方便,能解決大多數的DOM操作問題,但是,並不能解決所有的問題。
- 所以某些情況下,vue內建指令不能滿足我們的需求,咋辦呢。當然Vue創始人也想到了這個問題,所以,就搞了vue自定義指令,封裝了一套鉤子函式和對應引數的規則、以供我們使用去,從而更方便解決相應問題 > vue自定義指令就是直接操作DOM了,某些場景下,vue自定義指令是一個很好的選擇
vue自定義指令的分類
vue自定義指令有兩種
- 1. 全域性自定義指令(需要全域性註冊)
- 2. 元件自定義指令(需要元件內部註冊)
以下案例一是後者,案例二是前者
自定義指令其實就是一個物件,物件身上有一些鉤子函式,自定義指令物件身上的鉤子函式和vue元件的生命週期鉤子函式類似,後續會通過案例闡述
一般使用全域性自定義指令會多一些,畢竟複用方便
vue自定義指令使用講解
案例一 el-input初始獲取焦點(元件自定義指令 )
這個案例其實官網的案例,這裡我們修改一下,更加便於我們理解之。
假設我們需要這樣一個效果:頁面載入完畢以後,el-input輸入框自動獲取焦點,類似開啟百度一下頁面以後,輸入框自動獲取焦點一樣。
```js
```
演示的話,直接複製貼上程式碼即可
案例二 仿寫v-show功能(全域性自定義指令)
效果圖如下
看了效果圖,功能其實和v-show沒啥區別,舉這樣一個例子是方便更加好理解vue自定義指令
第一步,新建utils資料夾中存放index.js檔案,此檔案用於書寫全域性自定義指令
js
// 引入vue並使用vue的directive方法去註冊一個自定義指令
import Vue from 'vue'
Vue.directive('showshow', { // 指令的名字叫做showshow
// bind函式一般用來做初始化資料,也可以繫結事件什麼的
bind(el, binding, vnode) {
console.log(el, binding.value, vnode);
// el引數是當前使用指令的元素,bind引數是指令繫結的資料,vnode是虛擬dom
const flag = binding.value // 找到元件中繫結的標識
if (flag == false) {
el.style.display = 'none'
} else {
el.style.display = 'inline-block'
}
},
// inserted函式是在元素插入dom節點呼叫
inserted(el, binding, vnode) { },
// update和componentUpdated都是更新使用,但是前者更加常用些,oldVnode引數只有在這兩個鉤子中才會有
componentUpdated(el, binding, vnode, oldVnode) { },
update(el, binding, vnode, oldVnode) {
const flag = binding.value
if (flag == false) {
el.style.display = 'none'
} else {
el.style.display = 'inline-block'
}
},
// unbind解綁時候使用,比如用來移除第一個bind函式中繫結的事件
unbind(el, binding, vnode) { }
});
第二步,在main.js中引入這個書寫全域性自定義指令的檔案(表示使用之)
```js import Vue from 'vue' import App from './App.vue' import router from "@/router/index.js" //引入路由表 import store from './store/index' // 引入vuex // ...
// 引入就可以使用全域性自定義指令啦 ^_^ import './views/utils/index.js'
let vvvue = new Vue({ render: h => h(App), router, store // 掛載上去 }).$mount('#app') ```
第三步,在元件中使用全域性自定義指令
```js
```
有的道友說,蛤?這不是多此一舉嘛?其實不是,因為還沒遇到特定的場景。上述兩個例子主要是學習自定義指令的思想。接下來我們舉一個小例子,點選文字一鍵複製功能。
案例三 實現v-copy自定義指令
效果圖
點選就複製成功了,然後在電腦的相應位置就可以執行 Ctrl V 就可以直接貼上這個點選的文字了
第一步,寫自定義指令程式碼
```js import Vue from 'vue' Vue.directive('copy', { // 指令的名字叫做v-copy // bind函式初始化 bind(el, binding, vnode) { }, // inserted函式是在元素插入dom節點呼叫 inserted(el, binding, vnode) { // el引數是當前使用指令的元素,bind引數是指令繫結的資料,vnode是虛擬dom // 將copyFn函式掛在el身上方便使用 el.copyFn = () => { console.log('點選的是哪個DOM', el); //建立選中範圍 var range = document.createRange();
// 選擇點選的這個dom
range.selectNode(el);
//移除剪下板中內容,不新增這個語句的話,在ie和Edge中複製不到
window.getSelection().removeAllRanges();
//將el中的文字內容複製到剪下板
window.getSelection().addRange(range);
// 開啟複製貼上功能
let flag = document.execCommand('copy');
// 需注意相容性問題
flag ? alert('複製成功,可以貼上啦') : alert('當前瀏覽器不支援一鍵複製功能,請手動複製貼上')
}
el.addEventListener('click', el.copyFn)
},
// update和componentUpdated都是更新使用,但是前者更加常用些
// oldVnode引數只有在這兩個鉤子中才會有,更新以後才會有更新前和更新後的DOM
componentUpdated(el, binding, vnode, oldVnode) {
console.log('componentUpdated');
},
update(el, binding, vnode, oldVnode) {
console.log('update');
},
// unbind解綁時候使用,比如用來移除第一個bind函式中繫結的事件
unbind(el, binding, vnode) {
el.removeEventListener('click', el.copyFn)
}
});
/* * 為了快速上手自定義指令鉤子,我們可以這樣簡單理解。 * * bind和inserted鉤子 --> 類似created和mounted鉤子 * componentUpdated和update鉤子 --> 類似updated鉤子 * unbind鉤子類似 --> destroyed鉤子 * * 具體順序大家可以拷貝程式碼執行以後列印看一下,這樣更加方便精準理解 * / ```
第二步,在.vue檔案中使用
```js
```
補充案例中知識
- Range物件:http://developer.mozilla.org/zh-CN/docs/Web/API/Document/createRange
- Selection物件:http://developer.mozilla.org/zh-CN/docs/Web/API/Window/getSelection
- execCommand方法:http://developer.mozilla.org/zh-CN/docs/Web/API/Document/execCommand
關於MDN說,execCommand方法將來可能被刪除的這個問題,思否上有一個回答挺好的,也順帶貼上:http://segmentfault.com/q/1010000022841994?utm_source=tag-newest
總結
在什麼時候需要用自定義指令?
當內建指令不夠用的時候,當需要做一些特殊的效果的時候,當需要對普通DOM元素進行底層操作的時候
自定義指令就是貼近原生js書寫方式,我們合理使用其鉤子函式以及相應引數,可以實現更加靈活的效果功能。畢竟vue雖然提供了很多的內建指令,方便我們直接使用,上手快,但是也是限制了程式設計師的一些發散思維。各有利弊,所以需要權衡 ^_^
- 什麼?後端要一次性返回我10萬條資料!且看我這8種方案機智應對!
- 效能優化之通俗易懂學習requestAnimationFrame和使用場景舉例
- 23個css動畫效果,持續更新中...
- elementui原始碼學習之仿寫一個el-message
- 專案優化之使用compression-webpack-plugin外掛開啟gzip壓縮,以vue為例
- 巧妙使用Vue.extend繼承元件實現el-table雙擊可編輯(不使用v-if和v-else)
- 通俗易懂講解並手寫一個vue資料雙向繫結案例
- vue中使用docx-preview外掛預覽word文件(後端express)
- react元件通訊方式之~圖解父子元件通訊和兄弟元件通訊pubsub-js
- 解決react警告:findDOMNode is deprecated in StrictMode. findDOMNode was passed an...
- vue自定義指令使用~以仿寫v-show和實現v-copy為例講解
- el-table表頭文字換行的三種方式
- elementUI時間日期選擇器更改小圖示的位置和icon
- 兩種方式解決頁面重新整理vuex中資料丟失問題(詳細講解)
- vue元件的遞迴自呼叫~程式碼思路分析
- el-tree樹元件的懶載入寫法步驟