淺談Vue組件

1. 什么是組件

image.png

組件化就是把頁面拆分成一塊塊的唠梨,后期維護(hù)很簡(jiǎn)單
組件其實(shí)也是vue的實(shí)例洞坑,組件是可以反復(fù)使用的vue實(shí)例

  • 全局注冊(cè)組件
    就是把組件用Vue.component()注冊(cè)
<body>
  <div id="app">
    <!-- 3添履、使用組件 -->
    <my-header></my-header>
  </div>
</body>
<script src="vue.js"></script>
<script>
  // 全局注冊(cè)組件

  // 1、定義組件
  const MyHeader = { 
    template: `<header>頭部</header>`, 
  }

  // 2、全局注冊(cè)組件
  Vue.component('my-header', MyHeader)

  new Vue({
    el: '#app'
  })
</script>
  • 局部注冊(cè)組件
    就是把組件注冊(cè)在某個(gè)Vue實(shí)例中,用components:{}注冊(cè)
<body>
  <div id="app">
    <!-- 3双炕、使用組件 -->
    <my-header></my-header>
  </div>
</body>
<script src="vue.js"></script>
<script>
  // 局部注冊(cè)組件
  // 1、定義組件
  const MyHeader = { 
    template: `<header>頭部</header>`, 
  }
  new Vue({
    el: '#app',
    // 2撮抓、局部注冊(cè)組件
    components: {
      'my-header': MyHeader
    }
  })
</script>

2. 組件間的傳值

1. 父組件給子組件傳值
  • 父組件在調(diào)用子組件的地方需要添加一個(gè)屬性<my-content test = "測(cè)試"/>
  • 屬性的值”測(cè)試”就是你要傳遞給子組件的值
  • 在子組件定義的地方添加一個(gè)選項(xiàng)叫props:{}
  • 在props里放父組件傳遞的屬性名妇斤,也就是test就可以了,要注意的是丹拯,如果父組件傳遞給子組件的值是變量站超,Number或者布爾值就需要v-bind了!props內(nèi)存放值有兩種方式
  • 第一種:數(shù)組:props:[‘test’],之后就可以在子組件中使用了
  • 第二種:對(duì)象:props:{test:String}乖酬,這是寫法一用來驗(yàn)證傳遞數(shù)據(jù)的有效性死相,因?yàn)楦缸咏M件可能不是一個(gè)人寫的,如果數(shù)據(jù)類型不對(duì)剑刑,就會(huì)警告,可以及時(shí)調(diào)整双肤。
  • Props:{test:{type:String施掏,default:’默認(rèn)值’}}這是第二種寫法,既要驗(yàn)證數(shù)據(jù)類型也要設(shè)置默認(rèn)值茅糜,如果默認(rèn)值是對(duì)象或者函數(shù)七芭,則默認(rèn)值需要時(shí)一個(gè)有返回值的函數(shù)function () {return {}}
<body>
  <div id="app">
    <!-- <my-content test = "測(cè)試" :count="100" :flag="true" :tip="tip"/> -->
    <my-content :count="100" :flag="true" :tip="tip"/>
  </div>
</body>
<template id="content">
  <div>
    我這里是內(nèi)容區(qū)域 --- {{ test }} -- {{ count }} --- {{ flag }} --- {{ tip }}
  </div>
</template>
<script src="vue.js"></script>
<script>
  // 組件的名稱不能和模板的id同名
  const Content = {
    template: '#content',
    // props: ['test', 'count', 'flag', 'tip']
    // props: {
    //   test: String,
    //   count: Number,
    //   flag: Boolean,
    //   tip: String
    // }
    props: {
      test: {
        type: String,
        default: '測(cè)試數(shù)據(jù)了' // 如果父組件有這個(gè)屬性,那么就用父組件的值蔑赘,沒有這個(gè)屬性狸驳,直接使用這個(gè)值
      }
    }
  }
  new Vue({
    el: '#app',
    data: {
      tip: '提示'
    },
    components: {
      'my-content': Content
    }
  })
</script>
2. 子組件給父組件傳值
  • 子組件給父組件傳值時(shí),需要在父組件調(diào)用子組件的地方缩赛,給它綁定一個(gè)自定義事件耙箍,事件后面不要加(),例:<my-content @myevent="getData"/>
  • 在父組件選項(xiàng)methods中使用這個(gè)getData(val){}酥馍,其中參數(shù)val是默認(rèn)傳遞的辩昆,傳遞的就是子組件傳遞給父組件的值
  • 而在子組件如何傳遞呢?如下旨袒!
  • 在子組件種汁针。你可以通過生命周期的鉤子函數(shù)术辐,也可以是組件自己的事件去觸發(fā)父組件中的自定義事件myevent,使用固定語法emit來傳遞例:this.$emit('myevent', 10000)施无,這樣就把名字為myevent的參數(shù)名辉词,參數(shù)為10000的整個(gè)值廣播出去了,父組件只要接受myevent就可以了猾骡!
<body>
  <div id="app">
    <my-content @myevent="getData"/>
  </div>
</body>
<template id="content">
  <div>
    我這里是內(nèi)容區(qū)域
  </div>
</template>
<script src="vue.js"></script>
<script>
  /**
   * 父組件調(diào)用子組件的地方瑞躺,給他綁定一個(gè)自定義的事件, 事件不要加()
   *      <my-content @myevent="getData"/>
   * 在父組件選項(xiàng)methods中實(shí)現(xiàn)此事件,默認(rèn)參數(shù)為你將從子組件得到的值
   *    methods: {
          getData (val) { // val為從子組件中獲取到的值
            console.log(val)
          }
        },
      
      在子組件中卓练,可以是生命周期鉤子函數(shù)隘蝎,也可以是組件自己的事件 去 觸發(fā) 父組件中的自定義事件
          this.$emit('myevent', 10000)
   **/
  const Content = {
    template: '#content',
    mounted () {
      this.$emit('myevent', 10000)
    }
  }

  new Vue({
    el: '#app',
    data: {},
    methods: {
      getData (val) { // val為從子組件中獲取到的值
        console.log(val)
      }
    },
    components: {
      'my-content': Content
    }
  })
</script>
3. 非父子組件間傳值
  • 中央事件總線傳值const bus = new Vue()他就類似于一個(gè)快遞員的身份,需要確保數(shù)據(jù)有人接受的情況下襟企,就可以接受參數(shù)然后傳遞參數(shù)給需要的人嘱么!
  • 第一步:給需要這個(gè)參數(shù)的組件,定義bus.$on(‘參數(shù)名’,(val)={對(duì)收到的val做手腳})顽悼,一般寫在鉤子函數(shù)mounted中曼振。還要注意這里盡量使用箭頭函數(shù)避免this指向出現(xiàn)問題
  • 第二步:在確定了有接受的組件時(shí),就可以給要發(fā)送的組件設(shè)置了蔚龙!在發(fā)送參數(shù)的組建中的methods中添加一個(gè)自定義函數(shù)冰评,在里面定義bus.emit(‘參數(shù)名’,參數(shù))木羹,當(dāng)觸發(fā)了bus.emit時(shí)甲雅,像外廣播了一個(gè)參數(shù)名,然后另一個(gè)組件通過bus.$on接收到了參數(shù)名相同的參數(shù)值坑填,這樣就形成了非父子組件之間的值傳遞
<body>
  <div id="app">
    <my-list></my-list>
    <my-count></my-count>
  </div>
</body>
<template id="list">
  <ul>
    <li>111<button @click="add">+1</button></li>
    <li>222<button @click="add">+1</button></li>
    <li>333<button @click="add">+1</button></li>
    <li>444<button @click="add">+1</button></li>
    <li>555<button @click="add">+1</button></li>
  </ul>
</template>
<template id="count">
  <div>
    總量是:{{ num }}
  </div>
</template>
<script src="vue.js"></script>
<script>
  /**
   *  非父子組件傳值 ---- 兄弟組件傳值                   (郵差與信的故事)
   *  ------------------ 中央事件總線傳值  1. const bus = new Vue()
   * 
   *  先要確保 收信 的那個(gè)人是存在的
   *  然后寫信的人 寫信 給郵差
   *  郵差給送
   * 
   *  // 此處一定要注意this指向抛人,可以使用 => 
   *  2.在接收端通過 bus.$on('收信信號(hào)', function (val) {
   * 
   *  })
   * 
   *  3.在發(fā)送端通過 bus.$emit('收信信號(hào)', val)
   * */
const bus = new Vue()

const List = {
  template: '#list',
  methods: {
    add () {
      bus.$emit('count-event', 1)
    }
  }
}
const Count = {
  template: '#count',
  data () {
    return {
      num: 0
    }
  },
  mounted () { // 一般情況下接收都使用 生命周期鉤子函數(shù)
    bus.$on('count-event', (val) => { // 此處一定要注意this指向脐瑰,可以使用 =>
      console.log(val)
      this.num += val
    })
  }
}
new Vue({
  el: '#app',
  components: {
    'my-list': List,
    'my-count': Count
  }
})
</script>
4. 動(dòng)態(tài)組件

<component is="組件名稱"></component>

概述:讓當(dāng)前畫面在幾個(gè)組件中來回切換妖枚,類似你的手機(jī)屏幕,同一個(gè)屏幕可以打開不同的app顯示不同的內(nèi)容苍在。

使用:一般在頁面只寫一個(gè)類似于<component :is="tem"></component>的組件绝页,頁面有按鈕操控tem在data中的值,一旦改變值寂恬,在components中注冊(cè)名稱為改變得值得組件续誉,就可以在頁面中顯示出所對(duì)應(yīng)的組件了。

但是隨之的問題就出現(xiàn)了初肉,每次切換回前一個(gè)組件時(shí)屈芜,上次的操作就會(huì)被清除,所以需要用keep-alive把components包裹起來

keep-alive:保留組件的狀態(tài),避免組件的重新渲染 --- 類似于手機(jī)軟件使用中按了home鍵之后應(yīng)用程序的狀態(tài)
但是有些時(shí)候就是需要切換回頁面數(shù)據(jù)清除井佑,所以只需要給keep-alive添加一個(gè)include屬性就可以了属铁,后面的屬性值是在組件注冊(cè)時(shí)定義的名稱name的值。添加上的組件就會(huì)保存之前的信息躬翁,而沒有添加的組件name就會(huì)數(shù)據(jù)消失

動(dòng)態(tài)組件生命周期鉤子函數(shù)

每個(gè)組件都會(huì)有兩個(gè)鉤子函數(shù)activated()---正在用的焦蘑,deactivated()---后臺(tái)的,如果該組件在keep-alive的include內(nèi)盒发,那么該組件再被切換時(shí)例嘱,會(huì)觸發(fā)deactivated()鉤子函數(shù)類似于后臺(tái)運(yùn)行,在使用時(shí)會(huì)觸發(fā)activated()鉤子函數(shù)

<body>
  <div id="app">
    <button @click="tem='my-a'">AAA</button>
    <button @click="tem='my-b'">BBB</button>
    <button @click="tem='my-c'">CCC</button>
    <keep-alive include="a,b">
      <component :is="tem"></component>
    </keep-alive>
    
  </div>
</body>
<template id="acom">
  <div>
    <input type="text" placeholder="a組件">
  </div>
</template>
<template id="bcom">
  <div>
    <input type="text" placeholder="b組件">
  </div>
</template>
<template id="ccom">
  <div>
    <input type="text" placeholder="c組件">
  </div>
</template>
<script src="vue.js"></script>
<script>
  /**
   * keep-alive 
   *  保留組件的狀態(tài)宁舰,避免組件的重新渲染  ---  類似于手機(jī)軟件使用中按了home鍵之后應(yīng)用程序的狀態(tài)
   *  添加include 可以 只給部分組件保留狀態(tài)拼卵,需要定義組件時(shí)添加name屬性
   * 
   * 每個(gè)組件都會(huì)有 兩個(gè)生命周期鉤子函數(shù)
   *    activated()     正在用的
   *    deactivated()   后臺(tái)的
   * */
const Acom = {
  name: 'a',
  template: '#acom',
  activated () {
    console.log(' a 正在被使用')
  },
  deactivated () {
    console.log(' a 被雪藏了')
  }
}
const Bcom = {
  name: 'b',
  template: '#bcom',
  activated () {
    console.log(' b 正在被使用')
  },
  deactivated () {
    console.log(' b 被雪藏了')
  }
}
const Ccom = {
  template: '#ccom',
  activated () {
    console.log(' c 正在被使用')
  },
  deactivated () {
    console.log(' c 被雪藏了')
  }
}

new Vue({
  el: '#app',
  data: {
    tem: 'my-a'
  },
  components: {
    'my-a': Acom,
    'my-b': Bcom,
    'my-c': Ccom
  }
})
</script>
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市蛮艰,隨后出現(xiàn)的幾起案子腋腮,更是在濱河造成了極大的恐慌,老刑警劉巖壤蚜,帶你破解...
    沈念sama閱讀 218,204評(píng)論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件即寡,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡袜刷,警方通過查閱死者的電腦和手機(jī)聪富,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,091評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來著蟹,“玉大人墩蔓,你說我怎么就攤上這事∠舳梗” “怎么了奸披?”我有些...
    開封第一講書人閱讀 164,548評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)炕横。 經(jīng)常有香客問我源内,道長(zhǎng)葡粒,這世上最難降的妖魔是什么份殿? 我笑而不...
    開封第一講書人閱讀 58,657評(píng)論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮嗽交,結(jié)果婚禮上卿嘲,老公的妹妹穿的比我還像新娘。我一直安慰自己夫壁,他們只是感情好拾枣,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,689評(píng)論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般梅肤。 火紅的嫁衣襯著肌膚如雪司蔬。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,554評(píng)論 1 305
  • 那天姨蝴,我揣著相機(jī)與錄音俊啼,去河邊找鬼。 笑死左医,一個(gè)胖子當(dāng)著我的面吹牛授帕,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播浮梢,決...
    沈念sama閱讀 40,302評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼跛十,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了秕硝?” 一聲冷哼從身側(cè)響起芥映,我...
    開封第一講書人閱讀 39,216評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎缝裤,沒想到半個(gè)月后屏轰,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,661評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡憋飞,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,851評(píng)論 3 336
  • 正文 我和宋清朗相戀三年霎苗,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片榛做。...
    茶點(diǎn)故事閱讀 39,977評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡唁盏,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出检眯,到底是詐尸還是另有隱情厘擂,我是刑警寧澤,帶...
    沈念sama閱讀 35,697評(píng)論 5 347
  • 正文 年R本政府宣布锰瘸,位于F島的核電站刽严,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏避凝。R本人自食惡果不足惜舞萄,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,306評(píng)論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望管削。 院中可真熱鬧倒脓,春花似錦、人聲如沸含思。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,898評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至饲做,卻和暖如春线婚,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背盆均。 一陣腳步聲響...
    開封第一講書人閱讀 33,019評(píng)論 1 270
  • 我被黑心中介騙來泰國(guó)打工酌伊, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人缀踪。 一個(gè)月前我還...
    沈念sama閱讀 48,138評(píng)論 3 370
  • 正文 我出身青樓居砖,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親驴娃。 傳聞我的和親對(duì)象是個(gè)殘疾皇子奏候,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,927評(píng)論 2 355

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

  • 組件(Component)是Vue.js最核心的功能,也是整個(gè)架構(gòu)設(shè)計(jì)最精彩的地方唇敞,當(dāng)然也是最難掌握的蔗草。...
    六個(gè)周閱讀 5,614評(píng)論 0 32
  • Vue 實(shí)例 屬性和方法 每個(gè) Vue 實(shí)例都會(huì)代理其 data 對(duì)象里所有的屬性:var data = { a:...
    云之外閱讀 2,210評(píng)論 0 6
  • 40、React 什么是React疆柔?React 是一個(gè)用于構(gòu)建用戶界面的框架(采用的是MVC模式):集中處理VIE...
    萌妹撒閱讀 1,016評(píng)論 0 1
  • 一咒精、了解Vue.js 1.1.1 Vue.js是什么? 簡(jiǎn)單小巧旷档、漸進(jìn)式模叙、功能強(qiáng)大的技術(shù)棧 1.1.2 為什么學(xué)習(xí)...
    蔡華鵬閱讀 3,323評(píng)論 0 3
  • 前言 開發(fā)一個(gè)React應(yīng)用,更多的是在編寫組件,而React組件最小的單位就是React元素,編寫組件的最大的好...
    itclanCoder閱讀 1,153評(píng)論 0 1