Vue从入门到实战:使用Prop向子组件传递数据

来自CloudWiki
跳转至: 导航搜索

在使用组件时,给组件元素设置属性,组件内部如何接收呢 ?

首先需要在组件内部注册一些自定义的属性,称为prop

Vue.component('blog-post', {
  props: ['title'],
  template: '<h3>{{ title }}</h3>'
})

之后,在使用组件时,就可以通过属性向组件传递数据:

<blog-post title="My journey with Vue"></blog-post>
<blog-post title="Blogging with Vue"></blog-post>
<blog-post title="Why Vue is so fun"></blog-post>

基本使用

这是一个父子组件的典型例子,演示如何向组件之中传递数据。

<!DOCTYPE html>
<html>
	<head>
		<meta charset="UTF-8">
		<script src="vue.js"></script>
	</head>
	<body>
		<div id="app">
			<post-list></post-list>
		</div>
	
		<script>
			Vue.component('PostItem', {
				// 声明props
				props: ['postTitle'],
				// postTitle就像data中定义的数据属性一样,
				// 在该组件中可以像 "this.postTitle" 这样使用
	      template: '<h3>{{ postTitle }}</h3>'
  		});
  		
  		Vue.component('PostList', {
  			data() {
  				return {
  					title: 'Vue.js无难事'
  				}
  			},
  			// 在字符串模板中可以直接使用PascalCase命名的组件名
  			// 和camelCase命名的prop名
	      template: '<div><PostItem :postTitle="title"></PostItem></div>'
  		});
  		
			new Vue({
			  el: '#app'
			})
		</script>
	</body>
</html>

注:

  • 在字符串模板中,不必必须使用kebab-case命名法(短横线分割命名),各种命名可以直接使用。
  • 与普通的HTML元素的属性传值一样,要想接收动态值,需要使用v-bind指令,否则,接收的值都是静态的字符串值

传递多个数值

如果组件需要接收多个传值,那么可以定义多个prop:

<!DOCTYPE html>
<html>
	<head>
		<meta charset="UTF-8">
		<script src="vue.js"></script>
	</head>
	<body>
		<div id="app">
			<post-list></post-list>
		</div>
	
		<script>
			Vue.component('PostItem', {
				props: ['author','title','content'],
	      template: `
	      	<div>
	      		<h3>{{ title }}</h3>
	      		<p> 作者:{{ author }}</p>
	      		<p>{{ content }}</p>
	      	</div>`
  		});
  		
  		Vue.component('PostList', {
  			data() {
  				return {
  					
  						author: '孙鑫',
  						title: 'Vue.js无难事',
  						content: '这本书不错'
  					
  				}
  			},
	      template: `<div><PostItem 
		  :author="author"
		  :title="title"
		  :content="content">
		  </PostItem></div>`
  		});
  		
			new Vue({
			  el: '#app'
			})
		</script>
	</body>
</html>

通过对象传值

如果需要传入的属性较多,也可以封装一个对象来传值。

 
<!DOCTYPE html>
<html>
	<head>
		<meta charset="UTF-8">
		<script src="vue.js"></script>
	</head>
	<body>
		<div id="app">
			<post-list></post-list>
		</div>
	
		<script>
			Vue.component('PostItem', {
				props: ['post'],
	      template: `
	      	<div>
	      		<h3>{{ post.title }}</h3>
	      		<p> 作者:{{ post.author }}</p>
	      		<p>{{ post.content }}</p>
	      	</div>`
  		});
  		
  		Vue.component('PostList', {
  			data() {
  				return {
  					post: {
  						author: '孙鑫',
  						title: 'Vue.js无难事',
  						content: '这本书不错'
  					}	
  				}
  			},
	      template: '<div><PostItem :post="post"/></div>'
  		});
  		
			new Vue({
			  el: '#app'
			})
		</script>
	</body>
</html>


单向数据流

通过prop传递数据是单向的,父组件的属性变化会向下传递给组件,

但是反过来不行,防止子组件意外改变父组件的状态。

如果在子组件内确需改变prop的值,有两种方法:

  • 将prop赋给一个本地数据
  • 将prop赋给一个本地的计算属性。

prop验证

我们希望父组件通过prop传递的数据类型是符合要求的,

为此,vue.js提供了prop的验证机制。

当验证失败时,开发版本下,vue会在控制台抛出一个警告。

<!DOCTYPE html>
<html>
	<head>
		<meta charset="UTF-8">
		<script src="vue.js"></script>
	</head>
	<body>
		<div id="app">
			
		</div>
	
		<script>
			Vue.component('my-component', {
			  props: {
			    // 基本类型检查('null 和 'undefined'会通过任何类型验证)
			    age: Number,
			    // 多个可能的类型
			    tel: [String, Number],
			    // 必填的字符串
			    username: {
			      type: String,
			      required: true
			    },
			    // 带有默认值的数字
			    sizeOfPage: {
			      type: Number,
			      default: 10
			    },
			    // 带有默认值的对象
			    greeting: {
			      type: Object,
			      //  对象或数组默认值必须从一个工厂函数获取
			      default: function () {
			        return { message: 'hello' }
			      }
			    },
			    // 自定义验证函数
			    info: {
			      validator: function (value) {
			        // 这个值必须匹配下列字符串中的一个
			        return ['success', 'warning', 'danger'].indexOf(value) !== -1
			      }
			    }
			  }
			})
			  		
			new Vue({
			  el: '#app'
			})
		</script>
	</body>
</html>

非prop的属性

在Vue.js中,组件可以接受任意的属性,而这些外部设置的属性会被添加到这个组件的根元素上。

<!DOCTYPE html>
<html>
	<head>
		<meta charset="UTF-8">
		<script src="vue.js"></script>
	</head>
	<body>
		<div id="app">
           <my-comp   data-title="learn vue" class="mycls" style="color:red;"></my-comp>
        </div>
    <script>
    Vue.component('my-comp', {
        template: '<div class="child">我是组件</div>'
    });
    new Vue({
        el: '#app'
    });
</script>
	</body>
</html>

注:

  • 外部添加的属性mycls 将会添加到my-comp组件的根元素div上,
  • 只有class和style属性的值会合并,其他属性会替换组件内部的值。