Vue(篇幅二)

關(guān)于如何學(xué)習(xí)Vue,Vue的締造者尤雨溪前輩曾經(jīng)在知乎發(fā)表過(guò)一篇新手向:Vue 2.0 的建議學(xué)習(xí)順序
關(guān)于Vue其他知識(shí)介紹:篇幅一

5. 組件
  1. 創(chuàng)建(注冊(cè))組件
// 注冊(cè)(全局注冊(cè))
Vue.component('my-component', {
  template: '<div>A custom component!</div>'
})

組件在注冊(cè)之后,便可以在父實(shí)例的模塊中以自定義元素 <my-component></my-component> 的形式使用。要確保在初始化根實(shí)例之前注冊(cè)了組件:

<div id="example">
  <my-component></my-component>
</div>
//這里注冊(cè)
// 創(chuàng)建根實(shí)例
new Vue({
  el: '#example'
})
  1. data
    通過(guò)Vue構(gòu)造器創(chuàng)建的組件中,data屬性必須是函數(shù)。
Vue.component('my-app',{
 template: '<span>{{message}}</span>',
data: function(){
  return {
    message: 'hello'
  }
}
})
  1. Props
    子組件通過(guò)顯式地用props選項(xiàng)聲明它期待獲得的數(shù)據(jù)。
  2. 單向數(shù)據(jù)流
    prop 是單向綁定的:當(dāng)父組件的屬性變化時(shí),將傳導(dǎo)給子組件,但是不會(huì)反過(guò)來(lái)。每次父組件更新時(shí),子組件的所有 prop 都會(huì)更新為最新值。這意味著你不應(yīng)該在子組件內(nèi)部改變 prop。
    為什么我們會(huì)有修改 prop 中數(shù)據(jù)的沖動(dòng)呢?通常是這兩種原因:
    (1)prop 作為初始值傳入后,子組件想把它當(dāng)作局部數(shù)據(jù)來(lái)用;
    (2)prop 作為初始值傳入,由子組件處理成其它數(shù)據(jù)輸出。
    對(duì)這兩種原因,正確的應(yīng)對(duì)方式是:
    定義一個(gè)局部變量,并用 prop 的值初始化它:
props: ['initialCounter'],
data: function () {
  return { counter: this.initialCounter }
}

定義一個(gè)計(jì)算屬性,處理 prop 的值并返回。

props: ['size'],
computed: {
  normalizedSize: function () {
    return this.size.trim().toLowerCase()
  }
}
  1. Prop驗(yàn)證
    組件傳入的props可以進(jìn)行數(shù)據(jù)驗(yàn)證。要指定驗(yàn)證規(guī)格,需要用對(duì)象的形式,而不能用字符串?dāng)?shù)組。如:
Vue.component('my-app',{
  props: {
    propA: Number,//基本類型,null表示任何類型都行
    propB: [String,Number],//多種類型
    propC: {
      type: String,
      required: true //必須傳,且時(shí)字符串
    },
    propD: {
      type: Number,
      default: 100  // 數(shù)字,有默認(rèn)值
    },
    propE: {
      type: Object,
      default: function () {
        return { message: 'hello' }
      } // 數(shù)組/對(duì)象的默認(rèn)值應(yīng)當(dāng)由一個(gè)工廠函數(shù)返回
    }, 
    propF: {
      validator: function (value) {
        return value > 10  // 自定義驗(yàn)證函數(shù)
      }
    }
  }
})

注意:props會(huì)在組件實(shí)例創(chuàng)建之前進(jìn)行校驗(yàn),所以在 defaultvalidator 函數(shù)里,諸如datacomputedmethods 等實(shí)例屬性還無(wú)法使用。

  1. 自定義事件
    子組件通過(guò)自定義事件跟父組件通信。
    5.1 使用v-on綁定自定義事件
    每個(gè)Vue實(shí)例都實(shí)現(xiàn)了事件接口,即:
  • 使用 $on(eventName) 監(jiān)聽(tīng)事件
  • 使用 $emit(eventName) 觸發(fā)事件
    另外,父組件可以在使用子組件的地方直接用v-on來(lái)監(jiān)聽(tīng)子組件觸發(fā)的事件。
    注意:不能用 $on 偵聽(tīng)子組件釋放的事件,而必須在模板里直接用 v-on 綁定。例如:
<template>
<div id = "app">
   {{ count }}
  <child v-on:add="addcount"></child>
</div>
</template>
Vue.component('child',{
  template: '<button @click="increment">父組件count +1={{number}}</button>',
  data: function(){
    return {
      number : 0
    },
    method : {
      increment: function(){
        this.number++
        $.emit(add)
      }
    }
  }
})

new Vue({
  el: '#app',
  data: {
    count  : 0
  },
  methods: {
    addcount: function(){
      this.count++
    }
  }
})

以上代碼表示,點(diǎn)擊子組件按鈕時(shí)候,會(huì)觸發(fā)父組件的addcount() 事件
5.2 .sync修飾符
.sync作為一個(gè)編譯語(yǔ)法糖存在,他會(huì)被擴(kuò)展為一個(gè)自動(dòng)更新父組件屬性的v-on偵聽(tīng)器,如:
<comp :foo.sync="bar"></comp>
擴(kuò)展為:
<comp :foo="bar" @update:foo="val => var =val"></comp>
當(dāng)組件需要需要更新foo的值時(shí),它需要顯示地觸發(fā)一個(gè)更新事件:
this.$emit('update:foo',newValue)
5.3 非父子組件通信
有時(shí)候兩個(gè)組件也需要通信(非父子關(guān)系),簡(jiǎn)單的場(chǎng)景下,可以使用一個(gè)空的Vue實(shí)例作為中央事件總線:
var bus = new Vue()
bus.$emit('id-selected',1) //觸發(fā)組件A中的事件
bus.$on('id-selected',function(id){})//在組件B創(chuàng)建的鉤子中監(jiān)聽(tīng)事件
注意:復(fù)雜情況下,應(yīng)該考慮專門的狀態(tài)管理模式

  1. 使用插槽分發(fā)內(nèi)容
    為了讓組件可以結(jié)合,我們需要一種方式來(lái)混合組租間的內(nèi)容與子組件自己的模板,這個(gè)過(guò)程被稱為內(nèi)容分發(fā),Vue使用<slot>作為原始內(nèi)容的插槽。如下:
//app-layout 組件模板如下
<div class="container">
  <header>
    <slot name="header"></slot> //具名插槽
  </header>
  <main>
    <slot></slot> //默認(rèn)插槽
  </main>
  <footer>
    <slot name="footer"></slot>
  </footer>
</div>
//父組件模板:
<app-layout>
  <h1 slot="header">這里可能是一個(gè)頁(yè)面標(biāo)題</h1>
  <p>主要內(nèi)容的一個(gè)段落。</p>
  <p>另一個(gè)主要段落。</p>
  <p slot="footer">這里有一些聯(lián)系信息</p>
</app-layout>
渲染結(jié)果為:
<div class="container">
  <header>
    <h1>這里可能是一個(gè)頁(yè)面標(biāo)題</h1>
  </header>
  <main>
    <p>主要內(nèi)容的一個(gè)段落。</p>
    <p>另一個(gè)主要段落。</p>
  </main>
  <footer>
    <p>這里有一些聯(lián)系信息</p>
  </footer>
</div>

6.1 編譯作用域
分發(fā)內(nèi)容實(shí)在父作用域內(nèi)編譯。
6.2 作用域插槽
作用域插槽是一種特殊類型的插槽,用作一個(gè)替換已渲染元素的 (能被傳遞數(shù)據(jù)的) 可重用模板。
在子組件中,只需將數(shù)據(jù)傳遞到插槽,就像你將 props 傳遞給組件一樣:

<div class="child">
  <slot text="hello from child"></slot>
</div>

在父級(jí)中,具有特殊屬性 scope 的 <template> 元素必須存在,表示它是作用域插槽的模板。scope 的值對(duì)應(yīng)一個(gè)臨時(shí)變量名,此變量接收從子組件中傳遞的 props 對(duì)象:

<div class="parent">
  <child>
    <template scope="props">
      <span>hello from parent</span>
      <span>{{ props.text }}</span>
    </template>
  </child>
</div>

如果我們渲染以上結(jié)果,得到的輸出會(huì)是:

<div class="parent">
  <div class="child">
    <span>hello from parent</span>
    <span>hello from child</span>
  </div>
</div>

作用域插槽更具代表性的用例是列表組件,允許組件自定義應(yīng)該如何渲染列表每一項(xiàng):

<my-awesome-list :items="items">
  <!-- 作用域插槽也可以是具名的 -->
  <template slot="item" scope="props">
    <li class="my-fancy-item">{{ props.text }}</li>
  </template>
</my-awesome-list>

列表組件的模板:

<ul>
  <slot name="item"
    v-for="item in items"
    :text="item.text">
    <!-- 這里寫入備用內(nèi)容 -->
  </slot>
</ul>
  1. 子組件索引
    有時(shí)候需要在js中直接訪問(wèn)子組件,為此可以使用ref為子組件制定一個(gè)索引 ID,如下:
<div id="parent">
  <user-profile ref="profile"></user-profile>
</div>
var parent = new Vue({ el: '#parent' })
// 訪問(wèn)子組件
var child = parent.$refs.profile

注意:$refs 只在組件渲染完成后才填充,并且它是非響應(yīng)式的。它僅僅作為一個(gè)直接訪問(wèn)子組件的應(yīng)急方案——應(yīng)當(dāng)避免在模板或計(jì)算屬性中使用 $refs

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,345評(píng)論 6 531
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 98,494評(píng)論 3 416
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人,你說(shuō)我怎么就攤上這事。” “怎么了?”我有些...
    開(kāi)封第一講書人閱讀 176,283評(píng)論 0 374
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我,道長(zhǎng),這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書人閱讀 62,953評(píng)論 1 309
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 71,714評(píng)論 6 410
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書人閱讀 55,186評(píng)論 1 324
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼。 笑死,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,255評(píng)論 3 441
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書人閱讀 42,410評(píng)論 0 288
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 48,940評(píng)論 1 335
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 40,776評(píng)論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 42,976評(píng)論 1 369
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,518評(píng)論 5 359
  • 正文 年R本政府宣布,位于F島的核電站,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 44,210評(píng)論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 34,642評(píng)論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 35,878評(píng)論 1 286
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 51,654評(píng)論 3 391
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 47,958評(píng)論 2 373

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