Vue的组件化
组件化是Vue.js中的重要思想:它提供了一种抽象,让我们可以开发出一个个独立可复用的小组件来构造我们的应用,任何的应用都会被抽象成一棵组件树。
组件化思想的应用:有了组件化的思想,我们在之后的开发中就要充分利用它,尽可能将页面拆分成一个个小的可复用的组件,这样让我们的代码更加方便组织和管理,并且扩展性很强(因此组件开发常常离不开slot标签的应用)
通常我们将包含一个功能模块的div,或是多页面均需展示的功能栏div拆分成组件。
注册组件的基本步骤
组件的使用分成三个步骤:1.创建组件构造器;2.注册组件;3.使用组件
案例如下:
<div id = "app">
<!-- 3.使用组件-->
<my-comp/>
</div>
<script src = "../JS/vue.js"></script>
<script>
//1.创建组件构造器
const myComponent = Vue.extend({
template: `
<div>
<h2>我是一个组件</h2>
</div>
`
});
//2.注册组件,并定义组件标签的名称
Vue.component('my-comp', myComponent);
let app = new Vue({
el: "#app",
data:{
name: '',
},
})
创建组件构造器时我们使用到模板字符串` ... `,也可称模板字面量,这是允许嵌入表达式的字符串字面量。你可以使用多行字符串和字符串插值功能。由于我们需要自定义组件样式,在不创建.vue文件的前提下,将多行文本以更优雅直观的方式串接更推荐使用模板字符串。
组件创造好后,可在该文件内对应挂载实例下的任何地方进行引用(当前文件夹下其他文件若未注册将无法渲染成功)
结果如下显示:
注册组件的步骤解析
1.Vue.extend():
1).调用Vue.extend()创建的是一个组件构造;
2).通常在创建组件构造器的同时,传入template代表我们自定义组件的模板;
3).编译预显示的html代码需要被写入template中
4).事实上这种写法在Vue2.x的文档中几乎已经看不到了(多是使用脚手架在component中创建.vue文件再导入),一般会直接使用语法糖,尽管如此以上方法是我们了解vue组件构建的基础。
2.Vue.component():
1).调用Vue.coponent()是将刚才的组件构造器注册为一个组件,并且给它起一个组件的标签名称;
2).需要传递两个参数: 1.注册组件的标签名, 2.组件构造器
3.组件必须挂载到某一个Vue实例下,否则它不会生效,见下:
<div id = "app">
<!-- 使用组件-->
<my-comp/>
</div>
<my-comp/>
由于注册组件my-comp并未挂载到id 为 app 的div内,因此my-comp中的内容并未成功被渲染。
全局组件与局部组件
全局组件写法见上创建注册组件方法,全局组件必须写在Vue实例创建前,这样才能在根元素下生效。使用Vue.component()可在多个Vue实例下使用,(Vue.funcxxx()方法多为全局方法)案例见下:
<div id = "app">
<h2>app</h2>
<!-- 使用组件-->
<my-comp1/>
</div>
<div id="app1">
<h2>app1</h2>
<my-comp1/>
</div>
<script src = "../JS/vue.js"></script>
<script>
//1.创建组件构造器
const myComponent1 = Vue.extend({
template: `
<div>
<h2>我是一个全局组件</h2>
</div>
`
});
/2.注册组件,并定义组件标签的名称
Vue.component('my-comp1', myComponent1);
let app = new Vue({
el: "#app",
data:{
name: '',
},
});
let app1 = new Vue({
el: "#app1",
data:{
name: '',
},
})
</script>
结果如下:
局部组件仅可在注册下的vue实例下成功渲染。案例见下:
<div id = "app">
<h2>app</h2>
<!-- 使用组件-->
<my-comp2/>
</div>
<div id="app1">
<h2>app1</h2>
<my-comp2/>
</div>
<script src = "../JS/vue.js"></script>
<script>
//1.创建组件构造器
const myComponent2 = Vue.extend({
template: `
<div>
<h2>我是一个局部组件</h2>
</div>
`
});
//2.注册组件,并定义组件标签的名称
let app = new Vue({
el: "#app",
data:{
name: '',
},
components: {
'my-comp2': myComponent2
}
});
let app1 = new Vue({
el: "#app1",
data:{
name: '',
},
})
</script>
结果见下:
但挂载div中若同时出现全局组件与局部组件,且局部组件已在对应实例下注册,页面最终仅保留全局组件渲染结果(原理暂不清楚)
注册组件语法糖
按照上面注册组件的方法较为繁琐,vue为了简化这个过程,提供了注册的语法糖。主要是省去了调用Vue.extend()步骤,可以直接使用一个对象来代替。以语法糖创建全局组件与局部组件为例:
//注册全局组件语法糖
Vue.component('my-comp1', {
template: `
<div>
<h2>我是一个全局组件</h2>
</div>
`
});
let app = new Vue({
el: "#app",
data:{
name: '',
},
//注册局部组件语法糖
components: {
'my-comp2': {
template: `
<div>
<h2>我是一个局部组件</h2>
</div>
`
}
}
});
将extend方法中创建的对象转移到原来需写入构造器名称的地方代替,操作内核未变,类似不通过中间变量指针直接操纵代码块。
模板的分离写法
由上述过程我们通过语法糖简化了Vue组件的注册过程,另外还有一个地方比较麻烦,就是template模块写法,代码量如果增大势必造成代码臃肿不便维护。如果我们能将其中的HTML分离出来写,然后挂载到对应的组件上,必然结构会变得非常清晰。
vue提供了两种方案来定义html模块内容:1.使用script标签;2.使用template标签(多用2)
使用script标签必须标明类型是text/x-template,id表示组件需要挂载的编号名,为方便我将局部组件与全局组件按这种方式定义的代码一起放上,如下:
<div id = "app">
<h2>app</h2>
<cpn1></cpn1>
<cpn></cpn>
</div>
<script type="text/x-template" id="cpn">
<div>
<h2>这是一个局部组件</h2>
</div>
</script>
<script type="text/x-template" id="cpn1">
<div>
<h2>这是一个全局组件</h2>
</div>
</script>
<script src = "../JS/vue.js"></script>
<script>
Vue.component('cpn1', {
template: '#cpn1'
})
let app = new Vue({
el: "#app",
data:{
name: '',
},
components: {
'cpn' : {
template: '#cpn'
}
}
});
结果如下:
使用template标签只需要标记id即可,代码与上相似,如下:
<div id = "app">
<h2>app</h2>
<cpn1></cpn1>
<cpn></cpn>
</div>
<template id="cpn">
<div>
<h2>这是一个局部组件</h2>
</div>
</template>
<template id="cpn1">
<div>
<h2>这是一个全局组件</h2>
</div>
</template>
<script src = "../JS/vue.js"></script>
<script>
Vue.component('cpn1', {
template: '#cpn1'
})
let app = new Vue({
el: "#app",
data:{
name: '',
},
components: {
'cpn' : {
template: '#cpn'
}
}
});
组件是一个单独功能模块的封装,这个模块有属于自己的HTML模板,也应有属于自己的数据data。组件不能直接访问Vue实例中的data,案例如下:
<div id = "app">
<h2>app</h2>
<cpn1></cpn1>
<cpn></cpn>
</div>
<template id="cpn1">
<div>
<h2>{{message}}</h2>
<h2>这是一个全局组件</h2>
</div>
</template>
<script src = "../JS/vue.js"></script>
<script>
Vue.component('cpn1', {
template: '#cpn1'
})
let app = new Vue({
el: "#app",
data:{
message: "hello",
},
});
结果见下:
模板中并没有显示message信息
组件自己的数据与vue实例存放数据格式类似,组件对象也有一个data属性(也可以是methods等属性),不同的是该data属性必须是一个函数,且这个函数返回一个对象,对象内部保存着数据。修改案例见下:
<div id = "app">
<h2>app</h2>
<cpn1></cpn1>
<cpn></cpn>
</div>
<template id="cpn1">
<div>
<h2>{{message}}</h2>
<h2>这是一个全局组件</h2>
</div>
</template>
<script src = "../JS/vue.js"></script>
<script>
Vue.component('cpn1', {
template: '#cpn1',
data() {
return {
message: "hello"
}
}
})
let app = new Vue({
el: "#app",
data:{
message: "hello",
},
});
结果见下:
message信息被正常渲染到页面,证明该方法可行。
由于这里用到的是以全局组件为例,若需要使用局部组件方法一样,只需在对象内部添加data方法,并在返回对象中加入相应需要属性即可