自定義指令 v-xxx 的 directive
上篇内容是關于 mixin 混入的一些操作, 也是關于代碼複用層面的, 本篇講自定義指令 directive 也是為了實作複用而設計的一些小功能啦.
先來看看, 如果不用 directive 的場景下, 如何進行代碼複用.
<!DOCTYPE html>
<html lang="en">
<head>
<title>不用 directive 時</title>
<script src="https://unpkg.com/vue@3"></script>
</head>
<body>
<div id="root"></div>
<script>
const app = Vue.createApp({
// 當頁面加載完就讓其自動獲得焦點
mounted () {
this.$refs.input1.focus()
this.$refs.input2.focus()
this.$refs.input3.focus()
},
template: `
<div>
<input ref="input1" />
<input ref="input2" />
<input ref="input3" />
</div>
`
})
const vm = app.mount('#root')
</script>
</body>
</html>
可以看到這裡的 this.$refs.input2.focus( ) 被重複調用了3次, 這種寫法是沒有能實作咱說的複用的. 而 derective 則就是為了将其封裝為一個指令而設計的啦.
全局指令 directive
先來一個直覺示範, 如上例我們自定義一個名為 focus 的全局指令, 功能是使其 dom 能獲得焦點.
<!DOCTYPE html>
<html lang="en">
<head>
<title>自定義全局指令</title>
<script src="https://unpkg.com/vue@3"></script>
</head>
<body>
<div id="root"></div>
<script>
const app = Vue.createApp({
template: `
<div>
<input ref="input1" v-focus />
</div>
`
})
// 自定義一個全局指令 focus, 作用是讓其 dom 獲得焦點
app.directive('focus', {
mounted (el) {
el.focus()
}
})
const vm = app.mount('#root')
</script>
</body>
</html>
全局指令即可通過 app.directive('xxx', { }) 來定義, 使用的使用直接在 dom 中通過 v-xxx 即可.
局部指令 directive
同局部元件, 局部 mixin 幾乎一樣的操作, 就是在 vue 之外寫一個對象, 然後通過 vue 中的某個屬性進行引入啦.
<!DOCTYPE html>
<html lang="en">
<head>
<title>自定義局部指令</title>
<script src="https://unpkg.com/vue@3"></script>
</head>
<body>
<div id="root"></div>
<script>
// 自定義局部指令
const myDirective = {
focus: {
mounted (el) {
el.focus()
}
}
}
const app = Vue.createApp({
directives:myDirective,
template: `
<div>
<input ref="input1" v-focus />
</div>
`
})
const vm = app.mount('#root')
</script>
</body>
</html>
需要注意這裡的引入寫法是鍵值對的方式哦, 感覺也是亂七八糟的:
directives:myDirective
當然關于指令的作用周期也可以是結合咱的8大生命周期函數如下:
- beforCreate, created: 在 vue 執行個體建立前, 後 的自動執行
- beforMount, mounted: 在 vue 元件渲染到頁面前, 後 的自動執行
- beforUpdate, updated: 在 data 資料變化前, 資料變化後并渲染後 的自動執行
- beforUnmount, unmounted: 在 vue 執行個體被銷毀 前, 後 的自動執行
自定義指令開發
這裡簡單來開發一個指令叫 v-position 實作元素的位置自定義效果.
<!DOCTYPE html>
<html lang="en">
<head>
<title>自定義指令開發</title>
<script src="https://unpkg.com/vue@3"></script>
<style>
.test {
position: absolute;
height: 100px;
background: orange;
}
</style>
</head>
<body>
<div id="root"></div>
<script>
const app = Vue.createApp({
data () {
return { num: 200 }
},
template: `
<div>
<div v-position="num" class="test">v-position 測試</div>
</div>
`
})
// 自定義全局指令 v-position 開發
app.directive('position', {
mounted (el, binding) {
el.style.top = binding.value + 'px'
},
updated (el, binding) {
el.style.top = binding.value + 'px'
}
})
const vm = app.mount('#root')
</script>
</body>
</html>
當隻有 mounted 和 updated 的時候可以有個簡寫如下:
app.directive('position', (el, binding) => {
el.style.top = binding.value + 'px'
})
結合之前我們對指令傳參的應用, 如 v-on:click = 'xxx' 的這種寫法, 也是可以将參數傳遞給到 binding 的 arg中的, 那這樣就可以對咱的這個 position 做 top, right, bottom, left 等參數啦.
<!DOCTYPE html>
<html lang="en">
<head>
<title>自定義指令開發</title>
<script src="https://unpkg.com/vue@3"></script>
<style>
.test {
position: absolute;
height: 100px;
background: orange;
}
</style>
</head>
<body>
<div id="root"></div>
<script>
const app = Vue.createApp({
data () {
return { num: 200 }
},
// v-position:xxx 這裡就可以傳參數啦
template: `
<div>
<div v-position:left="num" class="test">v-position 測試</div>
</div>
`
})
// 自定義全局指令 v-position 開發
app.directive('position', (el, binding) => {
// console.log('binding:', binding)
el.style[binding.arg] = binding.value + 'px'
})
const vm = app.mount('#root')
</script>
</body>
</html>
其實核心就是這個 binding 對象啦:
app.directive('position', (el, binding) => {
el.style[binding.arg] = binding.value + 'px'
})
小結
- 自定義指令 directive 結合生命周期函數可是實作代碼的複用
- 分為全局指令 app.directive( ) 和局部指令 directives: xxx 的形式
- 自定義開發即是對傳輸的 el 進行操作, 也可以通過 binding 對象進行傳參 arg