vue組件深入
組件注冊
- 全局注冊
- 局部注冊
prop
prop的大小寫
camelCase vs Kebab-case
kebab-case
prop類型
props: {
title: String,
likes: Number,
isPublished: Boolean,
commentIds: Array,
author: Object,
callback: Function,
contactsPromise: Promise // or any other constructor
}
傳靜態(tài)或動態(tài)prop
prop可以通過v-bind動態(tài)賦值
<!-- 動態(tài)賦予一個變量的值 -->
<blog-post v-bind:title="post.title"></blog-post>
<!-- 動態(tài)賦予一個復雜表達式的值 -->
<blog-post
v-bind:title="post.title + ' by ' + post.author.name"
></blog-post>
- 傳入一個數字
- 傳入一個布爾值
<!-- 包含該 prop 沒有值的情況在內,都意味著 `true`智玻。-->
<blog-post is-published></blog-post>
- 傳入一個數組
- 傳入一個對象
v-bind告訴JavaScript表達式是動態(tài)的而不是一個字符串
prop單向數據流
- 在組件中使用props來從父親組件接受數據爆惧,在props中定義的屬性,都可以在組件中直接使用
- props來自父級俏竞,而組件中的data return的數據就是組件自己的數據至非,兩種情況作用域就是組件本身篷朵,可以直接在template勾怒,computed,methods中直接使用
- 使用v-bind動態(tài)綁定來自父組件的值声旺。input
單向下行綁定:父級 prop 的更新會向下流動到子組件中笔链,但是反過來則不行。這樣會防止從子組件意外改變父級組件的狀態(tài)腮猖,從而導致你的應用的數據流向難以理解鉴扫。
不應該在一個子組件內部改變 prop。如果你這樣做了澈缺,Vue 會在瀏覽器的控制臺中發(fā)出警告坪创。
注意在 JavaScript 中對象和數組是通過引用傳入的,所以對于一個數組或對象類型的 prop 來說姐赡,在子組件中改變這個對象或數組本身將會影響到父組件的狀態(tài)莱预。
兩種常見的prop情形
一種是父組件傳遞初始值進來,子組件將它作為初始值保存起來项滑,在自己的作用域 下可以隨意使用和修改依沮。這種情況可以在組件 data 內再聲明一個數據,引用父組件 的 prop
步驟一:注冊組件
步驟二:將父組件的數據傳遞進來枪狂,并在子組件中用props接收 步驟三:將傳遞進來的數據通過初始值保存起來
props: ['initialCounter'], data: function () { return { counter: this.initialCounter } }
另一種情況就是 prop 作為需要被轉變的原始值傳入危喉。這種情況用計算屬性就可以了
步驟一:注冊組件
步驟二:將父組件的數據傳遞進來,并在子組件中用props接收 步驟三:將傳遞進來的數據通過計算屬性進行重新計算
props: ['size'], computed: { normalizedSize: function () { return this.size.trim().toLowerCase() } }
自定義事件
v-model
一個組件上的v-model會利用名為value的prop和名為input的事件州疾,但是像但是像單選框辜限、復選框等類型的輸入形控件可能會將value特性用于不同的目的
model選項可以用來避免這樣的沖突
Vue.component('base-checkbox', {
model: {
prop: 'checked',
event: 'change'
},
props: {
checked: Boolean
},
template: `
<input
type="checkbox"
v-bind:checked="checked"
v-on:change="$emit('change', $event.target.checked)"
>
`
})
現在在這個組件上使用v-model的時候
<base-checkbox v-model="lovingVue"></base-checkbox>
這里的 lovingVue
的值將會傳入這個名為 checked
的 prop。同時當 `` 觸發(fā)一個 change
事件并附帶一個新的值的時候严蓖,這個 lovingVue
的屬性將會被更新薄嫡。
.sync修飾符
對prop進行雙向綁定氧急,但真正的雙向綁定會帶來維護上的問題,因為子組件可以修改父組件岂座,但在父組件和子組件都沒有明顯的改動來源
推薦updata:myPropName
的模式取而代之。
在一個包含title prop的假設組件中杭措,我們可以用以下方法表達對其復新值的意圖
this.$emit('updata:title',newTitle)
然后父組件可以監(jiān)聽那個事件并根據需要更新一個本地的數據屬性费什。
<text-document
v-bind:title="doc.title"
v-on:update:title="doc.title = $event"
></text-document>
//doc.title = newTitle
1.當updata:title事件被觸發(fā)時,將newTitle通過自定義的updata:title事件拋出
2. 在父組件上監(jiān)聽并綁定本地數據手素,實現雙向綁定
為了方便起見鸳址,給這種模式提供一個縮寫.sync修飾符
<text-document v-bind:title.sync="doc.title"></text-document>
//子組件
this.$emit('updata:title',newTitle)
關于prop的雙向綁定
舉個例子就以title改變?yōu)槔?/p>
父 ->子
父的本地數據 data下的doc.title ->
父組件v-bind:title="doc.title"->
子組件的props title:{type:String}
子組件使用props可寫在子組件data中
子 -> 父
子組件 this.$emit('updata:title',newTitle) ->
父組件 v-on:update:title="doc.title = $event" ->
父組件 v-bind:title="doc.title" ->
父組件 data doc.title 改變
prop雙向綁定相比v-model更靈活,總結父子組件上的v-bind時雙向綁定的數據接口泉懦,父到子通過props 稿黍,子到父通過自定義事件。
關于在組件上使用v-model的雙向綁定
因為原生的JavaScript的<input>有value屬性 所以為了父到子通信
舉個例子
父->子
父自定義組件的data->
父的this.msg ->
父組件v-bind:value= 'msg' ->
子組件的props value:{type:String}改變 ->
子組件v-bind:value = value(來自子props)>
子的JavaScript<input>
因為原生的JavaScript的<input>有value屬性 所以為了父到子通信 父和子都要動態(tài)綁定value屬性崩哩。
子->父
子組件的JavaScript<input> ->
子組件輸入改變v-bind:value->
子組件v-on:input:$emit('input' , $event.target.value)
->
父組件v-on:input(msg = $event) ->
父的this.msg ->
父的data ->
父的{{msg}}
因為原生的JavaScript的<input>有input事件巡球,所以為了子到父通信,子組件觸發(fā)input事件時采用自定義input事件邓嘹,在父組件上監(jiān)聽input事件
插槽slot
一條規(guī)則
父級模板里的所有內容都是在父級作用域中編譯的酣栈;子模板里的所有內容都是在子作用域中編譯的。
編譯作用域
<navigation-link url="/profile">
Clicking here will send you to: {{ url }}
<!--
這里的 `url` 會是 undefined汹押,因為 "/profile" 是
_傳遞給_ <navigation-link> 的而不是
在 <navigation-link> 組件*內部*定義的矿筝。
-->
</navigation-link>
后備內容
<button type="submit">
<slot>Submit</slot>
</button>
如果提供內容Submit就會被取而代之
具名插槽slot
新語法v-slot或#
v-slot:default
v-slot:name
作用域插槽slot
V-slot:name = "slotProps"
動態(tài)組件&異步組件
用is在多標簽的界面來切換不同組件的時候,有時需要保持這些組件的狀態(tài)棚贾,避免反復沖渲染導致的性能問題
讓重新創(chuàng)建的動態(tài)組件能夠在它們被第一次創(chuàng)建的時候緩存下來窖维。為了解決這個問題,可以用個<keep-alive>
元素將其動態(tài)組件包裹起來妙痹。
<keep-alive>
<component v-bind:is="currentTabComponent"></component>
</keep-alive>
里面的組件一定要有自己的名字
處理邊界情況
訪問元素&組件
- 訪問根實例$root: 對于小型的有少量的組件應用來說是很方便铸史,大型項目使用vuex來管理應用的狀態(tài)
- 訪問父組件實例$parent:用與簡單直接的父子組件,當需要向任意更深層的組件提供上下文信息使怯伊,使用依賴注入
- 訪問子組件實例或子元素$refs:在組件渲染完成后生效沛贪。
依賴注入
provide inject
- provide選項,允許我們指定我們想要提供給后代組件的數據方法震贵。
- inject選項利赋,在后代組件里,使用inject選項來接受指定的想要添加在這個實例上的屬性
可以猩系;把依賴注入看作一部分"大范圍有效的prop"一樣
- 祖先組件不需要知道哪些后代組件使用它提供的屬性
- 后代組件不需要知道被注入的屬性來自哪里
程序化的事件偵聽器
組件之間的循環(huán)應用
兩個相互依賴的組件A媚送、B ,需要給系統(tǒng)一個點寇甸,告訴系統(tǒng)A是需要B的塘偎,但我們不需要向解析B
- 在生命周期鉤子beforeCreate時注冊
- 在本地注冊組件的時候疗涉,使用webpack的一步import