有这么一个情况,在父组件中,使用了子组件,现在想将父中的某些值传给子,或者将子中的某些值传给父。
为了解决以上问题,通常采用的是props来实现。props的值可以是两种:字符串数组、对象;
父传子
这里首先介绍数组的情况:
在子组件中,定义props:
<template>
<div>{{parentStr}}</div>
</template>
<script>
export default {
props: ["parentStr"]
};
</script>
然后在父组件中,使用该组件的时候,传入这个值就可以了:
<template>
<layout_head parentStr="这个是父组件传递的信息"/>
</template>
<script>
import layout_head from "./head.vue";
export default {
components: { aside_menu ,layout_head}
};
</script>
对象:
通常你希望每个props都有指定的值类型。这时,可以以对象形式列出props ,这些属性的名称和值分别是props各自的名称和类型:
props: {
title: String,
likes: Number,
isPublished: Boolean,
commentIds: Array,
author: Object
}
注意
- 如果说有多个数据需要传输,则在props中定义多个项,然后父组件在使用这个子组件的时候,设置好这些值就可以了。
- html中不区分大小写,所以,当使用DOM模版时,驼峰命令的props名称要为短横线分隔命名:myCom 写成my-com;
- 以上例子中,父传的值是写死的,也可以是动态的,使用v-bind来实现:<layout_head :parentStr=“str”/>
- 如果直接传递数字、布尔值、数组、对象,而不是使用v-bind,那么传递的仅仅是字符串
单向数据
有两点需要明白:
- 在Vue2.x中,数据的传递是单向的,也就是说,只能是父传给子,不能子传给父。
- 当时在JS中,对象和数组都是引用类型,指向同一个空间;
由于这两点,所以,直接修改父传递的值,就会由于第二点原因,造成违背第一点规则。所以直接修改这个传递的值,就会报错。
所以,如果父传的值,在子中,需要修改,通常的做法就是:(不直接操作传入的值)
export default {
props: ["parentStr"],
data() {
return {
sub_parentStr: this.parentStr
};
}
};
子传父
在了解了单向数据之后,明白了在Vue2.x中,只允许父传子,子传父是不允许的。
如果真的想在子中传数据的父中,可以使用$emit方式。
记住:单向数据的原则不能违背,所以,子传父,严格的来说,传的是子自己的一些信息,而不是父传的信息。
当然,可以使用一个变量来保存父传的信息,然后将这个变量传会给父,父在赋值给之前的那个变量:
子组件中的写法:
<script>
export default {
props: ["collapsed"],
data() {
return {
sub_collapsed: this.collapsed
};
},
methods: {
//改变sub_collapsed的值
sendCollapsed: function() {
this.sub_collapsed = !this.sub_collapsed;
//讲sub_collapsed的值,传递给父组件
this.$emit("receiveCollapsed", this.sub_collapsed);
} //~end sendCollapsed
}
};
</script>
父组件中的写法:
...
<layout_head :collapsed="collapsed" @receiveCollapsed="receiveCollapsed" />
...
<script>
import layout_head from "./head.vue";
export default {
data() {
return {
collapsed: false
};
},
components: { layout_head },
methods: {
//从子组件中,接收collapsed的变化
receiveCollapsed: function(sub_collapsed) {
this.collapsed = sub_collapsed;
}//~end receiveCollapsed
}
};
</script>
最后,需要说明的是:$emit()方法的第一个参数是自定义事件(父组件中,调用子组件的时候,写的那个值),然后第二个参数(或者第n个参数,也有可能没有)都是要传递的值。
v-model方式
有一种更加简便的方式:使用v-model
基于以上方法,只需要在子组件中,修改:
this.$emit("input", this.sub_collapsed);//这里的input是固定的
说明:这个input是一个特殊的事件名,不需要在父组件中进行@input="receiveCollapsed"的操作。
然后父组件在调用子组件的时候:
<layout_head :collapsed="collapsed" v-model="collapsed" />
这个时候的父组件,都不需要定义receiveCollapsed方法了。
两种方式的结果是一样的,v-model的方式虽然简单,但是仅仅适合赋值的情况。