[Vue] 自定義指令

自定義指令

Vue是不建議大家直接操作DOM的唤衫,但是Vue 允許你注冊自定義指令遥皂,實(shí)質(zhì)上是讓你教 Vue 一些新技巧:怎樣將數(shù)據(jù)的變化映射到 DOM 的行為畏陕。你可以使用Vue.directive(id, definition)的方法傳入指令id和定義對象來注冊一個全局自定義指令横媚。定義對象需要提供一些鉤子函數(shù)(可選的):

  • bind: 僅調(diào)用一次考赛,當(dāng)指令第一次綁定元素的時候。
  • update: 第一次是緊跟在 bind 之后調(diào)用今豆,獲得的參數(shù)是綁定的初始值侈沪;以后每當(dāng)綁定的值發(fā)生變化就會被調(diào)用,獲得新值與舊值兩個參數(shù)晚凿。
  • unbind:僅調(diào)用一次亭罪,當(dāng)指令解綁元素的時候。
Vue.directive('my-directive', {
  bind: function () {
    // 做綁定的準(zhǔn)備工作
    // 比如添加事件監(jiān)聽器歼秽,或是其他只需要執(zhí)行一次的復(fù)雜操作
  },
  update: function (newValue, oldValue) {
    // 根據(jù)獲得的新值執(zhí)行對應(yīng)的更新
    // 對于初始值也會被調(diào)用一次
  },
  unbind: function () {
    // 做清理工作
    // 比如移除在 bind() 中添加的事件監(jiān)聽器
  }
})

一旦注冊好自定義指令应役,就可以在 Vue.js 模板中來使用它(需要添加 Vue.js 的指令前綴,默認(rèn)為 v-)

<div v-my-directive="someValue"></div>

如果只需要 update 函數(shù)燥筷,就可以只傳入一個函數(shù)箩祥,而不用傳定義對象。

Vue.directive('my-directive', function (value) {
  // 這個函數(shù)會被作為 update() 函數(shù)使用
})

所有的鉤子函數(shù)會被復(fù)制到實(shí)際的指令對象中肆氓,而這個指令對象將會是所有鉤子函數(shù)的this上下文環(huán)境袍祖。指令對象上暴露了一些有用的公開屬性。這些屬性是只讀的谢揪,不要修改它們蕉陋。你也可以給指令對象附加自定義的屬性捐凭,但是注意不要覆蓋已有的內(nèi)部屬性。

  • el: 指令綁定的元素
  • vm: 擁有該指令的上下文 ViewModel
  • expression: 指令的表達(dá)式凳鬓,不包括參數(shù)和過濾器
  • arg: 指令的參數(shù)
  • raw: 未被解析的原始表達(dá)式
  • name: 不帶前綴的指令名
//使用指令對象屬性
<html>
<head lang="en">
    <meta charset="UTF-8">
    <title></title>
    <script src="vue.min.js"></script>
</head>
<body>
<div id="demo" v-demo-directive="LightSlateGray: msg"></div>

<script>
    Vue.directive('demoDirective', {
        bind: function () {
            this.el.style.color = '#fff'
            this.el.style.backgroundColor = this.arg
        },
        update: function (value) {
            this.el.innerHTML =
                'name - ' + this.name + '<br>' +
                'raw - ' + this.raw + '<br>' +
                'expression - ' + this.expression + '<br>' +
                'argument - ' + this.arg + '<br>' +
                'value - ' + value
        }
    });
    var demo = new Vue({
        el: '#demo',
        data: {
            msg: 'hello!'
        }
    })

</script>
</body>
</html>

多重從句

同一個特性內(nèi)部茁肠,逗號分隔的多個從句將被綁定為多個指令實(shí)例。在下面的代碼中缩举,指令會被創(chuàng)建和調(diào)用兩次:

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

如果想要用單個指令實(shí)例處理多個參數(shù)垦梆,可以利用字面量對象作為表達(dá)式:

<div v-demo="{color: 'white', text: 'hello!'}"></div>
Vue.directive('demo', function (value) {
  console.log(value) // Object {color: 'white', text: 'hello!'}
})

字面指令

如果在創(chuàng)建自定義指令的時候傳入 isLiteral: true ,那么特性值就會被看成直接字符串仅孩,并被賦值給該指令的 expression托猩。字面指令不會試圖建立數(shù)據(jù)監(jiān)視。

<div v-literal-dir="foo"></div>
Vue.directive('literal-dir', {
  isLiteral: true,
  bind: function () {
    console.log(this.expression) // 'foo'
  }
})

動態(tài)字面指令

然而辽慕,在字面指令含有 Mustache 標(biāo)簽的情形下站刑,指令的行為如下:

  • 指令實(shí)例會有一個屬性,this._isDynamicLiteral被設(shè)為true鼻百;
  • 如果沒有提供update函數(shù),Mustache 表達(dá)式只會被求值一次摆尝,并將該值賦給this.expression温艇。不會對表達(dá)式進(jìn)行數(shù)據(jù)監(jiān)視。
  • 如果提供了update函數(shù)堕汞,指令將會為表達(dá)式建立一個數(shù)據(jù)監(jiān)視勺爱,并且在計算結(jié)果變化的時候調(diào)用update。

雙向指令

如果指令想向 Vue 實(shí)例寫回數(shù)據(jù)讯检,你需要傳入 twoWay: true 琐鲁。該選項允許在指令中使用 this.set(value)

Vue.directive('example', {
  twoWay: true,
  bind: function () {
    this.handler = function () {
      // 把數(shù)據(jù)寫回 vm
      // 如果指令這樣綁定 v-example="a.b.c",
      // 這里將會給 `vm.a.b.c` 賦值
      this.set(this.el.value)
    }.bind(this)
    this.el.addEventListener('input', this.handler)
  },
  unbind: function () {
    this.el.removeEventListener('input', this.handler)
  }
})

內(nèi)聯(lián)語句

傳入 acceptStatement: true 可以讓自定義指令像 v-on 一樣接受內(nèi)聯(lián)語句:

<div v-my-directive="a++"></div>
Vue.directive('my-directive', {
  acceptStatement: true,
  update: function (fn) {
    // the passed in value is a function which when called,
    // will execute the "a++" statement in the owner vm's
    // scope.
  }
})

此功能比較容易搞出問題人灼,請謹(jǐn)慎使用围段,反正我是沒在開發(fā)中用過hhh。

深度數(shù)據(jù)觀察

如果希望在一個對象上使用自定義指令投放,并且當(dāng)對象內(nèi)部嵌套的屬性發(fā)生變化時也能夠觸發(fā)指令的 update 函數(shù)奈泪,那么你就要在指令的定義中傳入 deep: true

<div v-my-directive="obj"></div>
Vue.directive('my-directive', {
  deep: true,
  update: function (obj) {
    // 當(dāng) obj 內(nèi)部嵌套的屬性變化時也會調(diào)用此函數(shù)
  }
})

元素指令

有時候灸芳,我們可能想要我們的指令可以以自定義元素的形式被使用涝桅,而不是作為一個特性。元素指令可以看做是一個輕量的自定義組件烙样》胨欤可以像下面這樣注冊一個自定義的元素指令:

Vue.elementDirective('my-directive', {
  // 和普通指令的 API 一致
  bind: function () {
    // 對 this.el 進(jìn)行操作...
  }
})

使用時我們不再用這樣的寫法:

<div v-my-directive></div>

而是寫成:

<my-directive></my-directive>

元素指令不能接受參數(shù)或表達(dá)式,但是它可以讀取元素的特性谒获,來決定它的行為蛤肌。與通常的指令有個很大的不同壁却,元素指令是終結(jié)性的,這意味著寻定,一旦 Vue 遇到一個元素指令儒洛,它將跳過對該元素和其子元素的編譯 - 即只有該元素指令本身可以操作該元素及其子元素。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末狼速,一起剝皮案震驚了整個濱河市琅锻,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌向胡,老刑警劉巖恼蓬,帶你破解...
    沈念sama閱讀 211,743評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異僵芹,居然都是意外死亡处硬,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,296評論 3 385
  • 文/潘曉璐 我一進(jìn)店門拇派,熙熙樓的掌柜王于貴愁眉苦臉地迎上來荷辕,“玉大人,你說我怎么就攤上這事件豌〈剑” “怎么了?”我有些...
    開封第一講書人閱讀 157,285評論 0 348
  • 文/不壞的土叔 我叫張陵茧彤,是天一觀的道長骡显。 經(jīng)常有香客問我,道長曾掂,這世上最難降的妖魔是什么惫谤? 我笑而不...
    開封第一講書人閱讀 56,485評論 1 283
  • 正文 為了忘掉前任,我火速辦了婚禮珠洗,結(jié)果婚禮上溜歪,老公的妹妹穿的比我還像新娘。我一直安慰自己许蓖,他們只是感情好痹愚,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,581評論 6 386
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著蛔糯,像睡著了一般拯腮。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上蚁飒,一...
    開封第一講書人閱讀 49,821評論 1 290
  • 那天动壤,我揣著相機(jī)與錄音,去河邊找鬼淮逻。 笑死琼懊,一個胖子當(dāng)著我的面吹牛阁簸,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播哼丈,決...
    沈念sama閱讀 38,960評論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼启妹,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了醉旦?” 一聲冷哼從身側(cè)響起饶米,我...
    開封第一講書人閱讀 37,719評論 0 266
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎车胡,沒想到半個月后檬输,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,186評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡匈棘,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,516評論 2 327
  • 正文 我和宋清朗相戀三年丧慈,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片主卫。...
    茶點(diǎn)故事閱讀 38,650評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡逃默,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出簇搅,到底是詐尸還是另有隱情完域,我是刑警寧澤,帶...
    沈念sama閱讀 34,329評論 4 330
  • 正文 年R本政府宣布馍资,位于F島的核電站,受9級特大地震影響关噪,放射性物質(zhì)發(fā)生泄漏鸟蟹。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,936評論 3 313
  • 文/蒙蒙 一使兔、第九天 我趴在偏房一處隱蔽的房頂上張望建钥。 院中可真熱鬧,春花似錦虐沥、人聲如沸熊经。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,757評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽镐依。三九已至,卻和暖如春天试,著一層夾襖步出監(jiān)牢的瞬間槐壳,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,991評論 1 266
  • 我被黑心中介騙來泰國打工喜每, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留务唐,地道東北人雳攘。 一個月前我還...
    沈念sama閱讀 46,370評論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像枫笛,于是被迫代替她去往敵國和親吨灭。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,527評論 2 349

推薦閱讀更多精彩內(nèi)容

  • Vue指令 Vue的指令以v-開頭刑巧,作用在HTML元素上喧兄,將指令綁定在元素上,給綁定的元素添加一些特殊行為海诲。 例如...
    syd192閱讀 1,293評論 0 9
  • 除了內(nèi)置的指令外繁莹,Vue 也允許注冊自定義指令。 vue用Vue.directive(id,definition)...
    G_石頭閱讀 418評論 0 0
  • ??除了默認(rèn)設(shè)置的核心指令( v-model 和 v-show )特幔,Vue 也允許注冊自定義指令咨演。在Vue里,代碼...
    小小的開發(fā)人員閱讀 10,745評論 1 1
  • vue官方文檔中介紹了兩種自定義指令的方法:全局自定義和局部自定義蚯斯。 全局自定義組件可以在main.js中直接注冊...
    Erric_Zhang閱讀 407評論 2 1
  • 最近經(jīng)常使用指令來實(shí)現(xiàn)一些功能薄风,覺得甚是好用。然而卻遇到一個問題:v-if和我自定義指令在同一個標(biāo)簽里使用的時候拍嵌,...
    墨子柚閱讀 1,671評論 0 0