组件的作用不仅仅时进行模板的复用,更重要的是组件间进行通信。通常父组件中包含子组件,父组件要像子组件传递数据,子组件接收后根据参数的不同来渲染不同的内容或者执行不同的操作,这个数据传递的过程就是通过props属性来实现的。
props基本用法:
在组件中,使用属性props来声明从父级接收的数据,props的值可以是两种形式,一种是字符串数组,一种是对象。首先介绍字符串数组的用法。
在子组件mycom1中构造一个数组,用来接收父组件传递的数据parentMsg,并将其渲染在子组件的模板中。
实例:
在实例中,在父组件中利用自定义的属性绑定将值“这是来自父组件的msg”传递给子组件,在子组件中利用props属性定义的数组元素parentMsg接收,其在子组件模板中使用时与data中定义的数组childmsg方法一致,props中的数据和data中的数据主要的区别为:props中的数据都来自父级,data中数据是组件自身的。需要注意的是,在props中定义的接收父组件数据的parentMsg为驼峰形式的命名,由于HTML中不区分大小写,当使用DOM模板时,此种格式的props命名需要转换为短横分隔命名,如果不是驼峰形式的命名,则不需要转换。
在实列中,父组件传递的数据为固定值,有时候需要传递父组件的动态数据,这时可以利用v-bind来绑定props的值,当父组件的值发生变化时,也会传递给子组件。
实例2:props接收父级动态的值:
上述案列在父组件中定义了一个字符串msg,初始值为空,并将此变量使用v-model双向绑定了input文本输入框,调用子组件中,利用v-bind绑定了自定义属性parentmsg,子组件props属性中接收了父级传递过来的msg值。
需要注意的是,使用自定义属性传递值时,如果不使用v-bind绑定属性,无论传递的值是何种格式(数字、布尔值、数组、对象等),传递的都是字符串。
单向数据流:
在Vue.js2.0之后的版本中,通过props传递数据是单向的,也就是说,在实列2中,父组件数据发生变化时,会传递给子组件,反之不行,这样做的目的主要是为了尽可能地将父子组件解耦,避免子组件无意修改父组件的内容,影响程序运行。
在实际业务中可能会经常碰到两种需要改变props值的情况。第一种是父组件传递值过来,子组件需要在自己的作用域中进行使用和修改。这种情况只需要在子组件的data中声明一个数据,引用父组件中的props的值,即将父组件传递过来的值作为初始值保存起来,具体见实例3。
实例3:
<div id="app">
<mycom1:parentmsg="msg"></mycom1>
<p>父组件中的msg值:<input type="text"v-model="msg"></p>
</div>
<script>
var vm=new Vue({
el:'#app',
data:{
msg:'父组件的msg'
},
components:{
mycom1:{
template:"<div>{{parentmsg}}--{{sonfromparent}}</div>",
props:['parentmsg'],
data:function(){
return{
sonfromparent:this.parentmsg
}
}
}
}
})
</script>
在子组件中声明了数据sonfromparent,它在组件初始化时会获取来自父组件的parentmsg值,之后就与之无关了,子组件在其作用域内可任意使用和修改sonfromparent,这样可避免直接操作parentmsg。
另外一种情况就是props的值是作为需要被转换的原始值传入,这种情况使用上述的方法就不行了,此时可以采用计算属性,具体见实例4.
实例4:
上述案例中,父组件传递过来的初始值为200,但是因为width(宽度)的值要带单位(px),每次都写比较麻烦,而且如果传递过来的值要进行数值计算的话带单位处理起来比较麻烦,所以统一在组件中使用计算属性。