組件基本需要這三部分組成
props(屬性)
event(事件)
slot(插槽)
父子組件通信
# App.vue (父組件)
<template>
<div id="app">
<Child :msg="messsage" :model="obj" :myArr="arr"/>
</div>
</template>
<script>
import Child from './components/Child'
export default {
name: 'app',
components: {
Child
},
data(){
return{
messsage:'我是父組件的數據',
obj:{
name: "hello",
age:15,
},
arr:[1,2,3,4],
}
}
}
</script>
# Child.vue (子組件)
<template>
<div>
<h1>{{ msg }}</h1>
<h2>{{ model.name }} - {{model.age}}</h2>
<ul>
<li v-for="(item,index) in myArr" :key="index">
{{item}}
</li>
</ul>
</div>
</template>
<script>
export default {
// props 裏 推薦使用對象寫法,用於組件的數據結構校驗
/** 父子組件傳值 */
props: {
// 父組件傳入的屬性是一個基本數據類型
msg: {
type: String,
default: '',
},
// 父組件傳入的屬性是一個對象
model: {
type: Object,
default: () => {},
required:true,
},
// 父組件 傳入 一個數組
myArr:{
type:Array,
default:() => [],
}
}
}
</script>
<style scoped>
</style>
子向父組件通信 ( $on, $emit)
# 子組件 Child.vue
<template>
<div>
<h1>{{ msg }}</h1>
<button @click="changeHandle">change父組件的值</button>
</div>
</template>
<script>
export default {
props: {
msg: {
type: String,
default: '',
},
},
methods:{
changeHandle(){
this.$emit("changeParent","我是子組件的值")
}
}
}
</script>
# 父組件 App.vue
<template>
<div id="app">
<Child @changeParent="getChildData" :msg="messsage"/>
</div>
</template>
<script>
import Child from './components/Child'
export default {
name: 'app',
components: {
Child
},
data(){
return{
messsage:'我是父組件的數據',
}
},
methods:{
getChildData(params){
this.messsage = params;
}
}
}
</script>
子組件通過 $parent 獲取父組件的數據
# Child.vue (子組件)
<template>
<div>
<!-- this.$parent.messsage -->
<h1>{{ this.$parent.messsage }}</h1>
<button @click="changeHandle">change父組件的值</button>
</div>
</template>
<script>
export default {
props: {
msg: {
type: String,
default: '',
},
},
methods:{
changeHandle(){
this.$emit("changeParent","我是子組件的值")
}
}
}
</script>
# App.vue (父組件)
<template>
<div id="app">
<Child @changeParent="getChildData" :msg="messsage"/>
</div>
</template>
<script>
import Child from './components/Child'
export default {
name: 'app',
components: {
Child
},
data(){
return{
messsage:'我是父組件的數據',
}
},
methods:{
getChildData(params){
this.messsage = params;
}
}
}
</script>
父組件通過($children) 獲取子組件的值
# App.vue (父組件)
<template>
<div id="app">
<h1>{{messsage}}</h1>
<Child :msg="messsage"/>
<!-- <Other :msg="messsage"/> -->
<p>{{leader}}</p>
</div>
</template>
<script>
import Child from './components/Child'
// import Other from './components/Other'
export default {
name: 'app',
components: {
Child,
// Other,
},
data(){
return{
messsage:'我是父組件的數據',
leader:'',
}
},
mounted(){
this.$children.map(res=>{
console.log(res)
this.leader = res.miss
})
}
}
</script>
# Child.vue(子組件1)
<template>
<div>
<Other/>
<button @click="changeHandle">change父組件的值</button>
</div>
</template>
<script>
import Other from './Other'
export default {
components:{
Other,
},
props: {
msg: {
type: String,
default: '',
},
},
data(){
return{
message:"我是子組件的值",
miss:'我是Child'
}
},
methods:{
changeHandle(){
this.message = "hello"
}
}
}
</script>
# Other.vue(子組件2)
<template>
<div>
<h3>我是other</h3>
</div>
</template>
<script>
export default {
data(){
return{
miss:'我是other組件'
}
}
}
</script>
響應動態數據的變化
# App.vue (父組件)
<template>
<div id="app">
<Child :msg="Arr" />
<button @click="changeHandle">點擊改變子組件中渲染的值 </button>
</div>
</template>
<script>
import Child from './components/Child'
export default {
name: 'app',
components: {
Child,
},
data() {
return {
messsage: '我是父組件的數據',
num: 1,
Arr:[1,2,3,4],
}
},
methods: {
changeHandle() {
this.$set(this.Arr,2,{a:1})
}
}
}
</script>
# Child.vue (子組件)
<template>
<div>
<ul>
<li v-for="(item,index) in msg" :key="index">{{item}}</li>
</ul>
</div>
</template>
<script>
export default {
props: {
msg: {
type: Array,
default: ()=>[],
},
},
// 這個版本現在不需要作監聽也能響應父組件動態數據的變化了(以前是不行的)
watch:{
msg(oldValue,newValue){
console.log(newValue);
}
},
data(){
return{
message:"我是子組件的值",
}
},
methods:{
changeHandle(){
}
}
}
</script>
一種無依賴的組件通信:provide / inject 接口
# App.vue
<template>
<div>
app
<Brother />
<Child />
</div>
</template>
<script>
import Brother from './components/Brother'
import Child from './components/Child'
export default {
components: {
Brother,
Child,
},
provide: {
name: 'App父組件的值'
},
data() {
return {
}
}
}
</script>
<style scoped>
</style>
# Child.vue
<template>
<div>
Child組件
{{name}}
</div>
</template>
<script>
export default {
inject: ['name'],
data(){
return{
}
}
}
</script>
<style scoped>
</style>
# Brother.vue
<template>
<div>
兄弟組件
{{this.name}}
<Child/>
</div>
</template>
<script>
import Child from "./Child";
export default {
components:{
Child
},
data() {
return {
msg:'',
}
},
inject: ['name'],
}
</script>
<style scoped>
</style>
Vue 官方提示:provide 和 inject 綁定並不是可響應的。這是刻意爲之的。然而,如果你傳入了一個可監聽的對象,那麼其對象的屬性還是可響應的
通過 $refs 獲取子組件的值
此方法只能獲取值,不能響應數據變化
# App.vue
<template>
<div>
<Brother ref="brother"/>
{{myda}}
</div>
</template>
<script>
import Brother from './components/Brother'
export default {
components: {
Brother,
},
data(){
return{
myda:"",
}
},
mounted(){
this.myda = this.$refs.brother.msg
},
}
</script>
# Brother.vue
<template>
<div>
兄弟組件
</div>
</template>
<script>
export default {
data() {
return {
msg:'我是Brother組件',
}
}
}
</script>
兄弟組件通信(同樣適用於跨級組件通信)
//中央事件總線
var bus=new Vue();
// 還是利用 $on 和 $emit 的監聽和發射
var app=new Vue({
el:'#app',
template:`
<div>
<A1></A1>
<A2></A2>
</div>
`
})
// 在組件 A1 的 methods 方法中觸發事件
bus.$emit('say-hello', 'world')
// 在組件 A2 的 created 鉤子函數中監聽事件
bus.$on('say-hello', function (arg) {
console.log('hello ' + arg); // hello world
})
插槽 .... 略過,已經寫過如何使用!