父傳子(props、插槽、ref)
一、props
1.代碼實現(xiàn):
父組件
<template>
<!-- 通過:addTodo=""給子組件傳值 -->
<div class="todo-wrap"><MyHeader :addTodo="addTodo"/>父組件</div>
</template>
<script>
export default {
data() {};
components:{MyHeader},
methods: {
addTodo(todoObj){
this.todos.unshift(todoObj)
},;//給子組件傳的值
}
</script>
子組件
<template>
<!-- 通過props接受值后可直接使用 -->
<div>子組件{{addTodo}}</div>
</template>
<script>
export default {
name:'MyHeader',
//通過props接收父組件傳來的值
props: {
addTodo: {
// 定義接收的類型[String, Undefined, Number]
type: String,
// 定義是否必須傳
required: true,
// 定義默認值
default: ''
},
},
data() {},
};
</script>
props三種寫法:
1.(只接收)props:['name(父組件傳的值)']
2.(限制類型)props:{name(父組件傳的值):String( 定義接收的類型)}
3.(限制類型、限制必要性、指定默認值)
props: {
name(父組件傳的值)父組件傳的值: {
// 定義接收的類型[String, Undefined, Number]
type: String,
// 定義是否必須傳
required: true,
// 定義默認值
default: ''
注意:props是只讀的,Vue底層會監(jiān)測你對props的修改,如果進行了修改,就會發(fā)出警告,若業(yè)務需求確實需要修改,那么請復制props的內(nèi)容到data中一份,然后去修改data中的數(shù)據(jù)。
二、插槽
定義:所謂的插槽就是?個占位符,將?定義組件的內(nèi)容展示出來
- 作用:讓父組件可以向子組件指定位置插入html結(jié)構(gòu)。
- 分類:默認插槽、具名插槽、作用域插槽
- 默認插槽
使用場景:使用者沒有填充內(nèi)容,插槽指定默認數(shù)據(jù)。
代碼實現(xiàn):
父組件中:
<Category>
<div>html結(jié)構(gòu)1</div>
</Category>
子組件中:
<template>
<div>
<!-- 定義插槽 -->
<slot>插槽默認內(nèi)容...</slot>
</div>
</template>
4.具名插槽
使用場景:給特定的slot添加內(nèi)容。
代碼實現(xiàn):
父組件中:
<Category>
<template slot="center">
<div>html結(jié)構(gòu)1</div>
</template>
<template v-slot:footer>
<div>html結(jié)構(gòu)2</div>
</template>
</Category>
子組件中:
<template>
<div>
<!-- 定義插槽 -->
<slot name="center">插槽默認內(nèi)容...</slot>
<slot name="footer">插槽默認內(nèi)容...</slot>
</div>
</template>
5.作用域插槽
使用場景:子組件提供數(shù)據(jù),父組件決定如何渲染。
定義:數(shù)據(jù)在組件的自身,但根據(jù)數(shù)據(jù)生成的結(jié)構(gòu)需要組件的使用者來決定。
代碼實現(xiàn):
父組件中:
<Category>
<template scope="scopeData">
<!-- 生成的是ul列表 -->
<ul>
<li v-for="g in scopeData.games" :key="g">{{g}}</li>
</ul>
</template>
</Category>
<Category>
<template slot-scope="scopeData">
<!-- 生成的是h4標題 -->
<h4 v-for="g in scopeData.games" :key="g">{{g}}</h4>
</template>
</Category>
子組件中:
<template>
<div>
<!--通過v-bind來暴露數(shù)據(jù) :數(shù)據(jù)名=“要暴露的數(shù)據(jù)”-->
<slot :games="games"></slot>
</div>
</template>
<script>
export default {
name:'Category',
props:['title'],
//數(shù)據(jù)在子組件自身
data() {
return {
games:['紅色警戒','穿越火線','勁舞團','超級瑪麗']
}
},
}
</script>
三、ref
- 被用來給元素或子組件注冊引用信息(id的替代者)
- 應用在html標簽上獲取的是真實DOM元素,應用在組件標簽上是組件實例對象(vc)。
- 使用方式:
父組件
<template>
<!--1. 打標識-->
<h1 ref="xxx">.....</h1>或`<School ref="xxx"></School>
</template>
<script>
//引入子組件
import School from './components/School'
// 獲取:
export default {
name:'',
components:{School},
data() {
return {}},
methods: {
showDOM(){
console.log(this.$refs.title) //真實DOM元素
}
```this.$refs.xxx```
</script>
適用于,后面動態(tài)給子組件傳值,這樣會比較快速,但是操作的時候記得備注,方便后續(xù)追蹤及維護。
子傳父(組件的自定義事件)
原理:通過父組件給子組件綁定一個自定義事件實現(xiàn):子給父傳遞數(shù)據(jù)。
- 使用場景:A是父組件,B是子組件,B想給A傳數(shù)據(jù),那么就要在A中給B綁定自定義事件。
- 作用:在封裝組件時,為了讓組件的使用者可以監(jiān)聽到組件內(nèi)狀態(tài)的變化。
- 寫法:
父組件:
第一種寫法,使用@或v-on
<template>
<Student ref="student" @click.native="show"/>
</template>
第二種寫法,使用ref:
<template>
<Demo ref="demo"/>
</template>
......
<script>
import Student from './components/Student'
mounted(){
this.$refs.student .$on('atguigu',this.test)
}
</script>
若想讓自定義事件只能觸發(fā)一次(父組件),可以使用
once修飾符,或$once方法。觸發(fā)自定義事件(子組件):
this.$emit('自定義事件名',數(shù)據(jù))解綁自定義事件(子組件)
this.$off('自定義事件名')
this.$off() //解綁所有的自定義事件銷毀了當前t組件的實例(子組件)
this.$destroy()組件上也可以綁定原生DOM事件(父組件),需要使用
native修飾符。