第十八節(jié):Vue組件:Vue組件中的注意事項(xiàng)和特例


1. Vue組件名推薦使用駝峰命名

現(xiàn)在我們來(lái)看看為什么在Vue中推薦注冊(cè)組件是使用駝峰寫法, 在了解這個(gè)之前,詳細(xì)大家應(yīng)該都能明白為什么在Vue中, 局部組件的使用頻率高于全局組件.

推薦使用駝峰寫法也是和局部組件有關(guān)系

我們先看一個(gè)示例

<div id="app">
    <!-- 3. 在注冊(cè)了局部組件的實(shí)例中使用局部組件 -->
    <my-component></my-component>
</div>


<script>
    // 1. 創(chuàng)建局部組件的選項(xiàng)對(duì)象
    let MyComponent = {
        template: `
            <div>
                <h2>局部組件</h2>
            </div>
        `,
    }

    const vm = new Vue({
        el:"#app",
        // 2. 將選項(xiàng)對(duì)象注冊(cè)為局部組件
        components: {
            "my-component": MyComponent
        }

    })
</script>

通過前面的學(xué)習(xí),這個(gè)例子應(yīng)該已經(jīng)熟悉了,

  1. 首先定義一個(gè)選項(xiàng)對(duì)象myComponent
  2. 在Vue實(shí)例中通過components注冊(cè)為局部組件
  3. 在HTML模板中通過<my-component>自定義標(biāo)簽使用組件

示例中,不使用駝峰命名組件,依然可以正常運(yùn)行,那么為什么組件名還要推薦使用駝峰命名



那先看下面幾點(diǎn):

  1. 首先在定義選項(xiàng)對(duì)象的時(shí)候使用的變量名絕對(duì)不可以是連字符, 這是標(biāo)識(shí)符命名規(guī)范,因此如果要使用連字符就必須加引號(hào)
  2. 在注冊(cè)組件是,components中的屬性名my-component就是我們的組件名稱, 其值MyComponent就是將誰(shuí)注冊(cè)為組件


好此時(shí)大家想一想,如果組件名和選項(xiàng)對(duì)象的變量名一樣會(huì)怎么樣

是不是就會(huì)變成如下的寫法

const vm = new Vue({
    el:"#app",
    components: {
        MyComponent: MyComponent
    }
})


在思考一下,我們之前在學(xué)習(xí)ES6的時(shí)候講過在定義對(duì)象的是有一種簡(jiǎn)便寫法. 當(dāng)屬性跟值長(zhǎng)得一樣時(shí),就可以簡(jiǎn)寫
因此這里我們就可以簡(jiǎn)寫為

const vm = new Vue({
    el:"#app",
    components: {
        MyComponent
    }
})


所以,為什么推薦使用駝峰寫法,這里就應(yīng)該可以看出端倪了, 如果我們定義組件的組件名使用駝峰寫法,也就是和需要被注冊(cè)為組件的選項(xiàng)對(duì)象一致是,我們注冊(cè)組件將變得簡(jiǎn)單

如果此時(shí)需要注冊(cè)n個(gè)組件,就可以如下寫法

const vm = new Vue({
    el:"#app",
    components: {
        one,two,three,four.....
    }
})

是不是感覺很優(yōu)雅,


總結(jié):

  1. 在定義組件時(shí)推薦使用駝峰寫法,最好的組件名和需要被創(chuàng)建為組件的選項(xiàng)對(duì)象名一致
  2. 使用組件時(shí)推薦使用連字符


2. 組件中的template 選項(xiàng)

盡管語(yǔ)法糖簡(jiǎn)化了組件注冊(cè),但在template選項(xiàng)中拼接HTML元素比較麻煩,這也導(dǎo)致了HTML和JavaScript的高耦合性肩豁。

Vue.js提供了兩種方式將定義在JavaScript中的HTML模板分離出來(lái)缀程。


2.1 使用script標(biāo)簽將template模板分離出來(lái)

在使用script標(biāo)簽將template模板分離出來(lái)時(shí),要注意script標(biāo)簽的type類型選擇,

<div id="app">
    <!-- 3. 使用組件 -->
    <my-component></my-component>
</div>

<!-- 組件模板 -->
<!-- 注意: 如果不添加type屬性,可能會(huì)顯示效果,但是會(huì)報(bào)錯(cuò), -->
<script id="myComponent" type="text/x-template">
    <div>
        <h2>我想被創(chuàng)建為局部組件</h2>
    </div>
</script>


<script>
    // 1. 創(chuàng)建組件選項(xiàng)對(duì)象
    let MyComponent = {
        // 此時(shí)的模板template的值就是一個(gè)選擇器
        template: "#myComponent",

    }


    const vm = new Vue({
        el:"#app",
        // 2. 注冊(cè)組件
        components: {
            "my-component": MyComponent
        }

    })


</script>

template選項(xiàng)現(xiàn)在不再是HTML元素涧至,而是一個(gè)id艇拍,Vue.js根據(jù)這個(gè)id查找對(duì)應(yīng)的元素锅减,然后將這個(gè)元素內(nèi)的HTML作為模板進(jìn)行編譯辐董。

注意:

使用<script> 標(biāo)簽時(shí),type指定為text/x-template白对,意在告訴瀏覽器這不是一段js腳本掠廓,瀏覽器在解析HTML文檔時(shí)會(huì)忽略<script>標(biāo)簽內(nèi)定義的內(nèi)容。


2.2 使用template 標(biāo)簽處理模板

如果使用<template>標(biāo)簽甩恼,則不需要指定type屬性蟀瞧。

<div id="app">
    <!-- 3. 使用組件 -->
    <my-component></my-component>
</div>

<!-- 組件模板 -->
<!-- template標(biāo)簽不需要指定type,標(biāo)簽的本意就是告訴瀏覽器這是模板 -->
<template id="myComponent">
    <div>
        <h2>我想被創(chuàng)建為局部組件</h2>
    </div>
</template>


<script>
    // 1. 創(chuàng)建組件選項(xiàng)對(duì)象
    let MyComponent = {
        // 此時(shí)的模板template的值就是一個(gè)選擇器
        template: "#myComponent",

    }


    const vm = new Vue({
        el:"#app",
        // 2. 注冊(cè)組件
        components: {
            "my-component": MyComponent
        }

    })


</script>

在理解了組件的創(chuàng)建和注冊(cè)過程后沉颂,我建議使用<script><template>標(biāo)簽來(lái)定義組件的HTML模板。

這使得HTML代碼和JavaScript代碼是分離的黄橘,便于閱讀和維護(hù)兆览。

另外,在Vue.js中塞关,可創(chuàng)建.vue后綴的文件抬探,.vue文件就是一個(gè)組件,成為單文件組件,這個(gè)內(nèi)容我會(huì)在后面的文章介紹帆赢。


3. 組件選項(xiàng)對(duì)象中的特例

組件中的選項(xiàng)基本與實(shí)例選項(xiàng)對(duì)象一致, 但是有兩個(gè)選項(xiàng)是特例,分別為el 和 data 屬性

這個(gè)說(shuō)的特例是指組件的選項(xiàng)對(duì)象和實(shí)例選項(xiàng)對(duì)象使用的不同


3.1 在組件中不能使用el

el屬性的作用我們都了解了, 就是在實(shí)例中使用,決定Vue需要接管的DOM元素. 組件是在實(shí)例中使用,所以不需要el屬性,
如果一個(gè)選項(xiàng)對(duì)象被注冊(cè)為組件,添加el屬性就會(huì)造成報(bào)錯(cuò),

// 1. 創(chuàng)建局部組件的選項(xiàng)對(duì)象
let MyComponent = {
    el:"",
    template: "#myComponent",

}


const vm = new Vue({
    el:"#app",
    // 2. 將選項(xiàng)對(duì)象注冊(cè)為局部組件
    components: {
        "my-component": MyComponent
    }
})

// 會(huì)報(bào)錯(cuò), 告訴你el屬性只能在實(shí)例中使用
組件使用el選項(xiàng)報(bào)錯(cuò).png

可以通過報(bào)錯(cuò)信息了解到, el選項(xiàng)只能使用在new創(chuàng)建的vue實(shí)例上


3.2 組件中data屬性值必須是一個(gè)函數(shù),

組件中的data選項(xiàng)必須是一個(gè)函數(shù),返回一個(gè)數(shù)據(jù)對(duì)象.

為什么需要是一個(gè)函數(shù),而不可以像Vue實(shí)例的選項(xiàng)對(duì)象一樣是一個(gè)對(duì)象呢


3.2.1 組件data屬性值如果是一個(gè)對(duì)象的問題

不能使用對(duì)象的原因:

  1. 首先因?yàn)榻M件會(huì)被多次復(fù)用,
  2. 而對(duì)象是引用數(shù)據(jù)類型,如果組件數(shù)據(jù)使用對(duì)象的話,那么組件所有的復(fù)用都共享這些數(shù)據(jù),

這樣就會(huì)出現(xiàn)問題,看代碼:

示例代碼如下:

<div id="app">
    <!-- 3. 使用組件 -->
    <my-component></my-component>
    <my-component></my-component>
    <my-component></my-component>
</div>

<template id="myComponent">
    <div>
        <h2>組件{{num}}</h2>
        <button @click="handleClick">點(diǎn)擊+1</button>
    </div>
</template>


<script>
    // 組件共享數(shù)據(jù)
    let data = {
        num : 10
    }

    // 1. 選項(xiàng)對(duì)象
    let MyComponent = {
        template: "#myComponent",
        data: function(){
            return data
        },
        methods: {
            handleClick(){
                this.num++
            }
        }
    }

    const vm = new Vue({
        el:"#app",
        // 2. 注冊(cè)組件
        components: {
            "my-component": MyComponent
        }

    })
</script>

示例結(jié)果:

組件data數(shù)據(jù).png

實(shí)例說(shuō)明:

  1. 如果在組件的data中直接寫對(duì)象就會(huì)報(bào)錯(cuò),
  2. 因此我們將data函數(shù)中返回的對(duì)象提取出來(lái).這樣所有的組件都共用一個(gè)數(shù)據(jù)對(duì)象.
  3. 一次來(lái)模擬組件data選項(xiàng)值為對(duì)象的情景

通過案例我們就會(huì)發(fā)現(xiàn)如果所有的組件都共享數(shù)據(jù),當(dāng)有一個(gè)組件中的數(shù)據(jù)發(fā)生了變化,所有的組件顯示的數(shù)據(jù)都會(huì)發(fā)生變化, 這不是我們想要的,


3.2.2 解決組件共享數(shù)據(jù)的問題

所以組件的data數(shù)據(jù)屬性才會(huì)需要函數(shù),每次初始化化的時(shí)候都會(huì)執(zhí)行函數(shù),將返回的結(jié)果作為組件的數(shù)據(jù),
這樣每次執(zhí)行函數(shù)都會(huì)給每個(gè)組件創(chuàng)建一個(gè)獨(dú)立的數(shù)據(jù)

<div id="app">
    <!-- 3. 使用組件 -->
    <my-component></my-component>
    <my-component></my-component>
    <my-component></my-component>
</div>

<template id="myComponent">
    <div>
        <h2>組件{{num}}</h2>
        <button @click="handleClick">點(diǎn)擊+1</button>
    </div>
</template>


<script>
 
    // 1. 選項(xiàng)對(duì)象
    let MyComponent = {
        template: "#myComponent",
        data: function(){
            // 每次函數(shù)執(zhí)行都會(huì)返回新的數(shù)據(jù),非共享數(shù)據(jù)
            return {
                num : 10
            }
        },
        methods: {
            handleClick(){
                this.num++
            }
        }
    }


    const vm = new Vue({
        el:"#app",
        // 2. 注冊(cè)組件
        components: {
            "my-component": MyComponent
        }

    })


</script>

顯示結(jié)果:

組件data數(shù)據(jù)方法.png

通過示例就會(huì)發(fā)現(xiàn), 當(dāng)一個(gè)組件數(shù)據(jù)發(fā)生改變的時(shí)候, 其他組件的數(shù)據(jù)不會(huì)變化,因?yàn)槊總€(gè)組件都有自己獨(dú)立的數(shù)據(jù)


3.3 組件的命名

當(dāng)注冊(cè)組件 (或者 prop) 時(shí)小压,可以使用 kebab-case (短橫線分隔命名)、camelCase (駝峰式命名) 或 PascalCase (單詞首字母大寫命名)椰于。

// 在組件定義中
components: {
  // 使用 kebab-case 注冊(cè)
  'kebab-cased-component': { /* ... */ },
  // 使用 camelCase 注冊(cè) 俗稱小駝峰
  'camelCasedComponent': { /* ... */ },
  // 使用 PascalCase 注冊(cè) 俗稱大駝峰
  'PascalCasedComponent': { /* ... */ }
}

在 HTML 模板中怠益,請(qǐng)使用 kebab-case:

<!-- 在 HTML 模板中始終使用 kebab-case -->
<kebab-cased-component></kebab-cased-component>
<camel-cased-component></camel-cased-component>
<pascal-cased-component></pascal-cased-component>

這個(gè)問題已經(jīng)在前面認(rèn)真探討過了,這里不再詳細(xì)闡述


4. 組件使用問題

通過上面上的例子我們已經(jīng)了解了組件的使用,就是把組件名當(dāng)做自定義標(biāo)簽使用,但是這種使用方法有的時(shí)候也會(huì)出現(xiàn)問題,


4.1. 組件標(biāo)簽解析錯(cuò)誤

通過下面的實(shí)例了解組件標(biāo)簽解析是發(fā)生的問題.

例如:實(shí)例代碼如下

<div id="app">
    <!-- 3. 使用組件 -->
    <table>
        <tbody>
            <row></row>
            <row></row>
            <row></row>
        </tbody>
    </table>
</div>


<!-- 組件模板 -->
<template id="myComponent">
    <tr>
        <td>內(nèi)容</td>
        <td>123</td>
    </tr>
</template>


<script>


    // 1. 組件選項(xiàng)對(duì)象
    let MyComponent = {
        template: "#myComponent",
    }

     // 2. 注冊(cè)組件
    const vm = new Vue({
        el:"#app",
        components: {
            "row": MyComponent
        }

    })

</script>

顯示結(jié)果:

template模板編譯問題.png

實(shí)例中的寫法,在查看代碼結(jié)構(gòu)時(shí),發(fā)現(xiàn)子組件的tr標(biāo)簽并不在tbody里,

原因在與瀏覽器規(guī)范中tbody標(biāo)簽里面必須放tr標(biāo)簽,但是我們放的是row自定義標(biāo)簽,所以在解析的時(shí)候就會(huì)出問題


諸如此類的還有ul,ol標(biāo)簽里只能放li標(biāo)簽, select標(biāo)簽中只能放option,這些都是需要注意的事項(xiàng)

那么我們?cè)趺唇鉀Q這類問題呢?


4.2 通過is屬性使用組件

vue允許我們使用is屬性來(lái)使用組件, is屬性的值是組件名

所以可以采用is屬性來(lái)制定組件

示例代碼如下:

<div id="app">
     <!-- 3. 使用組件 -->
    <table>
        <tbody>
            <tr is="row"></tr>
            <tr is="row"/>
            <tr is="row"/>
        </tbody>
    </table>
</div>

顯示結(jié)果:

通過is屬性使用組件.png

此時(shí)我們就會(huì)發(fā)現(xiàn)不僅結(jié)果沒問題, 編譯后標(biāo)簽的嵌套也沒有什么問題,

因?yàn)槲覀兪前凑諛?biāo)準(zhǔn)在tbody標(biāo)簽中使用的是tr標(biāo)簽,只不過通過is屬性將tr標(biāo)簽替換為了組件row的模板標(biāo)簽.

此時(shí)tr標(biāo)簽中沒有嵌套內(nèi)容,所有使用單標(biāo)簽,雙標(biāo)簽都可以

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市瘾婿,隨后出現(xiàn)的幾起案子蜻牢,更是在濱河造成了極大的恐慌,老刑警劉巖偏陪,帶你破解...
    沈念sama閱讀 217,277評(píng)論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件抢呆,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡笛谦,警方通過查閱死者的電腦和手機(jī)抱虐,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,689評(píng)論 3 393
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)饥脑,“玉大人恳邀,你說(shuō)我怎么就攤上這事≡詈洌” “怎么了谣沸?”我有些...
    開封第一講書人閱讀 163,624評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)框往。 經(jīng)常有香客問我鳄抒,道長(zhǎng),這世上最難降的妖魔是什么椰弊? 我笑而不...
    開封第一講書人閱讀 58,356評(píng)論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮瓤鼻,結(jié)果婚禮上秉版,老公的妹妹穿的比我還像新娘。我一直安慰自己茬祷,他們只是感情好清焕,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,402評(píng)論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般秸妥。 火紅的嫁衣襯著肌膚如雪滚停。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,292評(píng)論 1 301
  • 那天粥惧,我揣著相機(jī)與錄音键畴,去河邊找鬼。 笑死突雪,一個(gè)胖子當(dāng)著我的面吹牛起惕,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播咏删,決...
    沈念sama閱讀 40,135評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼惹想,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了督函?” 一聲冷哼從身側(cè)響起嘀粱,我...
    開封第一講書人閱讀 38,992評(píng)論 0 275
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎辰狡,沒想到半個(gè)月后锋叨,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,429評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡搓译,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,636評(píng)論 3 334
  • 正文 我和宋清朗相戀三年悲柱,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片些己。...
    茶點(diǎn)故事閱讀 39,785評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡豌鸡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出段标,到底是詐尸還是另有隱情涯冠,我是刑警寧澤,帶...
    沈念sama閱讀 35,492評(píng)論 5 345
  • 正文 年R本政府宣布逼庞,位于F島的核電站蛇更,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏赛糟。R本人自食惡果不足惜派任,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,092評(píng)論 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望璧南。 院中可真熱鬧掌逛,春花似錦、人聲如沸司倚。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,723評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至皿伺,卻和暖如春员辩,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背鸵鸥。 一陣腳步聲響...
    開封第一講書人閱讀 32,858評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工奠滑, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人脂男。 一個(gè)月前我還...
    沈念sama閱讀 47,891評(píng)論 2 370
  • 正文 我出身青樓养叛,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親宰翅。 傳聞我的和親對(duì)象是個(gè)殘疾皇子弃甥,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,713評(píng)論 2 354