Vue學(xué)習(xí)筆記---初識(shí)組件

前言

Vue中,萬(wàn)物皆組件渡紫,學(xué)習(xí)組件乃是Vue的根基所在到推,假如一個(gè)頁(yè)面相當(dāng)于一張圖,那么組件就是一個(gè)小小的拼圖惕澎,通過(guò)組件可以拼出各式各樣的圖莉测,這也是Vue的魅力所在。

正文

基本示例

Vue.component('button-counter',{
    data() {
      return {
        count: 0
      }
    },
    template: '<button v-on:click="count++">You clicked me {{ count }} times.</button>'
})

上面我們創(chuàng)建了一個(gè)全局的名字為button-couter的組件唧喉,當(dāng)我們要在根實(shí)例(app.vue)中使用它的時(shí)候,直接把這個(gè)組件作為自定義的標(biāo)簽來(lái)使用捣卤。

<div>
  <button-counter></button-counter>
</div>

局部注冊(cè)

上面演示了如何全局注冊(cè)一個(gè)組件,但是組件不能全部都全局注冊(cè)八孝,會(huì)造成代碼的冗余董朝,所以大部分的組件需要局部注冊(cè)。

如何局部注冊(cè)呢干跛,首先把一個(gè)組件作為一個(gè)單個(gè)的文件放在components文件夾下子姜,在文件中將組件export,然后在實(shí)例中import它就實(shí)現(xiàn)了組件的局部注冊(cè)楼入。

// 組件文件的基本格式
// components/buttonCounter.vue
<template>
  // 模板內(nèi)容
</template>
<script>
  export default {
    name: '',  //這個(gè)name對(duì)外沒(méi)有實(shí)際作用哥捕,但是可以讓該組件遞歸調(diào)用自己
    data() {
      return {}
    }
  }
</script>
<style scoped>
  // scoped標(biāo)明style里面樣式僅適用于當(dāng)前組件
</style>

下面我們?cè)趯?shí)例中調(diào)用它

import buttonCounter from './component/buttonCounter'
// 引入組件,組件的名字也可以隨意定義(假如定一個(gè)abc)浅辙,下面使用它的時(shí)候就用<abc></abc>
<buttonCounter></buttonCounter>

基礎(chǔ)組件的自動(dòng)全局化注冊(cè)

有一些組件特別小扭弧,但是復(fù)用率特別高,必須輸入框按鈕之類的记舆,這些組件就必須全局注冊(cè)鸽捻,但是組件又特別多,一個(gè)個(gè)注冊(cè)顯得代碼特別臃腫,所以下面就用一段代碼來(lái)實(shí)現(xiàn)自動(dòng)注冊(cè)御蒲。

假如我們把基礎(chǔ)組件放在components文件夾下衣赶,組件的文件名都以Base開(kāi)頭,比如BaseInput,BaseButton厚满。首先我們引入符合Base開(kāi)頭匹配規(guī)則的所有組件府瞄,這里要用到require.context方法,然后用文件的名字來(lái)注冊(cè)全局組件碘箍。

import Vue from 'vue'
import upperFirst from 'lodash/upperFirst'
import camelCase from 'lodash/camelCase'

const requireComponent = require.context(
    './components',  //根目錄
    false,            // 是否查詢子目錄
    /Base[A-Z]\w+\.(vue|js)$/   //匹配規(guī)則
)
requireComponent.keys().forEach(fileName => {
    const componentConfig = requireComponent(fileName)

    const componentName = upperFirst(
        camelCase(
            fileName.replace(/^\.\/(.*)\.\w+$/, '$1')
        )
    )
    Vue.component(
        componentName,
        componentConfig.default || componentConfig
        // 組件中 export default 和 export
    )
})

上面代碼中upperFirstcamelCase都是lodash庫(kù)里面的方法遵馆。

組件里面也是有computed,methods,watch生命周期鉤子的,唯獨(dú)沒(méi)有el丰榴,這是根實(shí)例獨(dú)有的

那么data為何是個(gè)函數(shù)而不是對(duì)象呢货邓,這是因?yàn)榻M件是可以復(fù)用的,每次使用就創(chuàng)建一個(gè)新的實(shí)例四濒,把data里面的屬性作為函數(shù)的返回值的話换况,它就實(shí)現(xiàn)了每個(gè)實(shí)例的屬性的私有化,跟閉包一樣原理盗蟆。

通過(guò)prop向組件傳遞數(shù)據(jù)

Vue.component('blog-post',{
    props: ['title','name'],
    template: '<h3>{{ name }}{{ title }}</h3>'
})

我們創(chuàng)建了一個(gè)blog-post組件戈二,并用prop接收了2個(gè)參數(shù)titlename,下面在根實(shí)例中往組件中注入值

<blog-post title="myTitlt" name="myName"></blog-post>

上面是傳了幾個(gè)單個(gè)值,假如傳的值比較多喳资,或者傳的值是個(gè)數(shù)組的時(shí)候就要換一個(gè)方式

Vue.component('blog-post',{
    props: ['post'],
    template: '<h3>{{ post.name }}{{ post.title }}</h3>'
})

根實(shí)例中傳值

<blog-post v-for="post in posts" :post="post"></blog-post>

當(dāng)父級(jí)傳給子組件值時(shí)候觉吭,子組件改變這個(gè)值也會(huì)同時(shí)更改父級(jí)的值,這樣就會(huì)發(fā)生混亂仆邓,所以當(dāng)子組件有改變值的情況下亏栈,最好將父級(jí)傳來(lái)的值賦給自己的屬性

props: ['name'],
data() {
  return {
    myName: this.name
  }
}

組件向父級(jí)傳值

這里要用到一個(gè)Vue的內(nèi)置方法$emit,這個(gè)函數(shù)就相當(dāng)于js中的trigger(),就是在組件中可以觸發(fā)實(shí)例中綁定的事件宏赘,而且這個(gè)方法可以傳遞參數(shù)绒北。

Vue.component('welcome-button', {
  template: `
    <button v-on:click="$emit('welcome',1)">
      Click me to be welcomed
    </button>
  `
})

組件中觸發(fā)welcome事件并傳了個(gè)參數(shù)1,那么在實(shí)例中綁定這個(gè)事件

<welcome-button @welcome="couter=$event"></welcome-button>
<welcome-button @welcome="sayHi"></welcome-button>

new Vue({
    data: {
      couter: 0
    },
    methods: {
      sayHi(argsCouter) {
        // ..
      }
    }
})

在實(shí)例中可以使用$event獲取$emit傳遞的參數(shù)察署,如果$emit觸發(fā)的事件引用的是另外一個(gè)事件,那么$emit的參數(shù)將傳給它引用的事件(argsCouter即$emit傳遞的參數(shù))

在組件中使用v-model

<input v-model="searchText">這是一個(gè)v-model的使用場(chǎng)景闷游,那么它的本質(zhì)其實(shí)是

<input :value="searchText" @input="searchText=$event.target.value">

那么在組件上使用v-model就相當(dāng)于

<custom-input :value="searchText" @input="$event"></custom-input>
等同于
<custom-input v-model="searchText"></custom-input>

為了讓它工作,在組件中首先得把value綁在prop上贴汪,然后它得觸發(fā)input事件

Vue.component('custom-input',{
    prps: ['value'],
    template: `<input :value="value" @input="$emit('input',$event.target.value)"`
})

插槽

有時(shí)候我們?cè)谡{(diào)用組件的時(shí)候脐往,組件元素中間還有一些其他的東西,一般情況下扳埂,如果不處理這些東西會(huì)被舍棄的业簿,但是如果加上<slot>元素,這些東西就會(huì)被渲染在組件之中

<custom-link>
這是一個(gè)鏈接
</custom-link>

那么在組件中阳懂,如果要使用這是一個(gè)鏈接,就需要加<slot>元素

<a href=''>
  <slot></slot>   //這是一個(gè)鏈接
</a>

組件元素的閉合標(biāo)簽中間內(nèi)容就是插槽梅尤,在插槽可以加html模板柜思,甚至可以加組件

具名插槽

上面的只是一個(gè)插槽,那它默認(rèn)渲染的就是組件中的<slot>巷燥,但是當(dāng)有多個(gè)插槽赡盘,并且插槽還有指定位置的時(shí)候,就必須要給<slot>加上name屬性

<div class="container">
  <slot name="header"></slot>
  <slot></slot>
  <slot name="footer"></slot>
</div>

那么在父級(jí)提供插槽內(nèi)容的時(shí)候缰揪,必須加一個(gè)<template>元素包裹

<base-layout>
  <template slot="header">
    // 這里的內(nèi)容渲染header
  </template>
    // 這里的內(nèi)容沒(méi)有命名陨享,所以渲染<slot></slot>
  <template slot="footer">
    // 這里的內(nèi)容渲染footer
  </template>
</base-layout>

卡槽也可以有默認(rèn)內(nèi)容的,<slot>默認(rèn)內(nèi)容</slot>钝腺,當(dāng)父級(jí)有傳給子組件內(nèi)容時(shí)抛姑,會(huì)覆蓋默認(rèn)內(nèi)容

動(dòng)態(tài)組件

前端開(kāi)發(fā)中經(jīng)常會(huì)出現(xiàn)選項(xiàng)卡之類的功能,實(shí)現(xiàn)它就需要不同的組件切來(lái)切去艳狐,這個(gè)功能可以通過(guò)Vue<component>元素加一個(gè)特殊屬性is來(lái)實(shí)現(xiàn)

<component :is="currentTab"></component>

當(dāng)點(diǎn)擊選項(xiàng)卡的nav時(shí)途戒,只需要把currentTab指向?qū)⒁袚Q的組件名即可

但是這樣實(shí)現(xiàn)有個(gè)問(wèn)題,就是每次切換都會(huì)創(chuàng)建一個(gè)組件的實(shí)例僵驰,我們更多其實(shí)是希望它第一次創(chuàng)建以后緩存下來(lái),那么就需要keep-alive元素

<keep-alive>
<component :is="currentTab"></component>
</keep-alive>

異步組件

有時(shí)候我們加載組件的時(shí)候并不希望它一開(kāi)始就加載進(jìn)來(lái)唁毒,而是調(diào)用它的時(shí)候再加載進(jìn)來(lái)蒜茴,例如在VueRouter里面,當(dāng)我們跳轉(zhuǎn)到路由后再去加載它對(duì)應(yīng)的組件浆西。

components: {
  'my-component': () => import('./my-component')
}
// 或者
component(resolve){
  require(['@/index.vue'],resolve)
}

使用異步組件的時(shí)候粉私,返回的都是一個(gè)promise函數(shù)

結(jié)束語(yǔ)

組件相關(guān)的東西還有很多很多,比如官網(wǎng)的處理邊界情況,只不過(guò)應(yīng)用場(chǎng)景不是很多近零,所以暫時(shí)不深入研究诺核。
就這樣,收工久信。窖杀。。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末裙士,一起剝皮案震驚了整個(gè)濱河市入客,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌腿椎,老刑警劉巖桌硫,帶你破解...
    沈念sama閱讀 211,348評(píng)論 6 491
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異啃炸,居然都是意外死亡铆隘,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,122評(píng)論 2 385
  • 文/潘曉璐 我一進(jìn)店門南用,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)膀钠,“玉大人掏湾,你說(shuō)我怎么就攤上這事⊥行蓿” “怎么了忘巧?”我有些...
    開(kāi)封第一講書(shū)人閱讀 156,936評(píng)論 0 347
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)睦刃。 經(jīng)常有香客問(wèn)我宪躯,道長(zhǎng)绞惦,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 56,427評(píng)論 1 283
  • 正文 為了忘掉前任,我火速辦了婚禮铃剔,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘麦备。我一直安慰自己逃默,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,467評(píng)論 6 385
  • 文/花漫 我一把揭開(kāi)白布搓彻。 她就那樣靜靜地躺著如绸,像睡著了一般。 火紅的嫁衣襯著肌膚如雪旭贬。 梳的紋絲不亂的頭發(fā)上怔接,一...
    開(kāi)封第一講書(shū)人閱讀 49,785評(píng)論 1 290
  • 那天,我揣著相機(jī)與錄音稀轨,去河邊找鬼扼脐。 笑死,一個(gè)胖子當(dāng)著我的面吹牛奋刽,可吹牛的內(nèi)容都是我干的瓦侮。 我是一名探鬼主播,決...
    沈念sama閱讀 38,931評(píng)論 3 406
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼佣谐,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼肚吏!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起狭魂,我...
    開(kāi)封第一講書(shū)人閱讀 37,696評(píng)論 0 266
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤须喂,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后趁蕊,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體坞生,經(jīng)...
    沈念sama閱讀 44,141評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,483評(píng)論 2 327
  • 正文 我和宋清朗相戀三年掷伙,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了是己。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,625評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡任柜,死狀恐怖卒废,靈堂內(nèi)的尸體忽然破棺而出沛厨,到底是詐尸還是另有隱情,我是刑警寧澤摔认,帶...
    沈念sama閱讀 34,291評(píng)論 4 329
  • 正文 年R本政府宣布逆皮,位于F島的核電站,受9級(jí)特大地震影響参袱,放射性物質(zhì)發(fā)生泄漏电谣。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,892評(píng)論 3 312
  • 文/蒙蒙 一抹蚀、第九天 我趴在偏房一處隱蔽的房頂上張望剿牺。 院中可真熱鬧,春花似錦环壤、人聲如沸晒来。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,741評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)湃崩。三九已至,卻和暖如春接箫,著一層夾襖步出監(jiān)牢的瞬間攒读,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,977評(píng)論 1 265
  • 我被黑心中介騙來(lái)泰國(guó)打工列牺, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人拗窃。 一個(gè)月前我還...
    沈念sama閱讀 46,324評(píng)論 2 360
  • 正文 我出身青樓瞎领,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親随夸。 傳聞我的和親對(duì)象是個(gè)殘疾皇子九默,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,492評(píng)論 2 348

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

  • 組件(Component)是Vue.js最核心的功能,也是整個(gè)架構(gòu)設(shè)計(jì)最精彩的地方宾毒,當(dāng)然也是最難掌握的驼修。...
    六個(gè)周閱讀 5,584評(píng)論 0 32
  • 什么是組件? 組件 (Component) 是 Vue.js 最強(qiáng)大的功能之一诈铛。組件可以擴(kuò)展 HTML 元素乙各,封裝...
    youins閱讀 9,463評(píng)論 0 13
  • VUE介紹 Vue的特點(diǎn)構(gòu)建用戶界面,只關(guān)注View層簡(jiǎn)單易學(xué)幢竹,簡(jiǎn)潔耳峦、輕量、快速漸進(jìn)式框架 框架VS庫(kù)庫(kù)焕毫,是一封裝...
    多多醬_DuoDuo_閱讀 2,689評(píng)論 1 17
  • 這篇筆記主要包含 Vue 2 不同于 Vue 1 或者特有的內(nèi)容蹲坷,還有我對(duì)于 Vue 1.0 印象不深的內(nèi)容驶乾。關(guān)于...
    云之外閱讀 5,046評(píng)論 0 29
  • 一粒高粱落進(jìn)了玉米地。 小高粱剛出生的時(shí)候循签,它對(duì)這個(gè)世界充滿了好奇级乐。只是它母親可能是早產(chǎn)的緣故,與周圍玉米苗相比县匠,...
    歌凝閱讀 867評(píng)論 2 4