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


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

現在我們來看看為什么在Vue中推薦注冊組件是使用駝峰寫法, 在了解這個之前,詳細大家應該都能明白為什么在Vue中, 局部組件的使用頻率高于全局組件.

推薦使用駝峰寫法也是和局部組件有關系

我們先看一個示例

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


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

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

    })
</script>

通過前面的學習,這個例子應該已經熟悉了,

  1. 首先定義一個選項對象myComponent
  2. 在Vue實例中通過components注冊為局部組件
  3. 在HTML模板中通過<my-component>自定義標簽使用組件

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



那先看下面幾點:

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


好此時大家想一想,如果組件名和選項對象的變量名一樣會怎么樣

是不是就會變成如下的寫法

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


在思考一下,我們之前在學習ES6的時候講過在定義對象的是有一種簡便寫法. 當屬性跟值長得一樣時,就可以簡寫
因此這里我們就可以簡寫為

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


所以,為什么推薦使用駝峰寫法,這里就應該可以看出端倪了, 如果我們定義組件的組件名使用駝峰寫法,也就是和需要被注冊為組件的選項對象一致是,我們注冊組件將變得簡單

如果此時需要注冊n個組件,就可以如下寫法

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

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


總結:

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


2. 組件中的template 選項

盡管語法糖簡化了組件注冊,但在template選項中拼接HTML元素比較麻煩,這也導致了HTML和JavaScript的高耦合性。

Vue.js提供了兩種方式將定義在JavaScript中的HTML模板分離出來。


2.1 使用script標簽將template模板分離出來

在使用script標簽將template模板分離出來時,要注意script標簽的type類型選擇,

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

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


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

    }


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

    })


</script>

template選項現在不再是HTML元素,而是一個id,Vue.js根據這個id查找對應的元素,然后將這個元素內的HTML作為模板進行編譯。

注意:

使用<script> 標簽時,type指定為text/x-template,意在告訴瀏覽器這不是一段js腳本,瀏覽器在解析HTML文檔時會忽略<script>標簽內定義的內容。


2.2 使用template 標簽處理模板

如果使用<template>標簽,則不需要指定type屬性。

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

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


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

    }


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

    })


</script>

在理解了組件的創(chuàng)建和注冊過程后,我建議使用<script><template>標簽來定義組件的HTML模板。

這使得HTML代碼和JavaScript代碼是分離的,便于閱讀和維護。

另外,在Vue.js中,可創(chuàng)建.vue后綴的文件,.vue文件就是一個組件,成為單文件組件,這個內容我會在后面的文章介紹。


3. 組件選項對象中的特例

組件中的選項基本與實例選項對象一致, 但是有兩個選項是特例,分別為el 和 data 屬性

這個說的特例是指組件的選項對象和實例選項對象使用的不同


3.1 在組件中不能使用el

el屬性的作用我們都了解了, 就是在實例中使用,決定Vue需要接管的DOM元素. 組件是在實例中使用,所以不需要el屬性,
如果一個選項對象被注冊為組件,添加el屬性就會造成報錯,

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

}


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

// 會報錯, 告訴你el屬性只能在實例中使用
組件使用el選項報錯.png

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


3.2 組件中data屬性值必須是一個函數,

組件中的data選項必須是一個函數,返回一個數據對象.

為什么需要是一個函數,而不可以像Vue實例的選項對象一樣是一個對象呢


3.2.1 組件data屬性值如果是一個對象的問題

不能使用對象的原因:

  1. 首先因為組件會被多次復用,
  2. 而對象是引用數據類型,如果組件數據使用對象的話,那么組件所有的復用都共享這些數據,

這樣就會出現問題,看代碼:

示例代碼如下:

<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">點擊+1</button>
    </div>
</template>


<script>
    // 組件共享數據
    let data = {
        num : 10
    }

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

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

    })
</script>

示例結果:

組件data數據.png

實例說明:

  1. 如果在組件的data中直接寫對象就會報錯,
  2. 因此我們將data函數中返回的對象提取出來.這樣所有的組件都共用一個數據對象.
  3. 一次來模擬組件data選項值為對象的情景

通過案例我們就會發(fā)現如果所有的組件都共享數據,當有一個組件中的數據發(fā)生了變化,所有的組件顯示的數據都會發(fā)生變化, 這不是我們想要的,


3.2.2 解決組件共享數據的問題

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

<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">點擊+1</button>
    </div>
</template>


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


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

    })


</script>

顯示結果:

組件data數據方法.png

通過示例就會發(fā)現, 當一個組件數據發(fā)生改變的時候, 其他組件的數據不會變化,因為每個組件都有自己獨立的數據


3.3 組件的命名

當注冊組件 (或者 prop) 時,可以使用 kebab-case (短橫線分隔命名)、camelCase (駝峰式命名) 或 PascalCase (單詞首字母大寫命名)。

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

在 HTML 模板中,請使用 kebab-case:

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

這個問題已經在前面認真探討過了,這里不再詳細闡述


4. 組件使用問題

通過上面上的例子我們已經了解了組件的使用,就是把組件名當做自定義標簽使用,但是這種使用方法有的時候也會出現問題,


4.1. 組件標簽解析錯誤

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

例如:實例代碼如下

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


<!-- 組件模板 -->
<template id="myComponent">
    <tr>
        <td>內容</td>
        <td>123</td>
    </tr>
</template>


<script>


    // 1. 組件選項對象
    let MyComponent = {
        template: "#myComponent",
    }

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

    })

</script>

顯示結果:

template模板編譯問題.png

實例中的寫法,在查看代碼結構時,發(fā)現子組件的tr標簽并不在tbody里,

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


諸如此類的還有ul,ol標簽里只能放li標簽, select標簽中只能放option,這些都是需要注意的事項

那么我們怎么解決這類問題呢?


4.2 通過is屬性使用組件

vue允許我們使用is屬性來使用組件, is屬性的值是組件名

所以可以采用is屬性來制定組件

示例代碼如下:

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

顯示結果:

通過is屬性使用組件.png

此時我們就會發(fā)現不僅結果沒問題, 編譯后標簽的嵌套也沒有什么問題,

因為我們是按照標準在tbody標簽中使用的是tr標簽,只不過通過is屬性將tr標簽替換為了組件row的模板標簽.

此時tr標簽中沒有嵌套內容,所有使用單標簽,雙標簽都可以

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

友情鏈接更多精彩內容