1、基本示例
<div id="id1">
<button-counter></button-counter>
</div>
//定义一个名为button-counter的新组件
Vue.component('button-counter',{
data:function () {
return {
count:0
}
},
template:'<button v-on:click="count++">you clicked me {{count}} times.</button>'
})
//调用
new Vue({el:"#id1"})
因为组件是可复用的 Vue 实例,所以它们与 new Vue 接收相同的选项,例如 data、computed、watch、methods 以及生命周期钩子等。仅有的例外是像 el 这样根实例特有的选项。
注:一个组件的data选项必须是一个函数。因此每个实例可以维护一份被返回对象的独立的拷贝。
2、组件的复用
可以将组件进行任意次数的复用:
<div id="id1">
<button-counter></button-counter>
<button-counter></button-counter>
<button-counter></button-counter>
<button-counter></button-counter>
</div>
注:当点击按钮时,每个组件都会各自独立维护它的count。因为每用一次组件,就会有一个它的新实例被创建。
3、通过Prop向子组件传递数据
Prop——是可以在组件上注册的一些自定义特性。当一个值传递给一个prop特性的时候,它就变成了那个组件实例的一个属性。
<!--通过 Prop 向子组件传递数据-->
<div id="id2">
<blog-post v-for="post in posts" v-bind:key="post.id" v-bind:title="post.title"></blog-post>
</div>
//通过 Prop 向子组件传递数据,为组件传递一个标题
Vue.component('blog-post',{
props:['title'],
template:'<h3>{{title}}</h3>'
})
new Vue({
el:"#id2",
data:{
posts:[
{id:1,title:'h1'},
{id:2,title:'h2'},
{id:3,title:'h3'}
]
}
})
4、单个根元素
每个组件必须只有一个根元素——可以将模板的内容包裹在一个父元素内。
当组件变得越来越复杂的时候,不只需要标题和内容,还需要发布日期、评论等等。为每个相关的信息定义一个 prop 会变得很麻烦:
<blog-post |
重构一下这个 <blog-post> 组件,让它变成接受一个单独的 post prop:
<blog-post |
Vue.component('blog-post', { |
5、通过事件向父级组件发送消息
示例:引入一个可访问性的功能放大文字字号,同时让页面的其他部分保持默认的字号。在父组件中,添加一个postFontSize 数据属性来支持这个功能:
<!--通过事件向父级组件发送消息-->
<div id="id3">
<div :style="{ fontSize: postFontSize + 'em' }">
<wjy-post
v-for="post in posts"
v-bind:key="post.id"
v-bind:post="post"
v-on:enlarge-text="postFontSize += 0.1"
></wjy-post>
</div>
</div>
//通过事件向父级组件发送消息
//调用内建的 $emit 方法并传入事件的名字,来向父级组件触发一个事件
Vue.component('wjy-post', {
props: ['post'],
template: `
<div class="wjy-post">
<h3>{{ post.title }}</h3>
<button v-on:click="$emit('enlarge-text')">
Enlarge text
</button>
<div v-html="post.content"></div>
</div>
`
})
new Vue({
el:"#id3",
data:{
posts:[
{id:1,title:'aaaaaaaaaaaa',content:'ddddd'},
{id:2,title:'bbbbbbbbbbbb',content:'ddddd'},
{id:3,title:'cccccccccccc',content:'ddddd'}
],
postFontSize:1
}
})
6、在组件上使用v-model
<input v-model="searchText"> |
等价于:
<input |
当用在组件上时,v-model 则会这样:
<custom-input |
为了让它正常工作,这个组件内的 <input> 必须:
- 将其 value 特性绑定到一个名叫 value 的 prop 上
- 在其 input 事件被触发时,将新的值通过自定义的 input 事件抛出
如:
<custom-input v-model="searchText"></custom-input>
Vue.component('custom-input', {
props: ['value'],
template: `
<input
v-bind:value="value"
v-on:input="$emit('input', $event.target.value)"
>
`
})
7、通过插槽分发内容——向一个组件传递内容<slot>
<alert-box>
Something bad happened.
</alert-box>
//定义组件
Vue.component('alert-box', {
template: `
<div class="demo-alert-box">
<strong>Error!</strong>
<slot></slot>
</div>
`
})
8、解析DOM模板时的注意事项
自定义的组件可能会被作为无效的内容提升到元素外部,导致渲染结果出错——is
有些 HTML 元素,诸如 <ul>、<ol>、<table> 和 <select>,对于哪些元素可以出现在其内部是有严格限制的。而有些元素,诸如 <li>、<tr> 和 <option>,只能出现在其它某些特定的元素内部。
这会导致我们使用这些有约束条件的元素时遇到一些问题。例如:
<table> |
这个自定义组件 <blog-post-row> 会被作为无效的内容提升到外部,并导致最终渲染结果出错。幸好这个特殊的 is 特性给了我们一个变通的办法:
<table> |