Vue2 组件基础
发表于:2021-09-02分类:Vue.js创建并使用一个简单的组件
<div id="components-demo">
<button-counter></button-counter>
</div>
<script type="text/javascript">
//创建组件
Vue.component('button-counter', {
data: function() {
return {
//声明变量
count: 0
}
},
//模板并使用组件
template: '<button v-on:click="count++">点击了{{ count }}次.</button>'
})
//创建vue实例
new Vue({ el: '#components-demo' })
</script>
组件复用
<div id="components-demo">
<button-counter></button-counter>
<button-counter></button-counter>
<button-counter></button-counter>
</div>
组件可以复用,并且都以独立实例存在。
注意:组件里的data应该是一个函数,正是有了这个方法,各个组件之间才能独立存储数据。
组件的组织
组件分为全局注册和局部注册。
通过 Prop 向子组件传递数据
Prop 可以给组件添加自定义属性,并传递属性值
<div id="components-demo">
<blog-post title="值" content="内容"></blog-post>
</div>
<script type="text/javascript">
Vue.component('blog-post', {
props: ['title','content'],
template: '<div><h3>{{ title }}</h3><p>{{ content }}</p></div>'
})
new Vue({
el: '#components-demo'
})
</script>
<!-- 得到 -->
<div id="components-demo"><div><h3>值</h3><p>内容</p></div></div>
<div id="blog-post-demo">
<!-- 实用例子:
v-for循环posts迭代
v-bind:key绑定key值
v-bind:title绑定title值 -->
<blog-post v-for="post in posts" v-bind:key="post.id" v-bind:title="post.title"></blog-post>
</div>
<script type="text/javascript">
Vue.component('blog-post', {
//自定义属性title
props: ['title'],
template: '<h3>{{ title }}</h3>'
})
new Vue({
el: '#blog-post-demo',
data: {
//posts有多个title值
posts: [{
id: 1,
title: 'A'
},
{
id: 2,
title: 'B'
},
{
id: 3,
title: 'C'
}
]
}
})
</script>
单个根元素
组件模板中只能有一个根元素
<!-- 可以-->
<div>
<h3>{{ title }}</h3>
<div v-html="content"></div>
</div>
<!-- 不可以 -->
<h3>{{ title }}</h3>
<div v-html="content"></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>
<!-- 传递数组进去就行(每个数组值为对象) -->
<blog-post
v-for="post in posts"
v-bind:key="post.id"
v-bind:post="post"
></blog-post>
<script>
Vue.component('blog-post', {
props: ['post'],
//在模板中读取post的不同属性
template: `
<div class="blog-post">
<h3>{{ post.title }}</h3>
<div v-html="post.content"></div>
</div>
`
})
new Vue({
el: '#blog-post-demo',
data: {
posts: [{
id:0,
title:"A",
content:"aa"
}, {
id:1,
title:"B",
content:"bb"
}]
}
})
</script>
监听子组件的事件
上例中,可以传递数据给子组件了,子组件也可以使用$emit
传递事件给父组件
new Vue({
el: '#blog-posts-events-demo',
data: {
posts: [/* ... */],
postFontSize: 1
//添加一个postFontSize,来支持(声明以便使用)
}
})
<div id="blog-posts-events-demo">
<div :style="{ fontSize: postFontSize + 'em' }"><!-- 绑定样式读取postFontSize给字号 -->
<blog-post
v-for="post in posts"
v-bind:key="post.id"
v-bind:post="post"
v-on:enlarge-text="postFontSize += 0.1"
></blog-post>
<!-- 创建一个enlarge-text事件可以给postFontSize+0.1,对应修改了父组件的style -->
</div>
</div>
Vue.component('blog-post', {
props: ['post'],
//模板中添加一个按钮来放大字体用,使用$emit,触发父组件的enlarge-text事件
template: `
<div class="blog-post">
<h3>{{ post.title }}</h3>
<button v-on:click="$emit('enlarge-text')">
放大
</button>
<div v-html="post.content"></div>
</div>
`
})
$emit
的第二个参数可以携带值,父组件可以使用$event访问这个值
<button v-on:click="$emit('enlarge-text', 0.1)">
Enlarge text
</button>
<!-- $event -->
<blog-post
v-on:enlarge-text="postFontSize += $event"
></blog-post>
如果使用的是个方法,可以作为一个参数传递
//v-on:enlarge-text="onEnlargeText"
methods: {
onEnlargeText: function (enlargeAmount) {
this.postFontSize += enlargeAmount
}
}
自定义事件也可以创建支持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>
为了让它正常工作,我们需要prop一个value和input事件触发时,抛出值
Vue.component('custom-input', {
props: ['value'],
template: `
<input
v-bind:value="value"
v-on:input="$emit('input', $event.target.value)"
>
`
})
现在v-model
才可以使用,别忘了在vue实例的date里声明searchText。
<custom-input v-model="searchText"></custom-input>
插槽
组件标签之间的内容可以传递给组件渲染用,slot
就是这个插槽vue的自定义元素
Vue.component('alert-box', {
template: `
<div class="demo-alert-box">
<strong>Error!</strong>
<slot></slot>
</div>
`
})
//<slot></slot>之间就渲染组件标签之间的内容
动态组件
通过特殊的component
标签和is
属性实现组件动态切换
<!-- 组件会在 `name` 改变时改变 -->
<component v-bind:is="name"></component>
name可以是组件名称或组件的选项对象,通过改变name来切换不同的组件
解析DOM模板时的注意事项
html是由严格解析限制的例如ul中只能有li,table中应该是tr。当我们在这些元素中使用自定义组件时会被提升到外部造成错误,使用is
可以变通的方法
<table>
<blog-post-row></blog-post-row>
</table>
<!-- 上例中直接使用自定义组件会渲染错误,下面使用table内允许的元素tr,通过加is来指定自定义组件 -->
<table>
<tr is="blog-post-row"></tr>
</table>
注意单组件中不存在这个问题
评论已关闭