在Vue笔记(二)中简单看了一下组件 现在做一个更详细的学习
来看一个经典的组件代码(来源于Vue官网)
// 定义一个名为 button-counter 的新组件
Vue.component('button-counter', {
data: function () {
return {
count: 0
}
},
template: '<button v-on:click="count++">You clicked me {{ count }} times.</button>'
})
组件的名称是 “button-counter” 组件生成后我们可以在Vue根实例中调用它
<div id="components-demo">
<button-counter></button-counter>
</div>
new Vue({ el: '#components-demo' })
注意 在组件中data必须是一个函数 用于维护被返回对象 因此每个组件的data是独立的
注册
组件的注册分为全局注册和局部注册
Vue.component('my-component-name', {
// ... options ...
})
这样的声明是全局注册
那么如何进行局部注册呢?
首先定义组件
var ComponentA = { /* ... */ }
var ComponentB = { /* ... */ }
var ComponentC = { /* ... */ }
然后再components
中定义使用的组件
new Vue({
el: '#app',
components: {
'component-a': ComponentA,
'component-b': ComponentB
}
})
局部注册的组件,没有办法在其他的子组件中使用 除非在其他子组件中再次注册
使用ES模块 那么写法是
import ComponentA from './ComponentA.vue'
export default {
components: {
ComponentA
},
// ...
}
使用webpack这样的模块系统时 最好将组件放在各自的文件中 在需要时调用
import ComponentA from './ComponentA'
import ComponentC from './ComponentC'
export default {
components: {
ComponentA,
ComponentC
},
// ...
}
有的时候组件是一个基础组件 它可能只是一个输入框或者按钮 它将会被频繁的用到
单个根元素
Vue.component('blog-post', {
props: ['post'],
template: `
<div class="blog-post">
<h3>{{ post.title }}</h3>
<div v-html="post.content"></div>
</div>
`
})
利用props来重构组件 这个组件接受一个对象post 这样不用去给post对象绑定所有的属性了
理解 $emit
一直没搞懂什么叫父组件 子组件
父组件就是一个new Vue对象 子组件就是这个Vue对象管辖范围内的Vue对象
举例 现在有一个组件
Vue.component('blog-post', {
props: ['title'],
template: '<h3>{{ title }}</h3>'
})
这个组件存在于
<div id="blog-post-demo">
<blog-post v-for="post in posts" v-bind:key="post.id"v-bind:title="post.title"></blog-post>
</div>
注意 此时管辖blog-post-demo的Vue实例就是组件blog-post的父级
那么这个组件内的各种信息 post.id post.title都是父级传递给子组件的 在父组件内
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' }
]
}
})
所以说 子组件通过props来接受父级(父组件)的信息
同样 我们来看 $emit 怎么才能让子组件能够改变父级的信息呢
我们在子组件里添加一个$emit方法
<button v-on:click="$emit('enlarge-text')">
Enlarge text
</button>
即 点击这个button时 触发父级的enlarge-text事件
接着我们在父级中写明这个事件会发生什么 使用v-on进行绑定(后面我们会看到在Vue中使用methods也是可以的)
<blog-post
...
v-on:enlarge-text="postFontSize += 0.1"
></blog-post>
当子组件的按钮被点击时 enlarge-text事件被触发 这个事件将被父组件捕捉到并修改自身的postFontSize属性
现在就很清楚了
同样 $emit还可以传参
<button v-on:click="$emit('enlarge-text', 0.1)">
Enlarge text
</button>
这个参数在父级中 使用$event来捕捉
<blog-post
...
v-on:enlarge-text="postFontSize += $event"
></blog-post>
如果这个事件句柄是一个方法
<blog-post
...
v-on:enlarge-text="onEnlargeText"
></blog-post>
那么这个参数将作为方法的第一个参数
methods: {
onEnlargeText: function (enlargeAmount) {
this.postFontSize += enlargeAmount
}
}
自定义事件可以用于创建支持v-model
的自定义输入组件
在vue中 下面的代码
<input v-model="searchText">
等价于
<input
v-bind:value="searchText"
v-on:input="searchText = $event.target.value"
>
prop验证
为组件的prop指定验证要求 再需求没有被满足时 Vue将会进行警告
Vue.component('my-component', {
props: {
// 基础的类型检查 (`null` 和 `undefined` 会通过任何类型验证)
propA: Number,
// 多个可能的类型
propB: [String, Number],
// 必填的字符串
propC: {
type: String,
required: true
},
// 带有默认值的数字
propD: {
type: Number,
default: 100
},
// 带有默认值的对象
propE: {
type: Object,
// 对象或数组默认值必须从一个工厂函数获取
default: function () {
return { message: 'hello' }
}
},
// 自定义验证函数
propF: {
validator: function (value) {
// 这个值必须匹配下列字符串中的一个
return ['success', 'warning', 'danger'].indexOf(value) !== -1
}
}
}
})
组件切换
一个非常典型的场景就是点击某个标签时 出现不同的内容 即组件发生了切换
我们使用is
来实现组件的切换
<component v-bind:is="currentTabComponent"></component>
通过对currentTabComponent
进行计算属性computed
来实现切换
总结:组件的多种写法
1、全局组件
// 组件的注册
Vue.component( 'componentName', {
template: // 组件的html结构,
data(){
return{
// 组件中的属性
}
},
method: {
// 组件中的方法
}
...... // 组件其他的属性和方法
})
// 组件的使用
new Vue({
el: '#app'
})
2、局部组件
// 构造组件对象
const componentName = {
template: // 组件的html结构,
data(){
return{
// 组件中的属性
}
},
method: {
// 组件中的方法
}
...... // 组件其他的属性和方法
}
// 组件的使用
new Vue({
el: '#app',
components: {
// 组件注册、调用
componentName
}
})
3、使用template标签
先使用<template>
标签把组件的html结构写好
<template id="componnet">
// 组件的html结构
</template>
全局注册
// 全局组件的注册与使用
Vue.component( 'componentName', {
template: '#component',
data(){
return{
// 组件中的属性
}
},
method: {
// 组件中的方法
}
...... // 组件其他的属性和方法
})
new Vue({
el: '#app'
})
局部注册
// 局部组件的注册与使用
const componentName = {
template: '#component',
data(){
return{
// 组件中的属性
}
},
method: {
// 组件中的方法
}
...... // 组件其他的属性和方法
}
new Vue({
el: '#app',
components: {
// 组件注册、调用
componentName
}
})
4、单文件组件
<template lang="html">
// 组件中的html结构
</template>
<script>
//组件的逻辑
export default {
// 组件的属性和方法
}
</script>
<style lang="css" scoped>
// 组件的样式
</style>