官网说明
https://cn.vuejs.org/v2/guide/components.html
定义Vue组件
什么是组件:组件的出现,就是为了拆分Vue实例的代码量的,能够让我们以不同的组件,来划分不同的功能模块,将来我们需要什么样的功能,就可以去调用对应的组件即可;组件化和模块化的不同:
- 模块化:是从代码逻辑的角度进行划分的;方便代码分层开发,保证每个功能模块的职能单一;
- 组件化:是从UI界面的角度进行划分的;前端的组件化,方便UI组件的重用;
全局组件定义的三种方式
使用 Vue.extend 配合 Vue.component 方法:
var login = Vue.extend({
template: '登录
'
});
Vue.component('login', login);直接使用 Vue.component 方法:
Vue.component('register', {
template: '注册
'
});将模板字符串,定义到script标签种:
<script id="tmpl" type="x-template"><div><a href="#">登录a> | <a href="#">注册a>div>script>
同时,需要使用 Vue.component 来定义组件:
Vue.component('account', {
template: '#tmpl'
});
❝注意:组件中的DOM结构,有且只能有唯一的根元素(Root Element)来进行包裹!
❞
看来上面的这些定义,应该还不能很好得去理解,下面来逐个方式使用完整代码来进行示例。
使用 Vue.extend 配合 Vue.component 方法创建组件
使用Vue.extend
创建组件也有两种方式,第一种就是使用变量来传递创建的组件(上面示例中的写法),第二种就是直接写到Vue.component
中,不需要变量来传递了。
这两种的写法效果都是一样的,下面分别来示例一下看看。
1.使用变量来传递创建的组件
![42980d34e0aa0d749493c4bf87b35f3f.png](https://i-blog.csdnimg.cn/blog_migrate/061e1c9bc4ce8a571838f17965e413e6.png)
<script>// 使用 Vue.extend 来创建全局的Vue组件// 1.1 使用 Vue.extend 来创建全局的Vue组件var com1 = Vue.extend({template: '
这是使用 Vue.extend 创建的组件
这是使用 Vue.extend 创建的组件
' // 通过 template 属性,指定了组件要展示的HTML结构
})// 1.2 使用 Vue.component('组件的名称', 创建出来的组件模板对象)
Vue.component('myCom1', com1)// 2. 创建一个Vue的实例var vm = new Vue({el: '#app',data: {},
})script>
2.直接将Vue.extend
创建的组件写到Vue.component
中
![84f4992f0dfddef6ccaf0a8d5c526c1a.png](https://i-blog.csdnimg.cn/blog_migrate/1097d6c6544b0c0760fce6ec3654bd48.png)
<script>// 使用 Vue.extend 来创建全局的Vue组件// 1.1 使用 Vue.extend 来创建全局的Vue组件var com1 = Vue.extend({template: '
这是使用 Vue.extend 创建的组件
这是使用 Vue.extend 创建的组件
' // 通过 template 属性,指定了组件要展示的HTML结构
})// 1.2 使用 Vue.component('组件的名称', 创建出来的组件模板对象)
Vue.component('myCom1', com1)// 1.3 直接将Vue.extend创建的组件写到Vue.component中
Vue.component('myCom2', Vue.extend({template: '
直接将Vue.extend创建的组件写到Vue.component中
直接将Vue.extend创建的组件写到Vue.component中
'
}))// 2\. 创建一个Vue的实例var vm = new Vue({el: '#app',data: {},
})script>
3.对于命名为驼峰法的组件,需要使用-
来引用创建的组件
在上面创建的两个组件示例中,可以看到两个组件的命名是「驼峰法命名」(myCom1
, myCom2
),那么使用组件引用的时候,需要设置为-
的写法:
- 那么为了说明这种情况,那么先来一个「错误的示例」,如下:
![b33940250cec1385558d20c13fc9604d.png](https://i-blog.csdnimg.cn/blog_migrate/368e5a60a93c99afddac93b05d518df1.png)
打开浏览器查看报错的信息如下:
![2331e20dcfae2020eab336f03c46ba41.png](https://i-blog.csdnimg.cn/blog_migrate/8a057189757a753a9781c0a8d321fb5b.png)
错误提示如下:
vue.js:634 [Vue warn]: Unknown custom element: - did you register the component correctly? For recursive components, make sure to provide the "name" option.
(found in )
可以看到错误信息就是说找不到元素 mycom1
, 请确认是否正确注册该组件。
- 解决的方法:将驼峰命名的组件,在渲染模板的时候修改为
-
写法,如下:
![ca3c86ff014714be6370b8fadc0ab160.png](https://i-blog.csdnimg.cn/blog_migrate/2f79042dda7641ba867b4080ed4dd591.png)
查看浏览器正确显示组件的信息,如下:
![35b3d1dd61480803a138db30c0dff612.png](https://i-blog.csdnimg.cn/blog_migrate/fdb7c27cd2cd9fd3f2fba6125bfa34f9.png)
可以看到已经可以正常渲染组件的内容了,那么组件还可以重复多次渲染,每次渲染引用则会单独创建一个新的对象。
4.渲染多个组件
![49c553d0015c57451160217d245822bc.png](https://i-blog.csdnimg.cn/blog_migrate/4f641a545172b3601b59113a2518984c.png)
查看浏览器显示如下:
![667d9610bf26036fb6f7e1d40b2c9792.png](https://i-blog.csdnimg.cn/blog_migrate/6316689038ac61c18fa8e394c7c27252.png)
直接使用 Vue.component 方法创建组件
在上面使用Vue.extend
创建组件的时候,可以不用中间变量,直接写入Vue.component
中进行组件创建以及注册。
那么其实只要简写一下,就可以直接用Vue.component
创建组件,如下:
![b7020b882c15ceb89a27e9e5c41da078.png](https://i-blog.csdnimg.cn/blog_migrate/1af5604824b153c7d86c332d7bdb0a53.png)
可以对比看出,只要将Vue.extend
去除,就是直接简写使用Vue.component
来创建组件了。
将mycom3
在模板中使用,并且浏览器查看如下:
![ea3ddbea253ee45444e4c8de7f7c968a.png](https://i-blog.csdnimg.cn/blog_migrate/f3aaf39ec75adbff361824d0d4412566.png)
![69d2051e9743d4a41f42c2c0978d4fd8.png](https://i-blog.csdnimg.cn/blog_migrate/17c8cd2ce64142ccd045150057e789b8.png)
将模板字符串,定义到template标签中
在上面的示例中,讲解了如何去定义、注册全局组件的两种方式,但是还没有暴露一个问题。
问题:组件中的DOM结构,有且只能有唯一的根元素(Root Element)来进行包裹
这个在上面的说明中有提到要注意,那么这个问题到底是什么问题呢?
在组件的template
定义模板内容中,上面的示例的内容大致如下:
![5761bce23b430dd6612f01d860aac142.png](https://i-blog.csdnimg.cn/blog_migrate/a594d567251db959fb9c889821ed5f41.png)
从图中看到我前面的示例中的template
内容只写了一个html元素,下面来看看如果写多个html元素会如何报错,如下:
![2f0c2091cb52dc3986cdbbc6394ad23a.png](https://i-blog.csdnimg.cn/blog_migrate/312a64634590169a923269dd81b1a943.png)
在浏览器中查看错误如下:
![e23da293139ebdd4f78c0f45546ef74a.png](https://i-blog.csdnimg.cn/blog_migrate/030cbce006a43a89e8449ea2731e7190.png)
错误信息如下:
vue.js:634 [Vue warn]: Error compiling template:
Component template should contain exactly one root element. If you are using v-if on multiple elements, use v-else-if to chain them instead.
1 |
直接使用 Vue.component 方法创建组件 mycom3
直接使用 Vue.component 方法创建组件 mycom3
写多一个html元素span
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
found in
--->
这个错误信息就是因为在template
中写了两个html元素导致的,在Vue框架中对于组件是只能有一个唯一的根元素的。因为这两个html
元素相互独立,那么就相当于有两个「根元素」。
解决的办法就是再写一个div
来包裹这两个元素,保证只有一个唯一的根元素。
![a0f42fcf8e753f33f3cee108e1209343.png](https://i-blog.csdnimg.cn/blog_migrate/aa3be8949413b4e770b6c973c31b43e3.png)
再回到浏览器,查看信息如下:
![f67ee07d45a7f4218f9b75d81f637a7a.png](https://i-blog.csdnimg.cn/blog_migrate/631a93e44c07fa3a735a793a4182c2ba.png)
好了,从这里已经可以看出template
的组件内容可以写多个html元素,并且可以写得比较复杂。如果当作字符串一直写是挺麻烦的,又没有命令提示,体验很差。
那么可以将这部门的字符串内容提取出来,写到一个template
标签中。
将模板字符串,定义到template标签
![97a662da8bfeb79fb3b150de90524108.png](https://i-blog.csdnimg.cn/blog_migrate/a9b23b82ab2acfad4c797145bf974044.png)
浏览器显示如下:
![10f19945f2a3aaf7080ac5373888bde7.png](https://i-blog.csdnimg.cn/blog_migrate/366ce1d02e779fb1f9f481ad4a6e5ec0.png)
可以看到正常显示模板内容。
完整示例代码
span style="line-height: 26px;">html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Titletitle>
<script src="lib/vue.js">script>
head>
<body>
<div id="app">
<my-com1>my-com1>
<my-com1>my-com1>
<hr>
<my-com2>my-com2>
<my-com2>my-com2>
<hr>
<mycom3>mycom3>
<hr>
<my-com5>my-com5>
div>
<template id="tpl1">
<div>
<h5>使用template标签编写组件内容h5>
<span>html元素spanspan>
div>
template>
<script>// 1.5 将模板字符串,定义到template标签
Vue.component('my-com5',{template: '#tpl1',
})// 使用 Vue.extend 来创建全局的Vue组件// 1.1 使用 Vue.extend 来创建全局的Vue组件var com1 = Vue.extend({template: '
这是使用 Vue.extend 创建的组件myCom1
这是使用 Vue.extend 创建的组件myCom1
' // 通过 template 属性,指定了组件要展示的HTML结构
})// 1.2 使用 Vue.component('组件的名称', 创建出来的组件模板对象)
Vue.component('myCom1', com1)// 1.3 直接将Vue.extend创建的组件写到Vue.component中
Vue.component('myCom2', Vue.extend({template: '
直接将Vue.extend创建的组件myCom2写到Vue.component中
直接将Vue.extend创建的组件myCom2写到Vue.component中
'
}))// 1.4 直接使用 Vue.component 方法创建组件
Vue.component('mycom3',{template: '
直接使用 Vue.component 方法创建组件 mycom3
直接使用 Vue.component 方法创建组件 mycom3
写多一个html元素span
'
})// 2\. 创建一个Vue的实例var vm = new Vue({el: '#app',data: {},
})script>
body>
html>
使用components定义私有组件
上面讲诉的内容是如何定义全局组件,但是还有一种情况就是需要定义私有组件,因为并不是每个组件都需要进行全局共享的。
那么这时候只需要将组件定义到vm
实例中的components
属性内即可。
示例:创建私有组件
1.首先创建两个vm
示例
![a0ff5a2ac1d8bf03d8190d663c9830a9.png](https://i-blog.csdnimg.cn/blog_migrate/d44c4f2533a450239a2b082d90679af0.png)
在一个html文件中可以创建多个vm实例的,下面在浏览器打开来看看效果,如下:
![1deca9384efed9b0e8c3b003d0482b78.png](https://i-blog.csdnimg.cn/blog_migrate/814c35fbf96ee2533ad15befd5a70cf6.png)
2.在vm1创建一个私有的组件
![8c647bb0b5c1bb2bd5f424902ee6e0b5.png](https://i-blog.csdnimg.cn/blog_migrate/3307575acd4910f45802d58f0041345c.png)
在浏览器查看一下效果,如下:
![8c4a161ad80c82129659fb7297a95e1a.png](https://i-blog.csdnimg.cn/blog_migrate/cc059986500cee4d7bcd400304a03588.png)
3.在vm2引用vm1的私有组件,查看报错信息
![52a33ded145053202bd2e494d5afe528.png](https://i-blog.csdnimg.cn/blog_migrate/216e4a0e1addd1b90e38e14d31ba9df9.png)
打开浏览器查看,如下:
![1dcee345e22146f788fa54dad302b774.png](https://i-blog.csdnimg.cn/blog_migrate/a62cad857b58b52a784c7cea2e04cc68.png)
可以看到vm2实例因为没有注册这个组件,所以直接引用就会报错。如果要解决这个问题,那么就需要在vm2也注册这个组件。
4.在vm2注册私有组件,解决报错
![6858c38098652f2d446fb8db892001b2.png](https://i-blog.csdnimg.cn/blog_migrate/9da74f43d2816b85056c71d6bf56673b.png)
浏览器展示如下:
![f95e7d3481c3b7a0abf4924c8555e5b4.png](https://i-blog.csdnimg.cn/blog_migrate/4797554041ccc0881efd717a23fe9bf9.png)
完整实例代码
span style="line-height: 26px;">html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Titletitle>
<script src="lib/vue.js">script>
head>
<body>
<div id="app1">
<h1>{{ msg }}h1>
<my-com1>my-com1>
div>
<div id="app2">
<h1>{{ msg }}h1>
<my-com1>my-com1>
div>
<template id="tpl1">
<h2>创建vm1实例的私有组件h2>
template>
<script> // 创建第一个Vue的实例var vm1 = new Vue({el: '#app1',data: {"msg": "这是vm1实例"},components:{ // 注册私有组件"my-com1": {template: "#tpl1",
}
},
})// 创建第二个Vue的实例var vm2 = new Vue({el: '#app2',data: {"msg": "这是vm2实例"},components:{ // 注册私有组件"my-com1": {template: "#tpl1",
}
},
})script>
body>
html>
示例:私有组件创建的简化方式
1.将组件设置为一个变量,并以简写的方式写入私有组件中。
![f040a345c3f701144823dbd8315e0a32.png](https://i-blog.csdnimg.cn/blog_migrate/ee0d91b5ae1383338225011f611d30fd.png)
可以看到下面的简写方式就是将组件对象直接写在components
下。下面将已经简写与未简写的两种放行进行对比。
- 未简写的写法:
components:{ // 注册私有组件
"mycom1": mycom1, // 未简写的方式
},
- 简写后的写法:
components:{ // 注册私有组件
mycom1, // 简写的方式
},
2.简写后的组件与定义的注册名一直,将其渲染到模板中
![6c0f6ce95caf377bcef0ecd11afcbc66.png](https://i-blog.csdnimg.cn/blog_migrate/1320c1d0e365efdcbb053a77421c6c01.png)
浏览器显示如下:
![fd91fdd7819c969346cc74da106ffd69.png](https://i-blog.csdnimg.cn/blog_migrate/7dd8cd09e58732a0398ce4ca08fea128.png)
完整示例代码
span style="line-height: 26px;">html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Titletitle>
<script src="lib/vue.js">script>
head>
<body>
<div id="app1">
<h1>{{ msg }}h1>
<mycom1>mycom1>
div>
<div id="app2">
<h1>{{ msg }}h1>
<mycom1>mycom1>
div>
<template id="tpl1">
<h2>创建vm1实例的私有组件h2>
template>
<script> // 创建组件my-com1var mycom1 = {template: "#tpl1"
}// 创建第一个Vue的实例var vm1 = new Vue({el: '#app1',data: {"msg": "这是vm1实例"},components:{ // 注册私有组件"mycom1": mycom1, // 未简写的方式
},
})// 创建第二个Vue的实例var vm2 = new Vue({el: '#app2',data: {"msg": "这是vm2实例"},components:{ // 注册私有组件
mycom1, // 简写的方式
},
})script>
body>
html>
交流QQ群:
![b668bf2802b976b19e72f3c1bd34cef3.png](https://i-blog.csdnimg.cn/blog_migrate/9cad83620e80a5b8b85d19c9672d9f30.png)
点击下面,查看更多Vue系列文章