文章目錄
1.Vue組件名推薦使用大駝峯命名法
爲什麼我們一直在強調 Vue
組件命名使用大駝峯呢???
在此之前,我們對 Vue
組件已經有啦一定的瞭解,我們也知道局部組件的使用頻率會高於全局組件,推薦使用大駝峯命名也和我們局部組件的使用有關,接下來我們慢慢分析.
我們先寫一個簡單的組件來觀察一下:
<div id="app">
<!-- 在註冊了局部組件的實例中使用局部組件 -->
<my-component></my-component>
</div>
<script>
// 1.創建劇組件選項對象
let MyComponent = ({
template:`
<div>
<h3>我是組件1</h3>
</div>
`
})
let vm = new Vue({
el:"#app",
//2. 將選項對象註冊爲局部組價
components:{
"my-component":MyComponent,
}
})
</script>
在上面的代碼中:
- 首先定義了一個選項對象
mycomponent
, - 在
Vue
的實例化對象中將該實例化對象定義爲了一個局部組件 - 在html模板中通過標籤
<my-component></my-component>
使用局部組件
在上面的例子中,我們並沒有使用駝峯命名法,但是組件一件可以正常使用.
那麼我們看下面的兩點:
- 定義選項對象的時候使用的變量名不能包含連字符,這是標識符的命名規則,毫無疑問,如果我們非要在定義選項對象的時候使用連字符,那麼就必須加引號;
- 在上面的代碼中,我們在
Vue
的實例化對象中註冊組件的時候,componnets
選項中是一個對象,my-component
時我們後面要使用的組件名稱,MyComponent
就是我們要註冊爲組件的選項對象.
如果我們的選項對象和組件名相同會發生什麼事呢,在es6中我們知道,如果對象中的屬性名和屬性值相同的時候,我們就可以簡寫,想下面這樣:
const vm = new Vue({
el:"#app",
components: {
//普通寫法
MyComponent: MyComponent
//es6的寫法
MyComponent
}
})
所以有沒有發現我們爲什麼要腿甲使用駝峯命名法,從這裏就可以看出來了吧.
當我們定義組件的選項對象的時候使用駝峯命名,就是說和需要被註冊爲組件的選項對象和組件名字一致的時候,註冊組件將會變得很簡單.
但是我們通常不會只註冊一個組件,當我們需要註冊多個組件的時候,就可以按照下面這種寫法:
let vm = new Vue({
el:"#app",
//2. 將選項對象註冊爲局部組價
components:{
first,second,three
}
})
怎麼樣,代碼有沒有變得比以前優雅很多.
總結:
1. 定義組件時最好使用駝峯命名
2. 註冊組件的時候,最好讓組件名和即將被註冊爲組件的選項對象名稱一致
3. 在 html 總使用組件的時候使用連字符
2.template選項
雖然有語法糖簡化了組建的註冊,但是在 template
選項中拼接 HTML
元素依舊比較麻煩,這也導致了 html
和 JavaScript
的耦合性太高.
Vue.js提供了兩種方法將定義在 JavaScript
中的 html
分離出來.
2.1 使用 Script 標籤分離
使用 script
標籤分離 JavaScript
內的 html
的內容,此時 script
標籤內會有一個 id
屬性,通過這個 id
關聯.
<div id="app">
<my-component></my-component>
</div>
<script id="myCom" type="text/x-template">
<div>
<h3>我是組件1</h3>
</div>
</script>
<script>
let MyComponent = ({
template:"#myCom"
})
let vm = new Vue({
el:"#app",
components:{
MyComponent,
}
})
儘管我們可以使用 script
標籤將 html
的內容分離出來,但是要注意在 script
標籤內的 type
值的選擇.
使用這種方式後,此時的 template
已經不再是一個 html
模板了.而是一個 id
值,Vue.js
根據這個 id
查找對應的元素,然後將這個元素內的 HTML
作爲模板進行編譯。
注意的點:
使用<script>
標籤時,type指定爲text/x-template,意在告訴瀏覽器這不是一段js腳本,瀏覽器在解析HTML文檔時會忽略<script>
標籤內定義的內容。
2.2 使用 template 標籤分離
如果我們選擇使用 template
標籤來分離模板,那麼就只需要指定 id
的值,不再需要 type
屬性.
示例代碼如下:
<div id="app">
<my-component></my-component>
</div>
<template id = "MyCom">
<div>
<h3>我是組件1</h3>
</div>
</template>
<script >
let MyComponent = ({
template:"#MyCom"
})
let vm = new Vue({
el:"#app",
components:{
MyComponent,
}
})
</script>
在我們已經瞭解了組件基本使用之後,選擇使用 script
標籤或者是 template
標籤來分離內容這種方式會更好一些,折讓我們的 html
代碼和 JavaScript
代碼之間是相互分離的,更有利於我們的維護.
3. 組件選項中的特例
組件中的選項基本與實例選項對象一致, 但是有兩個選項是特例,分別爲el 和 data 屬性.
這兩個選項在在選項對象和實例對象中的使用方式是不同的.
3.1 組件選項中沒有el
el
屬性在實例對象中的作用我們是瞭解的,他用來綁定我們的 Vue
實例將來要接管的 DOM
元素,而我們的組件是在實例中使用的,所以並不需要指定 el
.
如果我們強行爲它綁定 el
則會報錯.所以要記住的是組件的選項對象中沒有 el
屬性.
3.2 組件中的data屬性爲什麼是一個函數???
組件中的data選項必須是一個函數,返回一個數據對象
他爲什麼不是和vue的實例化選項中一樣是一個函數呢?我們看下面的內容
3.2.1 組件中的data是對象的情況
不能使用對象的原因:
- 組件中會被重複多次調用
- 而對象是引用數據類型,如果組件數據使用對象的話,那麼組件所有的複用都共享這些數據.
看下面的代碼:
<div id="app">
<my-component></my-component>
<my-component></my-component>
<my-component></my-component>
</div>
<template id = "MyCom">
<div>
<h3>我是組件{{num}}</h3>
<button @click="add">點擊數字會增加哦</button>
</div>
</template>
<script >
//在這種情況下點擊一下,所有的數組都會增加,這不符合我們的目的,我們希望的結果是這些數據之間是不要互相干擾的
let data = {
num:1,
}
let MyComponent = ({
template:"#MyCom",
//在組件的data中直接寫對象是會報錯的,所以我們通過data函數中return出的對象來模擬data的值爲對象的情況
data:function () {
return data;
},
methods:{
add() {
this.num++
}
}
})
let vm = new Vue({
el:"#app",
components:{
MyComponent,
}
})
當我點擊其中的任何一個按鈕時,每一個的數字都會增加,原因是這三個組件共用了一個數據對象,所以當數據對象中的數據一旦發生改變,那麼所有使用了這個數據的地方都會跟着改變.
一些說明的點:
- 如果直接在選項對象的
data
中定義一個對象就會報錯 - 因此我們使用
return
將data
中的對象提取出來,以這樣的方式讓所有的組件共用一個數據對象
通過案例我們就會發現如果所有的組件都共享數據,當有一個組件中的數據發生了變化,所有的組件顯示的數據都會發生變化, 這不是我們想要的.我們想要的是每個數據之間不會相互影響.
3.2.2 組件中的data是函數的情況
所以組件的 data
數據屬性纔會需要函數,每次初始化化的時候都會執行函數,將返回的結果作爲組件的數據,
這樣每次執行函數都會給每個組件創建一個獨立的數據
實例代碼如下:
<div id="app">
<my-component></my-component>
<my-component></my-component>
<my-component></my-component>
</div>
<template id = "MyCom">
<div>
<h3>我是組件{{num}}</h3>
<button @click="add">點擊數字會增加哦</button>
</div>
</template>
<script >
// data是個函數,每次執行都會返回新的數據
//當其中某一個組件的數據發生改變的時候並不會影響其他的組件
let MyComponent = ({
template:"#MyCom",
data() {
//函數每次執行都會返回一個新的數據,這個數據並不是共享數據
return {
num : 1
}
},
methods : {
add() {
this.num++
}
}
})
let vm = new Vue({
el:"#app",
components:{
MyComponent,
}
})
當我點擊按鈕的時候,只會有自己的數據發生變化,其他的組的數據並不會發生變化,這是因爲雖然我們對組件進行了複用,但是每次複用的組件都有自己的數據對象,因此在數據上並不會相互影響.
一個組件數據發生改變的時候, 其他組件的數據不會變化,因爲每個組件都有自己獨立的數據.
4.組件的使用問題
通過上面上的例子我們已經瞭解了組件的使用,就是把組件名當做自定義標籤使用,但是這種使用方法有的時候也會出現問題.
看下面的內容就會了解:
4.1 組件標籤解析錯誤
示例代碼如下:
<div id="app">
<table>
<my-component></my-component>
</table>
</div>
<template id = "MyCom">
<tr>
<td>內容</td>
<td>123</td>
</tr>
</template>
<script>
let MyComponent =({
template:"#MyCom",
})
let vm = new Vue({
el:"#app",
components:{
MyComponent,
}
})
</script>
雖然按照我們的想法實現了,但是有沒有發現, tr
標籤竟然在 table
標籤的外面,
我們使用這個組件的目的就是希望在 table
標籤中渲染 tr
標籤,結果他跑去外面了…
原因在與瀏覽器規範中 table
標籤裏面必須放 tr
標籤,但是我們放的是 my-component
自定義標籤,所以在解析的時候就會出問題.
當使用 DOM
作爲模板時 (例如,使用 el
選項來把 Vue
實例掛載到一個已有內容的元素上),你會受到 HTML
本身的一些限制,因爲 Vue
只有在瀏覽器解析、規範化模板之後才能獲取其內容。
尤其要注意,像<ul>
、<ol>
、<table>
、<select>
這樣的元素裏允許包含的元素有限制,而另一些像 <option>
這樣的元素只能出現在某些特定元素的內部。通俗一點講,就是“龍生龍,鳳生鳳,老鼠的兒子會打洞.
特殊的一下父元素如<ul>
、<ol>
、<table>
、<select>
裏面不能包含不屬於它的子元素,而與之相對應的<li>
、<tr>
、<option>
只可以出現在特定的父元素裏面。
4.2 通過is屬性使用組件
vue允許我們使用 is
屬性來使用組件, is
屬性的值是組件名
所以可以採用 is
屬性來制定組件
<div id="app">
<table>
<tr is="my-component"></tr>
<tr is="my-component"/>
<tr is="my-component"/>
</table>
</div>
<template id = "MyCom">
<tr>
<td>姓名</td>
<td>學號</td>
<td>性別</td>
</tr>
</template>
<script>
let MyComponent =({
template:"#MyCom",
})
let vm = new Vue({
el:"#app",
components:{
MyComponent,
}
})
</script>
此時我們就會發現不僅結果沒問題, 編譯後標籤的嵌套也沒有什麼問題,
因爲我們是按照標準在 tbody
標籤中使用的是 tr
標籤,只不過通過 is
屬性將tr標籤替換爲了組件 my-component
的模板標籤.
此時 tr
標籤中沒有嵌套內容,所有使用單標籤,雙標籤都可以