Vue元件定義
簡介
元件是可複用的 Vue 例項。
本質上是一個物件,該物件包含data
、computed
、watch
、methods
、filters
以及生命週期鉤子等成員屬性。
元件結構:
{
data(){
return {
//
}
},
computed:{
displayName(){
return '';
}
},
methods:{
onClickHandler(params){
// do something
}
}
}
基礎知識
data屬性
-
data屬性維護一個元件內部狀態,其餘元件正常情況下不可見。
- 可以通過
props
傳遞給子元件; - 可以通過
$emit
的方式傳遞給父元件; -
可以通過
this.$refs.ref.$data
在mounted
生命週期內獲取子元件的內部狀態;- 目前不知道如何監聽其變化;
- 因為計算屬性
computed
和偵聽屬性watch
只能監聽 響應式依賴 的變化,而$refs
非響應式。
- 可以通過
-
一個元件的 data 選項必須是一個函式。
``` data選項有兩種定義方式: 一、物件形式: ``` data:{ //引用該元件的地方,共用一個狀態的引用,以至於,只要有一處修改了$data中的某一屬性值,其它引用該元件的地方也跟隨著改變該屬性值(其實,不是跟隨,本來就是同一個指向)。 } ``` 二、函式形式: ``` data(){ return { //引用該元件的地方,每一個元件都會獲得獨立的引用,互不干擾。 } } ``` ```
computed屬性 VS methods屬性 VS filter
區別 | method | computed | filter |
---|---|---|---|
型別 | 函式 | 資料變數 | 函式 |
用途 | 作事件處理函式 | 作資料 | 作管道符 |
作用範圍 | 組建內 | 組建內 | 組建內(區域性註冊)、全域性(全域性註冊) |
引數 | 可以帶參 | 不帶參(非函) | 帶參 |
返回值 | 不要求 | 必須有 | 必須有 |
觸發 | 互動時觸發 | 在它的相關依賴發生改變時才會重新求值 | 傳入的資料變化時執行 |
注意:
-
Vue
中並不是所有的屬性都是響應式的,如$refs
無法監聽它的變動;
元件構建的主要區別在於模板的生成方式。
模板定義方式
template選項
字串模板
- 以HTML標籤結構組成的字串;
- 示例:
{
template: '<h1 v-if="level === 1">簡單示例</h1>',
props: {
level: {
type: Number,
required: true
}
}
}
id選擇器指定的模板
- 以
id
標識的一段script
標籤包裹的HTML片段; - 示例:
<script type="text/x-template" id="anchored-heading-template">
<h1 v-if="level === 1">
簡單示例
</h1>
</script>
{
template: '#anchored-heading-template',
props: {
level: {
type: Number,
required: true
}
}
}
render
- 發揮JavaScript最大的程式設計能力,該函式接收一個
createElement
方法作為第一個引數用來建立VNode
; -
createElement
接收三個引數:元件根節點型別、元件配置物件、子節點(官方關於元件配置物件的說明); - 示例:
{
render: function (createElement) {
return createElement(
'h' + this.level, // tag name 標籤名稱
this.$slots.default // 子元件中的陣列
)
},
props: {
level: {
type: Number,
required: true
}
}
}
單檔案元件
單檔案元件將模板、邏輯、樣式在結構上分離,儲存在同一個檔案中。
<template>
<div>
...
</div>
</template>
<script>
...
export default{
...
}
...
</script>
<style>
...
</style>
方案選擇
template | 單檔案 | render |
---|---|---|
一行的簡單結構 | 常規的選擇 | 前邊兩種方案解決不了時候的選擇(靈活性高) |
注意:
- 不論選擇哪一種方案,定義模板時,一定要有一個非
template
標籤元素作根DOM,有且僅有一個。
元件註冊方式
區域性註冊
以上幾種方案定義的元件本質上都是一個物件,獲取該物件(假設變數名為TabBar),要求只在另一個元件(假設變數名為App)內使用:
App
元件的配置物件:
{
components:{
'tab-bar': TabBar,
}
}
這樣就是區域性註冊,該元件TabBar
只能在App
模板中使用<tab-bar></tab-bar>
,其它元件對TabBar
不可見。
全域性註冊
以上幾種方案定義的元件本質上都是一個物件,獲取該物件(假設變數名為TabBar),要求專案內任何元件可使用:
一般在專案的入口檔案(如:腳手架搭建專案的main.js
)中:
Vue.component('tab-bar',TabBar);
這樣就是全域性註冊,該元件TabBar
能在整個專案內使用<tab-bar></tab-bar>
,所有元件對TabBar
可見。
生命週期鉤子
以下用自己的語言將生命週期鉤子表述一下,如果有不對的地方,請校正:
beforeCreate
在這個時候,生命週期函式已經準備好。
- 元件例項已經構建,但本元件例項的資料、方法還沒有注入;
- 可以在各個生命週期內通過元件例項
this
呼叫根例項上注入的$router
、$store
等物件。 - 可以在本生命週期內進行資料初始化;
created
在這個時候,當前元件例項this
上的屬性($data
、props
、$methods
...)已經注入繫結,可以呼叫本例項上的成員屬性;
beforeMount
在進入本生命週期之前,會進行以下判斷:
-
是否有
el
選項(指定掛載目標):- 有
el
選項的是根例項; - 沒有
el
選項的是非根例項(預設掛載元素為元件呼叫的位置);
- 有
-
是否有
template
選項:- 有
template
選項的是內聯模板; - 沒有
template
選項的是單檔案元件; - 個人覺得,還有
render
選項的判斷;
- 有
最終這些模板都會轉換為render
函式進行渲染!!!
這個生命週期在解析模板,不知道有什麼實際用途。
mounted
在本生命週期之前,已經將模板渲染為真實DOM,其中vm.$el
為元件例項的根DOM元素;
- 本生命週期是初始化第三方外掛的場所;
- 必要時候,可以在本生命週期內對DOM進行操作;
- 本生命週期是獲取
this.$refs.ref
的場所;