在线观看不卡亚洲电影_亚洲妓女99综合网_91青青青亚洲娱乐在线观看_日韩无码高清综合久久

鍍金池/ 教程/ HTML/ 組件系統(tǒng)
過濾器
起步
自定義指令
事件監(jiān)聽
安裝
過渡效果
計算屬性
細(xì)節(jié)與最佳實踐
創(chuàng)建大型應(yīng)用
指令
常見問題
處理表單
自定義過濾器
組件系統(tǒng)
擴展 Vue
列表渲染

組件系統(tǒng)

使用組件

在 Vue.js 中,我們可以用 Vue 擴展出來的 ViewModel 子類當(dāng)做可復(fù)用的組件。這在概念上與 Web Components 非常相似,不同之處在于 Vue 的組件無需任何 polyfill。要創(chuàng)建一個組件,只需調(diào)用 Vue.extend() 來生成一個 Vue 的子類構(gòu)造函數(shù):

// 擴展 Vue 得到一個可復(fù)用的構(gòu)造函數(shù)
var MyComponent = Vue.extend({
  template: '<p>A custom component!</p>'
})

Vue 的構(gòu)造函數(shù)可接收的大部分選項都能在 Vue.extend() 中使用,不過也有兩個特例:datael。由于每個 Vue 的實例都應(yīng)該有自己的 $data$el,我們顯然不希望傳遞給 Vue.extend() 的值被所有通過這個構(gòu)造函數(shù)創(chuàng)建的實例所共享。因此如果要定義組件初始化默認(rèn)數(shù)據(jù)和元素的方式,應(yīng)該傳入一個函數(shù):

var ComponentWithDefaultData = Vue.extend({
  data: function () {
    return {
      title: 'Hello!'
    }
  }
})

接下來,就可以用 Vue.component() 來注冊這個構(gòu)造函數(shù)了:

// 把構(gòu)造函數(shù)注冊到 my-component 這個 id Vue.component('my-component', MyComponent)

為了更簡單,也可以直接傳入 option 對象來代替構(gòu)造函數(shù)。如果接收到的是一個對象,Vue.component() 會為你隱式調(diào)用 Vue.extend()

// 注意:該方法返回全局 Vue 對象,
// 而非注冊的構(gòu)造函數(shù)
Vue.component('my-component', {
  template: '<p>A custom component!</p>'
})

之后就能在父級實例的模板中使用注冊過的組件了 (務(wù)必在初始化根實例之前注冊組件) :

<!-- 父級模板 -->
<my-component></my-component>

渲染結(jié)果:

<p>A custom component!</p>

你沒有必要,也不應(yīng)該全局注冊所有組件。你可以限制一個組件僅對另一個組件及其后代可用,只要在另一個組件的 components 選項中傳入這個組件即可 (這種封裝形式同樣適用于其他資源,例如指令和過濾器) :

var Parent = Vue.extend({
  components: {
    child: {
      // child 只能被
      // Parent 及其后代組件使用
    }
  }
})

理解 Vue.extend()Vue.component() 的區(qū)別非常重要。由于 Vue 本身是一個構(gòu)造函數(shù),Vue.extend() 是一個類繼承方法。它用來創(chuàng)建一個 Vue 的子類并返回其構(gòu)造函數(shù)。而另一方面,Vue.component() 是一個類似 Vue.directive()Vue.filter() 的資源注冊方法。它作用是建立指定的構(gòu)造函數(shù)與 ID 字符串間的關(guān)系,從而讓 Vue.js 能在模板中使用它。直接向 Vue.component() 傳遞 options 時,它會在內(nèi)部調(diào)用 Vue.extend()

Vue.js 支持兩種不同風(fēng)格的調(diào)用組件的 API:命令式的基于構(gòu)造函數(shù)的 API,以及基于模板的聲明式的 Web Components 風(fēng)格 API。如果你感到困惑,想一下通過 new Image() 和通過 <img> 標(biāo)簽這兩種創(chuàng)建圖片元素的方式。它們都在各自的適用場景下發(fā)揮著作用,為了盡可能靈活,Vue.js 同時提供這兩種方式。

table 元素對能出現(xiàn)在其內(nèi)部的元素類型有限制,因此自定義元素會被提到外部而且無法正常渲染。在那種情況下你可以使用指令式組件語法: <tr v-component="my-component"></tr>。

數(shù)據(jù)流

通過 prop 傳遞數(shù)據(jù)

默認(rèn)情況下,組件有獨立作用域。這意味著你無法在子組件的模板中引用父級的數(shù)據(jù)。為了傳遞數(shù)據(jù)到擁有獨立作用域的子組件中,我們需要用到 prop

一個 “prop” 是指組件的數(shù)據(jù)對象上的一個預(yù)期會從父級組件取得的字段。一個子組件需要通過 prop 選項顯式聲明它希望獲得的 prop:

Vue.component('child', {
  // 聲明 prop
  props: ['msg'],
  // prop 可以在模板內(nèi)部被使用,
  // 也可以類似 `this.msg` 這樣來賦值
  template: '<span>{{msg}}</span>'
})

然后,我們可以像這樣向這個組件傳遞數(shù)據(jù):

<child msg="hello!"></child>

結(jié)果

  • hello!

駝峰命名 vs. 連字符命名

HTML 特性是大小寫不敏感的。當(dāng)駝峰式的 prop 名在 HTML 中作為特性名出現(xiàn)時,你需要用對應(yīng)的連字符(短橫)分隔形式代替:

Vue.component('child', {
  props: ['myMessage'],
  template: '<span>{{myMessage}}</span>'
})
<!-- 重要:使用連字符分隔的名稱! -->
<child my-message="hello!"></child>

動態(tài) prop

我們同樣能夠從父級向下傳遞動態(tài)數(shù)據(jù)。例如:

<div>
  <input v-model="parentMsg">
  <br>
  <child msg="{{parentMsg}}"></child>
</div>

結(jié)果

http://wiki.jikexueyuan.com/project/vue-js/images/8.png" alt="" />

暴露 $data 作為 prop 也是可行的。傳入的值必須是一個對象,它會被用來替換組件默認(rèn)的 $data 對象。

傳遞回調(diào)作為 prop

同樣可以向下傳遞一個方法或語句作為子組件的一個回調(diào)方法。借此可以進行聲明式的、解耦的父子通信:

Vue.component('parent', {
  // ...
  methods: {
    onChildLoaded: function (msg) {
      console.log(msg)
    }
  }
})
Vue.component('child', {
  // ...
  props: ['onLoad'],
  ready: function () {
    this.onLoad('message from child!')
  }
})
<!-- 父級模板 -->
<child on-load="{{onChildLoaded}}"></child>

prop 綁定類型

默認(rèn)情況下,所有 prop 都會在子級和父級的屬性之間建立一個單向向下傳遞的綁定關(guān)系:當(dāng)父級的屬性更新時,它將向下同步至子級,反之則不會。這種默認(rèn)設(shè)定是為了防止子級組件意外篡改父級的狀態(tài),那將導(dǎo)致難以推導(dǎo)應(yīng)用的數(shù)據(jù)流。不過也可以顯式指定一個雙向或者一次性的綁定:

對比這些語法:

<!-- 默認(rèn)情況下,單向綁定 -->
<child msg="{{parentMsg}}"></child>
`<!-- 顯式雙向綁定 -->
<child msg="{{@ parentMsg}}"></child>
`<!-- 顯示一次性綁定 -->
<child msg="{{* parentMsg}}"></child>

雙向綁定會反向同步子級的 msg 屬性到父級的 parentMsg 屬性。一次性綁定在完成之后不會在父級和子級之間同步未來發(fā)生的變化。

注意如果傳遞的 prop 值是對象或數(shù)組,將會是引用傳遞。在子級改動對象或數(shù)組將會影響到父級的狀態(tài),這種情況會無視你使用的綁定的類型。

prop 規(guī)則

組件可以對接收的 prop 聲明一定的規(guī)則限制。在開發(fā)給他人使用的組件時這會很有用,因為對 prop 的有效性檢驗可以看做是組件 API 的一部分,并且能保證用戶正確地使用了組件。與直接把 prop 定義成字符串不同,你需要使用包含驗證規(guī)則的對象:

Vue.component('example', {
  props: {
    // 基本類型檢查 (`null` 表示接受所有類型)
    onSomeEvent: Function,
    // 必需性檢查
    requiredProp: {
      type: String,
      required: true
    },
    // 指定默認(rèn)值
    propWithDefault: {
      type: Number,
      default: 100
    },
    // 對象或數(shù)組類型的默認(rèn)值
    // 應(yīng)該由工廠函數(shù)返回
    propWithObjectDefault: {
      type: Object,
      default: function () {
        return { msg: 'hello' }
      }
    },
    // 雙向 prop。
    // 如果綁定類型不匹配將拋出警告.
    twoWayProp: {
      twoWay: true
    },
    // 自定義驗證函數(shù)
    greaterThanTen: {
      validator: function (value) {
        return value > 10
      }
    }
  }
})

其中 type 可以是以下任一原生構(gòu)造函數(shù):

  • String
  • Number
  • Boolean
  • Function
  • Object
  • Array

另外,type 還可以是自定義構(gòu)造函數(shù),斷言將會是一個 instanceof 檢查。

如果 prop 檢驗不通過,Vue 會拒絕這次針對子組件的賦值,并且在使用開發(fā)版本時會拋出一個警告。

繼承父級作用域

如果有需要,你也可以使用 inherit: true 選項來讓子組件通過原型鏈繼承父級的全部屬性:

var parent = new Vue({
  data: {
    a: 1
  }
})
// $addChild() 是一個實例方法,
// 它允許你用代碼創(chuàng)建子實例。
var child = parent.$addChild({
  inherit: true,
  data: {
    b: 2
  }
})
console.log(child.a) // -> 1
console.log(child.b) // -> 2
parent.a = 3
console.log(child.a) // -> 3

這里有一點需要注意:由于 Vue 實例上的數(shù)據(jù)屬性都是 getter/setter,設(shè)置 child.a = 2 會直接改變 parent.a 的值,而非在子級創(chuàng)建一個新屬性遮蔽父級中的屬性:

child.a = 4
console.log(parent.a) // -> 4
console.log(child.hasOwnProperty('a')) // -> false

作用域注意事項

當(dāng)組件被用在父模板中時,例如:

<!-- 父模板 -->
<my-component v-show="active" v-on="click:onClick"></my-component>

這里的命令 (v-showv-on) 會在父作用域編譯,所以 activeonClick 的取值取決于父級。任何子模版中的命令和插值都會在子作用域中編譯。這樣使得上下級組件間更好地分離。

閱讀 組件作用域 了解更多細(xì)節(jié)。

組件生命周期

每一個組件,或者說 Vue 的實例,都有著自己的生命周期:它會被創(chuàng)建、編譯、插入、移除,最終銷毀。在這每一個時間點,實例都會觸發(fā)相應(yīng)的事件,而在創(chuàng)建實例或者定義組件時,我們可以傳入生命周期鉤子函數(shù)來響應(yīng)這些事件。例如:

var MyComponent = Vue.extend({
  created: function () {
    console.log('An instance of MyComponent has been created!')
  }
})

查閱 API 文檔中可用的 生命周期鉤子函數(shù)完整列表

動態(tài)組件

你可以使用內(nèi)置的 <component> 元素在組件間動態(tài)切換來實現(xiàn) “頁面切換”:

new Vue({
  el: 'body',
  data: {
    currentView: 'home'
  },
  components: {
    home: { /* ... */ },
    posts: { /* ... */ },
    archive: { /* ... */ }
  }
})
<component is="{{currentView}}">
  `<!-- 內(nèi)容隨 vm.currentview 一同改變! -->
</component>

如果希望被切換出去的組件保持存活,從而保留它的當(dāng)前狀態(tài)或者避免反復(fù)重新渲染,你可以加上 keep-alive 特性參數(shù):

<component is="{{currentView}}" keep-alive>
  `<!-- 不活躍的的組件會被緩存! -->
</component>

過渡控制

有兩個額外的特性參數(shù)能夠支持對需要渲染或過渡的組件進行高級控制。

wait-for 等待事件

等待即將進入的組件觸發(fā)該事件后再插入 DOM。這就允許你等待數(shù)據(jù)異步加載完成后再觸發(fā)過渡,避免顯示空白內(nèi)容。

這一特性可以用于靜態(tài)和動態(tài)組件。注意:對于動態(tài)組件,所有有待渲染的組件都必須通過 $emit 觸發(fā)指定事件,否則他們永遠(yuǎn)不會被插入。

示例

<!-- 靜態(tài)組件 -->
<my-component wait-for="data-loaded"></my-component>
`
`<!-- 動態(tài)組件 -->
<component is="{{view}}" wait-for="data-loaded"></component>

```// 組件定義 { // 獲取數(shù)據(jù)并在編譯完成鉤子函數(shù)中異步觸發(fā)事件。 // 這里jQuery只是用作演示。 compiled: function () { var self = this $.ajax({ // ... success: function (data) { self.$data = data self.$emit('data-loaded') } }) } }


### `transition-mode` 過渡模式

`transition-mode` 特性參數(shù)允許指定兩個動態(tài)組件之間的過渡應(yīng)如何進行。

默認(rèn)情況下,進入組件和退出組件的過渡是同時進行的。這個特性參數(shù)允許設(shè)置成另外兩種模式:

- `in-out`:先進后出;先執(zhí)行新組件過渡,當(dāng)前組件在新組件過渡結(jié)束后執(zhí)行過渡并退出。
- `out-in`:先出后進;當(dāng)前組件首先執(zhí)行過渡并退出,新組件在當(dāng)前組件過渡結(jié)束后執(zhí)行過渡并進入。

**示例**:

<component is="{{view}}" v-transition="fade" transition-mode="out-in">


## 列表與組件

對于一個對象數(shù)組,你可以把組件和 `v-repeat` 組合使用。這種場景下,對于數(shù)組中的每個對象,都以該對象為 `$data` 創(chuàng)建一個子組件,以指定組件作為構(gòu)造函數(shù)。

`<ul id="list-example">`
  `<user-profile v-repeat="users"></user-profile>`
`</ul>`

new Vue({ el: '#list-example', data: { users: [ { name: 'Chuck Norris', email: 'chuck@norris.com' }, { name: 'Bruce Lee', email: 'bruce@lee.com' } ] }, components: { 'user-profile': { template: '

  • {{name}} {{email}}
  • ' } } })

    
    **結(jié)果**:
    
    - Chuck Norris - chuck@norris.com
    - Bruce Lee - bruce@lee.com
    
    ### 在組件循環(huán)中使用標(biāo)識符
    
    在組件中標(biāo)識符語法同樣適用,并且被循環(huán)的數(shù)據(jù)會被設(shè)置成組件的一個屬性,以標(biāo)識符作為鍵名:
    
    
    >注意一旦組件跟 `v-repeat` 一同使用,同樣的作用域規(guī)則也會被應(yīng)用到該組件容器上的其他命令。結(jié)果就是,你在父級模板中將獲取不到 `$index`;只能在組件自身的模板中獲取。
    >
    >或者,你也可以通過循環(huán) `<template>` 來建立一個媒介作用域,但是大多數(shù)情況下在組件內(nèi)部使用 `$index` 是更好的實踐。
    
    ## 子組件引用
    
    某些情況下需要通過 JavaScript 訪問嵌套的子組件。要實現(xiàn)這種操作,需要使用 `v-ref` 為子組件分配一個 ID。例如:
    

    var parent = new Vue({ el: '#parent' }) // 訪問子組件 var child = parent.$.profile

    
    當(dāng) `v-ref` 與 `v-repeat` 一同使用時,會獲得一個與數(shù)據(jù)數(shù)組對應(yīng)的子組件數(shù)組。
    
    ## 事件系統(tǒng)
    
    雖然你可以直接訪問一個 Vue 實例的子級與父級,但是通過內(nèi)建的事件系統(tǒng)進行跨組件通訊更為便捷。這還能使你的代碼進一步解耦,變得更易于維護。一旦建立了上下級關(guān)系,就能使用組件的 **事件實例方法** 來分發(fā)和觸發(fā)事件。
    

    var parent = new Vue({ template: '

    ', created: function () { this.$on('child-created', function (child) { console.log('new child created: ') console.log(child) }) }, components: { child: { created: function () { this.$dispatch('child-created', this) } } } }).$mount()

    
    ## 私有資源
    
    有時一個組件需要使用類似命令、過濾器和子組件這樣的資源,但是又希望把這些資源封裝起來以便自己在別處復(fù)用。這一點可以用私有資源實例化選項來實現(xiàn)。私有資源只能被擁有該資源的組件及其繼承組件和子組件的實例訪問。
    

    // 全部5種類型的資源 var MyComponent = Vue.extend({ directives: { // “id : 定義”鍵值對,與處理全局方法的方式相同 'private-directive': function () { // ... } }, filters: { // ... }, components: { // ... }, partials: { // ... }, effects: { // ... } })

    
    >你可以通過設(shè)置 `Vue.config.strict = true` 阻止子組件訪問父組件的私有資源。
    
    又或者,可以用與全局資源注冊方法類似的鏈?zhǔn)?API 為現(xiàn)有組件構(gòu)造方法添加私有資源:
    

    MyComponent .directive('...', {}) .filter('...', function () {}) .component('...', {}) // ...

    
    ### 資源命名約定
    
    有些資源,諸如組件和指令,會以 HTML 特性或自定義 HTML 標(biāo)簽的方式出現(xiàn)在模板中。因為 HTML 特性名和標(biāo)簽名都是**大小寫不敏感**的,我們經(jīng)常需要用連字符(短橫)連接命名取代駝峰命名。**從 0.12.9 開始**,我們支持將資源進行駝峰命名,同時在模板里用連字符命名法使用它們。
    
    **示例**
    

    // in a component definition components: { // 用駝峰命名注冊組件 myComponent: { /... / } }

    上一篇:安裝下一篇:處理表單