共计 4847 个字符,预计需要花费 13 分钟才能阅读完成。
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 中去获取数据