前言
??组件之间数据传输。 template中用div包裹html元素是因为,template中只能包裹一个盒子。
1 父传子
通过属性值props接收
??父传子:自定义属性 + props ??props用于接收来自父组件的数据。 ??父传子:1)把数据当成子的自定义属性 2)在子对象中接收。 ??子组件需要在父组件中注册。
let Son = {
template:"#son",
=============================props的写法1:=============================
props:{
title:String,
abc:String,
}
=============================props的写法2:=============================
props:{
title:{
type:String,
default:"我是一个默认值"
},
abc:String,
}
=============================props的写法3:=============================
props:["title","abc"]
}
let Father = {
template:"#father",
components:{
Son
}
}
</script>
2 子传父
通过事件传值 $emit
??子传父:自定义事件 + $emit ??同样需要在父组件中注册。
<Son @click="g"></Son>写在父组件中 这里的事件名click就只是名字而已
let Son = {
template:"#son",
data(){
return{
msg:"son中的数据"
}
},
methods:{
k(){
this.$emit("click",this.msg)
}
}
}
3 处理边界情况(组件通信方案)
以下内容子组件据需注册到父组件中。
<div id="app">
<h1>{{msg}}</h1>
<hr>
<compa></compa>
</div>
3.1 $root(获得根组件实例)
??在每个 new Vue 实例的子组件(在根实例中注册的)中,其根实例可以通过 $root property 进行访问。
??this.$root 可以得到根组件实例
let compa = {
template: `
<h1>compa组件------<button @click="fn">点我</button></h1>
`,
methods: {
fn() {
console.log(this.$root);
console.log(this.$root.msg);
this.$root.f1()
this.$root.msg = "hi vue"
}
}
}
var vm = new Vue({
el: '#app',
data: {
msg: "hello vue"
},
methods: {
f1() {
console.log("f1.....");
}
},
components: {
compa
},
})
3.2 $parent(获得父组件实例)
??this.$parent 得到父组件实例
console.log(this.$parent);
console.log(this.$parent.a);
this.$parent.gn()
3.3 $children(获得子组件实例)
??this.$children 得到子组件实例 ??得到的是一个数组,原因是子可以有多个。
console.log(this.$children);
console.log(this.$children[0]);
console.log(this.$children[0].a);
this.$children[0].kn()
3.4 $refs(获得子组件实例)
??this.$refs.xxx获得ref为xxx 的子组件实例 ??如果把ref写在普通的标签上,和id 一样,是为了获取这个DOM元素
<input type="text" ref="ipt" value="123">
??如果把ref写在一个组件上,是为了获取这个组件实例(赋予ID引用)
<compa ref="a"></compa>
??这样在任意地方通过this.$refs.xxx获得ref为xxx 的子组件的实例
mounted(){
console.log(this.$refs.a);
console.log(this.$refs.a.number);
this.$refs.a.kn()
console.log(this.$refs.b.value);
},
3.5 provide & inject依赖注入
??作用:可实现跨组件传值,数据的流只能是向下传递
??provide : 必须在分级组件(不一定是app.vue)进行使用,用来给后代组件注入依赖(属性或方法)。 ??inject : 必须在子组件进行使用,用来获取根组件定义的跨组件传递的数据。
??provide在父中提供数据,在子子孙孙组件中都可以使用数据。 ??可以实现跨级传输数据
var app = new Vue({
el: '#app',
data: {
username:"wangcai"
},
methods:{
},
provide(){
return {
username:this.username
}
},
components:{
compa
}
})
??子或孙组件:
let compb = {
inject:["username"],
template:`
<h1>compb组件----------------{{username}}</h1>
`,
}
3.6 $attrs
??当一个组件中没有声明任何 prop 时,this.$attrs 可以获取到所有父作用域的属性绑定 (class 和 style 除外),并且可以通过 v-bind="$attrs" 传给其内部组件 —— 在创建高级别的组件时非常有用。
props:["a","b","c"],
$attrs props可以接收数据,
$attrs可以接收所有的数据
并没有使用props接收a b c 但是$attrs中已经接收完毕
<son :a="1" :b="2" :c="3"></son>
let grandSon = {
template:`
<div>--------- grandSon组件----{{data}}-----</div>
`,
props:["data"],
}
let son = {
template:`
<div>--------- Son组件 ---------<grandSon :data="$attrs" /></div>
`,
components:{
grandSon
}
}
3.7 $listeners
??v-on:click="xx" 绑定点击事件 ??v-on=$listeners 绑定多个自定义事件
<!-- @f1="f1" @f2="f2" @f3="f3" 在son组件上绑定三个自定义事件 -->
<son @f1="f1" @f2="f2" @f3="f3"></son>
let grandSon = {
template:`
<div>--------- grandSon组件----<button @click="kn">触发</button>-----</div>
`,
methods:{
kn(){
this.$listeners.f3()
}
}
}
let son = {
template:`
<div>--------- Son组件 ---------<grandSon v-on="$listeners" /></div>
//注释<div>--------- Son组件 ---------<grandSon :fn="$listeners" /></div>
`,
mounted(){
},
components:{
grandSon
}
}
3.8 event-bus(时间总线)
事件总线:
new一个Vue,可以创建一个根实例,也可以创建一条事件总线。
在事件总线上有一个机制,叫发布订阅:
发布:在合适的时机就可以发布 $emit()
订阅:订阅某个公众号 $on()
其实事件绑定也是发布订阅:
<button onclick="alert(6666)">登录</button>
事件绑定:订阅
当点击按钮时:发布
let eventBus = new Vue();
========根组件中发布meassge
methods:{
fn(){
eventBus.$emit("meassge","hello 事件总线");
}
},
========其他组件中订阅meassge
mounted(){
eventBus.$on("meassge",function(msg){
console.log("message这个事发生了...",msg);
})
},
3.9 sync(修饰props)
??sync对 props 起到了一种修饰的作用,使用 .sync 进行修饰的 props 意味子组件有修改它的意图,这种情况下它只起到一个标注性作用,有它没它都不会影响逻辑。
??:xxx="xxx" @update:xxx="fn" 可以写成:xxx.sync="xxx" ,减少代码量 ??同时也不用在根实例methods中写
<body>
<div id="app">
<custom-input :username.sync="username" ></custom-input>
<hr>
<h1>{{username}}</h1>
</div>
<script>
Vue.component("custom-input",{
template:`
<input type="text" :value="username" @change="$emit('update:username',$event.target.value)" />
`,
props:["username"]
})
var app = new Vue({
el: '#app',
data: {
username:"wangcai"
},
methods:{
}
})
</script>
</body>
??文章参考:Vue 组件通信 12 种解决方案
|