Vue 6 种组件通信方式
一、父→子
第一种:使用 props
- 先给父组件中绑定自定义的属性
- 在子组件中使用 props:[ ' '] 接收父组件传递的数据,该数据是只读的
- 可以在子组件中任意使用
第二种:父组件通过 provide
来提供 数据 或 方法 ,子组件中通过inject
来注入变量。
provide
和 inject
主要在**开发高阶插件/组件库 **时使用。并不推荐用于普通应用程序代码中。
- provide :
Object | () => Object
- inject :
Array<string> | { [key: string]: string | Symbol | Object }
inject
选项应该是:
- 一个字符串数组,或
- 一个对象,对象的 key 是本地的绑定名,value 是:
- 在可用的注入内容中搜索用的 key (字符串或 Symbol),或
- 一个对象,该对象的:
from
property 是在可用的注入内容中搜索用的 key (字符串或 Symbol)default
property 是降级情况下使用的 value
提示:provide
和 inject
绑定并 不是可响应的 。这是刻意为之的。然而,如果你传入了一个可监听的对象,那么其对象的 property 还是可响应的。
不论子组件有多深,只要调用了 inject 那么就可以注入 provide 中的数据。而不是局限于只能从当前父组件的 prop
属性来获取数据, 只要在父组件的生命周期内,子组件就可以调用 :
<script>
Vue.component('Child', {
data() {
return {
msg: ''
}
},
template: `
<div>
我是孩子{{ msg }}
</div>
`,
inject: ['app'],
created() {
this.msg = this.app;
}
});
Vue.component('Parent', {
template: `
<div>
<p>我是 Parent</p>
<Child/>
</div>
`
});
var App = {
data() {
return {}
},
provide: {
app: 'i am App' /*app 属性名*/
},
template: `
<div>
<h2>我是入口组件 App</h2>
<Parent/>
</div>
`
};
new Vue({
el: '#app',
data() {
return {}
},
components: {
App,
},
template: `
<App/>
`
})
</script>
注意:依赖注入还是有负面影响的。它将你应用程序中的组件与它们当前的组织方式耦合起来,使重构变得更加困难。同时所提供的属性是非响应式的。这是出于设计的考虑,因为使用它们来创建一个中心化规模化的数据跟 使用 $root 做这件事都是不够好的。
如果你想要共享的这个属性是你的应用特有的,而不是通用化的,或者如果你想在祖先组件中更新所提供的数据,那么这意味着你可能需要换用一个像 Vuex 这样真正的状态管理方案了
二、子→父
使用 $emit
- 在父组件绑定自定义的事件
- 在子组件中触发原生的事件,在函数中使用
this.$emit
触发父组件中自定义的事件
- 在子组件中触发原生的事件,在函数中使用
<script>
Vue.component("Parent", {
data() {
return {
msg: "我是父组件中的数据",
};
},
template: `
<div>
<Vbtn type="primary">denglu</Vbtn>
<p>父组件</p>
<Child :childData="msg" @childHandler='childHandler'/><!--//1.绑定自定义的属性、事件-->
</div>
`,
methods: {
childHandler(val) {
console.log(val);
},
},
});
Vue.component("Child", {
props: ["childData"], //2.在子组件中使用 props 接收父组件传递的数据
template: `
<div>
<p>孩子组件接收{{childData}}</p>
<input type="text" v-model="childData" @input='changeValue(childData)' /> <!--//任意使用-->
</div>
`,
methods: {
changeValue(val) {
//自定义的事件一定通过 this.$emit() 去触发
//$emit(自定义的事件名,消息 )
this.$emit("childHandler", val); //2.在子组件中触发原生的事件,在函数中使用 this.$emit 触发父组件中自定义的事件
},
},
});
</script>
三、父↔子
第一种:使用 $attrs
和 $listeners、$emit
<script>
Vue.component("C", {
template: `
<div>
<div @click='cClickHandler'>{{ $attrs.messagec }}</div>
</div>
`,
methods: {
cClickHandler() {
this.$emit("getCData", "我是 c 的数据");
},
},
});
Vue.component("B", {
template: `
<div>
<C v-bind="$attrs" v-on="$listeners"></C>
</div>
`,
});
Vue.component("A", {
data() {
return {};
},
props: ["message"],
template: `
<div>
<B v-bind="$attrs" v-on="$listeners"></B>
<!-- <input type="text" v-model="$attrs.messagec"/> -->
</div>
`,
});
new Vue({
data() {
return {
msg: "我是父组件的内容",
messagec: "hello c",
};
},
template: `
<div>
<p>这是一个父组件</p>
<A :messagec="messagec" v-on:getCData="getCData"></A>
</div>
`,
methods: {
//执行 c 组件的触发的函数
getCData(val) {
console.log(val);
},
},
});
</script>
第二种:使用 this. $parent
、this. $children
[0] 完成父子组件的通信
<script>
Vue.component("Child", {
props: {
value: String, //v-model 会自动传递一个字段为 value 的 prop 属性
},
data() {
return {
mymessage: this.value,
};
},
template: `
<div>
<input type="text" v-model="mymessage" v-on:change="changeValue">
</div>
`,
methods: {
changeValue() {
//通过如此调用可改变父组件的值
console.log(this.$parent);
// 设置子组件的数据
this.$parent.message = this.mymessage;
},
},
});
Vue.component("Parent", {
data() {
return {
message: "I am your Parent",
};
},
template: `
<div>
<p>我是 Parent 组件{{ message }}</p>
<button @click="changeChildValue">changeChildValue</button>
<Child></Child>
</div>
`,
methods: {
changeChildValue() {
// 设置子组件的数据
this.$children[0].mymessage = "hello";
},
},
});
</script>
四、兄弟组件通信
使用 bus 中央事件总线的方式
新建一个 Vue 事件 bus 对象,然后通过 bus. 触发事件,.emit 触发事件,bus.on 监听触发的事件
<script>
var bus = new Vue();
bus.$emit('globalEvent', val);
bus.$on('globalEvent', (val) => {
this.brother2Msg = val;
})
</script>
<script>
var bus = new Vue();
Vue.component("brother2", {
data() {
return {
msg: "hello i am brother2",
};
},
template: `
<div>
<p>我是 brother2</p>
<input type="text" v-model="msg" @input="passData(msg)"/>
</div>
`,
methods: {
passData(val) {
//触发全局事件 globalEvent
bus.$emit("globalEvent", val);
},
},
});
Vue.component("brother1", {
data() {
return {
msg: "hello i am brother1",
brother2Msg: "",
};
},
template: `
<div>
<p>我是 brother1</p>
<p>brother2 传递过来的数据:{{ brother2Msg }}</p>
</div>
`,
mounted() {
//绑定全局事件 globalEvent
bus.$on("globalEvent", (val) => {
this.brother2Msg = val;
});
},
});
var App = {
data() {
return {
msg: "我是父组件的内容",
messgaec: "hello c",
};
},
template: `
<div>
<brother1></brother1>
<brother2></brother2>
</div>
`,
};
new Vue({
el: "#app",
components: {
App,
},
template: `
<App/>
`,
});
</script>
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
上一篇: Vue 全局配置
下一篇: Covenant 利用分析
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论