对组件的理解
我们先看看使用传统方式编写应用:
例如我们编写如左图的页面,我们先使用html搭建基础结构,再使用css文件对每一个部分进行美化(如此方便维护),最后使用js编写每个部分的交互逻辑(方便维护)。
现在我们多了一个需求,还要写一个页面结构如左下角所示,其中顶部和底部完全相同:
我们的做法是:再写一个HTML文件,然后引入顶部和底部相应的css、js文件达到复用,最后编写商品列表的样式和逻辑:
以上的过程存在两个问题:
- 依赖关系混乱,不好维护
- 代码复用率不高(css、js代码达到了复用,但是html的代码是单纯的复制)
接下来我们来看使用组件方式编写应用:
完成同样的需求,使用组件的方式,相当于是把每一个部分的css、js、html片段进行了封装,在遇到相同的部分时可以直接引入来达到复用。
注意:组件里面只是html片段,只需要实现那一部分的结构即可。至于说什么body标签、html标签都不需要写。
我们通过一张图更好的理解组件:
组件就是实现应用中局部
功能代码
和资源
的集合
还有几个概念需要知道:
①模块
理解:向外提供特定功能的 js 程序, 一般就是一个 js 文件
存在意义:js 文件很多很复杂
作用:复用 js, 简化 js 的编写, 提高 js 运行效率
②模块化
当应用中的 js 都以模块来编写的, 那这个应用就是一个模块化的应用。
③组件化
当应用中的功能都是多组件的方式来编写的, 那这个应用就是一个组件化的应用。
非单文件组件
非单文件组件
:一个文件中包含有n个组件- 结构图:
单文件组件
:一个文件中只包含有1个组件- 结构图:
在使用Vue进行大型项目开发的时候,一般都使用的单文件组件,如此条理清晰代码好维护。
接下来我们按照如下的样式去创建一个非单文件组件:
这个组件里面绝大多数的配置项跟原来vm中的相同。也就是说原来的计算属性、监视属性等等在这里也可以使用。同时还要注意组件定义中不能有el配置项,因为最终所有的组件都要被一个vm管理,由vm决定服务于哪个容器。
还要注意data配置项要为一个函数形式,不能再用原来的对象形式。
这么做是因为如果使用对象形式,这个组件在被复用的时候,如果在其他复用的地方被修改,那么在这个地方也会跟着被修改。所以我们使用函数式,每次使用他会为我们返回新的data对象,不会被其他的地方给影响。
使用组件有三个步骤:
- 创建组件
- 注册组件
- 利用组件标签使用组件
使用组件的完整代码:
<body>
<div id="root">
<!-- 使用组件 -->
<school></school>
<hr>
<student></student>
</div>
</body>
<script>
//创建school组件
const school = Vue.extend({
template:`
<div>
<h2>学校名称:{{schoolName}}</h2>
<h2>学校地址:{{schoolAddress}}</h2>
</div>
`,
data(){
return {
schoolName:'NEFU',
schoolAddress:'哈尔滨',
}
}
})
//创建student组件
const student = Vue.extend({
template:`
<div>
<h2>学生名称:{{studentName}}</h2>
<h2>学生年纪:{{studentAge}}</h2>
</div>
`,
data(){
return {
studentName:'张三',
studentAge:'18'
}
}
})
new Vue({
el:'#root',
//注册组件
components:{
school:school,
student:student
}
})
</script>
不使用组件的代码:
<body>
<div id="root">
<h2>学校名称:{{schoolName}}</h2>
<h2>学校地址:{{schoolAddress}}</h2>
<hr>
<h2>学生名称:{{studentName}}</h2>
<h2>学生年纪:{{studentAge}}</h2>
</div>
</body>
<script>
new Vue({
el:'#root',
data:{
schoolName:'NEFU',
schoolAddress:'哈尔滨',
studentName:'张三',
studentAge:'18'
}
})
</script>
组件代码中有几个注意点:
new Vue({
el:'#root',
//注册组件
components:{
school:school,
student:student
}
})
components中的键是使用组件标签时标签的名字。而值是你创建组件时一开始取的名字,也就是const后面的东西。
template:`
<div>
<h2>学生名称:{{studentName}}</h2>
<h2>学生年纪:{{studentAge}}</h2>
</div>
`,
因为template里面只能有一个根标签,所以我们要使用div标签给包起来。
我们的vm中也可以放数据不冲突,例如:
<body>
<div id="root">
<h2>欢迎来到{{msg}}</h2>
<hr>
<!-- 使用组件 -->
<school></school>
<hr>
<student></student>
</div>
</body>
<script>
//创建school组件
const school = Vue.extend({
template:`
<div>
<h2>学校名称:{{schoolName}}</h2>
<h2>学校地址:{{schoolAddress}}</h2>
</div>
`,
data(){
return {
schoolName:'NEFU',
schoolAddress:'哈尔滨',
}
}
})
//创建student组件
const student = Vue.extend({
template:`
<div>
<h2>学生名称:{{studentName}}</h2>
<h2>学生年纪:{{studentAge}}</h2>
</div>
`,
data(){
return {
studentName:'张三',
studentAge:'18'
}
}
})
new Vue({
el:'#root',
//注册组件
components:{
school:school,
student:student
},
data:{
msg:'CSDN'
}
})
</script>
我们可以利用这个例子体会使用函数返回data对象的好处:
我们将student组件复用一份:
<body>
<div id="root">
<h2>欢迎来到{{msg}}</h2>
<hr>
<!-- 使用组件 -->
<school></school>
<hr>
<student></student>
<student></student>
</div>
</body>
然后我们通过Vue开发者工具进行数据的修改,发现两者是不会互相影响的:
局部注册和全局注册
我们前面使用的就是局部注册。如果使用局部注册,那么在哪注册的哪里可以使用。而如果使用全局注册,则在哪都可以使用。
例如我们现在创建两个容器,然后创建一个hello组件:
现在我们的hello组件既可以在root容器里面用,也可以在root2容器里面用。
总结:
Vue中使用组件的三大步骤:
一、定义组件(创建组件)
二、注册组件
三、使用组件(写组件标签)
一、如何定义一个组件?
使用Vue.extend(options)创建,其中options和new Vue(options)时传入的那个options几乎一样,但也有点区别;
区别如下:
1.el不要写,为什么? ——— 最终所有的组件都要经过一个vm的管理,由vm中的el决定服务哪个容器。
2.data必须写成函数,为什么? ———— 避免组件被复用时,数据存在引用关系。
备注:使用template可以配置组件结构。
二、如何注册组件?
1.局部注册:靠new Vue的时候传入components选项
2.全局注册:靠Vue.component('组件名',组件)
三、编写组件标签:
<school></school>