假如我们需要开发一个文章列表页面,该页面通过 v-for 指定动态渲染列表项,为了复用,决定将列表项封装成一个组件。但是,列表项中显示的数据需要动态传递,不然 v-for 将迭代渲染多个一样的组件,这不符合需求。Vue 为了解决向组件传输数据,提供了 props 属性。
Prop 是你可以在组件上注册的一些自定义属性。当一个值传递给一个 prop 属性的时候,它就变成了那个组件实例的一个属性。为了给列表项组件传递一个标题,我们可以用一个 props 选项将其包含在该组件可接受的 prop 列表中,例如:
// 创建一个组件
Vue.component('article-item', {
// 给组件定义一些 prop,用于调用组件的时候传值
props: ['title'],
// 组件模板
template: '<div>{{ title }}</div>'
})一个组件默认可以拥有任意数量的 prop,任何值都可以传递给任何 prop。在上述模板中,你会发现我们能够在组件实例中访问这个值(即访问 title),就像访问 data 中的值一样。
该示例将演示文章列表页,自定义文章项组件以及动态传值,如下:
<html>
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Vue</title>
<!-- 使用 CDN 引入 Vue 库 -->
<script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
</head>
<body>
<div id="app">
<!-- v-bind:title="article.title" 表示将当前迭代的文章标题绑定到组件的title属性,传递给组件 -->
<article-item v-for="article in articles"
v-bind:key="article.id"
v-bind:title="article.title"></article-item>
</div>
<script type="text/javascript">
// 定义文章相组件
Vue.component('article-item', {
// 自定义 prop
props: [ "title" ],
template: '<div>{{title}}</div>'
});
var app = new Vue({
el: "#app",
data: {
articles: [
{ id:1, title:"Vue 入门" },
{ id:2, title:"Vue 生命周期" },
{ id:3, title:"Vue 内部实现原理" }
]
}
});
</script>
</body>
</html>运行效果如下图:

了解了怎样传递字符串到自定义组件,当构建一个 <article-item> 组件时,你的模板最终会包含的东西远不止一个标题:
<div>{{title}}</div>最起码,你会包含这篇文章的标题、文章浏览数量、发布时间等信息。例如:
<div>{{title}}</div>
<div>
<label>发布日期:{{date}}</label>
<label>浏览量:{{count}}</label>
</div>然而如果你在模板中尝试这样写,Vue 会显示一个错误,并解释道 every component must have a single root element (每个组件必须只有一个根元素)。你可以将模板的内容包裹在一个父元素内,来修复这个问题,例如:
<div class="article_item">
<div>{{title}}</div>
<div>
<label>发布日期:{{date}}</label>
<label>浏览量:{{count}}</label>
</div>
</div>看起来当组件变得越来越复杂的时候,我们的文章项组件不只需要标题、发布日期、浏览量,还需要点赞票、反对票等等。如果为每个相关的信息都定义一个 prop 属性会变得很麻烦,就像这样:
<article-item v-for="article in articles" v-bind:key="article.id" v-bind:title="article.title" v-bind:date="article.date" v-bind:count="article.count"></article-item>
所以是时候重构一下 <article-item> 组件了,让它变成接受一个单独的 article 对象 prop 属性,例如:
<html>
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Vue</title>
<!-- 使用 CDN 引入 Vue 库 -->
<script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
</head>
<body>
<div id="app">
<article-item v-for="article in articles"
v-bind:key="article.id"
v-bind:article="article"></article-item>
</div>
<script type="text/javascript">
// 定义文章相组件
Vue.component('article-item', {
// 自定义 prop
props: [ "article" ],
template: `
<div style="background:#F0F0F0;margin-bottom:10px;padding:10px;">
<div>{{article.title}}</div>
<div style="font-size:14px;color:#555;">
<label>发布日期:{{article.date}}</label>
<label>浏览量:{{article.count}}</label>
</div>
</div>
`
});
var app = new Vue({
el: "#app",
data: {
articles: [
{ id:1, title:"Vue 入门", date:"昨日", count:189 },
{ id:2, title:"Vue 生命周期", date:"上周", count:320 },
{ id:3, title:"Vue 内部实现原理", date:"2023年6月9日", count:102 }
]
}
});
</script>
</body>
</html>运行效果如下:

注意:
(1)现在不论何时为 <article-item> 组件的 article 对象添加一个新的属性,它都会自动地在 <article-item> 内可用。
(2)上面 <article-item> 组件的模板使用了模板字符串来支持多行文本。但是,在 IE 下并没有被支持,所以如果你需要在不 (经过 Babel 或 TypeScript 之类的工具) 编译的情况下支持 IE,请使用折行转义字符取而代之。