about
基于vue2.6.14,https://github.com/vuejs/vue/releases/tag/v2.6.14
在Vue快速入门篇,我们学习Vue的基本用法,但说白了,我们是将Vue当成jQuery一样使用,就是在写Vue版的JavaScript代码。
接下来,我们学习Vue的组件化开发模式,这也是开发中最常用的模式。
什么是组件?
组件(Component)就像外置网卡、外置蓝牙一样,插到主机上,就能提供的相关的功能,组件可以是一段代码、一个完整功能、一个模块的封装。
组件有两个明显的特点:
- 内聚性:高内聚。
- 耦合性:低耦合。
Vue中,也推荐使用组件化开发模式,将一个完整的功能封装成组件,然后,就是哪里需要直接使用即可。
组件的分类
Vue的组件分为普通组件和单文件组件,二者都有各自的应用场景。而普通组件又可以分为局部组件和全局组件。
这里我们先来通过学习普通组件,而单文件组件通常结合脚手架使用,我们后面再聊。
我们可以在组件内部使用watch、computed、filter等等功能,也可以在组件中嵌套组件。
局部组件
局部组件的使用,分为3步:创建组件、挂在组件、使用组件。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>局部组件</title>
</head>
<body>
<div id="app">
<!-- 3. 使用组件 -->
<!-- 如果组件的命名是Comp这样的驼峰体,你在dom中可以如下使用组件 -->
<compa></compa>
<Compa></Compa>
<!-- 如果组件的命名是CompB这样的驼峰体,你在dom中可以如下使用组件,但不推荐 -->
<comp-b></comp-b>
</div>
<script src="./vue.min.js"></script>
<script>
// 局部组件的使用
// 1. 创建组件
const Compa = {
// 注意:在组件中这个data必须是一个函数,而且必须返回一个对象
data() {
return {
msg: "我是局部组件A"
}
},
// 模板最外层必须是一个闭合标签,所以通常在模板中定义一个div来包裹所有的子标签
template: `
<div>
{{msg}}
</div>
`
// 你也可以在组件中使用的数据、监听、构建方法等
}
const CompB = {
// 在局部组件内想要嵌套另一个子组件,先要挂载
components: {
Compa
},
template: `
<div>
我是局部组件B
<Compa></Compa>
</div>
`
}
new Vue({
el: "#app",
data: {},
components: {
// 2. 挂载组件,注意组件名必须字母全小写且必须包含一个连接符,或者使用驼峰体
Compa,
CompB
}
})
</script>
</body>
</html>
注意,为了避免组件和未来HTML页面元素相冲突,组件名命名:强烈建议使用字母全小写且必须包含一个连接符,或者使用驼峰体也行,更多规范参考:
PS:局部组件用的不多。
全局组件
全局组件的使用只需要两步就可以了,创建组件,使用组件。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>全局组件</title>
</head>
<body>
<div id="app">
<!-- 2. 使用组件 -->
<comp-a></comp-a>
<Compb></Compb>
<compb></compb>
<compc></compc>
</div>
<script src="./vue.min.js"></script>
<script>
// 全局组件的使用
// 1. 创建组件
Vue.component('comp-a', {
// 注意:在组件中这个data必须是一个函数,而且必须返回一个对象
data() {
return {
msg: "我是全局组件A"
}
},
// 模板最外层必须是一个闭合标签,所以通常在模板中定义一个div来包裹所有的子标签
template: `
<div>
{{msg}}
</div>
`
})
Vue.component('Compb', {
// 模板最外层必须是一个闭合标签,所以通常在模板中定义一个div来包裹所有的子标签
template: `
<div>
<h2>我是全局组件B,我嵌套了组件A</h2>
<comp-a></comp-a>
</div>
`
})
Vue.component('Compc', {
// 模板最外层必须是一个闭合标签,所以通常在模板中定义一个div来包裹所有的子标签
template: `
<div>
<h2>我是全局组件C,我嵌套了组件B</h2>
<Compb></Compb>
<compb></compb>
</div>
`
})
new Vue({
el: "#app",
data: {}
})
</script>
</body>
</html>
组件中虽然可以嵌套组件,但不允许循环嵌套,即组件a中嵌套b,b中再嵌套a,这是不允许的。
如果你仔细的研究了Vue官网的命名规则,那么:
- 如果组件命名遵循kebab-case格式即
Vue.component('my-component-name', { /* ... */ })
,那么你使用时也要<my-component-name></my-component-name>
。 - 如果组件命名遵循PascalCase。
- 如果是
Vue.component('MyComponentName', { /* ... */ })
,那么在组件的模板中,<MyComponentName></MyComponentName>
或者<my-component-name></my-component-name>
都可以,但是在dom中,只有<my-component-name></my-component-name>
。 - 如果是
Vue.component('Mycomponentname', { /* ... */ })
,那么在组件的模板和dom中,<Mycomponentname></Mycomponentname>
或者<mycomponentname></mycomponentname>
都可以。
所以,组件命名推荐遵循kebab-case,如果是PascalCase,推荐使用首字母大写的驼峰体。
你也可以将全局组件单独封装成js文件,然后哪里需要就在哪里引入了。
comp-b.js
:
Vue.component('comp-b', {
// 注意:在组件中这个data必须是一个函数,而且必须返回一个对象
data() {
return {
msg: "我是全局组件A"
}
},
// 模板最外层必须是一个闭合标签,所以通常在模板中定义一个div来包裹所有的子标签
template: `
<div>
{{msg}}
<CompA></CompA>
</div>
`
})
在HTML文件中引入:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>全局组件</title>
</head>
<body>
<div id="app">
<h3>组件可以多次使用,且相互隔离</h3>
<comp-b></comp-b>
<comp-b></comp-b>
<comp-b></comp-b>
<comp-b></comp-b>
</div>
<script src="./vue.min.js"></script>
<script src="comp-b.js"></script>
<script>
new Vue({
el: "#app",
data: {},
})
</script>
</body>
</html>
但很明显,这种操作不太符合Vue的相关规范,对于这种使用模式,我们通常是以插件的形式引入,当然,我们后面再学习插件的相关用法。
组件通信
组件间的通信可以分为父传子、子传父、兄弟之间的通信。