從頭開(kāi)始學(xué)Vue

模版語(yǔ)法

不管是使用v-指令綁定attribute還是Mustache語(yǔ)法禽车,后面可以跟值或者js表達(dá)式婆排,如果是事件監(jiān)聽(tīng)后面可以跟函數(shù)或js語(yǔ)句巍糯,例如:

<button v-bind:disabled="isButtonDisabled">Button</button>
<a v-bind:href="isButtonDisabled ? url : ''">...</a>
{{ message.split('').reverse().join('') }}
<el-checkbox @change="getPort"></el-checkbox>
<el-checkbox @change="(val, $event) => getPort(val, event, 'check')"></el-checkbox>

動(dòng)態(tài)屬性

上面說(shuō)的是值是動(dòng)態(tài)的,從2.6.0開(kāi)始,新增屬性動(dòng)態(tài)

<a v-bind:[attributeName]="url"> ... </a>
<a :[attributeName]="url"> ... </a>
<a @[event]="doSomething"> ... </a>

Class和Style綁定

Class對(duì)象語(yǔ)法

<div v-bind:class="{ active: isActive }"></div>
<div class="static" v-bind:class="{ active: isActive, 'text-danger': hasError }"></div>
<div v-bind:class="classObject"></div>
data: {
  classObject: {
    active: true,
    'text-danger': false
  }
}
<div v-bind:class="classObject"></div>
computed: {
  classObject: function () {
    return {
      active: this.isActive && !this.error,
      'text-danger': this.error && this.error.type === 'fatal'
    }
  }
}
// 用于自定義組件
<my-component v-bind:class="{ active: isActive }"></my-component>

Class數(shù)組語(yǔ)法

<div v-bind:class="[{ active: isActive }, errorClass]"></div>
<div v-bind:class="[isActive ? activeClass : '', errorClass]"></div>
<div v-bind:class="[activeClass, errorClass]"></div>
data: {
  activeClass: 'active',
  errorClass: 'text-danger'
}

通過(guò)以上例子我們總結(jié)出如果是對(duì)象饶套,那么變量必須是布爾值,如果是數(shù)組垒探,那么變量必須是值或js表達(dá)式妓蛮。

Style對(duì)象語(yǔ)法

<div v-bind:style="{ color: activeColor, fontSize: fontSize + 'px' }"></div>
data: {
  activeColor: 'red',
  fontSize: 30
}
<div v-bind:style="styleObject"></div>
data: {
  styleObject: {
    color: 'red',
    fontSize: '13px'
  }
}

Style數(shù)組語(yǔ)法

<div v-bind:style="[baseStyles, overridingStyles]"></div>
  data () {
    return {
      baseStyles: {
        color: 'red'
      },
      overridingStyles: {
        fontSize: '70px'
      }
    }
  }

從上面我們可以看到如果是對(duì)象,變量就是值或js表達(dá)式圾叼,如果是數(shù)組內(nèi)部對(duì)象的變量同樣是值或js表達(dá)式蛤克。

列表渲染

<ul id="example-2">
  <li v-for="(item, index) in items" :key="item.message">
    {{ parentMessage }} - {{ index }} - {{ item.message }}
  </li>
</ul>

  data: {
    parentMessage: 'Parent',
    items: [
      { message: 'Foo' },
      { message: 'Bar' }
    ]
  }
<ul id="example-2">
  <li v-for="(item, index) of items" :key="item.message">
    {{ parentMessage }} - {{ index }} - {{ item.message }}
  </li>
</ul>

  data: {
    parentMessage: 'Parent',
    items: [
      { message: 'Foo' },
      { message: 'Bar' }
    ]
  }
<div v-for="(value, name, index) in object" :key="name">
  {{ index }}. {{ name }}: {{ value }}
</div>
  data: {
    object: {
      title: 'How to do lists in Vue',
      author: 'Jane Doe',
      publishedAt: '2016-04-10'
    }
  }

從上面例子中我們可以看出v-for可以遍歷數(shù)組也可以遍歷對(duì)象,遍歷數(shù)組最多兩個(gè)參數(shù)夷蚊,遍歷對(duì)象可以有三個(gè)參數(shù)构挤,in和of遍歷效果一樣,只不過(guò)of更接近js迭代器語(yǔ)法惕鼓。v-for的變量只能是值或js表達(dá)式筋现,比如從計(jì)算屬性、方法里面返回的值箱歧,也可以是整數(shù)例如v-for="n in 10"

在<template>上使用v-for

類(lèi)似于v-if矾飞,也可以利用帶有v-for的<template>來(lái)循環(huán)渲染一段包含多個(gè)元素的內(nèi)容。
比如:

<ul>
  <template v-for="item in items">
    <li>{{ item.msg }}</li>
    <li class="divider" role="presentation"></li>
  </template>
</ul>

v-for和v-if不能在同一個(gè)層級(jí)使用呀邢,但是可以跟v-show一起使用

事件處理

監(jiān)聽(tīng)事件

v-on指令監(jiān)聽(tīng)DOM事件洒沦,并在觸發(fā)時(shí)運(yùn)行一些js語(yǔ)句或函數(shù),直接把 JavaScript 代碼寫(xiě)在 v-on 指令中是不可行的
下面的例子是一個(gè)特例:

<input onKeypress='javascript:if(event.keyCode==32)event.returnValue=false' />

可以寫(xiě)成下面這樣

<button v-on:click="counter += 1">Add 1</button>

$event變量

有時(shí)候需要在內(nèi)聯(lián)語(yǔ)句處理器中訪問(wèn)原始的DOM事件驼鹅,可以使用特殊變量$event把它傳入方法:
Vue模版

<div @click="submit">Submit1</div>
<div @click="submitFile('file', $event)">Submit2</div>
methods: {
   submit(event) {
      event.preventDefault()
   },
   submitFile(type, event) {
      // 現(xiàn)在我們可以訪問(wèn)原生事件對(duì)象
      if (event) {
           console.log(event)
           event.preventDefault()
      }
   }
}
// 正確寫(xiě)法
<div @change="(val, $event) => getPort(val, event, 'check')"></div>
<el-checkbox @change="(val, $event) => getPort(val, event, 'check')"></el-checkbox>
// 錯(cuò)誤寫(xiě)法
<div @change="function(val, $event) {getPort(val, event, 'check')}"></div>
methods: {
   getPort (val, event, type) {
      console.log(val, event, type)
   }
}

我們可以看到觸發(fā)方法如果沒(méi)有傳參微谓,那么調(diào)用方法第一個(gè)參數(shù)默認(rèn)是原生DOM對(duì)象森篷,也可以將原生DOM對(duì)象以參數(shù)的形式傳遞,

事件修飾符

<div @click="clickEvent">
     <a @click="test" >百度</a>   // 觸發(fā)test豺型、clickEvent仲智、自身事件
    <a @click.stop="test" >百度</a>   // 阻止事件冒泡,觸發(fā)test姻氨、自身事件
    <a @click.prevent="test" >百度</a>   // 阻止a標(biāo)簽?zāi)J(rèn)行為钓辆,觸發(fā)test、clickEvent
    <a @click.capture="test" >百度</a>   // 事件在捕獲階段觸發(fā)肴焊,觸發(fā)test前联、clickEvent、自身事件
    <a @click.self="test" >百度</a>   // 事件在目標(biāo)階段觸發(fā)娶眷,觸發(fā)test似嗤、clickEvent、自身事件
    <a @click.once="test" >百度</a>   // 點(diǎn)擊事件只會(huì)觸發(fā)一次届宠,觸發(fā)test烁落、clickEvent、自身事件豌注,test事件只會(huì)觸發(fā)一次伤塌,其他不影響,不像其它只能對(duì)原生的 DOM 事件起作用的修飾符轧铁,`.once` 修飾符還能被用到自定義組件事件上每聪,例如<base-checkbox v-model.once="lovingVue"></base-checkbox>
</div>

<div v-on:scroll.passive="onScroll">頁(yè)面滾動(dòng)</div> .passive 會(huì)告訴瀏覽器你不想阻止事件的默認(rèn)行為,.passive 修飾符尤其能夠提升移動(dòng)端的性能齿风。不要把 .passive 和 .prevent 一起使用药薯,因?yàn)?.prevent 將會(huì)被忽略,同時(shí)瀏覽器可能會(huì)向你展示一個(gè)警告聂宾。
methods: {
   clickEvent () {
      alert('點(diǎn)擊')
   },
   test () {
      alert('測(cè)試')
   }
}

組件基礎(chǔ)

data必須是一個(gè)函數(shù)

data不是直接提供一個(gè)對(duì)象果善,而必須是一個(gè)函數(shù),因此每個(gè)實(shí)例可以維護(hù)一份被返回對(duì)象的獨(dú)立拷貝系谐。

在組件上使用v-model

v-model是vue的語(yǔ)法糖

<input v-model="searchText">
// 等價(jià)于
<input  v-bind:value="searchText" v-on:input="searchText = $event.target.value">

當(dāng)用在組件上時(shí),v-model 則會(huì)這樣:

<custom-input v-bind:value="searchText" v-on:input="searchText = $event"></custom-input>
// 等價(jià)于
<custom-input v-model="searchText"></custom-input>

為了讓它正常工作讨跟,這個(gè)組件內(nèi)的 <input> 必須:

  • 將其 value attribute 綁定到一個(gè)名叫 value 的 prop 上
  • 在其 input 事件被觸發(fā)時(shí)纪他,將新的值通過(guò)自定義的 input 事件拋出
    寫(xiě)成代碼之后是這樣的:
Vue.component('custom-input', {
  props: ['value'],
  template: `
    <input
      v-bind:value="value"
      v-on:input="$emit('input', $event.target.value)">
  `
})

Prop

Prop類(lèi)型

以字符串?dāng)?shù)組形式列出的 prop:

props: ['title', 'likes', 'isPublished', 'commentIds', 'author']

prop 指定的值類(lèi)型

props: { title: String, likes: Number, isPublished: Boolean, commentIds: Array, author: Object, callback: Function, contactsPromise: Promise // or any other constructor }

傳遞靜態(tài)或動(dòng)態(tài)Prop

// 包含該 prop 沒(méi)有值的情況在內(nèi),都意味著 `true`
<blog-post is-published></blog-post>
// 如果你想要將一個(gè)對(duì)象的所有 property 都作為 prop 傳入晾匠,你可以使用不帶參數(shù)的 v-bind
<blog-post v-bind="post"></blog-post>
// 等價(jià)于
<blog-post
  v-bind:id="post.id"
  v-bind:title="post.title">
</blog-post>

單向數(shù)據(jù)流

所有的 prop 都使得其父子 prop 之間形成了一個(gè)單向下行綁定:父級(jí) prop 的更新會(huì)向下流動(dòng)到子組件中茶袒,如果傳遞的是基本數(shù)據(jù)類(lèi)型,改變子組件的prop會(huì)報(bào)錯(cuò)凉馆,如果傳遞的是對(duì)象或數(shù)組 薪寓,改變子組件的prop父組件的值也會(huì)被改變亡资。
有兩種常見(jiàn)的試圖變更一個(gè)prop的情形:
1.這個(gè)prop用來(lái)傳遞一個(gè)初始值,這個(gè)子組件接下來(lái)希望將其作為一個(gè)本地的prop數(shù)據(jù)來(lái)使用向叉∽赌澹可以在data中將這個(gè)prop用作初始值:

props: ['initialCounter'],
data: function () {
  return {
    counter: this.initialCounter
  }
}

2.這個(gè)prop以一種原始的值傳入且需要進(jìn)行轉(zhuǎn)換。這時(shí)候最好使用計(jì)算屬性:

props: ['size'],
computed: {
  normalizedSize: function () {
    return this.size.trim().toLowerCase()
  }
}

Prop驗(yàn)證

我們可以為組件的prop指定驗(yàn)證要求母谎,如果需求沒(méi)有滿(mǎn)足則Vue會(huì)在瀏覽器中報(bào)錯(cuò)瘦黑。

Vue.component('my-component', {
  props: {
    // 基礎(chǔ)的類(lèi)型檢查 (`null` 和 `undefined` 會(huì)通過(guò)任何類(lèi)型驗(yàn)證)
    propA: Number,
    // 多個(gè)可能的類(lèi)型
    propB: [String, Number],
    // 必填的字符串
    propC: {
      type: String,
      required: true
    },
    // 帶有默認(rèn)值的數(shù)字
    propD: {
      type: Number,
      default: 100
    },
    // 帶有默認(rèn)值的對(duì)象
    propE: {
      type: Object,
      // 對(duì)象或數(shù)組默認(rèn)值必須從一個(gè)工廠函數(shù)獲取
      default: function () {
        return { message: 'hello' }
      }
    },
    // 自定義驗(yàn)證函數(shù)
    propF: {
      validator: function (value) {
        // 這個(gè)值必須匹配下列字符串中的一個(gè)
        return ['success', 'warning', 'danger'].indexOf(value) !== -1
      }
    }
  }
})

注意那些 prop 會(huì)在一個(gè)組件實(shí)例創(chuàng)建之前進(jìn)行驗(yàn)證,所以實(shí)例的 property (如 data奇唤、computed 等) 在 default 或 validator 函數(shù)中是不可用的幸斥。

非Prop的Attribute

一個(gè)非prop的attribute是指?jìng)飨蛞粋€(gè)組件,但是改組件并沒(méi)有相應(yīng)prop定義的attribute咬扇。

<bootstrap-date-input data-date-picker="activated"></bootstrap-date-input>

然后這個(gè) data-date-picker="activated" attribute 就會(huì)自動(dòng)添加到 <bootstrap-date-input> 的根元素上甲葬。

替換/合并已有的Attribute

想象一下 <bootstrap-date-input> 的模板是這樣的:

<input type="date" class="form-control">

為了給我們的日期選擇器插件定制一個(gè)主題,我們可能需要像這樣添加一個(gè)特別的類(lèi)名:

<bootstrap-date-input
  type="text"
  data-date-picker="activated"
  class="date-picker-theme-dark">
</bootstrap-date-input>

最終結(jié)果

<input type="text" class="form-control date-picker-theme-dark" data-date-picker="activated">

我們看到內(nèi)部模版的type被替換成外部傳入的懈贺,class被合并经窖。class和style會(huì)合并內(nèi)外的值,其他的屬性都會(huì)被替換成外部傳入的值隅居。

禁用Attribute繼承

inheritAttrs:默認(rèn)值為true钠至,默認(rèn)情況下父作用域不被子組件認(rèn)作props特性的屬性將會(huì)作為子組件根元素的屬性,inheritAttrs就是去掉這一默認(rèn)行為胎源,class和style除外棉钧。
$attrs:包含了父作用域中不作為prop被識(shí)別的屬性(class和style除外)。
inheritAttrs和$attrs可以實(shí)現(xiàn)跨組件通信涕蚤。

<template>
  <div>
    <p>我是父組件</p>
    <test name="tom" :age="12" :id="12345" class="child" style="color: red" />
  </div>
</template>

<script>
export default {
  components: {
    test: {
      template: `
      <div>
        <p>我是子組件</p>
        <test2 v-bind="$attrs" s1="sss" s2="sss" />
      </div>`,
      inheritAttrs: false,
      props: ["name"],
      created() {
        console.log(this.$attrs); // {age: 12, id: 12345}
      },
      components: {
        test2: {
          template: `<p>我是孫子組件</p>`,
          inheritAttrs: false,
          props: ["age", "s1"],
          created() {
            console.log(this.$attrs); // {s2: "sss", id: 12345}
          }
        }
      }
    }
  }
};
</script>

自定義組件的v-model

一個(gè)組件上的v-model默認(rèn)會(huì)利用名為value的prop和名為input的事件宪卿,但是像單選框、復(fù)選框等類(lèi)型的輸入控件可能會(huì)將value的attribute用于不用的目的万栅。model就是用來(lái)改變v-model默認(rèn)屬性和方法

Vue.component('base-checkbox', {
  model: {
    prop: 'checked',
    event: 'change'
  },
  props: {
    checked: Boolean
  },
  template: `
     <input
       type="checkbox"
       v-bind:checked="checked"
       v-on:change="$emit('change', $event.target.checked)">
  `
})

父組件

<base-checkbox v-model="lovingVue"></base-checkbox>

.sync修飾符

在有些情況下佑钾,我們可能需要對(duì)某些數(shù)據(jù)雙向綁定,父子組件數(shù)據(jù)同步烦粒,prop是單向數(shù)據(jù)流休溶,不建議直接改變prop,以往的做法是將數(shù)據(jù)傳遞給子組件扰她,子組件使用$emit觸發(fā)父組件的監(jiān)聽(tīng)方法重新賦值兽掰,現(xiàn)在這個(gè)方法有個(gè)語(yǔ)法糖.sync

<text-document v-bind:title="doc.title" v-on:update:title="doc.title = $event"></text-document>
// .sync簡(jiǎn)寫(xiě)
<text-document :title.sync="doc.title"></text-document>

子組件

<template>
  <button @click="changeTitle"></button>
</template>
export default {
  props: {
    title: String
  },
  methods: {
    changeTitle () {
      this.$emit('update:title', newTitle)
    }
  }
}

v-model和.sync

共同點(diǎn)
  • 只能跟變量,都不能跟表達(dá)式一起使用
  • 都可以實(shí)現(xiàn)數(shù)據(jù)的雙向綁定
不同點(diǎn)
  • v-model一個(gè)組件只能使用一個(gè)徒役,.sync一個(gè)組件可以使用多個(gè)
<text-document :title.sync="doc.title" :name.sync="doc.name"></text-document>
// 可以簡(jiǎn)寫(xiě)
<text-document :title.sync="doc"></text-document>

具體可參考:http://www.reibang.com/p/f0673a9eba3f

$listeners

包含了父作用域(不含.native修飾符)v-on事件監(jiān)聽(tīng)器孽尽。它可以通過(guò)v-on="$listeners"傳入內(nèi)部組件。它是一個(gè)對(duì)象忧勿,里面包含了作用在這個(gè)組件上的所有事件監(jiān)聽(tīng)器杉女,相當(dāng)于子組件繼承了父組件的事件瞻讽,可以實(shí)現(xiàn)跨組件傳遞方法。
father.vue組件

<template>
   <child :name="name" :age="age" :infoObj="infoObj" @updateInfo="updateInfo" @delInfo="delInfo" />
</template>

child.vue組件

<template>
    <grand-son @addInfo="addInfo" v-bind="$attrs" v-on="$listeners"  />
    // 通過(guò) $listeners 將父作用域中的事件熏挎,傳入 grandSon 組件速勇,使其可以獲取到 father 中的事件
</template>
<script>
    import GrandSon from '../components/grandSon.vue'
    export default {
        components: { GrandSon },
        created() {
            console.log(this.$listeners); // updateInfo: f, delInfo: f
        }
    }
</script>

grandSon.vue組件

<template>
    <div>
        {{ $attrs }} --- {{ $listeners }}
    <div>
</template>
<script>
    export default {
        created() {
            console.log(this.$listeners) // updateInfo: f, delInfo: f, addInfo: f
            this.$emit('updateInfo') // 可以觸發(fā) father 組件中的updateInfo函數(shù)
        }
    }
</script>

處理邊界情況

provide和inject

父子組件可以使用prop、$emit實(shí)現(xiàn)數(shù)據(jù)或方法傳遞婆瓜,但是針對(duì)嵌套多層組件這種情況快集,除了使用vuex還可以使用依賴(lài)注入,我們可以將依賴(lài)注入理解成大范圍有效的prop廉白,不過(guò)依賴(lài)注入不是響應(yīng)式的个初。

// 祖先元素
export default {
  name: "grandfather",
  provide(){
    return{
      foo:'halo'
    }
  },
}

//后代組件 注入foo
export default {
  inject:['foo'],
}

改成響應(yīng)式的,只需要傳遞的是對(duì)象即可

provide(){
  return{
    test:this.activeData
  }
},
data() {
  return {
    activeData:{name:'halo'},
  }
}
mounted(){
  setTimeout(()=>{
    this.activeData.name = 'world';
  },3000)
}

插槽

父級(jí)模版里的所有內(nèi)容都是在父級(jí)作用域中編譯的猴蹂;子模版里的所有內(nèi)容都是在子作用域中編譯的院溺。如果讓父組件中的插槽內(nèi)容訪問(wèn)子組件中數(shù)據(jù),就需要用到作用域插槽磅轻。綁定在slot元素上的attribute被稱(chēng)為插槽prop珍逸,在這個(gè)例子中,我們將所有插槽prop的對(duì)象命名為slotProps聋溜,也可以命名為其他名字谆膳。
父組件

<current-user>
    <template v-slot:default="slotProps">
         {{slotProps.user.firstName}}
    </template>
</current-user>

// 解構(gòu)插槽prop,跟js解構(gòu)賦值寫(xiě)法一樣
<current-user>
    <template v-slot:default="{{user}}">
         {{user.firstName}}
    </template>
</current-user>

子組件

<template>
  <section>
    <slot v-bind:user="user">{{user.lastName}}</slot>
  </section>
</template>

<slot></slot>這個(gè)是插槽撮躁,v-slot是對(duì)應(yīng)插槽的內(nèi)容漱病,但是必須添加在template標(biāo)簽上,只有一種情況除外把曼,就是被提供的內(nèi)容只有默認(rèn)插槽的時(shí)候杨帽,組件的標(biāo)簽才可以被當(dāng)作插槽的模版來(lái)使用,這一點(diǎn)和已經(jīng)廢棄的slot attribute不同嗤军。

<current-user v-slot:default="slotProps">
    {{slotProps.user.firstName}}
</current-user>

動(dòng)態(tài)插槽名

<base-layout>
  <template v-slot:[dynamicSlotName]>
    ...
  </template>
</base-layout>

具名插槽的縮寫(xiě)

跟v-on和v-bind一樣注盈,v-slot也有縮寫(xiě),v-slot替換為字符#叙赚,例如v-slot:header可以被重寫(xiě)為#header

<base-layout>
  <template #header>
    <h1>Here might be a page title</h1>
  </template>
  <template #footer>
    <p>Here's some contact info</p>
  </template>
</base-layout>

使用場(chǎng)景

  • 通過(guò)插槽可以讓用戶(hù)可以拓展組件老客,去更好地復(fù)用組件和對(duì)其做定制化處理
  • 如果父組件在使用到一個(gè)復(fù)用組件的時(shí)候,獲取這個(gè)組件在不同的地方有少量的更改震叮,如果去重寫(xiě)組件是一件不明智的事情
  • 通過(guò)slot插槽向組件內(nèi)部指定位置傳遞內(nèi)容沿量,完成這個(gè)復(fù)用組件在不同場(chǎng)景的應(yīng)用,比如布局組件冤荆、表格列、下拉選擇权纤、彈框顯示內(nèi)容等

自定義指令

除了核心功能默認(rèn)內(nèi)置的指令(v-model和v-show)钓简,Vue也允許注冊(cè)自定義指令乌妒。
一個(gè)指令定義對(duì)象可以提供如下幾個(gè)鉤子函數(shù)(均為可選):

  • bind:只調(diào)用一次,指令第一次綁定到元素時(shí)調(diào)用外邓。在這里可以進(jìn)行一次性初始化設(shè)置撤蚊。
  • inserted:被綁定元素插入父節(jié)點(diǎn)時(shí)調(diào)用
  • update:所在組件的VNode更新時(shí)調(diào)用,也可能在其子VNode更新之前調(diào)用
  • componentUpdated:指令所在組件VNode及其子VNode全部更新后調(diào)用
  • unbind:只調(diào)用一次损话,指令與元素解綁時(shí)調(diào)用

鉤子函數(shù)參數(shù)

  • el:指令所綁定的元素侦啸,可以用來(lái)直接操作DOM
  • binding:一個(gè)對(duì)象,包含以下property:
    1.name:指令名丧枪,不包括v-前綴
    2.value:指令的綁定值光涂,例如v-my-directive=“1+1”,綁定值為2
    3.oldValue:指令綁定的前一個(gè)值
    4.expression:字符串形式的指令表達(dá)式拧烦。例如v-my-directive=“1+1”忘闻,表達(dá)式為‘1+1’
    5.arg:傳給指令的參數(shù)。例如v-my-directive=“foo”中恋博,參數(shù)為‘foo’
    6.modifiers:一個(gè)包含修飾符的對(duì)象齐佳。例如:v-my-directive.foo.bar中,修飾符對(duì)象為{foo:true, bar: true}
  • vnode:Vue編譯生成的 虛擬節(jié)點(diǎn)
  • oldVnode:上一個(gè)虛擬節(jié)點(diǎn)

除了el之外债沮,其他參數(shù)都應(yīng)該是只讀的炼吴,切勿進(jìn)行修改。如果需要在鉤子之間共享數(shù)據(jù)疫衩,建議通過(guò)元素的dataset來(lái)進(jìn)行硅蹦。
這是一個(gè)自定義鉤子樣例:

<div id="hook-arguments-example" v-demo:foo.a.b="message"></div>
Vue.directive('demo', {
  bind: function (el, binding, vnode) {
    var s = JSON.stringify
    el.innerHTML =
      'name: '       + s(binding.name) + '<br>' +
      'value: '      + s(binding.value) + '<br>' +
      'expression: ' + s(binding.expression) + '<br>' +
      'argument: '   + s(binding.arg) + '<br>' +
      'modifiers: '  + s(binding.modifiers) + '<br>' +
      'vnode keys: ' + Object.keys(vnode).join(', ')
  }
})

new Vue({
  el: '#hook-arguments-example',
  data: {
    message: 'hello!'
  }
})
動(dòng)態(tài)指令參數(shù)

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

例如你想要?jiǎng)?chuàng)建一個(gè)自定義指令辐脖,用來(lái)通過(guò)固定布局將元素固定在頁(yè)面上。我們可以像這樣創(chuàng)建一個(gè)通過(guò)指令值來(lái)更新豎直位置像素值的自定義指令:

<div id="baseexample">
  <p>Scroll down the page</p>
  <p v-pin="200">Stick me 200px from the top of the page</p>
</div>
 Vue.directive('pin', {
  bind: function (el, binding, vnode) {
    el.style.position = 'fixed'
    el.style.top = binding.value + 'px'
  }
})

new Vue({
  el: '#baseexample'
})

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

<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>
Vue.directive('pin', {
  bind: function (el, binding, vnode) {
    el.style.position = 'fixed'
    var s = (binding.arg == 'left' ? 'left' : 'top')
    el.style[s] = binding.value + 'px'
  }
})

new Vue({
  el: '#dynamicexample',
  data: function () {
    return {
      direction: 'left'
    }
  }
})

函數(shù)簡(jiǎn)寫(xiě)

在很多時(shí)候幕庐,你可能想在 bind 和 update 時(shí)觸發(fā)相同行為久锥,而不關(guān)心其它的鉤子。比如這樣寫(xiě):

Vue.directive('color-swatch', function (el, binding) {
  el.style.backgroundColor = binding.value
})

對(duì)象字面量

如果指令需要多個(gè)值异剥,可以傳入一個(gè) JavaScript 對(duì)象字面量瑟由。記住,指令函數(shù)能夠接受所有合法的 JavaScript 表達(dá)式冤寿。

<div v-demo="{ color: 'white', text: 'hello!' }"></div>
Vue.directive('demo', function (el, binding) {
  console.log(binding.value.color) // => "white"
  console.log(binding.value.text)  // => "hello!"
})
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末歹苦,一起剝皮案震驚了整個(gè)濱河市青伤,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌殴瘦,老刑警劉巖狠角,帶你破解...
    沈念sama閱讀 207,248評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異蚪腋,居然都是意外死亡丰歌,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,681評(píng)論 2 381
  • 文/潘曉璐 我一進(jìn)店門(mén)屉凯,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)立帖,“玉大人,你說(shuō)我怎么就攤上這事神得±宓耄” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 153,443評(píng)論 0 344
  • 文/不壞的土叔 我叫張陵哩簿,是天一觀的道長(zhǎng)宵蕉。 經(jīng)常有香客問(wèn)我,道長(zhǎng)节榜,這世上最難降的妖魔是什么羡玛? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 55,475評(píng)論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮宗苍,結(jié)果婚禮上稼稿,老公的妹妹穿的比我還像新娘。我一直安慰自己讳窟,他們只是感情好让歼,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,458評(píng)論 5 374
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著丽啡,像睡著了一般谋右。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上补箍,一...
    開(kāi)封第一講書(shū)人閱讀 49,185評(píng)論 1 284
  • 那天改执,我揣著相機(jī)與錄音,去河邊找鬼坑雅。 笑死辈挂,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的裹粤。 我是一名探鬼主播终蒂,決...
    沈念sama閱讀 38,451評(píng)論 3 401
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了后豫?” 一聲冷哼從身側(cè)響起悉尾,我...
    開(kāi)封第一講書(shū)人閱讀 37,112評(píng)論 0 261
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎挫酿,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體愕难,經(jīng)...
    沈念sama閱讀 43,609評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡早龟,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,083評(píng)論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了猫缭。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片葱弟。...
    茶點(diǎn)故事閱讀 38,163評(píng)論 1 334
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖猜丹,靈堂內(nèi)的尸體忽然破棺而出芝加,到底是詐尸還是另有隱情,我是刑警寧澤射窒,帶...
    沈念sama閱讀 33,803評(píng)論 4 323
  • 正文 年R本政府宣布藏杖,位于F島的核電站,受9級(jí)特大地震影響脉顿,放射性物質(zhì)發(fā)生泄漏蝌麸。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,357評(píng)論 3 307
  • 文/蒙蒙 一艾疟、第九天 我趴在偏房一處隱蔽的房頂上張望来吩。 院中可真熱鬧,春花似錦蔽莱、人聲如沸弟疆。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,357評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)怠苔。三九已至,卻和暖如春正塌,著一層夾襖步出監(jiān)牢的瞬間嘀略,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,590評(píng)論 1 261
  • 我被黑心中介騙來(lái)泰國(guó)打工乓诽, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留帜羊,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 45,636評(píng)論 2 355
  • 正文 我出身青樓鸠天,卻偏偏與公主長(zhǎng)得像讼育,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,925評(píng)論 2 344