目錄
正文
Vue渲染的兩大基礎(chǔ)方式
new 一個(gè)Vue的實(shí)例
這個(gè)我們一般會(huì)使用在掛載根節(jié)點(diǎn)這一初始化操作上:
new Vue({ el: '#app'})
注冊(cè)組件并使用
通過Vue.component()去注冊(cè)一個(gè)組件,你就可以全局地使用它了,具體體現(xiàn)在每個(gè)被new的 Vue
實(shí)例/注冊(cè)組件, 的template選項(xiàng)屬性或者對(duì)應(yīng)的DOM模板中,去直接使用
注冊(cè)組件
全局注冊(cè)
例如,放在通過new創(chuàng)建的Vue實(shí)例當(dāng)中:
Vue.component('my-component', { template: '<p>我是被全局注冊(cè)的組件</p>'})/* Vue.component(組件名稱[字符串], 組件對(duì)象)*/new Vue({ el: '#app', template: '<my-component></my-component>'})
demo:
又例如,放在另外一個(gè)組件中:
Vue.component('my-component', { template: '<p>我是被全局注冊(cè)的組件</p>'}) Vue.component('other-component', { template: '<div>我是另一個(gè)全局組件:<my-component></my-component></div>'})new Vue({ el: '#app', template: '<other-component></other-component>'})
局部注冊(cè)
const child ='<p>我是局部注冊(cè)的組件</p>''#app''<my-component></my-component>''my-component'
demo:
通過組件組合(嵌套),構(gòu)建大型的應(yīng)用:
const child ='<p>我是child組件</p>'='<p>我是father組件,我包含了:<child-component></child-component></p>''child-component'='<p>我是grandFather組件,我包含了:<father-component></father-component></p>''father-component''#app''<my-component></my-component>''my-component'
demo:
通過new創(chuàng)建Vue實(shí)例, 全局注冊(cè)組件,局部注冊(cè)組件三者的使用頻率(場(chǎng)景)
1.new Vue(), 盡管在Vue官方文檔上在相當(dāng)多的例子中使用到了創(chuàng)建Vue實(shí)例這個(gè)操作,實(shí)際上它的使用可能并沒有你想象的那么平凡,在很多時(shí)候,它可能就只在掛載根實(shí)例的時(shí)候使用到
【這段話給寫react框架的人看】
對(duì) new Vue()做個(gè)最簡(jiǎn)單的描述?。涸谑褂蒙项愃朴赗eactDOM.render()...對(duì),就是那個(gè)一開始你擼文檔的時(shí)候覺得好像很重要,但最后發(fā)現(xiàn)在整個(gè)APP中就只使用了一次的那個(gè)頂層API ....
2.全局注冊(cè)組件的使用也不太頻繁,首先來說,如果大量使用全局注冊(cè)的話,當(dāng)然容易產(chǎn)生組件的命名沖突,這就意味著你在構(gòu)建大型組件的時(shí)候,你不應(yīng)該選擇用全局注冊(cè)構(gòu)建具體的細(xì)顆粒度的組件(實(shí)際上即使是小型應(yīng)用也不推薦啦~~~)
那么全局注冊(cè)組件會(huì)在哪里使用到呢?
2.1 有許多可全局復(fù)用的公共UI組件,你可能希望通過Vue.component({ ...})的方式全局注冊(cè)它
2.2 可以很簡(jiǎn)單地添加第三方UI框架
【對(duì)比】大凡使用過一些UI框架的人,都知道一般情況下,使用這些UI組件的方式就是為元素添加類,像這樣:
<div class='UI框架中定義的類名'></div>
而在Vue中,你可以通過直接使用組件名稱去使用,就和react相關(guān)的UI框架一樣
3.大多數(shù)時(shí)候我們通過組件組合的方式構(gòu)建頁面的時(shí)候,運(yùn)用的是局部注冊(cè),就像上文所提及的那樣
【注意點(diǎn)】
1.注冊(cè)組件必須發(fā)生在根實(shí)例初始化前
2.data是函數(shù)!
Vue中的props數(shù)據(jù)流
【寫給react學(xué)習(xí)者們看的】這跟react中設(shè)計(jì)非常類似,連名稱都相同,所以學(xué)過react的同學(xué)看這里應(yīng)該會(huì)很輕松吧~~
這里要用到Vue的一個(gè)選項(xiàng)屬性——props;
通過在注冊(cè)組件中聲明需要使用的props,然后通過props中與模板中傳入的對(duì)應(yīng)的屬性名,去取用這傳入的值
例子:
model部分:
Vue.component('my-component', { props: ['name', 'birthTime'], template: '<p>我叫:{{name}} 我出生于:{{birthTime}}</p>', created: function () { console.log('在created鉤子函數(shù)中被調(diào)用') console.log('我叫:', this.name) console.log('我出生于:', this.birthTime) } })new Vue({ el: '#app'})
HTML部分:
<div id='app'> <my-component name="彭湖灣" birth-time="1997 -06 - 06"></my-component> <div id='app'>
demo:
你在注冊(cè)組件的時(shí)候通過props選項(xiàng)聲明了要取用的多個(gè)prop:
props: ['name', 'birthTime'],
然后在模板中通過屬性傳值的方式進(jìn)行數(shù)據(jù)的注入:
<my-component name="彭湖灣" birth-time="1997 -06 - 06"></my-component>
再然后我們就可以在注冊(cè)組件的模板中使用到props選項(xiàng)中聲明的值了:
template: '<p>我叫:{{name}} 我出生于:{{birthTime}}</p>'
這里要注意幾個(gè)點(diǎn):
props取值的方式
1.如果是在注冊(cè)組件的模板內(nèi)部,直接通過prop的名稱取就OK了,例如
template: '<p>我叫:{{name}} 我出生于:{{birthTime}}</p>'
2.如果在注冊(cè)組件的其他地方,用this.prop的方式取用,例如
console.log('我叫:', this.name)
props內(nèi)寫的是駝峰命名法,為什么在HTML(模板)中又用了短橫線命名法?
(camelCased VS kebab-case)
首先我們知道,Vue組件的模板可以放在兩個(gè)地方:
1. Vue組件的template選項(xiàng)屬性中,作為模板字符串
2.放在index.html中,作為HTML
這里的問題在于,HTML特性是不區(qū)分大小寫的
所以在Vue注冊(cè)組件中通用的駝峰命名法,顯然不適用于HTML中的Vue模板,所以
在HTML中寫入props屬性,必須寫短橫線命名法(就是把原來props屬性中的每個(gè)prop大寫換成小寫,并且在前面加個(gè)“-”)
總結(jié):
1.在template選項(xiàng)屬性中,可以寫駝峰命名法,也可以寫短橫線命名法
2.在HTML(模板)中,只能寫短橫線命名法,不能寫駝峰
下面我就來證明以上兩點(diǎn):
對(duì)1
Vue.component('my-component''name', 'birthTime''<p>我叫:{{name}} 我出生于:{{birthTime}}</p>''在created鉤子函數(shù)中被調(diào)用''我叫:', '我出生于:',
new Vue({ el: '#app', template: '<my-component name="彭湖灣" birthTime="1997 -06 - 06"></my-component>'})
demo:
name和birthTime都正常顯示,這說明在template模板字符串中,是可以寫駝峰的
(請(qǐng)注意到一點(diǎn):name既符合駝峰寫法也符合短橫線寫法,而birthTime只符合駝峰寫法)
JS部分
Vue.component('my-component', { props: ['name', 'birthTime'], template: '<p>我叫:{{name}} 我出生于:{{birthTime}}</p>', created: function () { console.log('在created鉤子函數(shù)中被調(diào)用') console.log('我叫:', this.name) console.log('我出生于:', this.birthTime) } }) new Vue({ el: '#app'})
HTML(模板)部分
<div id='app'> <my-component name="彭湖灣" birthTime="1997 -06 - 06"></my-component> </div>
demo:
這里有個(gè)有趣的現(xiàn)象:name對(duì)應(yīng)的值可以正常地顯示,但!birthTime不能
這是因?yàn)樯衔奶岬降模?/span>
name既符合駝峰寫法也符合短橫線寫法,而birthTime只符合駝峰寫法,不符合HTML要求的短橫線寫法
使用v-bind的必要性:props不綁定的前提下,只能被作為字符串解析
Vue.component('my-component', { props: ['number'], template: '<p>檢測(cè)number的類型</p>', created: function () { console.log(typeof this.number) } })new Vue({ el: '#app', template: '<my-component number="1"></my-component>'})
demo:
number被檢測(cè)為字符串,這表明在不加v-bind綁定的情況下,props接受到的都是字符串,(注:如果被作為javacript,”1“會(huì)被解析為Number的1,而” ‘1’ “才會(huì)被解析為String的1)
沒錯(cuò),僅僅這一點(diǎn)就會(huì)讓我們非常為難,所以,我們需要使用v-bind:
當(dāng)使用v-bind的時(shí)候,在模板中props將會(huì)被作為javascript解析:
Vue.component('my-component', { props: ['number'], template: '<p>檢測(cè)number的類型</p>', created: function () { console.log(typeof this.number) } })new Vue({ el: '#app', template: '<my-component v-bind:number="1"></my-component>'})
demo:
這可能拓展我們對(duì)v-bind的認(rèn)知:
1.用v-bind一般是為了做數(shù)據(jù)的動(dòng)態(tài)綁定
2.有時(shí)v-bind并不為了實(shí)現(xiàn)點(diǎn)1,只是純粹為了讓字符串內(nèi)的內(nèi)容被當(dāng)作JS解析罷了
Vue的自定義事件
自定義事件是我非常喜歡的Vue的一大特性!?。?看文檔的第一眼我就對(duì)它情有獨(dú)鐘(雖然那一天離現(xiàn)在也就幾天而已的時(shí)間。。。)
先展示代碼和demo:
Vue.component('button-counter', { template: '<button v-on:click="increment">{{counter}}</button>', data: function () { return { counter: 0 } }, methods: { increment: function () { this.counter += 1 this.$emit('increment-event') } } }) new Vue({ el: '#app', data: { totalCounter: 0 }, methods: { total_increment: function () { this.totalCounter += 1 } } })
模板HTML部分:
<div id='app'> <button>{{ totalCounter }}</button> </br> <button-counter v-on:increment-event='total_increment'></button-counter> <button-counter v-on:increment-event='total_increment'></button-counter> </div>
demo:
下面兩個(gè)按鈕是兩個(gè)相同的子組件,并和上面那個(gè)按鈕共同組成了父組件。
當(dāng)點(diǎn)擊任意一個(gè)子組件的按鈕,使其加1,都會(huì)使得父組件+1,最終:父組件的數(shù)值 = 子組件的數(shù)值之和
點(diǎn)擊下方左邊button
點(diǎn)擊下方右邊button
自定義事件的原理
通過$emit(event)觸發(fā)一個(gè)自定義事件
然后通過$on(event,callback) 去執(zhí)行對(duì)應(yīng)的callback(回調(diào)函數(shù))
(兩個(gè)event是字符串,且必須名稱相同)
但$on不能在父組件中監(jiān)聽子組件拋出的事件,所以我們要做到這一點(diǎn),可以在父組件的模板中使用到子組件的時(shí)候,直接用v-on綁定 (和$on作用效果一致) 就像上面那樣:
<button-counter v-on:increment-event='total_increment'></button-counter>
這樣一來,自定義事件的雛形就變得和原生事件一樣了
即使這樣,上面的代碼可能還是有些難理解,我認(rèn)為比較重要的是這一段:
increment: function () { this.counter += 1 this.$emit('increment-event') }
因?yàn)槲覀?span style="margin: 0px; padding: 0px; color: rgb(255, 0, 0);">對(duì)于事件的運(yùn)用主要是:利用事件和函數(shù)綁定,從而在事件觸發(fā)的時(shí)候能執(zhí)行相印的函數(shù)
所以! 對(duì)于自定義事件,我們要解決的問題就是,“這個(gè)事件在什么時(shí)候被觸發(fā)” 在上面的代碼中,觸發(fā)事件的時(shí)間(執(zhí)行 this.$emit('increment-event')的時(shí)間)
就恰恰是執(zhí)行this.counter += 1 的時(shí)候
自定義事件的作用
對(duì)此,我主要從兩點(diǎn)闡述我的觀點(diǎn):(非官方文檔內(nèi)容,自己思考的,覺得不對(duì)的可以指出):
自定義事件的作用1 ——“重新定義”了事件監(jiān)聽機(jī)制的范圍
MDN是這樣描述DOM事件的:“DOM事件被發(fā)送以通知代碼已發(fā)生的有趣的事。每個(gè)事件都由基于Event接口的一個(gè)對(duì)象表示”
在我看來:當(dāng)你使用事件的時(shí)候,你可能試圖做這樣一件事情: 在某一個(gè)特定的時(shí)間節(jié)點(diǎn)(或場(chǎng)景)做某個(gè)操作,例如調(diào)用一個(gè)函數(shù)。 而定位這個(gè)“時(shí)間節(jié)點(diǎn)”或“場(chǎng)景”的,就是事件。而我們對(duì)事件最喜歡做的事情,就是把事件和某個(gè)函數(shù)給綁定起來
但我們可能一直都忽略了一個(gè)認(rèn)知:我們認(rèn)知范圍內(nèi)的事件,好像只有原生事件呀?例如click(點(diǎn)擊),focus(聚焦),keydown(按鍵)
我們認(rèn)知內(nèi)的事件,難道只有這些個(gè)固定的范圍嗎?點(diǎn)擊是事件,按下鍵盤按鈕是事件。那么,我們能不能人為地定義一個(gè)事件呢? 例如上面的,我們通過代碼處理,讓"某個(gè)數(shù)據(jù)增加1"也作為一個(gè)事件,從而去觸發(fā)一個(gè)函數(shù)呢?
這,就是自定義事件的目的和魅力
自定義事件的作用2 ——使得父子組件權(quán)責(zé)明確
就讓我們看一下 父組件的這個(gè)模板吧,在這里,我們發(fā)現(xiàn):
1.父組件不知道子組件究竟做了什么(increment事件觸發(fā)前的處理),同時(shí)也無需關(guān)心
2.父組件只要完成它的任務(wù):在increment事件觸發(fā)的時(shí)候執(zhí)行對(duì)應(yīng)的函數(shù)就足夠了
對(duì)子組件反是
所以,從這個(gè)角度上說,自定義事件使得父子組件“權(quán)責(zé)明確”
【注意】官方文檔的示例可能容易制造這樣一種錯(cuò)覺:自定義事件是以原生事件(如click)為基礎(chǔ)的,但實(shí)際上并不是這樣。
雖然自定義事件和原生事件息息相關(guān),但自定義事件并不以原生事件的觸發(fā)為基礎(chǔ)的
Slot的使用
當(dāng)你試圖使用slot的時(shí)候,你可能試圖做這樣一件事情:
用父組件動(dòng)態(tài)地控制子組件的顯示的內(nèi)容
Vue.component('son-component', { template: '<div><slot></slot></div>'})new Vue({ el: '#app'})
模板HTML:
<div id='app'> <p>這是slot的內(nèi)容</p> <son-component> <p>你好,我是slot</p> </son-component> </div>
demo:
【寫給react的同學(xué)看的】你可以把slot看作是個(gè)3.0版本的props.children
通俗的理解:
在父組件模板中使用子組件的時(shí)候,如果在子組件里面嵌套了HTML的內(nèi)容,它會(huì)以”props“的方式傳遞給子組件的模板,并被子組件中的slot接受,例如:
【一個(gè)不太專業(yè)的說法】
<son-component> <p>你好,我是slot</p> </son-component>
等同于
<son-component slot = '<p>你好,我是slot</p>'></son-component>
具名slot
為了使增強(qiáng)slot的用法,使父組件能夠更加靈活地控制子組件,Vue引入了具名slot
通過name屬性,可以把在父組件中控制子組件同時(shí)渲染不同的slot
Vue.component('son-component', { template: '<div><slot name="h1"></slot><slot name="button"></slot><slot name="a"></slot></div>'})new Vue({ el: '#app'})
HTML模板部分:
<div id='app'> <son-component> <h1 slot='h1' >我是標(biāo)題</h1> <button slot='button'>我是按鈕</button> <a href='#' slot='a'>我是鏈接</a> </son-component> </div>
demo:
【注意事項(xiàng)】
1.實(shí)際上,我覺得我這篇文章的語言有些過于羅嗦(其實(shí)很為難,因?yàn)檎f多了怕羅嗦——”太長(zhǎng)不看“),說少了又怕不能完整地表達(dá)自己的意思,這是我權(quán)衡后的所做的結(jié)果
2.文中很多只為知識(shí)點(diǎn)服務(wù),跟實(shí)際的項(xiàng)目構(gòu)建存在很大差異,例如我把很多模板都放在template選項(xiàng)中,而實(shí)際上我們會(huì)使用Vue單文件組件來實(shí)現(xiàn)這些
【完】
http://www.cnblogs.com/penghuwan/p/7222106.html