1. 父子组件间的数据传递
1.1 从父组件获取子组件的数据
1.1.1 通过绑定 props 将父组件的数据关联到子组件,并修饰 .sync 或者用 v-model 同步来自子组件的数据变化
// 使用.sync:// 父组件
<template>
<div class="home">
<my-dialog :show.sync="valueChild"/>
<button @click="changeValue">toggle</button>
</div>
</template>
<script>
import myDialog from '@/components/myDialog.vue'
export default {
name: 'home',
components: {myDialog},
data(){
return{valueChild:true,}
},
methods:{changeValue(){this.valueChild = !this.valueChild}
}
}
</script>
// 子组件
<template>
<div>
<div>myDialog</div>
<div v-if="show">
<p> 默认初始值是 {{show}},所以是显示的 </p>
<button @click.stop="closeDiv"> 关闭 </button>
</div>
</div>
</template>
<script>
export default {props:['show'],
methods:{closeDiv(){this.$emit('update:show',false)
}
}
}
</script>
// v-model :
// 父组件:<template>
<div class="home">
<myDialog v-model="show"></myDialog>
<button @click="toggle">Toggle</button>
</div>
</template>
<script>
import myDialog from '@/components/myDialog.vue'
export default {
name: 'home',
components: {myDialog},
data() {
return {show: false}
},
methods: {toggle() {this.show = !this.show}
}
}
</script>
// 子组件:<template>
<div>
<div v-if="value" class="modal">
{{value}}
<button @click="close">x</button>
</div>
</div>
</template>
<script>
export default {props: ['value'],
methods: {close() {this.$emit('input', false)
}
}
}
</script>
1.1.2 绑定 listener 事件监听器,当子组件状态或者数据发生变化时,触发事件并将数据传递到父组件
$listeners 和 $attrs 两者表面层都是一个意思,$attrs 是向下传递数据,$listeners 是向下传递方法,通过手动去调用 $listeners 对象里的方法,原理就是 $emit 监听事件,$listeners 也可以看成一个包裹监听事件的一个对象。
// 父组件:<template>
<div class="home">
{{firstMsg}}
<myDialog v-on:changeData="changeData" v-on:another='another'></myDialog>
</div>
</template>
<script>
import myDialog from '@/components/myDialog.vue'
export default {
name: 'home',
components: {myDialog},
data() {
return {firstMsg: '父组件'}
},
methods: {changeData(params) {this.firstMsg = params},
another() {alert(2)
}
}
}
</script>
// 子组件:<template>
<div>
<p @click="$emit('another')"> 子组件 </p>
<other v-on="$listeners"/>
</div>
</template>
<script>
import other from '@/components/other.vue'
export default {props: ['value'],
components:{other},
created () {
// eslint-disable-next-line no-console
console.log(this.$listeners)
}
}
</script>
// 孙子组件:<template>
<div>
<p @click='$listeners.changeData("change")'> 孙子组件 </p>
</div>
</template>
<script>
export default {
name: 'demo',
created () {
// eslint-disable-next-line no-console
console.log(this.$listeners)
},
}
</script>
1.2 从子组件获取父组件的数据
1.2.1 获取 props 或者 $attrs 传下来的数据
// 父组件:
<template>
<div class="home">
<myDialog :foo="foo" :boo="boo" :coo="coo" :doo="doo" title="前端工匠"></myDialog>
</div>
</template>
<script>
import myDialog from '@/components/myDialog.vue'
export default {
name: 'home',
components: {myDialog},
data() {
return {
foo: "Javascript",
boo: "Html",
coo: "CSS",
doo: "Vue"
}
},
methods: {changeData(params) {this.firstMsg = params},
another() {alert(2)
}
}
}
</script>
// 子组件:<template>
<div>
<p>foo:{{foo}}</p>
<p> 子组件的 $attrs: {{$attrs}}</p>
<other v-bind="$attrs" />
</div>
</template>
<script>
import other from '@/components/other.vue'
export default {
components: {other},
inheritAttrs: false, // 可以关闭自动挂载到组件根元素上的没有在 props 声明的属性
props: {foo: String // foo 作为 props 属性绑定},
created() {
// eslint-disable-next-line no-console
console.log(this.$attrs);
}
}
</script>
// 孙子组件:<template>
<div>
<p>boo: {{boo}}</p>
<p> 孙子:{{$attrs}}</p>
</div>
</template>
<script>
export default {
name: 'demo',
inheritAttrs: false,
props: {boo: String},
created() {
// eslint-disable-next-line no-console
console.log(this.$attrs);
},
}
</script>
2. 兄弟组件间的数据传递
处于兄弟关系的组件
2.1 通过 EventBus 或者 $root 去注册事件,由兄弟组件去监听事件传递过来的数据变化
2.2 在 Vuex 存放状态,并在两个组件中都监听状态变化
2.3 在父组件上绑定状态,并通过 v-model 或者 .sync 绑定到两个兄弟组件中去,以同步数据变化
3. 祖孙组件间的数据传递
3.1 孙组件被直接写在了祖先组件的 template 内
在 Vue 中,处于祖孙关系的组件,而且孙组件被直接写在了祖先组件的 template 内,要从祖先组件获取孙组件的数据,有以下几种方式:
3.1.1 可以在模板上给孙组件绑定 ref 并通过 $refs 调用孙组件的方法获取数据
// 父组件
<template>
<div class="home">
{{title}}
{{text}}
<myDialog ref="comA"></myDialog>
</div>
</template>
<script>
import myDialog from '@/components/myDialog.vue'
export default {
name: 'home',
components: {myDialog},
data() {
return {
title:'',
text:''
}
},
computed: { },
mounted() {
const comA = this.$refs.comA;
// console.log(comA.title); // Vue.js
this.title = comA.title
this.text = comA.text
comA.sayHello(); // 弹窗},
methods: {}}
</script>
// 子组件:<template>
<div>
<div v-if="show">sayHello</div>
<other ref="comB" />
</div>
</template>
<script>
import other from '@/components/other.vue'
export default {
components: {other},
data() {
return {
title: 'Vue.js',
show: false,
text:''
}
},
created() {},
mounted() {
const comB = this.$refs.comB;
this.text = comB.text
},
methods: {sayHello() {
this.show = true
// window.alert('Hello');
}
}
}
</script>
// 孙子组件:<template>
<div>
</div>
</template>
<script>
export default {
name: 'demo',
data(){
return{text:'c'}
},
created() {},
}
</script>
3.1.2 可以在模板上给孙组件绑定 listener 获取孙组件传过来的数据
3.1.3 可以在模板上给孙组件绑定 v-model 或者 .sync 同步孙组件的数据
3.2 孙组件不在祖先组件的 template 内,要从祖先组件获取孙组件的数据
3.2.1 先在子组件上绑定 v-model 或者 .sync,接着再在子组件的模板上通过 v-model 或者 .sync 绑定孙组件,以同步孙组件的数据
3.2.2 现在孙组件上绑定 listener,再给子组件绑定 listener,数据由事件层层上传给祖先组件
3.3 孙组件在祖先组件的 template 内,要从孙组件获取祖先组件的数据
3.3.1 直接在祖先组件的 template 中通过 v-bind 将数据传递到孙组件中,孙组件通过 props 或者 $attrs 进行接收
3.4 孙组件不在祖先组件的 template 内,要从孙组件获取祖先组件的数据
3.4.1 先在子组件上 v-bind 绑定数据,接着再在子组件上通过 v-bind 绑定孙组件,数据层层向下传递
3.4.2 孙组件在 EventBus 中注册事件,监听来自祖先组件触发的事件数据
3.4.3 祖先组件将数据挂到 Vuex 中,再由孙组件从 Vuex 中去获取数据