Vue Implementation 03
Vue's Platform Related Decoration
Now, we made clear about the constructor of Vue
, which is core/instance/index.js
and core/index.js
. The former one is the definition of the constructor of Vue
. The latter one is to define global APIs, which is static functions and properties to Vue
. These two files have something in common: They are both located in core
. We has descriped the directory when we introducing Vue
. Files stored in core
is platform-unrelated code. Therefore, core/instance/index.js
and core/index.js
are both decorating core Vue
parts and they are both platform-unrelated.
However, Vue
is a multi-platform project, and it can be ported into Web and Weex. Different platform has different components, directives and some platform-related functions. Thereform, Vue
has to be packaged targeting to different platforms. So what we are going to take a look at is platforms/web/runtime/index.js
, which is our path to find Vue's construtor.
Before we are taking dive into this file, we can open platforms
folder and we can see there are two sub-directories, which is web
and weex
. These folders is to pack Vue
targeting to different platform. As for our concerning web
platform, it is included here as well.
Then, we open platform/web/runtime/index.js
and look at it. There are a lot import
at the beginning of this file, including importing Vue
from core/index.js
.
Below import
, there is a piece of code:
// install platform specific utils
Vue.config.mustUseProp = mustUseProp
Vue.config.isReservedTag = isReservedTag
Vue.config.isReservedAttr = isReservedAttr
Vue.config.getTagNamespace = getTagNamespace
Vue.config.isUnknownElement = isUnknownElement
Do you remember Vue.config
? What it proxying is the object exported by core/config.js
. It first looks like this:
Vue.config = {
optionMergeStrategies: Object.create(null),
silent: false,
productionTip: process.env.NODE_ENV !== 'production',
devtools: process.env.NODE_ENV !== 'production',
performance: false,
errorHandler: null,
warnHandler: null,
ignoredElements: [],
keyCodes: Object.create(null),
isReservedTag: no,
isReservedAttr: no,
isUnknownElement: no,
getTagNamespace: noop,
parsePlatformTagName: identity,
mustUseProp: no,
_lifecycleHooks: LIFECYCLE_HOOKS
}
We can see, properties of the config
object exported by core/config.js
, are mostly defined as a initial value. And we can see many comments in core/config.js
as below:
/**
* Check if a tag is reserved so that it cannot be registered as a
* component. This is platform-dependent and may be overritten.
*/
isReservedTag: no,
/**
* Check if an attribute is reserved so that it cannot be used as a component
* prop. This is platform-dependent and may be overritten.
*/
isReservedAttr: no,
This is platform-dependent and may be overritten. What it means is that this configuration is platform-dependent. And it is very likely to be overritten. Now, we can go back to this code:
// install platform specific utils
Vue.config.mustUseProp = mustUseProp
Vue.config.isReservedTag = isReservedTag
Vue.config.isReservedAttr = isReservedAttr
Vue.config.getTagNamespace = getTagNamespace
Vue.config.isUnknownElement = isUnknownElement
Actually, it is overriding properties of config
exported by default. It is commented that it will install platform specific utils. As for their effect, we will discuss later.
And there are two lines of code:
// install platform runtime directives & components
extend(Vue.options.directives, platformDirectives)
extend(Vue.options.components, platformComponents)
They will install platform runtime directives and components. Do you remember how is Vue.options
look like? Before these lines executed, it is something like this:
Vue.options = {
components: {
KeepAlive
},
directives: Object.create(null),
filters: Object.create(null),
_base: Vue
}
We have once met extend
function. In case you forget that, you can always refer to the appendix for /shared/util.js
. So what will it look like after these lines? We need to know what is platformDirectives
and platformComponents
.
According to import
at the beginning:
import platformDirectives from './directives/index'
import platformComponents from './components/index'
We know that these varible is imported from runtime/directives/index.js
and runtime/components/index.js
. We open runtime/directives/index.js
and:
import model from './model'
import show from './show'
export default {
model,
show
}
That is to say that platformDirectives
is:
platformDirectives = {
model,
show
}
Therefore, after extend
is executed, Vue.options
become:
Vue.options = {
components: {
KeepAlive
},
directives: {
model,
show
},
filters: Object.create(null),
_base: Vue
}
runtime/components/index.js
is:
import Transition from './transition'
import TransitionGroup from './transition-group'
export default {
Transition,
TransitionGroup
}
So platformComponents
is:
platformComponents = {
Transition,
TransitionGroup
}
After extend
, Vue.options become:
Vue.options = {
components: {
KeepAlive,
Transition,
TransitionGroup
},
directives: {
model,
show
},
filters: Object.create(null),
_base: Vue
}
So we make clear about these code. It added specific components and directives targeting web
platform.
Let's get to the remaining code:
// install platform patch function
Vue.prototype.__patch__ = inBrowser ? patch : noop
// public mount method
Vue.prototype.$mount = function (
el?: string | Element,
hydrating?: boolean
): Component {
el = el && inBrowser ? query(el) : undefined
return mountComponent(this, el, hydrating)
}
It added __patch__
to Vue.prototype
. If you are running in a browser, it will be patch
function. Else, it will be a empty function noop
. Then, it added $mount
function to Vue.prototype
. We skip the $mount
and its effect.
Next, it is the global hook of vue-devtools
. It is wrapped in setTimeout
and finally exports Vue
.
So we have read platforms/web/runtime/index.js
. Its effect is decorating Vue
targeting different platform:
- It sets
Vue.config
for platform - It mixed two
directives
:model
andshow
- It mixed two
components
:Transition
andTransitionGroup
- It added two functions to
Vue.prototype
:__patch__
and$mount
After this file excuted, Vue.options
, Vue.config
and Vue.prototype
are changed. We can refer these changes in appendix.