._vue 组件 官方">
赞
踩
基本示例
// 定义一个名为 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: '#components-demo' })
<div id="components-demo">
<button-counter></button-counter>
</div>
组件是可以复用的Vue实例,所以可以接受与Vue相同的选项,如data,computed,watch,methods等,还有生命周期函数,除了根实例el。
组件的复用
组件的data需要写成一个方法,因为我们需要每个组件单独维护一个data所指的对象,所以我们可以用一个函数,返回一个对象,这样每个组件就单独维护自己的data了。
data: function () {
return {
count: 0
}
}
假如直接写成data:{…}这种形式的话,就会导致所有的组件都指向一个data。
组件的组织
Vue的组件是通过树形组织的,组件要使用必须先注册,注册有两种,局部注册和全局注册,前面用Vue.component注册是全局注册,后续文档还会细讲,先不慌。
全局注册的组件可以用在其被注册之后的任何 (通过 new Vue) 新创建的 Vue 根实例,也包括其组件树中的所有子组件的模板中。
通过 Prop 向子组件传递数据
可以通过配置props属性来给组件传递数据:
Vue.component('blog-post', {
props: ['title'],
template: '<h3>{{ title }}</h3>'
})
一个组件默认可以拥有任意数量的 prop,任何值都可以传递给任何 prop
一个 prop 被注册之后,你就可以像这样把数据作为一个自定义 attribute 传入:
<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>
可以用v-for来渲染:
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' }
]
}
})
<blog-post
v-for="post in posts"
v-bind:key="post.id"
v-bind:title="post.title"
></blog-post>
Vue根实例就可以把数据传给组件了。
单个根元素
模板应该被包裹在一个根元素里面:
<h3>{{ title }}</h3>
<div v-html="content"></div>
上面会报错:every component must have a single root element
应该像下面这样包裹在一个元素中,这里是div:
<div class="blog-post">
<h3>{{ title }}</h3>
<div v-html="content"></div>
</div>
假如一个组件有太多的属性,而这些属性其实都是一个对象的属性,那么我们可以绑定这个对象,而不是单独绑定属性。
<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>
这样就很复杂,其实有很多属性都是post的属性,改成这样:
<blog-post
v-for="post in posts"
v-bind:key="post.id"
v-bind:post="post"
></blog-post>
Vue.component('blog-post', {
props: ['post'],
template: `
<div class="blog-post">
<h3>{{ post.title }}</h3>
<div v-html="post.content"></div>
<div v-html="post.publishedAt"></div>
<div v-html="post.comments"></div>
</div>
`
})
这样我们要在template里面去使用post的属性都是可以访问的了,不用单独绑定。
这里template使用了模板字符串,之前的JavaScript的教程中谈到过,它会保留换行,而IE不支持,想要IE支持需要用转义字符。
监听子组件事件
通过 $emit 方法来进行事件交互:
new Vue({
el: '#blog-posts-events-demo',
data: {
posts: [/* ... */],
postFontSize: 1
}
})
<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>
`
})
这里的button不会触发任何事件,我们需要用$emit 方法
在父组件里面用v-on来绑定一个监听自定义事件:
<blog-post
...
v-on:enlarge-text="postFontSize += 0.1"
></blog-post>
在button里面加入$emit方法,触发这个事件:
<button v-on:click="$emit('enlarge-text')">
Enlarge text
</button>
就可以了
使用事件抛出一个值
$emit是可以传值的:
<button v-on:click="$emit('enlarge-text', 0.1)">
Enlarge text
</button>
<blog-post
...
v-on:enlarge-text="postFontSize += $event"
></blog-post>
传递过去的值,通过$event访问
如果事件处理函数里面是一个方法,那么$event会作为第一个参数传给这个方法:
<blog-post
...
v-on:enlarge-text="onEnlargeText"
></blog-post>
methods: {
onEnlargeText: function (enlargeAmount) {
this.postFontSize += enlargeAmount
}
}
在组件上使用 v-model
v-model实际是一个语法糖:
<input v-model="searchText">
等价于:
<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>
如果我们要正常使用组件内的input标签,需要:
将其 value attribute 绑定到一个名叫 value 的 prop 上
在其 input 事件被触发时,将新的值通过自定义的input 事件抛出
<custom-input
v-bind:value="searchText"
v-on:input="searchText = $event"
></custom-input>
Vue.component('custom-input', {
props: ['value'],
template: `
<input
v-bind:value="value"
v-on:input="$emit('input', $event.target.value)"
>
`
})
这里,template里面的input标签会先触发自己的input事件,然后去调用后面的 e m i t , 接 下 来 e m i t 会 去 调 用 组 件 的 自 定 义 事 件 i n p u t , 然 后 这 里 的 自 定 义 事 件 i n p u t 再 让 s e a r c h T e x t 赋 值 为 传 来 的 参 数 emit,接下来emit会去调用组件的自定义事件input,然后这里的自定义事件input再让searchText赋值为传来的参数 emit,接下来emit会去调用组件的自定义事件input,然后这里的自定义事件input再让searchText赋值为传来的参数event.target.value,而这个是input标签的事件。
改一下上面的代码,在里面加入打印方法就可以验证这个顺序:
<custom-input
v-bind:value="searchText"
v-on:input="log(e);searchText = $event"
></custom-input>
Vue.component('custom-input', {
props: ['value'],
template: `
<input
v-bind:value="value"
v-on:input="log(e);$emit('input', $event.target.value)"
>
`,
method:{
log(e){
console.log(e);
}
}
})
这里的两个log方法要分别在Vue实例和组件的method中定义,这里Vue实例就不展示了,结果如下:
默认的input事件先触发了,然后传入input的值1
通过插槽分发内容
我们要在模板中传入一些默认html的节点,就要用插槽,slot标签,这和影子DOM有点像。
<alert-box>
Something bad happened.
</alert-box>
Vue.component('alert-box', {
template: `
<div class="demo-alert-box">
<strong>Error!</strong>
<slot></slot>
</div>
`
})
文本节点被放入到slot中了。
动态组件
可以通过is属性来动态切换组件:
<!-- 组件会在 `currentTabComponent` 改变时改变 -->
<component v-bind:is="currentTabComponent"></component>
传入的currentTabComponent 可以包括
已注册组件的名字,
或
一个组件的选项对象
然后就可以动态的切换组件,这里还有很多内容,需要后续再看,
动态和异步组件
特殊属性,如is可以用在常规HTML元素上,但是像value这样的属性,可能需要 .prop修饰才能正常使用,可以看这
解析 DOM 模板时的注意事项
有些元素的内部元素是有规定的,比如<ul>
、<ol>
、<table>
和 <select>
<table>
<blog-post-row></blog-post-row>
</table>
以上<blog-post-row>
会被提升到外部导致渲染有问题
<table>
<tr is="blog-post-row"></tr>
</table>
这样就可以用了
这些限制条件在下面三种情况是不存在的:
以下来源使用模板:
字符串 (例如:template: '...')
单文件组件 (.vue)
<script type="text/x-template">
但是我不知道还有其他什么来源,后面可能会讲。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。