父组件通过props属性向子组件传递数据,定义组件的时候可以定义一个props属性,值可以是一个字符串数组或一个对象。
例如:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Document</title> <script src="https://cdn.jsdelivr.net/npm/vue@2.5.16/dist/vue.js"></script> </head> <body> <div id="app"><child :title="message"></child></div> <script> Vue.component('child',{ template:'<h1>{{title}}</h1>',props:['title'] //这里props是一个字符串数组 }) var app = new Vue({ el:'#app',data:{message:'Hello World'} }) </script> </body> </html>
这里我们给child这个组件定义了名为title的props,父组件通过title特性传递给子组件,渲染为:
props除了数组,也可以是一个对象,此时对象的键对应的props的名称,值又是一个对象,可以包含如下属性:
type: ;类型,可以设置为:String、Number、Boolean、Array、Object、Date等等 ;如果只设置type而未设置其他选项,则值可以直接用类型,例如:props:{title:Object}
default ;默认值
required ;布尔类型,表示是否必填项目
validator ;自定义验证函数
例如:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <script src="https://cdn.jsdelivr.net/npm/vue@2.5.16/dist/vue.js"></script> <title>Document</title> </head> <body> <div id="app"><child></child></div> <script> Vue.component('child',{ template:'<h1>{{title}}</h1>',props:{title:{default:'Hello World'}} //这里我们定义的title是个对象,含有默认值 }) var app = new Vue({ el:'#app' }) </script> </body> </html>
这里父组件app没有给子组件child传递数据,子组件使用了默认值Hello World,渲染的结果和第一个例子是一样的。
源码分析
以上面的例1为例,Vue.component()注册组件的时候会调用Vue.extend()生成一个Vue基础构造器,内部会调用mergeOptions函数合并属性, mergeOptions又会调用normalizeProps对props的属性进行一些规范化的修饰,如下:
function normalizeProps (options, vm) { //第1361行 规范化props属性 var props = options.props; //尝试获取props属性 if (!props) { return } var res = {}; var i, val, name; if (Array.isArray(props)) { //如果props是个数组 ;这是props的数组用法的分支 i = props.length; while (i--) { //遍历props val = props[i]; if (typeof val === 'string') { //如果值是一个字符串 name = camelize(val); res[name] = { type: null }; //保存到res里面 ;例如:{ title: {type: null} } } else { warn('props must be strings when using array syntax.'); } } } else if (isPlainObject(props)) { //如果props是个对象 ;这是props的对象用法的分支 for (var key in props) { val = props[key]; name = camelize(key); res[name] = isPlainObject(val) ? val : { type: val }; } } else { warn( "Invalid value for option \"props\": expected an Array or an Object, " + "but got " + (toRawType(props)) + ".", vm ); } options.props = res; }
经过normalizeProps规范后,props被修饰为一个对象格式,例子里的执行到这里等于:
接下来_render函数执行遇到该组件时会执行createComponent函数,该函数又会执行extractPropsFromVNodeData(da