本篇总结Vue中组件的使用,对组件的理解以及使用组件需要特别注意的点。
符号约定:
.html文件表示该项目是传统web项目,即没用使用Vue脚手架工具,通过<script>引入vue.js的方法.vue文件表示该项目是使用vue脚手架工具创建的
文章目录
- 1、非单文件组件和单文件组件
- 2、单文件组件使用
- 2.1 组件使用三大步骤
- 2.2 组件使用的注意点
- 3、VueComponent构造函数
- 4、VueComponent 和Vue之间的关系
1、非单文件组件和单文件组件
(1)非单文件组件
非单文件组件是指一个文件中不止一个组件,主要是指在.html文件中的使用方式。
(2)单文件组件
单文件组件是指在.vue文件中的使用方式。
接下来我们主要讲单文件组件。
2、单文件组件使用
2.1 组件使用三大步骤
- 定义组件
- 注册组件
- 使用组件
Vue中组件也分为全局组件和局部组件,这里先说局部组件:
(1)定义组件
用Vue.extend()方法可创建一个组件。
const HelloWorld= Vue.extend({
template: `
<div>
<h1>{{msg}}</h1>
</div>
`,
data() {
return {
msg: 'hello world!',
}
}
})上面的组件定义当时还可以简写,省略Vue.extend(),即:
const HelloWorld = {
template: `
<div>
<h1>{{msg}}</h1>
</div>
`,
data() {
return {
msg: 'hello world!',
}
}
};(2)注册组件
在Vue实例中,通过components属性进行局部组件注册:
new Vue({
el: '#root',
data: {
msg: '你好啊!'
},
components: {
HelloWorld,
}
});(3)使用组件
组件的使用是用过组件标签的方式进行:
<div id="root">
<hello-world></hello-world>
</div>上面三步都进行完后,就可以在浏览器界面看到输出的内容了:

再来说全局组件:
全局组件的创建方式以及使用方式和局部组件类似,只是在注册时有所不同。
拿上面的helloworld组件为例,若想将其作为全局组件使用,则需要想下面这样进行注册(通过Vue.component(),区别于上面的Vue.extend()方法):
Vue.component('helloworld', helloworld);2.2 组件使用的注意点
(1) 组件名
- 一个单词组成
- 第一种写法(首字母小写):hello
- 第二种写法(首字母大写):Hello
- 多个单词组成
- 第一种写法(kebab-case命名):hello-world
- 第二种写法(CamelCase命名):HelloWorld (这种写法仅限于
.vue文件中)
(2) 组件标签
- 当组件名由一个单词组成
- 用第一种写法(首字母小写):hello ,则组件标签使用:
<hello></hello> - 用第二种写法(首字母大写):Hello,则组件标签使用:
<hello></hello>或<Hello></Hello>都可
- 当组件名由多个单词组成
- 无论是第一种写法(kebab-case命名):hello-world,还是二种写法(CamelCase命名):HelloWorld,组件标签都使用:
<hello-world></hello-world>
组件标签在使用的时候还可以采用单标签闭合的方式<hello-world />。但需注意,这种方式在.html文件中如果多次使用<hello-world />,会导致后续的<hello-world />不渲染:

3、VueComponent构造函数
我们打印前文创建的HelloWorld组件(基于Vue.extend()创建的),可以发现控制台的输出:
ƒ VueComponent (options) {
this._init(options);
}结果说明,HelloWorld其实是一个函数,并且是一个构造函数VueComponent。我们在vue.js的源码中也可以看到:
Vue.extend = function (extendOptions) {
/*......此处省略n行代码........*/
var Sub = function VueComponent (options) {
this._init(options);
};
/*......此处省略n行代码........*/
return Sub
};Vue.extend最后确实返回的是一个函数,且名字为VueComponent。
关于VueComponent有几个值得注意的地方:
-
HelloWorld组件本质上是一个名为VueComponent的构造函数,该构造函数不是由我们定义的,而是Vue.extend生成的; - 该构造函数不需要我们来实例化,我们只需要写
<hello-world />或<hello-world></hello-world>,Vue解析时会帮我们创建HelloWorld组件的实例对象,即Vue帮我们执行的:new VueComponent(options); - 特别注意:每次调用
Vue.extend,返回的都是一个新的VueComponent(从上面源码也可以看到,每次调用Vue.extend都会定义一个VueComponent函数); - 关于this指向:
- 组件配置中:
data函数、methods中的函数、watch中的函数、computed中的函数 它们的this均是【VueComponent实例对象】(称为组件实例对象,简称为vc)。 -
new Vue(options)配置中:data函数、methods中的函数、watch中的函数、computed中的函数 它们的this均是【Vue实例对象】(简称为vm)。
4、VueComponent 和Vue之间的关系
VueComponent.prototype.__proto__ === Vue.prototype还是那上文的HelloWorld组件为例,我们打印一下:
const HelloWorld = Vue.extend({
template: `
<div>
<h1>{{msg}}</h1>
</div>
`,
data() {
return {
msg: 'hello world!',
}
}
});
console.log(HelloWorld.prototype.__proto__ === Vue.prototype); // true那这有什么用呢?答案是:让组件实例对象可以访问到 Vue原型上的属性以及方法等等。
那为什么组件实例对象就能访问到Vue原型上的属性和及方法呢?
我们来缕一缕它们之间的关系,若按照正常的原型和原型链情况,它们之间的原型链图应该是下面这样:
注意:实线表示显式原型属性(prototype),虚线表示隐式原型属性(__proto__)。

注意图中VueComponent.prototype到Object.protorype的红色虚线,为了让组件实例对象可以访问到 Vue原型上的属性以及方法,Vue框架对该处的原型链做了调整:

注意已图中蓝色的虚线,Vue将VueComponent.prototype.__proto__指向了Vue.prototype。
这就好比当组件实例要找某个属性或着某个方法的时候,最上层可以到Vue上去找,最后找到Object。
vue.js中的修改了VueComponent原型对象的地方:

打印结果:

















