Vue2:组件
- 非单文件组件
- 定义
- 注册
- 使用
- 单文件组件
组件是Vue
中最核心的内容,在编写页面时,将整个页面视为一个个组件,再把组件拼接起来,这样每个组件之间相互独立,有自己的结构样式,使页面编写思路更清晰,模块更分明,而且提高了复用性。
Vue
中组件分为非单文件组件
和单文件组件
。
非单文件组件
所谓非单文件组件
,是指一个组件的html
、css
、JavaScript
三者是可以分离的,它们可以分别放在不同的文件中,这种组件并不常用,更多的时候使用单文件组件
。不过两者的语法是相通的,后者需要引入脚手架,所以主要使用前者来讲解组件语法。
定义
组件的创建依赖于Vue.entend
方法:
const vc = Vue.extend({组件对象})
调用方法时,传入一个组件对象,此时Vue.extend
返回值就是一个组件对象。
在组件对象中,大部分语法和vm
一致比如数据data
、方法methods
等。
示例:
const hello = Vue.extend({
data(){
return {
message: "hello Wrold!",
count: 0
}
},
methods: {
add(){
this.count++
}
},
})
以上代码定义了一个hello
组件,其包含data
和methods
属性,但是与vm
不太一样的是data
必须是一个函数,函数返回值是配置对象,如果在vm
中,data
应该写为下面这样:
data{
message: "hello Wrold!",
count: 0
}
这是因为组件是可以复用的,如果直接以对象的形式写data
,那么多个组件会共用一个data
对象,导致组件之间数据共享。当把data
写为一个函数,每次使用组件时,都会返回一个新创建的data
对象,组件之间的数据就是相互独立的了。
现在的组件有数据和方法了,但是还缺少html
结构,在vm
中这可以通过el
来指定挂载的元素,随后就可以直接在元素内部使用模板了:
<div id="root">
</div>
<script>
new Vue({
el:'#root',
// ...
})
</script>
但是非单文件组件不能这样做,其使用一个template
配置项,传入一个字符串,在字符串内写html
结构:
const hello = Vue.extend({
template:`
<div class="demo">
<p> {{message}} </p>
<p> {{count}} </p>
<button @click="add">count++</button>
</div>
`,
// ...
})
这里要注意使用的是模板字符串,否则无法在一个字符串内部换行。在template
的字符串内部,可以写html
结构,{{}}
插值语法、@click
事件监听等等功能。
另外的,在template
中最外层必须只有一个标签,不能同时存在多个标签同时在最外层的情况。
比如刚才的组件不能写为:
const hello = Vue.extend({
template:`
<p> {{message}} </p>
<p> {{count}} </p>
<button @click="add">count++</button>
`,
// ...
})
此处把最外层的<div>
丢掉了,导致template
下同时存在三个标签,这是不允许的。
注册
现在已经定义好了一个组件,组件想要被使用,就需要被注册到vm
中,分为全局注册
和局部注册
两种形式。
- 全局注册:
Vue.component('组件名', 组件对象)
- 局部注册:
new Vue({
components:{
组件名: 组件对象
}
})
全局注册的组件,可以被所有vm
使用,而局部注册的组件,只有当前vm
可以使用。由于大部分情况下都只有一个vm
,所以基本都使用局部注册。
将刚才的hello
组件注册到vm
中:
<div id="root">
<p>{{msg}}</p>
</div>
<script>
new Vue({
el:'#root',
data:{
msg:'我是VM'
},
components:{
hello
}
})
</script>
其中components:{hello}
就是在注册hello
组件,不过由于组件名和对象名相同进行了缩写,原本应该写为hello:hello
。
组件命名时,如果组件名有多个单词,采用kebab-case
命名,比如:
components:{
'hello-world': hello
}
如果使用了脚手架,还可以使用驼峰命名:HelloWorld
。
如果现在查看浏览器的输出结果,是看不到组件的内容的:
注册组件时,组件还没有生效,如果想要hello
组件生效,还需要进行组件标签的引入。
使用
组件的使用非常简单,当组件成功注册后,直接把组件当作一个html
标签使用。
<div id="root">
<p>{{msg}}</p>
<hello></hello>
</div>
当注册完hello
组件后,就可以使用<hello>
这个标签,这个标签就代表了这个组件:
此时就可以看到组件的内容生效了。
并且组件可以复用,也就是可以使用多个<hello>
标签:
<div id="root">
<p>{{msg}}</p>
<hello></hello>
<hello></hello>
</div>
输出结果:
此处点击了count++
按钮,两个组件的count
值不一样了,这是因为之前的data
是一个函数,两个组件使用的不是同一个data
对象,数据之间相互独立。
由于组件的使用是基于html
标签的,所以组件命名不要与现有标签冲突,比如说不要出现某个组件名称叫做div
、body
等。
以上是组件的复用,除此之外组件还可以进行嵌套:
const date = Vue.extend({
template:`
<div class="demo">
<p> 当前时间为: {{time}} </p>
</div>
`,
data(){
return {
time: "2024.11.14"
}
}
})
const hello = Vue.extend({
template:`
<div class="demo">
<p> {{message}} </p>
<p> {{count}} </p>
<button @click="add">count++</button>
<date></date>
</div>
`,
// ...
components:{
date
}
})
以上代码定义了两个组件date
和hello
,并在hello
中使用components
引入了组件date
。
其余代码和原先一致,在vm
中引入了hello
。
此时嵌套的组件date
作为了hello
的一部分,在vm
中一起展示了。
单文件组件
在非单文件组件
中,要把html
结构定义在template
,并且要以字符串的形式,这样实在是太麻烦了。单文件组件
提供了更加方便的语法:
单文件组件以.vue
为结尾,一个文件就是一个组件的全部内容,在一个文件内部同时编写html
、css
、JavaScript
内容,并且这些内容共同构成一个组件。
一个.vue
基本结构如下:
<template> <!-- .html -->
</template>
<script> //.js
</script>
<style> /* .css */
</style>
其包含三个标签:
<template>
:该组件的html
结构<script>
:该组件的JavaScript
脚本<style>
:该组件的css
样式
比如hello
组件的单文件形式:
<template> <!-- .html -->
<div class="demo">
<p> {{message}} </p>
<p> {{count}} </p>
<button @click="add">count++</button>
</div>
</template>
<script> //.js
const hello = Vue.extend({
data(){
return {
message: "hello Wrold!",
count: 0
}
},
methods: {
add(){
this.count++
}
}
})
export default hello
</script>
<style> /* .css */
.demo{
background-color: orange;
}
</style>
样式不在写在template
属性内部,而是写在<template>
标签内部。在<style>
中,为组件添加了一个背景色。在<script>
中,定义了该组件的对象,并通过export
暴露给外部,这样其它文件就可以导入这个组件。
其它的使用方式与非单文件组件一致,并且这种单文件组件一般结合脚手架使用,就不再讲解了。