vue2之深入理解组件实例VueComponent

1,258 阅读2分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第18天,点击查看活动详情

我们在使用vue组件的时候,可能搭个脚手架就开始创建.vue文件了,然后在需要使用的页面或组件中再引入组件开始使用,很少去关注组件内部的东西,其实VueComponent,也叫组件实例在vue组件中是个很重要的概念,能够帮助我们更深入理解组件,以及后面看vue源码也会更加容易。

组件到底是什么

从代码层面来看,组件的本质就是一个名叫VueComponent的构造函数。 这里以非单文件组件来看:

  <div id="root">
    <test></test>
  </div>
  <script src="https://cdn.jsdelivr.net/npm/vue@2.7.14/dist/vue.js"></script>
  <script>
    const test = Vue.extend({
      name: 'test',
      template: '<p>{{firstName}} {{lastName}}</p>',
      data: function () {
        return {
          firstName: 'Walter',
          lastName: 'White',
        }
      }
    });
    const vm = new Vue({
      el: '#root',
      components: {test}
    });
    console.log(test);
  </script>

效果如下:

image.png

那为什么会是一个VueComponent的构造函数,是因为我们在创建vue组件的时候,调用了 Vue.extend,这个方法底层会帮我们创建VueComponent的构造函数。具体如下:

Vue.extend = function(extendOptions: Object): Function {
    // 此处省略。。。
    
    // 创建Sub构造函数
    const Sub = function VueComponent(options) {
      this._init(options)
    }
    // 此处省略。。。
    
    return Sub
}

我们只需要写或<testx,Vue解析时会帮我们创建school组件的实例对象,即Vue帮我们执行的: new VueComponent(options).

每次调用Vue.extend,返回的都是一个全新的VueComponent!!!!也就是说我们每次在页面中引入同一个组件都是一个全新的VueComponent。

<script>
    const test1 = Vue.extend({
      name: 'test1',
      template: '<p>{{firstName}} {{lastName}}</p>',
      data: function () {
        return {
          firstName: 'Walter',
          lastName: 'White',
        }
      }
    });
    const test2 = Vue.extend({
      name: 'test2',
      template: '<p>{{firstName}} {{lastName}}</p>',
      data: function () {
        return {
          firstName: 'Walter',
          lastName: 'White',
        }
      }
    });
    const vm = new Vue({
      el: '#root',
      components: {test1, test2}
    });
    console.log(test1 === test2);
  </script>

效果如下:

image.png

this指向

  1. .组件配置中:data函数、methods中的函数、watch中的函数、computed中的函数 它们的this均是VueComponent实例对象
  2. new Vue(options)能置中:data阴数、methods中的函数、watch中的两数、computed中的函数 它们的this均是Vue实例对象
<script>
    const test = Vue.extend({
      name: 'test2',
      template: '<p>{{firstName}} {{lastName}}</p>',
      data: function () {
        return {
          firstName: 'Walter',
          lastName: 'White',
        }
      },
      created(){
        console.log('组件this', this);
      }
    });
    const vm = new Vue({
      el: '#root',
      components: {test},
      created(){
        console.log('vue的this', this);
      }
    });
  </script>

效果如下:

image.png

image.png

vue实例和组件实例的关系

从上面vue实例和组件实例的打印关系我们可以看出,vue实例内部属性和组件实例的内部属性非常相似,那么它们之间有什么关系呢?

1671205919664.png

从这个图我们可以看出一个重要的内置关系:VueComponent.prototype.__proto=== Vue.prototype。 之所以有这个关系主要就是让组件实例对象可以访问到 Vue原型上的属性、方法。