Vue.js破冰系列-6組件基礎(chǔ)(二)

1單文件組件

前面在vue.js破冰系列2中提到HTML模板有4中方式定義刃滓,分別是:在掛載點內(nèi)定義模板计呈、在template選項中定義模板茁彭、以x-template方式類型模板尉间,以及使用單文件組件(single-file components)的方式贪薪。這里我們在講解單文件組件。

單文件組件顧名思義霍弹,一個文件就是一個組件台丛,文件的擴展名為.vue防嗡。它的好處有很多他嫡,比如支持語法高亮近顷,css樣式等。最重要的是譬挚,有效的支持前端工程化以及關(guān)注點分離。前端工程化一般使用webpack等構(gòu)建工具,當(dāng)我們項目越來越大時统舀,使用單文件組件方便代碼的組織和維護(關(guān)注點分離)。

一個單文件組件.vue包含3個頂級語言塊<template>毛甲、<scirpt>叮叹、<style>,vue通過外部loader將這3個語言塊解析為一個組件選項對象闲勺。

一個單文件中只能包含一個template和一個script語言塊,但是可以包含多個style語言塊,在template標(biāo)簽中只能存在一個根節(jié)點谚中。格式如下:

//xxx.vue
<template></template>
<scirpt></scirpt>
<style></style>

2Props數(shù)據(jù)傳遞

2.1 props的定義

在注冊組件時,使用props選項定義組件的特征比搭,父組件通過這些特征向子組件傳遞數(shù)據(jù)抄囚,props可以接收數(shù)組和對象作為參數(shù),數(shù)組中包含string類型的值锅劝,如果要對屬性做更多的配置隅津,則需要使用object類型。

<template>
    <div>
    <!--props的引用-->
    <h4>{{message}}</h4>
  </div>
</template>
<script>
    export default{
    //數(shù)組的方式定義props
    //props:["message"],
    //對象的方式定義props
    props:{
      message:String,
    }
  }
</script>

props的數(shù)組寫法相對簡單,只需要定義屬性名即可协怒。如果要對屬性做一些約定則需要用到對象寫法孕暇,對象的鍵為屬性名隧哮,值可以是類型或一個屬性參數(shù)對象鉴竭。當(dāng)屬性值為類型時矢洲,表示對該屬性做類型約束袁滥,如果是屬性參數(shù)對象,則可以做更高級的約束:

<script>
    export default{
    props:{
      屬性名:{
        type:'屬性類型,String|Number|Boolean|Array|Object|Data|Function|Symbol|[可能的類型集合]',
        default:'默認(rèn)值彼硫,Object和Array類型的prop需要使用函數(shù)的方式(工廠函數(shù))返回,原理同組件中的data使用函數(shù)返回一樣',
        required:'是否為必填項掖肋,Boolean',
        validator:'驗證函數(shù)纫溃,返回Boolean值疗锐,如果返回false口芍,在控制臺會發(fā)出警告'
      }
    }
  }
</script>

可以看到props使用對象語法時,可以定義屬性的類型,默認(rèn)值踊赠,是否為必須已經(jīng)驗證信息等。

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

2.2 props的使用

html標(biāo)簽是不區(qū)分大小寫的烫堤,如果porps使用Pascal命名,Vue會將其轉(zhuǎn)換為kebab-case形式(我們在上一章提到過Pascal和kebab)立倍。

//子組件welcome.vue
<tempalte>
    <div>
    <span>你好 {{name}},上次登錄時間:{{lastLoginTime}}</span>
  </div>
</tempalte>
<script>
    export default{
    props:['name','lastLoginTime']
  }
</script>

父組件調(diào)用:

<tempalte>
    <div>
    <!-- 使用kebab形式調(diào)用子組件的屬性 -->
    <welcome :name="name" :last-login-time="time" />
  </div>
</tempalte>
<script>
  //導(dǎo)入
    import Welcome from 'welcome.vue'
  export default{
    //局部注冊
    components:{
      Welcome,
    },
    data(){
      return {
        name:'張三',
        time:'2019-09-17',
      }
    }
  }
</script>

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

子組件定義props君珠,父組件向子組件傳遞數(shù)據(jù)材部,當(dāng)父組件中的數(shù)據(jù)改變后摩窃,子組件會重新渲染账阻,數(shù)據(jù)從父向子流動叫做數(shù)據(jù)的單向流動。Vue不允許在子組件中改變props的值,如果強行修改挎扰,Vue會在控制臺中發(fā)出警告信息。

//子組件 child-component.vue
<template>
    <div>
    <h4>子組件中的title:{{title}}</h4>
    <button @click="changePropsHandle">修改Props</button>
  </div>
</template>
<script>
    export default{
    props:{
      title:String,
    },
    methods:{
      changePropsHandle(){
        this.title="子組件修改的title"
      }
    }
  }
</script>
<template>
    <div>
    <h4>父組件中的title:{{title}}</h4>
    <child :title="title" />
  </div>
</template>
<script>
  import Child from 'child-component.vue'
    export default{
    components:{
      Child
    },
    data(){
      return {
        title:"我是父組件中的title"
      }
    }
  }
</script>

這個例子在點擊子組件中的按鈕是會在控制臺中出現(xiàn)警告信息,原因是Vue中不允許直接修改props中的數(shù)據(jù)。如果要修改props煞抬,可以用data和computed替待革答。

//子組件 child-component.vue
<script>
    export default{
    props:{
      title:String,
    },
    //title作為初始值保存在localTilte中
    data(){
      return{
        loaclTitle:this.title,
      }
    },
    computed:{
      //將title轉(zhuǎn)換為另一個字符串曙强,
      computeTilte:function(){
        return "Hello"+this.title;
      }
    },
  }
</script>

注意:當(dāng)props的類型為Object或Array時途茫,在子組件中修改props的項時,會影響到父組件囊卜,原因可以參考其他語言的引用傳遞和值傳遞。

3組件間通信

組件之間的關(guān)系可以簡單的分為父子關(guān)系和非父子關(guān)系栅组。父子關(guān)系的組件,父組件直接調(diào)用子組件刃麸,比如使用子組件的props傳值給組件司浪,或者使用子組件的slot插槽將內(nèi)容分發(fā)到子組件。

3.1自定義事件

上面說了,子組件中不允許修改父組件傳遞的數(shù)據(jù)智政。有些情況下认罩,子組件需要修改父組件傳遞來的值续捂,這時,可以使用自定義事件通知父組件牙瓢,由父組件修改其數(shù)據(jù),間接的的達(dá)到子組件修改props矾克。

我們在vue.js破冰系列2中提到v-on事件監(jiān)聽的內(nèi)部指令,過程大致是這樣的胁附,父組件在子組件的標(biāo)簽中使用v-on監(jiān)聽事件,子組件中使用實例的內(nèi)部方法$emit觸發(fā)事件控妻,$emit方法的定義如下:

vm.$emit('evnetName',[...args])

vm表示的是實例,在具體的組件中郎哭,可以使用this指代。$emit的第1個參數(shù)為事件名稱夸研,他是一個字符串,vue不能自動轉(zhuǎn)換其大小寫陈惰,然而畦徘,使用v-on監(jiān)聽事件是在DOM標(biāo)簽中抬闯,我們知道DOM標(biāo)簽是不區(qū)分大小寫的,DOM會將全部標(biāo)簽轉(zhuǎn)換為小寫溶握,更進一步,要事件的觸發(fā)睡榆,$emit中事件名必須完全匹配v-on指令中的參數(shù)(事件名),所以vue建議在$emitv-on定義的事件名使用kebab樣式塘揣,或者也可以使用全小寫的方式。

<div id="app">
  <!--DOM 會將MyEvent轉(zhuǎn)換為小寫myevnet -->
  <child @MyEvent="myEventHandler"></child>
  <!-- 推薦使用kebab形式的事件名 -->
  <child @my-event="myEventHandler" />
</div>

<!--子組件-->
<script>
export default{
  methods:{
    btnClicked(){
      //該emit無效亲铡,因為v-on指令監(jiān)聽的事件名為myevent,而這里觸發(fā)的是MyEvent事件
      this.$emit('MyEvent');
      //該emit有效
      this.$emit('my-event');
    }
  }
}
</script>

$emit的第2個參數(shù)為不定參數(shù)奖蔓,表示的是該事件對應(yīng)處理函數(shù)的實參讹堤。關(guān)于自定義事件可以參考vue.js破冰系列2中的v-onv-model章節(jié)。

3.2中央事件總線

上面我們講了父子組件之間的通信疑务,他們是逐級傳遞的梗醇,也就是說父組件要和孫子組件通信,需要經(jīng)過子組件婴削,其他的還有兄弟組件之間的通信需要通過父組件。這種非父子組件之間的通信Vue推薦使用中央事件總線(bus)唉俗,原理是這樣的配椭,創(chuàng)建一個vue的空實例雹姊,使用vue實例方法$emit來觸發(fā)事件,使用vue實例方法$on來監(jiān)聽事件敦姻。

//創(chuàng)建一個vue的空實例歧杏,注意不能使用一個Object實例,因為我們要用到Vue實例的$emit和$on方法
var bus = new Vue();


//組件A注冊監(jiān)聽bus上事件
export ComA={
  created(){
    //注冊監(jiān)聽bus上的事件
    bus.$on('my-evnet',myEvnetHandler)
  },
    methods:{
    myEvnetHandler(arg1){
      //事件處理邏輯
    },
  }
}

//組件B
export ComB = {
  methods:{
    clicked(){
      //觸發(fā)bus上的my-event事件
      bus.$emit('my-event','Hello World!')
    }
  }
}

上面的例子演示了組件A和組件B之間的通信旺入。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末凯力,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子咐鹤,更是在濱河造成了極大的恐慌,老刑警劉巖聘殖,帶你破解...
    沈念sama閱讀 221,198評論 6 514
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件行瑞,死亡現(xiàn)場離奇詭異餐禁,居然都是意外死亡,警方通過查閱死者的電腦和手機氧吐,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,334評論 3 398
  • 文/潘曉璐 我一進店門末盔,熙熙樓的掌柜王于貴愁眉苦臉地迎上來陨舱,“玉大人,你說我怎么就攤上這事游盲÷福” “怎么了?”我有些...
    開封第一講書人閱讀 167,643評論 0 360
  • 文/不壞的土叔 我叫張陵然想,是天一觀的道長欣范。 經(jīng)常有香客問我,道長妨蛹,這世上最難降的妖魔是什么驳癌? 我笑而不...
    開封第一講書人閱讀 59,495評論 1 296
  • 正文 為了忘掉前任,我火速辦了婚禮表窘,結(jié)果婚禮上甜滨,老公的妹妹穿的比我還像新娘。我一直安慰自己昂验,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 68,502評論 6 397
  • 文/花漫 我一把揭開白布既琴。 她就那樣靜靜地躺著泡嘴,像睡著了一般。 火紅的嫁衣襯著肌膚如雪酌予。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,156評論 1 308
  • 那天松靡,我揣著相機與錄音建椰,去河邊找鬼。 笑死阅茶,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的蹦浦。 我是一名探鬼主播撞蜂,決...
    沈念sama閱讀 40,743評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼溉贿!你這毒婦竟也來了浦旱?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,659評論 0 276
  • 序言:老撾萬榮一對情侶失蹤宣蠕,失蹤者是張志新(化名)和其女友劉穎甥捺,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體皿曲,經(jīng)...
    沈念sama閱讀 46,200評論 1 319
  • 正文 獨居荒郊野嶺守林人離奇死亡吴侦,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,282評論 3 340
  • 正文 我和宋清朗相戀三年备韧,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片盯蝴。...
    茶點故事閱讀 40,424評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡捧挺,死狀恐怖尿瞭,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤捕发,帶...
    沈念sama閱讀 36,107評論 5 349
  • 正文 年R本政府宣布扎酷,位于F島的核電站遏匆,受9級特大地震影響法挨,放射性物質(zhì)發(fā)生泄漏凡纳。R本人自食惡果不足惜帝蒿,卻給世界環(huán)境...
    茶點故事閱讀 41,789評論 3 333
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望暴氏。 院中可真熱鬧巩掺,春花似錦、人聲如沸胖替。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,264評論 0 23
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽燃箭。三九已至,卻和暖如春敬拓,著一層夾襖步出監(jiān)牢的瞬間裙戏,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,390評論 1 271
  • 我被黑心中介騙來泰國打工营勤, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人葛作。 一個月前我還...
    沈念sama閱讀 48,798評論 3 376
  • 正文 我出身青樓赂蠢,卻偏偏與公主長得像,于是被迫代替她去往敵國和親客年。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,435評論 2 359

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

  • 一輪冷月清, 百般相思情绍傲。 年花上市時, 更待歸家急猎塞。 2014年1月22日于廣州天河
    桓舟子閱讀 149評論 0 1
  • 大家好铝量,歡迎大家來到美糖直播間银亲,今天講解一些清潔產(chǎn)品的分類:皂基和非皂基洗面奶 皂這個東西一直被很多關(guān)注潔面的...
    美糖化妝品分析0閱讀 6,430評論 0 1
  • 自由,簡單的兩個字拍谐,單看我們?nèi)绾味x馏段。 提到自由,我腦子里不禁想起兩部電影的鏡頭院喜,《勇敢的心》中主角的那一聲響徹云...
    金桔金閱讀 179評論 0 0