组件间的数据传递
数据传递的方式
- 父传子props;
- 基于发布订阅实现 $emit $on;
- eventBus;
父传子props
如何让子组件获取到父组件中的数据?
步骤:
- 把父组件的数据以动态属性的方式当在子组件的行间属性上;
- 在子组件中用props这个属性接收,(对象、数组)
- 在子组件中使用动态的属性名保持一致;
props可以是数组,也可以是对象;
<body>
<div id="app">
<!--普通的行间属性的属性值就是一个字符串-->
<!--动态属性取父组件中的数据-->
<child v-bind:m="msg" :t="hh"></child>
</div>
<script src="node_modules/vue/dist/vue.js"></script>
<script>
let child = {
data(){
return{num:100}
},
props:["m","t"], //props中放的是动态属性的属性名
template:'<div>{{m}}{{t}}</div>' //和props对应;
}
let vm = new Vue({
el:'#app',
data:{
msg:'today',
hh:0902
},
components:{
child
}
})
</script>
</body>
child是vm的一个子组件;
props验证
可以为组件的 prop 指定验证要求;
为了定制 prop 的验证方式,可以为 props 中的值提供一个带有验证需求的对象;
<div id="app">
<child :m="msg"></child>
</div>
<script src="node_modules/vue/dist/vue.js"></script>
<script>
let child = {
data(){
return {num:100,}
},
props:{
m:{ //对象
//1.type:对传递过来的数据进行验证
type:[Number,String],
//2.required:必须传递的属性
required:true,
//3.default:默认值
default:200,
//4.validator:自定义验证函数
validator(val){
// 如果这个函数返回一个布尔值,如果是true,没有问题,如果是false,那么会抛出异常
return [1,2,3].indexOf(val)!==-1;
}
}
},
template:"<div>{{m}}</div>"
}
let vm = new Vue({
el:"#app",
data:{
msg:99,
hh:"lalal"
},
components:{
child
}
});
</script>
注意:那些 prop 会在一个组件实例创建之前进行验证,所以实例的属性 (如 data、computed 等) 在 default 或 validator 函数中是不可用的。
vue的单向数据流
当父组件中数据发生改变,子组件数据会变吗?
如果子组件使用了父组件中的数据,当父组件通过某些方法发生更改时,更改了自己的数据时,那么子组件也会随着发生改变,父组件中的数据又流向了子组件,子组件发生了更改;这就是组件之间数据传递的单向数据流;
<div id="app">
{{num}}
<button @click="add">加一</button>
<son v-bind:t="num"></son>
</div>
<script src="node_modules/vue/dist/vue.js"></script>
<script>
let son = {
data(){
return {val:100}
},
props:["t"],
template:"<div @click='fn'>{{t}}:{{val}}</div>",
methods:{
fn(){
//this.t++ 不能在子组件中修改父组件中的属性值
this.val=200;
}
},
beforeUpdate(){
console.log("子组件更新前")
},
updated(){
console.log("子组件更新后")
}
}
let vm = new Vue({
el:"#app",
data:{num:20},
methods:{
add(){this.num++}
},
components:{
son
},
beforeUpdate(){
console.log("父组件更新前")
},
updated(){
console.log("父组件更新后")
}
});
</script>
- 当父组件数据更新时,beforeUpdate(父)–>beforeUpdate(子)–>updated(子)—>updated(父)
- 如果子组件只改变自己的数据,那么不会让父组件中的更新钩子函数执行;
- 父组件中不能使用子组件中的数据;
发布订阅 $emit $on
子传父:在父组件中定义一个修改自己属性的方法,把这个方法以自定事件的方式绑定给子组件,子组件触发动作,从而触发了自定义的事件($emit);
- 在vue中,子组件中不能直接修改父组件中的数据;
- 在子组件中不能直接修改prop接收到的父组件中的属性;
- props接收的数据最终也会放到当前的组件实例上;
<div id="app">
{{money}}
<!--订阅自定义事件的方法-->
<son v-bind:m="money" @changemoney="change"></son>
</div>
<script src="node_modules/vue/dist/vue.js"></script>
<script>
let son = {
data(){
return {}
},
methods:{
//不能直接修改prop接收到的父组件中的属性;
//fn(){this.m=2000;}
f(){ //$emit : 发布自定义事件
this.$emit("changemoney",3000);
}
},
props:["m"],//props接收的数据最终也会放到当前的组件实例上;
template:"<div>{{m}}<button @click='f'>多要点</button></div>"
}
let vm = new Vue({
el:"#app",
data:{
money:200
},
methods:{
change(val){// 可以接收参数,$emit的第二个参数会传给change的第一个参数;
this.money=val;
}
},
components:{
son
}
});
</script>
sync修饰符
<div id="app">
{{money}}
<!-- 第一种写法 -->
<!-- <son v-bind:m="money" v-on:update:m="money=$event"></son> -->
<!-- 第二种写法 -->
<son v-bind:m.sync="money"></son>
</div>
<script src="node_modules/vue/dist/vue.js"></script>
<script>
let son = {
data(){
return {}
},
methods:{
f(){this.$emit("update:m",3000);}
},
props:["m"],
template:"<div>{{m}}<button @click='f'>多要点</button></div>"
}
let vm = new Vue({
el:"#app",
data:{money:200},
components:{
son
}
});
</script>
事件车 eventBus
eventBus:把组件上的方法都通过$on
订阅到eventBus上,当执行时,通过$emit
派发;
<body>
<div id="app">
<bro1></bro1>
<bro2></bro2>
</div>
<script src="node_modules/vue/dist/vue.js"></script>
<script>
let eventBus = new Vue; //相当于第三方;
let bro1 = {
data(){return{color:'红色'}},
created () {
//把自己实例上的方法订阅了eventBus这个实例的changeG这个自定义的事件上
eventBus.$on("changeG",this.changeGreen)
},
methods:{
changeGreen(){this.color="绿色"},
fn2(){eventBus.$emit("changeR")}
},
template:"<div>{{color}}<button @click='fn2'>变红</button></div>"
};
let bro2 = {
data(){return{color:'绿色'}},
created() {
eventBus.$on("changeR",this.changeRed)
},
methods:{
changeRed(){this.color="红色"},
fn1(){
//点击button时,触发eventBus的changeG 这个订阅的事件;那么就会执行哥哥组件的changeGreen 方法;
eventBus.$emit("changeG");
}
},
template:"<div>{{color}}<button @click='fn1'>变绿</button></div>"
};
let vm = new Vue({
el:'#app',
data:{msg:'hello'},
components:{
bro1,
bro2
}
});
</script>
</body>
关于Vuex,知识点很多,接下来的几天会另外更新一篇博客;?