This is the 16th day of my participation in Gwen Challenge

preface

When reading the Vue source code, it is common to see a VM object with many attributes and various attribute operations. Although I know that this VM is the current Vue instance, but the source code is not clear for me to look at the dizzy, which attribute is which, completely do not remember. The purpose of this article is to take a look at the vm object and see what its common attributes mean.

Let’s start with a common definition of vm objects:

The vm defined

Assign the current this value directly to the VM

const vm: Component = this
Copy the code

By passing in the input

function initInternalComponent (vm: Component, options: InternalComponentOptions) 
Copy the code

From watcher (one of the attributes in the watcher constructor is VM)

const vm = watcher.vm
Copy the code

Take a quick look at the definition of vm in the Watcher constructor:

export default class Watcher{
    vm: Component; .constructor(vm: Component){
        this.vm = vm;
        if (isRenderWatcher) {
            vm._watcher = this
        }
        vm._watchers.push(this)... }... }Copy the code

Vm Attributes

You have seen from the definition that the VM is a VueComponet, or Vue component.

Take a look at a specific Vue component example:

<template>
    <div id="example" @click="changeMessage">
        {{ message }}

        <no-rights />
    </div>
</template>

<script>
import noRights from '@/common/components/noRights';
export default {
    name: 'Test'.components: {
        noRights
    },
    data() {
        return {
            message: 'test vm'
        };
    },

    watch: {
        message() {
            console.log('the message has changed'); }},mounted() {
        window.vm = this;
    },
    methods: {
        changeMessage() {
            this.message = 'Value has changed'; }}};</script>

Copy the code

The corresponding VM object returns:

$el

The actual DOM node of the current Vue instance

$options

$options = $options;

// merge options
if(options && options._isComponent){
    ...
    const opts = vm.$options = Object.create(vm.constructor.options)
}else {
    vm.$options = mergeOptions(
        resolveConstructorOptions(vm.constructor),
        options || {},
        vm
    )
}
Copy the code

$options is the result of combining the Vue constructor with the options of the Vue instance.

$parent

The parent Vue instance of the current instance

$children

The child component of the current instance (in this case, the Rights component in Componets)

$root

The root Vue instance of the current component tree. If there is no parent instance, the vm.$root points to itself

$vnode

The parent virtual node of the current Vue instance. If null, it indicates that the current instance is the root Vue

vm.$vnode = parentVnode // update vm's placeholder node without re-render
Copy the code

_vnode

The virtual node of the current Vue instance, _vnode, has a parent attribute that points to the parent virtual node of the instance, namely $vnode

vm._vnode = vnode

if (vm._vnode) { // update child tree's parent
  vm._vnode.parent = parentVnode
}
Copy the code

_self

The current Vue instance itself

vm._self = vm
Copy the code

_uid

The unique flag ID, incremented when the Vue instance’s private method _init is called

let uid = 0;

Vue.prototype._init = function(Vue: Class<Component>) {
    const vm: Component = this; vm._uid = uid ++; . }Copy the code

_isVue

This property is also defined in the _init method to prevent this from being observed

// a flag to avoid this being observed
vm._isVue = true
Copy the code

Observe’s definition of this:

export function observe (value: any, asRootData: ? boolean) :Observer | void {...let ob: Observer | void
  if (hasOwn(value, '__ob__') && value.__ob__ instanceof Observer) {
    ob = value.__ob__
  } else if( shouldObserve && ! isServerRendering() && (Array.isArray(value) || isPlainObject(value)) &&
    Object.isExtensible(value) && ! value._isVue ) { ob =new Observer(value)
  }
  ...
}

Copy the code

As can be seen from the code, if _isVue is true, the new Observer instance will not be created, i.e. if the Vue instance itself will not be constructed.

_isMounted

If the instance is mounted, set $mount to true if it is the root Vue instance

if (vm.$vnode == null) {
    vm._isMounted = true
    callHook(vm, 'mounted')}Copy the code