Bases des composants
Répertoire
Exemple de base
Voici un exemple de composant Vue :
// 定义一个名为 button-counter 的新组件 Vue.component('button-counter', { data: function () { return { count: 0 } }, template: '<button v-on:click="count++">You clicked me {{ count }} times.</button>' })
Un composant est une instance Vue réutilisable avec un nom : dans ce cas <button-counter>
. Nous pouvons utiliser ce composant comme élément personnalisé dans une instance racine de Vue créée via new Vue
: <button-counter>
。我们可以在一个通过 new Vue
创建的 Vue 根实例中,把这个组件作为自定义元素来使用:
<div id="components-demo"> <button-counter></button-counter> </div>
new Vue({ el: '#components-demo' })
因为组件是可复用的 Vue 实例,所以它们与 new Vue
接收相同的选项,例如 data
、computed
、watch
、methods
以及生命周期钩子等。仅有的例外是像 el
这样根实例特有的选项。
组件的复用
你可以将组件进行任意次数的复用:
<div id="components-demo"> <button-counter></button-counter> <button-counter></button-counter> <button-counter></button-counter> </div>
注意当点击按钮时,每个组件都会各自独立维护它的 count
。因为你每用一次组件,就会有一个它的新实例被创建。
data
必须是一个函数
当我们定义这个 <button-counter>
组件时,你可能会发现它的 data
data: { count: 0 }
data: function () { return { count: 0 } }🎜🎜Parce que les composants sont des instances de Vue réutilisables, ils sont les mêmes que lorsque
nouvelle Vue< /code> reçoit la même chose options, telles que données
, calculé
, watch
, méthodes
et crochets de cycle de vie. Les seules exceptions sont les options spécifiques à l'instance racine comme el
. 🎜🎜🎜🎜🎜🎜Réutilisation des composants🎜🎜🎜🎜🎜Vous pouvez réutiliser les composants autant de fois que vous le souhaitez : 🎜Vue.component('my-component-name', {
// ... options ...
})
🎜🎜🎜Notez que lorsqu'un bouton est cliqué, chaque composant le maintiendra indépendamment < code>count< /code>. Parce que chaque fois que vous utilisez un composant, une nouvelle instance de celui-ci est créée. 🎜🎜🎜🎜
🎜data🎜🎜
🎜 Ce doit être une fonction🎜🎜🎜🎜Lorsque nous définissons ce composant <button-counter>
, vous constaterez peut-être que ses data
ne fournissent pas directement un objet comme celui-ci : 🎜Vue.component('blog-post', {
props: ['title'],
template: '<h3>{{ title }}</h3>'
})
Au lieu de cela, l'option data
d'un composant doit être une fonction, afin que chaque instance puisse conserver une copie indépendante de l'objet renvoyé : data
选项必须是一个函数,因此每个实例可以维护一份被返回对象的独立的拷贝:
<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>
如果 Vue 没有这条规则,点击一个按钮就可能会像如下代码一样影响到其它所有实例:
组件的组织
通常一个应用会以一棵嵌套的组件树的形式来组织:
例如,你可能会有页头、侧边栏、内容区等组件,每个组件又包含了其它的像导航链接、博文之类的组件。
为了能在模板中使用,这些组件必须先注册以便 Vue 能够识别。这里有两种组件的注册类型:全局注册和局部注册。至此,我们的组件都只是通过 Vue.component
全局注册的:
new Vue({
el: '#blog-post-demo',
data: {
posts: [
{ id: 1, title: 'My journey with Vue' },
{ id: 2, title: 'Blogging with Vue' },
{ id: 3, title: 'Why Vue is so fun' }
]
}
})
全局注册的组件可以用在其被注册之后的任何 (通过 new Vue
) 新创建的 Vue 根实例,也包括其组件树中的所有子组件的模板中。
到目前为止,关于组件注册你需要了解的就这些了,如果你阅读完本页内容并掌握了它的内容,我们会推荐你再回来把组件注册读完。
通过 Prop 向子组件传递数据
早些时候,我们提到了创建一个博文组件的事情。问题是如果你不能向这个组件传递某一篇博文的标题或内容之类的我们想展示的数据的话,它是没有办法使用的。这也正是 prop 的由来。
Prop 是你可以在组件上注册的一些自定义特性。当一个值传递给一个 prop 特性的时候,它就变成了那个组件实例的一个属性。为了给博文组件传递一个标题,我们可以用一个 props
选项将其包含在该组件可接受的 prop 列表中:
<blog-post
v-for="post in posts"
v-bind:key="post.id"
v-bind:title="post.title"
></blog-post>
一个组件默认可以拥有任意数量的 prop,任何值都可以传递给任何 prop。在上述模板中,你会发现我们能够在组件实例中访问这个值,就像访问 data 中的值一样。
一个 prop 被注册之后,你就可以像这样把数据作为一个自定义特性传递进来:
<h3>{{ title }}</h3>
然而在一个典型的应用中,你可能在 data
<h3>{{ title }}</h3>
<div v-html="content"></div>
Si Vue ne respecte pas cette règle, cliquez sur un Le bouton peut affecter toutes les autres instances comme le code suivant : 🎜🎜
🎜🎜 Organisation du composant< /h2>
🎜Habituellement, une application est organisée sous la forme d'une arborescence de composants imbriquée :
🎜🎜🎜🎜Par exemple, vous pouvez avoir un en-tête et une barre latérale, une zone de contenu et d'autres composants, chaque composant contient d'autres composants tels que liens de navigation, articles de blog, etc. 🎜🎜Pour pouvoir être utilisés dans des modèles, ces composants doivent d'abord être enregistrés afin que Vue puisse les reconnaître. Il existe deux types d'enregistrement de composants : 🎜enregistrement global et 🎜enregistrement local. Jusqu'à présent, nos composants n'ont été enregistrés globalement que via Vue.component
: 🎜<div class="blog-post">
<h3>{{ title }}</h3>
<div v-html="content"></div>
</div>
🎜Les composants enregistrés globalement peuvent être utilisés dans n'importe quoi après avoir été enregistrés (via new Vue
). L'instance racine Vue nouvellement créée inclut également les modèles de tous les sous-composants dans son arborescence de composants. 🎜🎜Jusqu'à présent, c'est tout ce que vous devez savoir sur l'enregistrement des composants. Si vous avez fini de lire cette page et maîtrisez son contenu, nous vous recommanderons de revenir et de Enregistrement des composants Terminez la lecture. 🎜🎜
🎜🎜Transmettre les données aux composants enfants via Prop
🎜Plus tôt, nous avons mentionné la création d'un composant d'article de blog. Le problème est que si vous ne pouvez pas transmettre les données que nous souhaitons afficher, comme le titre ou le contenu d'un article de blog, à ce composant, ils ne peuvent pas être utilisés. C'est de là que viennent les accessoires. 🎜🎜Les props sont des propriétés personnalisées que vous pouvez enregistrer sur le composant. Lorsqu'une valeur est transmise à un attribut prop, elle devient une propriété de cette instance de composant. Afin de transmettre un titre au composant article de blog, nous pouvons utiliser une option props
pour l'inclure dans la liste des props acceptées par le composant : 🎜<blog-post
v-for="post in posts"
v-bind:key="post.id"
v-bind:title="post.title"
v-bind:content="post.content"
v-bind:publishedAt="post.publishedAt"
v-bind:comments="post.comments"
></blog-post>
🎜Un composant peut avoir n'importe quel nombre de props par par défaut, et n'importe quelle valeur Peut être transmise à n'importe quel accessoire. Dans le modèle ci-dessus, vous remarquerez que nous pouvons accéder à cette valeur dans l'instance du composant, tout comme pour accéder à la valeur dans les données. 🎜🎜Une fois qu'un accessoire est enregistré, vous pouvez transmettre les données en tant que fonctionnalité personnalisée comme ceci : 🎜<blog-post
v-for="post in posts"
v-bind:key="post.id"
v-bind:post="post"
></blog-post>
🎜🎜🎜Cependant, dans une application typique, vous pouvez avoir un tableau d'articles de blog dans data
: 🎜 Vue.component('blog-post', {
props: ['post'],
template: `
<div class="blog-post">
<h3>{{ post.title }}</h3>
<div v-html="post.content"></div>
</div>
`
})
🎜 et souhaitez afficher un composant pour chaque article de blog : 🎜new Vue({
el: '#blog-posts-events-demo',
data: {
posts: [/* ... */],
postFontSize: 1
}
})
Comme indiqué ci-dessus, vous constaterez que nous pouvons utiliser v-bind
pour transmettre dynamiquement des accessoires. C'est lorsque vous ne connaissez pas le contenu spécifique à afficher au début, comme par exemple obtenir une liste d'articles de blog à partir d'un API est très utile. v-bind
来动态传递 prop。这在你一开始不清楚要渲染的具体内容,比如从一个 API 获取博文列表的时候,是非常有用的。
到目前为止,关于 prop 你需要了解的大概就这些了,如果你阅读完本页内容并掌握了它的内容,我们会推荐你再回来把 prop 读完。
单个根元素
当构建一个 <blog-post>
组件时,你的模板最终会包含的东西远不止一个标题:
<div id="blog-posts-events-demo">
<div :style="{ fontSize: postFontSize + 'em' }">
<blog-post
v-for="post in posts"
v-bind:key="post.id"
v-bind:post="post"
></blog-post>
</div>
</div>
最最起码,你会包含这篇博文的正文:
Vue.component('blog-post', {
props: ['post'],
template: `
<div class="blog-post">
<h3>{{ post.title }}</h3>
<button>
Enlarge text
</button>
<div v-html="post.content"></div>
</div>
`
})
然而如果你在模板中尝试这样写,Vue 会显示一个错误,并解释道 every component must have a single root element (每个组件必须只有一个根元素)。你可以将模板的内容包裹在一个父元素内,来修复这个问题,例如:
<button>
Enlarge text
</button>
看起来当组件变得越来越复杂的时候,我们的博文不只需要标题和内容,还需要发布日期、评论等等。为每个相关的信息定义一个 prop 会变得很麻烦:
<blog-post
...
v-on:enlarge-text="postFontSize += 0.1"
></blog-post>
所以是时候重构一下这个 <blog-post>
组件了,让它变成接受一个单独的 post
prop:
<button v-on:click="$emit('enlarge-text')">
Enlarge text
</button>
<button v-on:click="$emit('enlarge-text', 0.1)">
Enlarge text
</button>
上述的这个和一些接下来的示例使用了 JavaScript 的模板字符串来让多行的模板更易读。它们在 IE 下并没有被支持,所以如果你需要在不 (经过 Babel 或 TypeScript 之类的工具) 编译的情况下支持 IE,请使用折行转义字符取而代之。
现在,不论何时为 post
对象添加一个新的属性,它都会自动地在 <blog-post>
内可用。
监听子组件事件
在我们开发 <blog-post>
组件时,它的一些功能可能要求我们和父级组件进行沟通。例如我们可能会引入一个辅助功能来放大博文的字号,同时让页面的其它部分保持默认的字号。
在其父组件中,我们可以通过添加一个 postFontSize
Pour l'instant, c'est à peu près tout ce que vous devez savoir sur prop. Si vous avez fini de lire cette page et maîtrisez son contenu, nous vous recommanderons de revenir prop Terminez la lecture.
Élément racine unique
Lors de la création d'un composant <blog-post>
, votre modèle finira par contenir bien plus qu'un simple titre :
🎜<blog-post
...
v-on:enlarge-text="postFontSize += $event"
></blog-post>
🎜Au minimum, vous Contient le texte de cet article de blog : 🎜<blog-post
...
v-on:enlarge-text="onEnlargeText"
></blog-post>
🎜 Cependant, si vous essayez d'écrire ceci dans un modèle, Vue affichera une erreur et expliquera quechaque composant doit avoir un seul élément racine (chaque composant ne doit avoir qu'un seul élément racine). élément racine) . Vous pouvez résoudre ce problème en enveloppant le contenu du modèle dans un élément parent, par exemple : 🎜methods: {
onEnlargeText: function (enlargeAmount) {
this.postFontSize += enlargeAmount
}
}
🎜 Il semble qu'à mesure que les composants deviennent de plus en plus complexes, nos articles de blog ont non seulement besoin du titre et du contenu, mais aussi de la publication. date, commentaires et plus encore. Définir un accessoire pour chaque article pertinent peut s'avérer fastidieux : 🎜<input v-model="searchText">
🎜 Il est donc temps de refactoriser le composant <blog-post>
pour accepter un seul accessoire code>post
: 🎜<input
v-bind:value="searchText"
v-on:input="searchText = $event.target.value"
>
<custom-input
v-bind:value="searchText"
v-on:input="searchText = $event"
></custom-input>
🎜Ceci et certains des exemples suivants utilisent JavaScript Chaîne de modèle pour rendre les modèles multilignes plus lisibles. Ils ne sont pas pris en charge sous IE, donc si vous devez prendre en charge IE sans compiler (via des outils comme Babel ou TypeScript), veuillez utiliser caractère d'échappement de ligne de rupture à la place. 🎜
🎜Désormais, chaque fois que vous ajoutez une nouvelle propriété à l'objet post
, elle sera automatiquement disponible dans <blog-post>
. 🎜🎜
🎜Écouter les événements des composants enfants
🎜Lorsque nous développons le composant <blog-post>
, certaines de ses fonctions peuvent nécessiter que nous communiquions avec le composant parent. Par exemple, nous pourrions introduire une fonction auxiliaire pour augmenter la taille de police d'un article de blog tout en conservant le reste de la page à la taille de police par défaut.
🎜🎜Dans son composant parent, nous pouvons prendre en charge cette fonctionnalité en ajoutant un attribut de données postFontSize
: 🎜Vue.component('custom-input', {
props: ['value'],
template: `
<input
v-bind:value="value"
v-on:input="$emit('input', $event.target.value)"
>
`
})
🎜Il peut être utilisé dans les modèles pour contrôler la taille de la police de tous les articles de blog : 🎜 <custom-input v-model="searchText"></custom-input>
🎜Maintenant, nous ajoutons un bouton avant le texte de chaque article de blog pour agrandir la taille de la police : 🎜<alert-box>
Something bad happened.
</alert-box>
Le problème est que ce bouton ne fait rien :
Vue.component('alert-box', {
template: `
<div class="demo-alert-box">
<strong>Error!</strong>
<slot></slot>
</div>
`
})
Lorsque l'on clique sur ce bouton, nous devons dire au composant parent d'agrandir le texte de tous les articles de blog. Heureusement, les instances Vue fournissent un système d'événements personnalisé pour résoudre ce problème. Le composant parent peut écouter tous les événements de l'instance du composant enfant via v-on
, tout comme la gestion des événements DOM natifs : v-on
监听子组件实例的任意事件:
<!-- 组件会在 `currentTabComponent` 改变时改变 -->
<component v-bind:is="currentTabComponent"></component>
同时子组件可以通过调用内建的 $emit
方法 并传入事件名称来触发一个事件:
<table>
<blog-post-row></blog-post-row>
</table>
有了这个 v-on:enlarge-text="postFontSize += 0.1"
监听器,父级组件就会接收该事件并更新 postFontSize
的值。
使用事件抛出一个值
有的时候用一个事件来抛出一个特定的值是非常有用的。例如我们可能想让 <blog-post>
组件决定它的文本要放大多少。这时可以使用 $emit
的第二个参数来提供这个值:
<table>
<tr is="blog-post-row"></tr>
</table>
然后当在父级组件监听这个事件的时候,我们可以通过 $event
访问到被抛出的这个值:
rrreee或者,如果这个事件处理函数是一个方法:
rrreee那么这个值将会作为第一个参数传入这个方法:
rrreee
在组件上使用 v-model
自定义事件也可以用于创建支持 v-model
的自定义输入组件。记住:
rrreee等价于:
rrreee当用在组件上时,v-model
则会这样:
rrreee为了让它正常工作,这个组件内的 <input>
必须:
将其 value
特性绑定到一个名叫 value
的 prop 上
在其 input
事件被触发时,将新的值通过自定义的 input
事件抛出
写成代码之后是这样的:
rrreee现在 v-model
rrreee
En même temps, le composant enfant peut appeler le $emit
et transmettez le nom de l'événement pour déclencher un événement : rrreeeAvec cet écouteur v-on:enlarge-text="postFontSize += 0.1"
, le composant parent recevra l'événement et mettra à jour la valeur de postFontSize
.
Utilisez un événement pour lancer une valeur
Parfois, il est très utile d'utiliser un événement pour lancer une valeur spécifique . Par exemple, nous pourrions souhaiter que le composant <blog-post>
détermine de combien son texte doit être agrandi. A ce moment, vous pouvez utiliser le deuxième paramètre de $emit
pour fournir cette valeur : rrreee
Ensuite, lors de l'écoute de cet événement dans le composant parent, nous pouvons passer $event
Accédez à la valeur qui a été renvoyée : rrreee
Ou, si le gestionnaire d'événements est une méthode : 🎜rrreee🎜 alors la valeur sera transmise à la méthode comme premier paramètre : 🎜rrreee🎜🎜🎜🎜Utilisez v-model
sur les composants🎜🎜🎜🎜Les événements personnalisés peuvent également être utilisés pour créer un support Composant d'entrée personnalisé pour v-modèle
. N'oubliez pas : 🎜rrreee🎜 équivaut à : 🎜rrreee🎜 Lorsqu'il est utilisé sur un composant, le v-model
ressemblera à ceci : 🎜rrreee🎜Pour le faire fonctionner correctement, le à l'intérieur de ce composant < ;input>
doit : 🎜- 🎜Lier son attribut
value
à un objet nommé Sur l'accessoire de valeur
🎜 - 🎜Lorsque son événement
input
est déclenché, la nouvelle valeur sera renvoyée via l'événement input
personnalisé 🎜 li>
🎜Après avoir écrit le code, cela ressemble à ceci : 🎜rrreee🎜Maintenant, v-model
devrait pouvoir fonctionner parfaitement sur ce composant : 🎜rrreee🎜Jusqu'ici Jusqu'à présent, c'est sur tout ce que vous devez savoir sur les événements personnalisés des composants. Si vous avez fini de lire cette page et maîtrisez son contenu, nous vous recommandons de revenir lire 🎜Événements personnalisés🎜. 🎜🎜🎜🎜🎜🎜🎜Distribuer du contenu via des slots 🎜🎜🎜🎜🎜Comme les éléments HTML, nous devons souvent transmettre du contenu à un composant, comme ceci : 🎜rrreee🎜 pourrait afficher quelque chose comme ceci : 🎜Heureusement, l'élément <slot>
personnalisé de Vue rend cela très simple : <slot>
元素让这变得非常简单:
rrreee如你所见,我们只要在需要的地方加入插槽就行了——就这么简单!
到目前为止,关于插槽你需要了解的大概就这些了,如果你阅读完本页内容并掌握了它的内容,我们会推荐你再回来把插槽读完。
动态组件
有的时候,在不同组件之间进行动态切换是非常有用的,比如在一个多标签的界面里:
上述内容可以通过 Vue 的 <component>
元素加一个特殊的 is
特性来实现:
rrreee在上述示例中,currentTabComponent
可以包括
已注册组件的名字,或
一个组件的选项对象
你可以在这里查阅并体验完整的代码,或在这个版本了解绑定组件选项对象,而不是已注册组件名的示例。
到目前为止,关于动态组件你需要了解的大概就这些了,如果你阅读完本页内容并掌握了它的内容,我们会推荐你再回来把动态和异步组件读完。
解析 DOM 模板时的注意事项
有些 HTML 元素,诸如 <ul>
、<ol>
、<table>
和 <select>
,对于哪些元素可以出现在其内部是有严格限制的。而有些元素,诸如 <li>
、<tr>
和 <option>
,只能出现在其它某些特定的元素内部。
这会导致我们使用这些有约束条件的元素时遇到一些问题。例如:
rrreee这个自定义组件 <blog-post-row>
会被作为无效的内容提升到外部,并导致最终渲染结果出错。幸好这个特殊的 is
特性给了我们一个变通的办法:
rrreee需要注意的是如果我们从以下来源使用模板的话,这条限制是不存在的:
字符串 (例如:template: '...'
rrreee
Comme vous pouvez le voir, nous n'avons besoin d'ajouter des emplacements que là où c'est nécessaire—— C'est aussi simple que cela ! 🎜🎜Pour l'instant, c'est à peu près tout ce que vous devez savoir sur les machines à sous. Si vous avez fini de lire cette page et maîtrisez son contenu, nous vous recommanderons de revenir et de slots Terminez la lecture. 🎜🎜
🎜Composants dynamiques
🎜Parfois, il est très utile de basculer dynamiquement entre différents composants, comme dans une interface multi-onglets :
🎜🎜🎜🎜Le contenu ci-dessus peut être ajouté via l'élément <component>
de Vue Un < spécial L'attribut code>is
est implémenté : 🎜rrreee🎜Dans l'exemple ci-dessus, le currentTabComponent
peut inclure 🎜- < li>🎜 Le nom d'un composant enregistré, ou 🎜
- 🎜L'objet options d'un composant🎜
🎜
Remarques lors de l'analyse des modèles DOM h2>
🎜Certains éléments HTML tels que <ul>
, <ol>
, <table>
et <select>
a des restrictions strictes sur les éléments qui peuvent apparaître à l'intérieur. Certains éléments, tels que <li>
, <tr>
et <option>
, ne peuvent apparaître que dans certains autres éléments du élément. 🎜🎜Cela nous amènera à rencontrer quelques problèmes lors de l'utilisation de ces éléments contraints. Par exemple : 🎜rrreee🎜Ce composant personnalisé <blog-post-row>
sera promu à l'extérieur en tant que contenu non valide et provoquera une erreur dans le résultat final du rendu. Heureusement, cette fonctionnalité spéciale is
nous offre une solution de contournement : 🎜rrreee🎜Il est à noter que cette restriction n'existe pas< si nous utilisons des modèles provenant des sources suivantes /em>< /strong> : 🎜- 🎜String (par exemple :
template: '...'
)🎜
< code><script type="text/x-template">À ce stade, vous devez connaître les précautions lors de l'analyse des modèles DOM - en fait, tout le contenu nécessaire pour Vue, c'est à peu près il. Félicitations! Il y a encore beaucoup à apprendre ensuite, mais d'abord, nous vous recommandons de faire une pause, d'essayer Vue et de créer vous-même des choses amusantes et aléatoires.
Si vous sentez que vous maîtrisez ces connaissances, nous vous recommandons de revenir lire toutes les pages du guide complet des composants, y compris le chapitre approfondi sur les composants dans la barre latérale. 🎜🎜🎜 🎜
template: '...'
)🎜