【Vue实践】一文搞懂Vue中的组件

本篇总结Vue中组件的使用,对组件的理解以及使用组件需要特别注意的点。
符号约定:

  1. .html文件表示该项目是传统web项目,即没用使用Vue脚手架工具,通过<script>引入vue.js的方法
  2. .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>都可
  • 当组件名由多个单词组成
    • 无论是第一种写法(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有几个值得注意的地方:

  1. HelloWorld组件本质上是一个名为VueComponent的构造函数,该构造函数不是由我们定义的,而是Vue.extend生成的;
  2. 该构造函数不需要我们来实例化,我们只需要写<hello-world /><hello-world></hello-world>Vue解析时会帮我们创建HelloWorld组件的实例对象,即Vue帮我们执行的:new VueComponent(options)
  3. 特别注意:每次调用Vue.extend,返回的都是一个新的VueComponent(从上面源码也可以看到,每次调用Vue.extend都会定义一个VueComponent函数 );
  4. 关于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.prototypeObject.protorype的红色虚线,为了让组件实例对象可以访问到 Vue原型上的属性以及方法,Vue框架对该处的原型链做了调整:
在这里插入图片描述

注意已图中蓝色的虚线,VueVueComponent.prototype.__proto__指向了Vue.prototype
这就好比当组件实例要找某个属性或着某个方法的时候,最上层可以到Vue上去找,最后找到Object

vue.js中的修改了VueComponent原型对象的地方:
在这里插入图片描述

打印结果:
在这里插入图片描述

  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值