【Vue实践】一文搞懂Vue中的组件
本篇总结Vue中组件的使用,对组件的理解以及使用组件需要特别注意的点。符号约定:.html文件表示该项目是传统web项目,即没用使用Vue脚手架工具,通过<script>引入vue.js的方法.vue文件表示该项目是使用vue脚手架工具创建的文章目录1、非单文件组件和单文件组件2、非单文件组件使用2.1 组件使用三大步骤2.2 组件使用的注意点3、VueComponnet构造函数4、V
本篇总结Vue中组件的使用,对组件的理解以及使用组件需要特别注意的点。
符号约定:
.html
文件表示该项目是传统web项目,即没用使用Vue脚手架工具,通过<script>
引入vue.js
的方法.vue
文件表示该项目是使用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>
都可
- 用第一种写法(首字母小写):hello ,则组件标签使用:
- 当组件名由多个单词组成
- 无论是第一种写法(kebab-case命名):hello-world,还是二种写法(CamelCase命名):HelloWorld,组件标签都使用:
<hello-world></hello-world>
- 无论是第一种写法(kebab-case命名):hello-world,还是二种写法(CamelCase命名):HelloWorld,组件标签都使用:
组件标签在使用的时候还可以采用单标签闭合的方式<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
原型对象的地方:
打印结果:
更多推荐
所有评论(0)