99re热这里只有精品视频,7777色鬼xxxx欧美色妇,国产成人精品一区二三区在线观看,内射爽无广熟女亚洲,精品人妻av一区二区三区

Vue 3.0 自定義指令

2022-03-07 09:44 更新

#簡介

除了核心功能默認內(nèi)置的指令 (v-modelv-show),Vue 也允許注冊自定義指令。注意,在 Vue2.0 中,代碼復(fù)用和抽象的主要形式是組件。然而,有的情況下,你仍然需要對普通 DOM 元素進行底層操作,這時候就會用到自定義指令。舉個聚焦輸入框的例子,如下:

點擊此處實現(xiàn)

當頁面加載時,該元素將獲得焦點 (注意:autofocus 在移動版 Safari 上不工作)。事實上,只要你在打開這個頁面后還沒點擊過任何內(nèi)容,這個輸入框就應(yīng)當還是處于聚焦狀態(tài)。此外,你可以單擊 Rerun 按鈕,輸入將被聚焦。

現(xiàn)在讓我們用指令來實現(xiàn)這個功能:

const app = Vue.createApp({})
// 注冊一個全局自定義指令 `v-focus`
app.directive('focus', {
  // 當被綁定的元素插入到 DOM 中時……
  mounted(el) {
    // Focus the element
    el.focus()
  }
})

如果想注冊局部指令,組件中也接受一個 directives 的選項:

directives: {
  focus: {
    // 指令的定義
    mounted(el) {
      el.focus()
    }
  }
}

然后你可以在模板中任何元素上使用新的 v-focus property,如下:

<input v-focus />

#鉤子函數(shù)

一個指令定義對象可以提供如下幾個鉤子函數(shù) (均為可選):

  • beforeMount:當指令第一次綁定到元素并且在掛載父組件之前調(diào)用。在這里你可以做一次性的初始化設(shè)置。
  • mounted:在掛載綁定元素的父組件時調(diào)用。
  • beforeUpdate:在更新包含組件的 VNode 之前調(diào)用。

提示

我們會在稍后討論渲染函數(shù)時介紹更多 VNodes 的細節(jié)。

  • updated:在包含組件的 VNode 及其子組件的 VNode 更新后調(diào)用。
  • beforeUnmount:在卸載綁定元素的父組件之前調(diào)用
  • unmounted:當指令與元素解除綁定且父組件已卸載時,只調(diào)用一次。

接下來我們來看一下在自定義指令 API 鉤子函數(shù)的參數(shù) (即 el、binding、vnodeprevNnode)

#動態(tài)指令參數(shù)

指令的參數(shù)可以是動態(tài)的。例如,在 v-mydirective:[argument]="value" 中,argument 參數(shù)可以根據(jù)組件實例數(shù)據(jù)進行更新!這使得自定義指令可以在應(yīng)用中被靈活使用。

例如你想要創(chuàng)建一個自定義指令,用來通過固定布局將元素固定在頁面上。我們可以像這樣創(chuàng)建一個通過指令值來更新豎直位置像素值的自定義指令:

<div id="dynamic-arguments-example" class="demo">
  <p>Scroll down the page</p>
  <p v-pin="200">Stick me 200px from the top of the page</p>
</div>

const app = Vue.createApp({})


app.directive('pin', {
  mounted(el, binding) {
    el.style.position = 'fixed'
    // binding.value is the value we pass to directive - in this case, it's 200
    el.style.top = binding.value + 'px'
  }
})


app.mount('#dynamic-arguments-example')

這會把該元素固定在距離頁面頂部 200 像素的位置。但如果場景是我們需要把元素固定在左側(cè)而不是頂部又該怎么辦呢?這時使用動態(tài)參數(shù)就可以非常方便地根據(jù)每個組件實例來進行更新。

<div id="dynamicexample">
  <h3>Scroll down inside this section ↓</h3>
  <p v-pin:[direction]="200">I am pinned onto the page at 200px to the left.</p>
</div>

const app = Vue.createApp({
  data() {
    return {
      direction: 'right'
    }
  }
})


app.directive('pin', {
  mounted(el, binding) {
    el.style.position = 'fixed'
    // binding.arg is an argument we pass to directive
    const s = binding.arg || 'top'
    el.style[s] = binding.value + 'px'
  }
})


app.mount('#dynamic-arguments-example')

結(jié)果:

點擊此處實現(xiàn)

我們的定制指令現(xiàn)在已經(jīng)足夠靈活,可以支持一些不同的用例。為了使其更具動態(tài)性,我們還可以允許修改綁定值。讓我們創(chuàng)建一個附加屬性 pinPadding,并將其綁定到 <input type="range">。

<div id="dynamicexample">
  <h2>Scroll down the page</h2>
  <input type="range" min="0" max="500" v-model="pinPadding">
  <p v-pin:[direction]="pinPadding">Stick me {{ pinPadding + 'px' }} from the {{ direction }} of the page</p>
</div>

const app = Vue.createApp({
  data() {
    return {
      direction: 'right',
      pinPadding: 200
    }
  }
})

讓我們擴展我們的指令邏輯來重新計算固定元件更新的距離。

app.directive('pin', {
  mounted(el, binding) {
    el.style.position = 'fixed'
    const s = binding.arg || 'top'
    el.style[s] = binding.value + 'px'
  },
  updated(el, binding) {
    const s = binding.arg || 'top'
    el.style[s] = binding.value + 'px'
  }
})

結(jié)果:

點擊此處實現(xiàn)

#函數(shù)簡寫

在很多時候,你可能想在 mountedupdated 時觸發(fā)相同行為,而不關(guān)心其它的鉤子。比如這樣寫:

app.directive('pin', (el, binding) => {
  el.style.position = 'fixed'
  const s = binding.arg || 'top'
  el.style[s] = binding.value + 'px'
})

#對象字面量

如果指令需要多個值,可以傳入一個 JavaScript 對象字面量。記住,指令函數(shù)能夠接受所有合法的 JavaScript 表達式。

<div v-demo="{ color: 'white', text: 'hello!' }"></div>

app.directive('demo', (el, binding) => {
  console.log(binding.value.color) // => "white"
  console.log(binding.value.text) // => "hello!"
})

#在組件中使用

在 3.0 中,有了片段支持,組件可能有多個根節(jié)點。如果在具有多個根節(jié)點的組件上使用自定義指令,則會產(chǎn)生問題。

要解釋自定義指令如何在 3.0 中的組件上工作的詳細信息,我們首先需要了解自定義指令在 3.0 中是如何編譯的。對于這樣的指令:

<div v-demo="test"></div>

將大概編譯成:

const vDemo = resolveDirective('demo')


return withDirectives(h('div'), [[vDemo, test]])

其中 vDemo 是用戶編寫的指令對象,其中包含 mountedupdated 等鉤子。

withDirectives 返回一個克隆的 VNode,其中用戶鉤子被包裝并作為 VNode 生命周期鉤子注入 (請參見渲染函數(shù)更多詳情):

{
  onVnodeMounted(vnode) {
    // call vDemo.mounted(...)
  }
}

因此,自定義指令作為 VNode 數(shù)據(jù)的一部分完全包含在內(nèi)。當在組件上使用自定義指令時,這些 onVnodeXXX 鉤子作為無關(guān)的 prop 傳遞給組件,并以 this.$attrs 結(jié)束

這也意味著可以像這樣在模板中直接掛接到元素的生命周期中,這在涉及到自定義指令時非常方便:

<div @vnodeMounted="myHook" />

這和 非 prop 的 attribute類似。因此,組件上自定義指令的規(guī)則將與其他無關(guān) attribute 相同:由子組件決定在哪里以及是否應(yīng)用它。當子組件在內(nèi)部元素上使用 v-bind="$attrs" 時,它也將應(yīng)用對其使用的任何自定義指令。

以上內(nèi)容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號