使用組件的細(xì)節(jié)點(diǎn)
is屬性:
有些html標(biāo)簽如table,ul,ol,select對(duì)哪些標(biāo)簽可以出現(xiàn)在其內(nèi)部是有著嚴(yán)格的要求的。
因此當(dāng)這些標(biāo)簽內(nèi)部出現(xiàn)了自定義組件,有可能會(huì)被作為無效的內(nèi)容提升到外部,導(dǎo)致頁面渲染出錯(cuò)。
而是用is屬性則可以解決這個(gè)問題,在子級(jí)標(biāo)簽中用is屬性來使用自定義組件。
<table>
<tr is="模板名稱"></tr>
</table>子組件中的data必須是一個(gè)函數(shù),并且返回一個(gè)對(duì)象,當(dāng)一個(gè)組件被多次使用的時(shí)候,組件間的數(shù)據(jù)不會(huì)相互影響。
Vue.component('row', {
data:function () {
return{
content:'this is row'
}
},
template:"<tr><td>{{content}}</td></tr>"
})
- 通過ref 獲取dom節(jié)點(diǎn)
<div @click="handdle" ref="hello">
hello world
</div>
handdle:function(){
console.log(this.$refs.hello)
}
父子組件傳值
- 父組件向子組件傳值
父組件通過屬性綁定將值綁定到子組件上,子組件通過 props 屬性來接收,然后子組件就可以使用父組件中傳遞過來的數(shù)據(jù)了。props是一個(gè)數(shù)組。
- 子組件向父組件傳值:
- 子組件通過this.$emit()方法向父組件傳值;
- $emit("事件名",args)第一個(gè)參數(shù)是自定義事件名,第二個(gè)參數(shù)是需要傳遞的數(shù)據(jù)
- 父組件使用v-on監(jiān)聽子組件
- 單向數(shù)據(jù)流
父組件可以隨意向子組件傳遞參數(shù),子組件不可以改變父組件的數(shù)據(jù),否則會(huì)報(bào)警告。
解決辦法:要想改變父組件的參數(shù),在子組件的data屬性中拷貝一份父組件的數(shù)據(jù),然后可以對(duì)數(shù)據(jù)進(jìn)行操作。
<div id="app">
<counter :count="1" @change="handleAdd"></counter>
<counter :count="2" @change="handleAdd"></counter>
<div>{{total}}</div>
</div>
<script>
var counter = {
props:['count'],
data:function(){
return{
number:this.count
}
},
template:'<div @click="handdle">{{number}}</div>',
methods:{
handdle:function(){
this.number++;
this.$emit('change',1)
}
}
}
var app = new Vue({
el:'#app',
data:{
total:3
},
components:{
counter:counter
},
methods: {
handleAdd:function(step){
this.total+=step
}
}
})
</script>
組件參數(shù)校驗(yàn)與非props特性
- 簡單校驗(yàn):限定傳入的值的類型,可以是單個(gè)類型,也可以是一個(gè)數(shù)組。
props:{
content: [String,Number]
}
- 復(fù)雜校驗(yàn):
props:{
content:{
type: String,//數(shù)據(jù)類型
required: false,//是否是必傳
default: 'default content',//如果沒傳值,默認(rèn)值
validator: function(val){//自定義校驗(yàn)器,數(shù)據(jù)必須>5
return (val.length>5)
}
}
}
給組件綁定原生事件
- 在父組件上綁定事件(如:@click.native="handleClick")
- 在vue實(shí)例中的methods下定義事件函數(shù)。
<child @click.native="handleClick" ></child>
傳統(tǒng)方法綁定事件:
- 在子組件上綁定事件
- 在子組件中的methods中設(shè)置相應(yīng)的事件函數(shù),并在函數(shù)中定義自定義事件函數(shù),將自定義事件函數(shù)傳給父組件(如 this.$emit('click'))
- 在父組件上綁定子組件methods函數(shù)中傳來的自定義函數(shù)
- 在父組件methods中設(shè)置對(duì)應(yīng)的事件函數(shù)
非父子組件間的傳值
- vuex,
- 發(fā)布訂閱模式(總線模式)
- 給 Vue 類加上原型屬性 bus, 這樣每個(gè) Vue 實(shí)例都能訪問到原型屬性 bus
Vue.prototype.bus = new Vue()
- 利用 bus 的實(shí)例方法 $emit 觸發(fā)事件
this.bus.$emit('觸發(fā)事件', this.selfContent)
- 再利用生命周期方法(鉤子) mounted 給 bus 綁定監(jiān)聽函數(shù), 在事件觸發(fā)時(shí)執(zhí)行
this.bus.$on('eventName', cellback)
- 建議使用箭頭函數(shù)做為回調(diào)函數(shù),不會(huì)影響回調(diào)函數(shù)中this的指向問題
this.bus.$on('eventName',(msg) => {
this.selfContent = mag;
})
完整代碼
<div id="app">
<child content="Dell"></child>
<child content="Lee"></child>
</div>
<script>
Vue.prototype.bus = new Vue()
Vue.component('child',{
data:function(){
return{
selfContent:this.content
}
},
props:{
content:{
type:String,
}
},
template:'<div @click="handClick">{{selfContent}}</div>',
methods: {
handClick:function () {
this.bus.$emit('change',this.selfContent)
}
},
mounted:function(){
var that = this;
this.bus.$on('change',function(msg){
that.selfContent = msg
})
}
})
var app = new Vue({
el:'#app',
})
</script>
vue中使用插槽
- 插槽:可以使父組件很容易向子組件傳遞DOM元素
- 匿名插槽:父組件內(nèi)部的DOM元素,可以通過子組件的<slot></slot>標(biāo)簽渲染,slot標(biāo)簽中可以寫默認(rèn)的內(nèi)容,如果父組件中不傳遞就顯示默認(rèn)內(nèi)容
Vue.component('child',{
template:'<div>' +
'<slot>默認(rèn)內(nèi)容</slot>' +
'</div>',
})
- 具名插槽:有名字的插槽,父組件中為slot屬性設(shè)置值,子組件slot中使用name屬性接收父組件slot的屬性值可以實(shí)現(xiàn)具名插槽。
<div id="app">
<body-content>
<div class="header" slot="header">header</div>
<div class="footer" slot="footer">footer</div>
</body-content>
</div>
<script>
Vue.component('body-content',{
template:'<div>' +
'<slot name="header">默認(rèn)</slot>' +
'<div class="content">content</div>' +
'<slot name = "footer"></slot>' +
'</div>'
})
var app = new Vue({
el:'#app',
})
</script>
- 作用域插槽
- 使用場(chǎng)景:當(dāng)子組件做循環(huán)的數(shù)據(jù)和結(jié)構(gòu)需要外部傳入時(shí)
- 父組件中必須以
<template slot-scope='自定義'></template>
作為包裹的標(biāo)簽,slot-scope接受子組件傳遞過來的值
- 作用是:可以使父組件靈活的控制樣式
<div id="app">
<child>
<template slot-scope="props">
<h1>{{props.item}}</h1>
</template>
</child>
</div>
<script>
Vue.component('child',{
data:function(){
return{
list:[1,2,3,4]
}
},
template:"<div><ul>" +
"<slot v-for='item of list' :item = item></slot>" +
"</ul></div>"
})
var app = new Vue({
el:'#app',
})
</script>
動(dòng)態(tài)組件與v-once指令
- 使用is與使用:is的區(qū)別:
- is:如果這里使用is,is=后面跟的是字符串,就是指將當(dāng)前使用is替換為名為type的組件,
- :is:如果使用:is,其實(shí),就是v-bind:is,:is=后面跟的就是一個(gè)JS表達(dá)式,表達(dá)式為type指向了type這個(gè)對(duì)象
- vue自帶的動(dòng)態(tài)標(biāo)簽
<component></component>
根據(jù)type的值變換為相應(yīng)的組件
如果點(diǎn)擊按鈕前是type=“one”則會(huì)顯示vue.component(“one”,{})這個(gè)組件
如果點(diǎn)擊前按鈕是type=“two”則會(huì)顯示vue.component(“two”,{})這個(gè)組件
<div id="app">
<component :is="type"></component>
<button @click="handclick">點(diǎn)擊</button>
</div>
<script>
Vue.component('child-one',{
template:'<div>one</div>'
})
Vue.component('child-two',{
template:'<div>two</div>'
})
var app = new Vue({
el:'#app',
data:{
type:'child-one'
},
methods:{
handclick:function(){
this.type = this.type =='child-one'?'child-two':'child-one'
}
}
})
- v-once只對(duì)內(nèi)部渲染一次,如果模板發(fā)生變化,也不會(huì)理會(huì)