1.父传后代 ( 后代拿到了父的数据 )
1. 父组件引入子组件,绑定数据
<List :str1=‘str1’></List>
子组件通过props来接收
props:{str1:{type:String,default:''}}
***这种方式父传子很方便,但是父传给孙子辈分的组件就很麻烦(父=》子=》孙)
这种方式:子不能直接修改父组件的数据
2. 子组件直接使用父组件的数据
子组件通过:this.$parent.xxx使用父组件的数据
这种方式:子可以直接修改父组件的数据
3. 依赖注入(使用 provide/inject API)
优势:父组件可以直接向某个后代组件传值(不让一级一级的传递)
1.在祖先组件中使用 provide
在祖先组件中,你可以使用 provide 选项来提供数据或方法。这些数据或方法可以被任何后代组件通过 inject 选项来接收。
<!-- AncestorComponent.vue -->
<template> <div> <DescendantComponent /> </div>
</template> <script>
import DescendantComponent from './DescendantComponent.vue'; export default { components: { DescendantComponent }, provide() { return { foo: 'foo', myMethod: this.myMethod }; }, methods: { myMethod() { console.log('This is a method from AncestorComponent.'); } }
};
</script>
2.在后代组件中使用 inject
在后代组件中,你可以使用 inject 选项来接收在祖先组件中 provide 的数据或方法。
<!-- DescendantComponent.vue -->
<template> <div> <p>{{ foo }}</p> <button @click="callAncestorMethod">Call Ancestor Method</button> </div>
</template> <script>
export default { inject: ['foo', 'myMethod'], methods: { callAncestorMethod() { this.myMethod(); } }
};
</script>
在这个例子中,DescendantComponent 接收了 foo 字符串和 myMethod 方法,它们都是在 AncestorComponent 中通过 provide 提供的。
2.后代传父 (父拿到了后代的数据)
1. 子组件传值给父组件
子组件定义自定义事件 this.$emit
子组件中:
// ChildComponent.vue
export default { methods: { sendToParent() { this.$emit('child-event', 'Data from child'); } }
};
父组件中:
<!-- ParentComponent.vue -->
<template> <div> <ChildComponent @child-event="handleChildEvent" /> </div>
</template> <script>
// ...
export default { // ... methods: { handleChildEvent(data) { console.log('Received data from child:', data); } }
};
</script>
2. 父组件直接拿到子组件的数据
<List ref=‘child’></List>
this.$refs.child
下面是一个简单的例子,展示了如何在父组件中通过 $refs 访问子组件的方法:
<!-- ChildComponent.vue -->
<template> <div> <button @click="sayHello">Say Hello</button> </div>
</template> <script>
export default { methods: { sayHello() { console.log('Hello from ChildComponent!'); } }
};
</script> <!-- ParentComponent.vue -->
<template> <div> <ChildComponent ref="child" /> <button @click="callChildMethod">Call Child's Method</button> </div>
</template> <script>
import ChildComponent from './ChildComponent.vue'; export default { components: { ChildComponent }, methods: { callChildMethod() { this.$refs.child.sayHello(); // 调用子组件的 sayHello 方法 } }
};
</script>
在这个例子中,点击父组件的按钮会触发 callChildMethod 方法,该方法通过 this.$refs.child.sayHello() 调用了子组件的 sayHello 方法。
3.平辈之间的传值 ( 兄弟可以拿到数据 )
通过新建bus.js文件来做
在 Vue.js 中,如果你想要在不直接依赖父子组件关系的情况下进行组件间的通信,一个常见的方法是创建一个全局的事件总线(Event Bus)。你可以通过创建一个新的 Vue 实例来作为这个事件总线,并在你的组件中通过它来进行事件的触发
($emit)和监听($on)
。
以下是如何通过新建一个 bus.js 文件来创建全局事件总线的步骤:
创建 bus.js 文件
在你的项目根目录或合适的地方,创建一个 bus.js 文件,并导出一个新的 Vue 实例:
// bus.js
import Vue from 'vue'; export const EventBus = new Vue();
在组件中触发事件 ,在你的组件中,你可以导入 EventBus 并使用 $emit 方法来触发事件:
// ChildComponent.vue
<template> <button @click="notify">Notify Parent</button>
</template> <script>
import { EventBus } from './bus.js'; // 假设 bus.js 和当前文件在同一目录下 export default { methods: { notify() { EventBus.$emit('child-event', 'Data from child'); } }
};
</script>
在组件中监听事件, 在另一个组件中,你可以导入 EventBus 并使用 $on 方法来监听事件:
// ParentComponent.vue 或其他任何组件
<script>
import { EventBus } from './bus.js'; // 假设 bus.js 和当前文件在同一目录下 export default { created() { EventBus.$on('child-event', (data) => { console.log('Received data from child:', data); }); }, beforeDestroy() { // 清除事件监听,避免内存泄漏 EventBus.$off('child-event'); }
};
</script>
注意,在组件销毁(beforeDestroy 或 destroyed 钩子)时,你应该使用 $off 方法来移除事件监听器,以避免内存泄漏。
使用事件总线的一个缺点是它可能导致你的应用状态变得难以追踪,特别是当你的应用变得复杂并且有很多组件在相互通信时。因此,尽管事件总线在某些场景下很有用,但在设计你的应用架构时,也要考虑其他状态管理解决方案,如 Vuex。