一、vue元件的概念
官方定義:元件(Component)是 Vue.js 最強大的功能之一。元件可以擴充 HTML 元素,封裝可重用的代碼。在較高層面上,元件是自定義元素, Vue.js 的編譯器為它添加特殊功能。在有些情況下,元件也可以是原生 HTML 元素的形式,以 is 特性擴充。
部落客了解:Vue裡面的元件可以了解為通過對普通html标簽的封裝,得到一套獨立而且可以通用的html标簽,我們在頁面裡面使用這些标簽傳入相應的參數即可調用封裝好的元件。通過下面這張圖相信可以一目了然。
由普通的html标簽form、input、button、label組成了一個新的元素集合,我們命名為i-form,這個i-form就是vue裡面元件的概念。我們在頁面裡面使用<i-form></i-form>時,通過vue的元件渲染機制,在浏覽器裡面最終就可以顯示成為普通的html标簽form、input、button、label。
二、元件原理
通過上圖我們知道,vue裡面的元件實際上就是一些普通html元素的集合。那麼,它是如何将這些自定義标簽轉換為普通html标簽的呢?在介紹元件原理之前,還是先來看一個最簡單的元件執行個體。
<div style="text-align:center;margin-top:200px;" id="app">
<!-- 3. 在Vue執行個體裡面使用元件-->
<b-component></b-component>
</div>
<script src="Content/vue/dist/vue.js"></script>
<script type="text/javascript">
// 1.建立元件構造器
var myComponent = Vue.extend({
template: '<div id="bComponent">我是自定義元件的内容</div>'
});
//2.注冊元件到vue裡面
Vue.component('b-component', myComponent)
new Vue({
el: '#app',
});
</script>
整個過程不難了解,主要分為三個大的步驟:
- 定義一個元件構造器,聲明元件要渲染的html内容
- 将元件構造器注冊到Vue的元件系統裡面,使其成為Vue的一個元件,給元件取一個名稱,比如b-component
- 在Vue的執行個體裡面使用元件。因為上面兩步定義了Vue的元件,既然是Vue的元件,那麼要使用元件,首先得有一個Vue的執行個體,元件必須要在Vue的執行個體裡面使用。
整個過程:
其實有時為了簡便,我們常将1、2步合并,代碼如下:
<div style="text-align:center;margin-top:200px;" id="app">
<!-- 2. 在Vue執行個體裡面使用元件-->
<b-component></b-component>
</div>
<script src="Content/vue/dist/vue.js"></script>
<script type="text/javascript">
//1.建立元件構造器,注冊元件到vue裡面
Vue.component('b-component', {
template: '<div id="bComponent">我是自定義元件的内容</div>'
})
new Vue({
el: '#app',
});
</script>
三、元件的使用
上述解釋了下元件的定義和原理,關于元件的簡單實用,我們主要介紹以下幾個方面。
(1)元件的作用域
這個應該不難了解,元件分為全局元件和局部元件,也就是說,你可以在頁面上面定義一個全局元件,頁面上面的任何Vue執行個體都可使用;而對于局部元件,是和具體的Vue執行個體相關的,隻能在目前Vue執行個體裡面使用元件。還有一點需要說明:元件必須在Vue的執行個體裡面使用,在Vue執行個體之外使用元件無效。通過下面一個例子即可清晰說明它們的差別。
<body>
<div style="text-align:center;margin-top:50px;" id="app">
<b-component></b-component>
<b-component2></b-component2>
</div>
<div style="text-align:center;margin-top:50px;" id="app2">
<b-component></b-component>
<b-component2></b-component2>
</div>
<b-component></b-component>
<b-component2></b-component2>
<script src="Content/vue/dist/vue.js"></script>
<script type="text/javascript">
//定義元件
Vue.component('b-component', {
template: '<div id="bComponent">我是全局元件,任何Vue執行個體都可使用</div>'
})
new Vue({
el: '#app',
components: {
'b-component2': {
template: '<div id="bComponent">我是局部元件,隻能在app這個div裡面使用</div>'
}
}
});
new Vue({
el: '#app2',
});
</script>
</body>
(2)元件的傳值
元件執行個體的作用域是孤立的。這意味着不能并且不應該在子元件的模闆内直接引用父元件的資料。可以使用 props 把資料傳給子元件。這段話怎麼了解呢?我們先來看幾個例子。
- 靜态Prop
我們先來看看下面的一段簡單的代碼
<body>
<div style="text-align:center;margin-top:50px;" id="app">
<b-component componentmessage="你好"></b-component>
</div>
<script src="Content/vue/dist/vue.js"></script>
<script type="text/javascript">
Vue.component('b-component', {
template: '<div>{{componentmessage}}</div>',
props: ['componentmessage'],
})
new Vue({
el: '#app'
});
</script>
</body>
通過在元件裡面使用props屬性,将外部的值傳入元件模闆。最終渲染到頁面上面就得到“<div>你好</div>”這麼一段html
- 動态Prop
在多數情況下,我們在使用Vue執行個體的時候,一般通過data屬性傳入模型,這個時候,我們的name和age如何傳到元件執行個體裡面呢?如下:
<body>
<div style="text-align:center;margin-top:50px;" id="app">
<b-component v-bind:my-name="name" v-bind:my-age="Age"></b-component>
</div>
<script src="Content/vue/dist/vue.js"></script>
<script type="text/javascript">
Vue.component('b-component', {
template: '<div>姓名:{{myName}},年齡:{{myAge}}</div>',
props: ['myName', 'myAge'],
})
new Vue({
el: '#app',
data: {
name: 'Jim',
Age: '28'
}
});
</script>
</body>
需要說明幾點:
- 在使用标簽<b-component>的時候,通過v-bind指令,将Vue執行個體裡面的name、Age屬性以别名my-name、my-age的形式傳入元件執行個體。
- 為什麼my-name、my-age傳到元件裡面就變成了['myName', 'myAge']呢?這是因為在子元件中定義prop時,使用了camelCase命名法。由于HTML特性不區分大小寫,camelCase的prop用于特性時,需要轉為 kebab-case(短橫線隔開)。
- 很多情況下,v-bind可以簡寫為冒号(:),是以上述代碼也可以這麼寫: <b-component :my-name="name" :my-age="Age"></b-component> 。效果也是一樣。
- 這裡很惡心的還有一點,在Props裡面定義的必須要使用所謂“駝峰式”的方式來定義變量,否則會因為一個變量名大小寫搞死你。比如props:["myName"]這樣可以正确,但是如果props:["myname"]這樣的話就錯誤,使用myname取值會是undefined。部落客第一次玩這個玩意找了好半天,新手一定注意,大坑,大坑,大坑!慎入!
在封裝元件裡面,props屬性使用非常多,更多props用法可參見文檔https://vuefe.cn/v2/guide/components.html#Prop
(3)元件的插槽
在使用元件的時候,我們經常需要在元件執行個體向元件模闆傳入html元素,這個時候我們就需要在元件的模闆标簽裡面留一些占位符(俗稱“坑”),然後在具體的元件執行個體裡面傳入标簽來填“坑”,在Vue裡面這些“坑”也叫插槽,使用<slot>來解決。對于開發人員來說,這個其實不陌生,從原來的母版頁到現在的layout頁面,基本都是使用的這種原理。
<body>
<div style="text-align:center;margin-top:50px;" id="app">
<b-component>
<h1 slot="header">這裡可能是一個頁面标題</h1>
<h2 slot="content">姓名:{{name}},年齡:{{Age}}</h2>
<h1 slot="footer">尾部</h1>
</b-component>
</div>
<template id="slottest">
<div class="container">
<header>
<slot name="header"></slot>
</header>
<main>
<slot name="content"></slot>
</main>
<footer>
<slot name="footer"></slot>
</footer>
</div>
</template>
<script src="Content/vue/dist/vue.js"></script>
<script type="text/javascript">
Vue.component('b-component', {
template: '#slottest',
})
new Vue({
el: '#app',
data: {
name: 'Jim',
Age: '28'
}
});
</script>
</body>
上述代碼應該不難了解,就是一個“挖坑”和“填坑”的過程。順便要提一筆的是,Vue的元件支援使用<templete>的模式來定義标簽模闆,使用更加靈活和友善。