內(nèi)直接使用組件時(shí)無效的。這種情況下,可以使用特殊的is屬性來掛載組件。
Vue.component("my-component", {
template: `這里是組件內(nèi)容
`
});
常見的限制元素還有、
、。
除了template選項(xiàng)外,組件中還可以像Vue實(shí)例那樣使用其他的選項(xiàng),比如data、computed、methods等。
但是在使用data時(shí),data必須是函數(shù),然后將數(shù)據(jù)return出去。
JavaScript對象是引用關(guān)系,如果return的對象引用了外部的一個(gè)對象,那這個(gè)對象就是共享的,任何一方修改都會(huì)同步。
使用props傳遞數(shù)據(jù)
組件不僅要把模板的內(nèi)容進(jìn)行復(fù)用,更重要的是組件間進(jìn)行通信。
通常父組件的模板中包含子組件,父組件要正向地向子組件傳遞數(shù)據(jù)或參數(shù),子組件接收后根據(jù)參數(shù)的不同渲染不同的內(nèi)容或者執(zhí)行操作。這個(gè)正向傳遞數(shù)據(jù)的過程通過props來實(shí)現(xiàn)。
在組件中,使用選項(xiàng)props聲明需要從父級接收的數(shù)據(jù),props的值可以是兩種,一種是字符串?dāng)?shù)組,一種是對象。
props: ["message"],
template: `{{message}}
`,
props中聲明的數(shù)據(jù)與組件data函數(shù)中return的數(shù)據(jù)主要區(qū)別就是props的數(shù)據(jù)來自父級,而data中的是組件自己的數(shù)據(jù),作用域是組件本身,這兩種數(shù)據(jù)都可以在模板template及計(jì)算屬性computed和方法methods中使用。
由于HTML特性不區(qū)分大小寫,當(dāng)使用DOM模板時(shí),駝峰命名的props名稱要轉(zhuǎn)為短橫線分割命名。
有時(shí)候,傳遞的數(shù)據(jù)并不是直接寫死,而是來自父級的動(dòng)態(tài)數(shù)據(jù),這時(shí)可以使用指令v-bind動(dòng)態(tài)綁定props的值,當(dāng)父組件的數(shù)據(jù)變化時(shí),也會(huì)傳遞子組件。
props: ["message"],
template: `{{message}}
`,
data: {
parentMessage: ""
}
這里用v-model綁定了父級的數(shù)據(jù)parentMessage,當(dāng)通過輸入框任意輸入時(shí),子組件接收到的props["message"]也會(huì)實(shí)時(shí)響應(yīng),并更新組件模板。
單向數(shù)據(jù)流
業(yè)務(wù)中會(huì)經(jīng)常遇到兩種需要改變prop的情況,一種是父組件傳遞初始值進(jìn)來,子組件將它作為初始值保存起來,在自己的作用域下可以隨意使用和修改。這種情況可以在組件data內(nèi)再聲明一個(gè)數(shù)據(jù),引用父組件的prop。
Vue.component("my-component", {
props: ["initCount"],
template: `{{count}}
`,
data() {
return {
count:this.initCount
}
}
});
組件中聲明了數(shù)據(jù)count,它在組件初始化時(shí)會(huì)獲取來自父組件的initCount,之后就與之無關(guān)了,只用維護(hù)count,這樣就可以避免直接操作initCount。
另一種情況就是prop作為需要被轉(zhuǎn)變的原始值傳入,這種情況用計(jì)算屬性就可以。
Vue.component("my-component", {
props: ["width"],
template: `組件內(nèi)容
`,
computed: {
style: function () {
return {
width: this.width + "px"
}
}
}
});
因?yàn)橛肅SS傳遞寬度要帶單位(px),數(shù)值計(jì)算一般不帶單位,所以統(tǒng)一在組件內(nèi)使用計(jì)算屬性。
在JavaScript中對象和數(shù)組時(shí)引用類型,指向同一個(gè)內(nèi)存空間,所以props是對象和數(shù)組時(shí),在子組件內(nèi)改變是會(huì)影響父組件。
數(shù)組驗(yàn)證
當(dāng)prop需要驗(yàn)證時(shí),需要對象寫法。
一般當(dāng)組件需要提供給別人使用時(shí),推薦都進(jìn)行數(shù)據(jù)驗(yàn)證。比如某個(gè)數(shù)據(jù)必須是數(shù)字類型,如果傳入字符串,就會(huì)在控制臺(tái)彈出警告。
See the Pen prop by whjin (@whjin) on CodePen.
驗(yàn)證的type類型可以是:
String
Number
Boolean
Object
Array
Function
type也可以是一個(gè)自定義構(gòu)造器,使用instanceof檢測。
組件通信
組件關(guān)系可分為父組件通信、兄弟組件通信、跨級組件通信。
自定義事件
當(dāng)子組件需要向父組件傳遞數(shù)據(jù)時(shí),就要用到自定義事件。
v-on除了監(jiān)聽DOM事件外,還可以用于組件之間的自定義事件。
JavaScript的設(shè)計(jì)模式——觀察者模式方法:
dispatchEvent
addEventListener
Vue組件的子組件用$emit()來觸發(fā)事件,父組件用$on()來監(jiān)聽子組件的事件。
父組件也可以直接在子組件的自定義標(biāo)簽上使用v-on來監(jiān)聽子組件觸發(fā)的自定義事件。
See the Pen 自定義事件 by whjin (@whjin) on CodePen.
在改變組件的data "counter"后,通過$emit()再把它傳遞給父組件,父組件用@increase和@reduce。$emit()方法的第一個(gè)參數(shù)是自定義事件的名稱。
除了用v-on在組件上監(jiān)聽自定義事件外,也可以監(jiān)聽DOM事件,這時(shí)可以用.native修飾符表示監(jiān)聽時(shí)一個(gè)原生事件,監(jiān)聽的是該組件的根元素。
使用v-model
Vue可以在自定義組件上使用v-model指令。
組件$emit()的事件名時(shí)特殊的input,在使用組件的父級,并沒有在上使用@input="handler",而是直接用了v-model綁定的一個(gè)數(shù)據(jù)total。
v-model還可以用來創(chuàng)建自定義的表單輸入組件,進(jìn)行數(shù)據(jù)雙向綁定。
See the Pen v-model雙向綁定 by whjin (@whjin) on CodePen.
實(shí)現(xiàn)這樣一個(gè)具有雙向綁定的v-model組件要滿足下面兩個(gè)要求:
接收一個(gè)value屬性
在有新的value時(shí)觸發(fā)input事件
非父子組件通信
在實(shí)際業(yè)務(wù)中,除了父子組件通信外,還有很多非父子組件通信的場景,非父子組件一般有兩種,兄弟組件和跨多級組件。
在Vue 1.x版本中,除了$emit()方法外,還提供了¥dispatch()和$broadcast()。
$dispatch()用于向上級派發(fā)事件,只要是它的父級(一級或多級以上),都可以在Vue實(shí)例的events選項(xiàng)內(nèi)接收。
此實(shí)例只在Vue 1.x版本中有效:
See the Pen dispatch派發(fā)事件 by whjin (@whjin) on CodePen.
$broadcast()是由上級向下級廣播事件,用法完全一致,方向相反。
這兩種方法一旦發(fā)出事件后,任何組件都可以接收到,就近原則,而且會(huì)在第一次接收到后停止冒泡,除非返回true。
這些方法在Vue 2.x版本中已廢棄。
在Vue 2.x中,推薦任何一個(gè)空的Vue實(shí)例作為中央事件總線(bus),也就是一個(gè)中介。
See the Pen Vue-bus事件總線 by whjin (@whjin) on CodePen.
首先創(chuàng)建了一個(gè)名為bus的空的Vue實(shí)例;然后全局定義了組件component-a;最后創(chuàng)建了Vue實(shí)例app。
在app初始化時(shí),也就是在生命周期mounted鉤子函數(shù)里監(jiān)聽了來自bus的事件on-message,而在組件component-a中,點(diǎn)擊按鈕后會(huì)通過bus把事件on-message發(fā)出去。此時(shí)app就會(huì)接收到來自bus的事件,進(jìn)而在回調(diào)里完成自己的業(yè)務(wù)邏輯。
這種方法巧妙而輕量地實(shí)現(xiàn)了任何組件間的通信,包括父子、兄弟、跨級。
如果深入使用,可以擴(kuò)展bus實(shí)例,給它添加data、methods、computed等選項(xiàng),這些都是可以公用的。
在業(yè)務(wù)中,尤其是協(xié)同開發(fā)時(shí)非常有用,因?yàn)榻?jīng)常需要共享一些通用的信息,比如用戶登錄的昵稱、性別、郵箱等,還有用戶的授權(quán)token等。
只需在初始化時(shí)讓bus獲取一次,任何時(shí)間、任何組件就可以從中直接使用,在單頁面富應(yīng)用(SPA)中會(huì)很實(shí)用。
除了中央事件總線bus外,還有兩種方法可以實(shí)現(xiàn)組件間通信:父鏈和子組件索引。
父鏈
在子組件中,使用this.$parent可以直接訪問該組件的父實(shí)例或組件,父組件也可以通過this.$children訪問它所有的子組件,而且可以遞歸向上或向下無限訪問,直到根實(shí)例或最內(nèi)層的組件。
Vue.component("component-a", {
template: ``,
methods: {
handleEvent: function () {
this.$parent.message = "來自組件component-a的內(nèi)容"
}
}
});
var app = new Vue({
el: "#app",
data: {
message: ""
}
});
盡管Vue允許這樣操作,但在業(yè)務(wù)中,子組件應(yīng)該盡可能地避免依賴父組件的數(shù)據(jù),更不應(yīng)該去主動(dòng)修改它的數(shù)據(jù),因?yàn)檫@樣使得父子組件緊耦合,只看父組件,很難理解父組件的狀態(tài),因?yàn)樗赡鼙蝗我饨M件修改,理想狀態(tài)下,只有組件自己能修改它的狀態(tài)。
父子組件最好還是通過props和$emit()來通信。
子組件索引
當(dāng)子組件較多時(shí),通過this.$children來遍歷出需要的一個(gè)組件實(shí)例是比較困難的,尤其是組件動(dòng)態(tài)渲染時(shí),它們的序列是不固定的。
Vue提供了子組件索引的方法,用特殊的屬性ref來為子組件指定一個(gè)索引名稱。
See the Pen Vue-$refs by whjin (@whjin) on CodePen.
在父組件模板中,子組件標(biāo)簽上使用ref指定一個(gè)名稱,并在父組件內(nèi)通過this.$refs來訪問指定名稱的子組件。
$refs只在組件渲染完成后才填充,并且它是非響應(yīng)式的。它僅僅作為一個(gè)直接訪問子組件的應(yīng)急方案,應(yīng)當(dāng)避免在模板或計(jì)算屬性中使用$refs。
Vue 2.x將v-el和v-ref合并成ref,Vue會(huì)自動(dòng)去判斷是普通標(biāo)簽還是組件。
使用slot分發(fā)內(nèi)容
當(dāng)需要讓組件組合使用,混合父組件的內(nèi)容與子組件的模板時(shí),就會(huì)用到slot,這個(gè)過程叫做內(nèi)容分發(fā)。
組件不知道它的掛載點(diǎn)會(huì)有什么內(nèi)容。掛載點(diǎn)的內(nèi)容是由的父組件決定的。
組件很可能有它自己的模板。
props傳遞數(shù)據(jù)、events觸發(fā)事件和slot內(nèi)容分發(fā)就構(gòu)成了Vue組件的3個(gè)API來源,再復(fù)雜的組件也是由這3部分構(gòu)成。
作用域
父組件中的模板:
{{message}}
這里的message就是一個(gè)slot,但是它綁定的是父組件的數(shù)據(jù),而不是組件的數(shù)據(jù)。
父組件模板的內(nèi)容是在父組件作用域內(nèi)編譯,子組件模板的內(nèi)容是在子組件作用域內(nèi)編譯。
Vue.component("child-component", {
template: `子組件1
`,
});
var app = new Vue({
el: "#app",
data: {
showChild: true
}
});
這里的狀態(tài)showChild綁定的是父組件的數(shù)據(jù)。
在子組件上綁定數(shù)據(jù):
Vue.component("child-component", {
template: `子組件
`,
data() {
return {
showChild: true
}
}
});
var app = new Vue({
el: "#app",
});
因此,slot分發(fā)的內(nèi)容,作用域是在父組件上。
單個(gè)slot
在子組件內(nèi)使用特殊的元素就可以為這個(gè)組件開啟一個(gè)slot(插槽),在父組件模板里,插入在子組件標(biāo)簽內(nèi)的所有內(nèi)容將替代子組件的標(biāo)簽及它的內(nèi)容。
分發(fā)的內(nèi)容
更多分發(fā)的內(nèi)容
Vue.component("child-component", {
template: `
如果沒有父組件插入內(nèi)容,我將作為默認(rèn)出現(xiàn)。
`,
});
var app = new Vue({
el: "#app",
});
子組件child-component的模板內(nèi)定義了一個(gè)元素,并且用一個(gè)
作為默認(rèn)的內(nèi)容,在父組件沒有使用slot時(shí),會(huì)渲染這段默認(rèn)的文本;如果寫入了slot,就會(huì)替換整個(gè)。
子組件內(nèi)的備用內(nèi)容,它的作用域是子組件本身。
具名Slot
給元素指定一個(gè)name后可以分發(fā)多個(gè)內(nèi)容,具名slot可以與單個(gè)slot共存。
See the Pen Vue-slot by whjin (@whjin) on CodePen.
子組件內(nèi)聲明了3個(gè)元素,其中在內(nèi)的
沒有使用
name特性,它將作為默認(rèn)
slot出現(xiàn),父組件沒有使用
slot特性的元素與內(nèi)容都將出現(xiàn)在這里。
如果沒有指定默認(rèn)的匿名slot,父組件內(nèi)多余的內(nèi)容都將被拋棄。
在組合使用組件時(shí),內(nèi)容分發(fā)API至關(guān)重要。
作用域插槽
作用域插槽是一種特殊的slot,使用一個(gè)可以復(fù)用的模板替換已渲染元素。
來自父組件的內(nèi)容
{{props.msg}}
Vue.component("child-component", {
template: `
`,
});
var app = new Vue({
el: "#app",
});
子組件的模板,在元素上有一個(gè)類似props傳遞數(shù)據(jù)給組件的寫法msg="xxx",將數(shù)據(jù)傳遞到插槽。
父組件中使用了元素,而且擁有一個(gè)scope="props"的特性,這里的props是一個(gè)臨時(shí)變量。
template內(nèi)可以通過臨時(shí)變量props訪問來自子組件插槽的數(shù)據(jù)msg。
作用域插槽更具代表性的用例是列表組件,允許組件自定義應(yīng)該如何渲染列表每一項(xiàng)。
{{props.bookName}}
Vue.component("my-list", {
props: {
books: {
type: Array,
default: function () {
return [];
}
}
},
template: `
`,
});
子組件my-list接收一個(gè)來自父級的prop數(shù)組books,并且將它在name為book的slot上使用v-for指令循環(huán),同時(shí)暴露一個(gè)變量bookName。
作用域插槽的使用場景是既可以復(fù)用子組件的slot,又可以使slot內(nèi)容不一致。
訪問slot
Vue 2.x提供了用來訪問被slot分發(fā)的內(nèi)容的方法$slots。
See the Pen Vue-$slots by whjin (@whjin) on CodePen.
通過$slots可以訪問某個(gè)具名slot,this.$slots.default包括了所有沒有被包含在具名slot中的節(jié)點(diǎn)。
組件高級用法
遞歸組件
給組件設(shè)置name選項(xiàng),組件在它的模板內(nèi)可以遞歸地調(diào)用自己。
Vue.component("child-component", {
name: "child-component",
props: {
count: {
type: Number,
default: 1
}
},
template: `
`,
});
組件遞歸使用可以用來開發(fā)一些具有未知層級關(guān)機(jī)的獨(dú)立組件,比如級聯(lián)選擇器和樹形控件等。
內(nèi)聯(lián)模板
組件的模板一般都是在template選項(xiàng)內(nèi)定義的,Vue提供了一個(gè)內(nèi)聯(lián)模板的功能,在使用組件時(shí),給組件標(biāo)簽使用inline-template特性,組件就會(huì)把它的內(nèi)容當(dāng)做模板,而不是把它當(dāng)內(nèi)容分發(fā),這讓模板更靈活。
See the Pen Vue-inline-template by whjin (@whjin) on CodePen.
在父組件中聲明的數(shù)據(jù)message和子組件中聲明的數(shù)據(jù)msg,兩個(gè)都可以渲染(如果同名,優(yōu)先使用子組件的數(shù)據(jù))。這是內(nèi)聯(lián)模板的缺點(diǎn),就是作用域比較難理解,如果不是非常特殊的場景,建議不要輕易使用內(nèi)聯(lián)模板。
動(dòng)態(tài)組件
Vue.js提供了一個(gè)特殊的元素用來動(dòng)態(tài)地掛載不同的組件,使用is特性來選擇要掛載的組件。
See the Pen Vue-component by whjin (@whjin) on CodePen.
可以直接綁定在組件對象上:
var Home = {
template: `Welcome home!
`
};
var app = new Vue({
el: "#app",
data: {
currentView: Home
}
});
異步組件
Vue.js允許將組件定義為一個(gè)工廠函數(shù),動(dòng)態(tài)地解析組件。
Vue.js只在組件需要渲染時(shí)觸發(fā)工廠函數(shù),并且把結(jié)果緩存起來,用于后面的再次渲染。
Vue.component("child-component", function (resolve, reject) {
window.setTimeout(function () {
resolve({
template: `我是異步渲染的!
`
})
}, 1000)
});
var app = new Vue({
el: "#app",
});
工廠函數(shù)接收一個(gè)resolve回調(diào),在收到從服務(wù)器下載的組件定義時(shí)調(diào)用。也可以調(diào)用reject(reason)指示加載失敗。
其他
$nextTick
異步更新隊(duì)列
Vue在觀察到數(shù)據(jù)變化時(shí)并不是直接更新DOM,而是開啟一個(gè)隊(duì)列,并緩沖在同一個(gè)事件循環(huán)中發(fā)生的所有數(shù)據(jù)變化。在緩沖時(shí)會(huì)去除重復(fù)數(shù)據(jù),從而避免不必要的計(jì)算和DOM操作。然后,在一下個(gè)事件循環(huán)tick中,Vue刷新隊(duì)列并執(zhí)行實(shí)際(已去重的)工作。
Vue會(huì)根據(jù)當(dāng)前瀏覽器環(huán)境優(yōu)先使用原生的Promise.then和MutationObserver,如果都不支持,就會(huì)采用setTimeout代替。
$nextTick就是用來確定什么時(shí)候DOM更新已經(jīng)完成。
See the Pen Vue-$nextTick by whjin (@whjin) on CodePen.
X-Templates
Vue提供了另一種定義模板的方式,在
Vue.component("my-component", {
template: `#my-component`,
});
var app = new Vue({
el: "#app",
});
手動(dòng)掛載實(shí)例
在一些非常特殊的情況下,需要?jiǎng)討B(tài)地創(chuàng)建Vue實(shí)例,Vue提供了Vue.extend和$mount兩個(gè)方法來手動(dòng)掛載一個(gè)實(shí)例。
Vue.extend是基礎(chǔ)Vue構(gòu)造器,創(chuàng)建一個(gè)“子類”,參數(shù)是一個(gè)包含組件選項(xiàng)的對象。
如果Vue實(shí)例在實(shí)例化時(shí)沒有收到el選項(xiàng),它就處于“未掛載”狀態(tài),沒有關(guān)聯(lián)的DOM元素??梢允褂?b>$mount手動(dòng)地掛載一個(gè)未掛載的實(shí)例。這個(gè)方法返回實(shí)例自身,因而可以鏈?zhǔn)秸{(diào)用其他實(shí)例方法。
See the Pen Vue-$mount by whjin (@whjin) on CodePen.
除了以上寫法外,還有兩種寫法:
new MyComponent().$mount("#app");
new MyComponent({
el: "#app"
})
手動(dòng)掛載實(shí)例(組件)是一種比較極端的高級用法,在業(yè)務(wù)中幾乎用不到,只在開發(fā)一些復(fù)雜的獨(dú)立組件時(shí)可能會(huì)使用。
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://m.hztianpu.com/yun/102637.html
-
摘要:指令帶有前綴,以表示它們是提供的特殊屬性。最后,我們需要為賦值世界舞王尼古拉斯趙四世界舞王尼古拉斯趙四初學(xué)就到這里了,相信你已經(jīng)在腦子里確定了的原理的概念也已經(jīng)非常清楚了,希望你能夠在學(xué)習(xí)的道路上越走越遠(yuǎn),最后感謝你的瀏覽。
vue.js
vue介紹
Vue.js(讀音 /vju?/,類似于 view) 是一套構(gòu)建用戶界面的漸進(jìn)式框架。與其他重量級框架不同的是,Vue 采用自底向上增量...
omgdog
評論0
收藏0
-
摘要:依舊采取傳統(tǒng)的開發(fā)技術(shù)棧進(jìn)行開發(fā),同時(shí)在終端的運(yùn)行體驗(yàn)不輸。首先來看下前端開發(fā)框架目前與構(gòu)成了三大最流行的前端開發(fā)框架,具有組件化以及三大特性,還學(xué)習(xí)的,引入了狀態(tài)管理模塊。
摘要: WEEX依舊采取傳統(tǒng)的web開發(fā)技術(shù)棧進(jìn)行開發(fā),同時(shí)app在終端的運(yùn)行體驗(yàn)不輸native app。其同時(shí)解決了開發(fā)效率、發(fā)版速度以及用戶體驗(yàn)三個(gè)核心問題。那么WEEX是如何實(shí)現(xiàn)的?目前WEEX已經(jīng)完全開...
ls0609
評論0
收藏0
-
摘要:在這一步,實(shí)例已完成以下的配置數(shù)據(jù)觀測,屬性和方法的運(yùn)算,事件回調(diào)??梢灾苯訉懙葮?biāo)簽的寫法之前會(huì)的工程師上手框架的成本較低
簡介
1.美團(tuán)工程師推出的基于Vue.js封裝的用于開發(fā)小程序的框架2.融合了原生小程序和Vue.js的特點(diǎn)3.可完全組件化開發(fā)
特點(diǎn)
1.組件化開發(fā)2.完成的Vue.js開發(fā)體驗(yàn)(前提是熟悉Vue)3.可使用Vuex管理狀態(tài)4.Webpack構(gòu)建項(xiàng)目5.最終H5...
IamDLY
評論0
收藏0
-
本文主要從8個(gè)章節(jié)詳解vue技術(shù)揭秘,小編覺得挺有用的,分享給大家。
為了把 Vue.js 的源碼講明白,課程設(shè)計(jì)成由淺入深,分為核心、編譯、擴(kuò)展、生態(tài)四個(gè)方面去講,并拆成了八個(gè)章節(jié),如下:
準(zhǔn)備工作
Introduction
認(rèn)識(shí) Flow
Vue.js 源碼目錄設(shè)計(jì)
Vue.js 源碼構(gòu)建
從入口開始
數(shù)據(jù)驅(qū)動(dòng)
Introduction
new Vue 發(fā)生了什么
Vue ...
saucxs
評論0
收藏0
男|高級講師
-
閱讀 1480·2023-04-26 03:05
-
閱讀 941·2021-10-19 11:43
-
閱讀 3557·2021-09-26 09:55
-
閱讀 954·2019-08-30 15:56
-
閱讀 1209·2019-08-30 15:44
-
閱讀 1385·2019-08-30 15:44
-
閱讀 2882·2019-08-30 14:23
-
閱讀 3444·2019-08-30 13:13