|
1 |
| -# Dig into the Core |
| 1 | +# Глубже в ядро |
2 | 2 |
|
3 |
| -This article belongs to the series [Read Vue Source Code](https://github.com/numbbbbb/read-vue-source-code). |
| 3 | +Эта статья - часть серии [Читая исходный код Vue](https://github.com/vvscode/tr--read-vue-source-code). |
4 | 4 |
|
5 |
| -In this article, we will: |
| 5 | +В этой статье мы: |
6 | 6 |
|
7 |
| -- Find the real Vue implementation |
| 7 | +- найдем, где реализована библиотека Vue |
8 | 8 |
|
| 9 | +## Ищем реализацию Vue |
9 | 10 |
|
10 |
| -## Find the Real Vue Code |
| 11 | +В [прошлой части](https://github.com/vvscode/tr--read-vue-source-code/blob/master/01-find-the-entry.md) мы нашли точку входа с упоминанимем `import Vue from './runtime/index'`. Продолжим. |
11 | 12 |
|
12 |
| -We have found the entry at [previous article](https://github.com/numbbbbb/read-vue-source-code/blob/master/01-find-the-entry.md) with the clue `import Vue from './runtime/index'`, let's go along that. |
13 |
| - |
14 |
| -Open `./runtime/index`. |
| 13 | +Откроем `./runtime/index`. |
15 | 14 |
|
16 | 15 | ```javascript
|
17 | 16 | /* @flow */
|
18 | 17 |
|
19 |
| -import Vue from 'core/index' |
20 |
| -import config from 'core/config' |
21 |
| -import { extend, noop } from 'shared/util' |
22 |
| -import { mountComponent } from 'core/instance/lifecycle' |
23 |
| -import { devtools, inBrowser, isChrome } from 'core/util/index' |
| 18 | +import Vue from 'core/index'; |
| 19 | +import config from 'core/config'; |
| 20 | +import { extend, noop } from 'shared/util'; |
| 21 | +import { mountComponent } from 'core/instance/lifecycle'; |
| 22 | +import { devtools, inBrowser, isChrome } from 'core/util/index'; |
24 | 23 |
|
25 | 24 | import {
|
26 | 25 | query,
|
27 | 26 | mustUseProp,
|
28 | 27 | isReservedTag,
|
29 | 28 | isReservedAttr,
|
30 | 29 | getTagNamespace,
|
31 |
| - isUnknownElement |
32 |
| -} from 'web/util/index' |
| 30 | + isUnknownElement, |
| 31 | +} from 'web/util/index'; |
33 | 32 |
|
34 |
| -import { patch } from './patch' |
35 |
| -import platformDirectives from './directives/index' |
36 |
| -import platformComponents from './components/index' |
| 33 | +import { patch } from './patch'; |
| 34 | +import platformDirectives from './directives/index'; |
| 35 | +import platformComponents from './components/index'; |
37 | 36 |
|
38 | 37 | // install platform specific utils
|
39 |
| -Vue.config.mustUseProp = mustUseProp |
40 |
| -Vue.config.isReservedTag = isReservedTag |
41 |
| -Vue.config.isReservedAttr = isReservedAttr |
42 |
| -Vue.config.getTagNamespace = getTagNamespace |
43 |
| -Vue.config.isUnknownElement = isUnknownElement |
| 38 | +Vue.config.mustUseProp = mustUseProp; |
| 39 | +Vue.config.isReservedTag = isReservedTag; |
| 40 | +Vue.config.isReservedAttr = isReservedAttr; |
| 41 | +Vue.config.getTagNamespace = getTagNamespace; |
| 42 | +Vue.config.isUnknownElement = isUnknownElement; |
44 | 43 |
|
45 | 44 | // install platform runtime directives & components
|
46 |
| -extend(Vue.options.directives, platformDirectives) |
47 |
| -extend(Vue.options.components, platformComponents) |
| 45 | +extend(Vue.options.directives, platformDirectives); |
| 46 | +extend(Vue.options.components, platformComponents); |
48 | 47 |
|
49 | 48 | // install platform patch function
|
50 |
| -Vue.prototype.__patch__ = inBrowser ? patch : noop |
| 49 | +Vue.prototype.__patch__ = inBrowser ? patch : noop; |
51 | 50 |
|
52 | 51 | // public mount method
|
53 |
| -Vue.prototype.$mount = function ( |
| 52 | +Vue.prototype.$mount = function( |
54 | 53 | el?: string | Element,
|
55 |
| - hydrating?: boolean |
| 54 | + hydrating?: boolean, |
56 | 55 | ): Component {
|
57 |
| - el = el && inBrowser ? query(el) : undefined |
58 |
| - return mountComponent(this, el, hydrating) |
59 |
| -} |
| 56 | + el = el && inBrowser ? query(el) : undefined; |
| 57 | + return mountComponent(this, el, hydrating); |
| 58 | +}; |
60 | 59 |
|
61 | 60 | // devtools global hook
|
62 | 61 | /* istanbul ignore next */
|
63 | 62 | setTimeout(() => {
|
64 | 63 | if (config.devtools) {
|
65 | 64 | if (devtools) {
|
66 |
| - devtools.emit('init', Vue) |
| 65 | + devtools.emit('init', Vue); |
67 | 66 | } else if (process.env.NODE_ENV !== 'production' && isChrome) {
|
68 | 67 | console[console.info ? 'info' : 'log'](
|
69 | 68 | 'Download the Vue Devtools extension for a better development experience:\n' +
|
70 |
| - 'https://github.com/vuejs/vue-devtools' |
71 |
| - ) |
| 69 | + 'https://github.com/vuejs/vue-devtools', |
| 70 | + ); |
72 | 71 | }
|
73 | 72 | }
|
74 |
| - if (process.env.NODE_ENV !== 'production' && |
| 73 | + if ( |
| 74 | + process.env.NODE_ENV !== 'production' && |
75 | 75 | config.productionTip !== false &&
|
76 |
| - inBrowser && typeof console !== 'undefined' |
| 76 | + inBrowser && |
| 77 | + typeof console !== 'undefined' |
77 | 78 | ) {
|
78 | 79 | console[console.info ? 'info' : 'log'](
|
79 | 80 | `You are running Vue in development mode.\n` +
|
80 |
| - `Make sure to turn on production mode when deploying for production.\n` + |
81 |
| - `See more tips at https://vuejs.org/guide/deployment.html` |
82 |
| - ) |
| 81 | + `Make sure to turn on production mode when deploying for production.\n` + |
| 82 | + `See more tips at https://vuejs.org/guide/deployment.html`, |
| 83 | + ); |
83 | 84 | }
|
84 |
| -}, 0) |
| 85 | +}, 0); |
85 | 86 |
|
86 |
| -export default Vue |
| 87 | +export default Vue; |
87 | 88 | ```
|
88 | 89 |
|
89 |
| -`import Vue` again! Let's look through this file step-by-step: |
| 90 | +И снова`import Vue` ! Разберем файл по пунктам: |
90 | 91 |
|
91 |
| -- import config |
92 |
| -- import util funcions |
93 |
| -- import patch, mountComponent |
94 |
| -- import directives and components |
95 |
| -- install platform specific utils |
96 |
| -- install platform runtime directives & components |
97 |
| -- install platform patch function |
98 |
| -- define public mount method |
99 |
| -- console log the message of Vue Devtools and development mode warning(now you know the origin of your console logs) |
| 92 | +- импортировать конфиг |
| 93 | +- импортировать вспомогательные функции |
| 94 | +- импортировать `patch`, `mountComponent` |
| 95 | +- импортировать директивы и компоненты |
| 96 | +- установим утилиты, специфичные для окружения |
| 97 | +- установим динамические директивы и компоненты |
| 98 | +- установим патчи для окружения |
| 99 | +- определим интерфейсный метод `mount` |
| 100 | +- выведем в консоль сообщение для панели разработчика Vue и предупреждение о дев-режиме (теперь вы знаете источних этих сообщений) |
100 | 101 |
|
101 |
| -As you can see, this file just adds some platform specific things to Vue. |
| 102 | +Как видите, этот файл просто добавляет несколько специфичных штук в окружение для Vue. |
102 | 103 |
|
103 |
| -Two important points here: |
| 104 | +Здесь два важных момента: |
104 | 105 |
|
105 |
| -1. `Vue.prototype.__patch__ = inBrowser ? patch : noop`, we will talk about patch in later articles, it's responsibility is updating the webpage, which means it will manipulate the DOM |
106 |
| -2. `mount` again, so the core implementation of `mountComponent` is encapsulated twice |
| 106 | +1. `Vue.prototype.__patch__ = inBrowser ? patch : noop`, мы поговорим про патч в следующих частых - он отвечает за обновление страницы, т.е. за манипуляции с DOM |
| 107 | +1. и снова `mount`, так что оригинальная реализация `mountComponent` имеет две обертки |
107 | 108 |
|
108 |
| -After checking the Vue directory, we can find there is another platform `weex`. It's a framework similar to ReactNative and it's maintained by Alibaba. |
| 109 | +Заглянув в директорию Vue, мы можем найти там еще одну платформу - `weex`. Этот фреймворк похож на ReactNative и он поддеживается Alibaba. |
109 | 110 |
|
110 |
| -Go on with our new clue `import Vue from 'core/index'`, again it `import Vue from './instance/index'`, open `./instance/index`. |
| 111 | +Потянем за нашу новую ниточку `import Vue from 'core/index'`, и снова `import Vue from './instance/index'`, откроем `./instance/index`. |
111 | 112 |
|
112 | 113 | ```javascript
|
113 |
| -import { initMixin } from './init' |
114 |
| -import { stateMixin } from './state' |
115 |
| -import { renderMixin } from './render' |
116 |
| -import { eventsMixin } from './events' |
117 |
| -import { lifecycleMixin } from './lifecycle' |
118 |
| -import { warn } from '../util/index' |
119 |
| - |
120 |
| -function Vue (options) { |
121 |
| - if (process.env.NODE_ENV !== 'production' && |
122 |
| - !(this instanceof Vue) |
123 |
| - ) { |
124 |
| - warn('Vue is a constructor and should be called with the `new` keyword') |
| 114 | +import { initMixin } from './init'; |
| 115 | +import { stateMixin } from './state'; |
| 116 | +import { renderMixin } from './render'; |
| 117 | +import { eventsMixin } from './events'; |
| 118 | +import { lifecycleMixin } from './lifecycle'; |
| 119 | +import { warn } from '../util/index'; |
| 120 | + |
| 121 | +function Vue(options) { |
| 122 | + if (process.env.NODE_ENV !== 'production' && !(this instanceof Vue)) { |
| 123 | + warn('Vue is a constructor and should be called with the `new` keyword'); |
125 | 124 | }
|
126 |
| - this._init(options) |
| 125 | + this._init(options); |
127 | 126 | }
|
128 | 127 |
|
129 |
| -initMixin(Vue) |
130 |
| -stateMixin(Vue) |
131 |
| -eventsMixin(Vue) |
132 |
| -lifecycleMixin(Vue) |
133 |
| -renderMixin(Vue) |
| 128 | +initMixin(Vue); |
| 129 | +stateMixin(Vue); |
| 130 | +eventsMixin(Vue); |
| 131 | +lifecycleMixin(Vue); |
| 132 | +renderMixin(Vue); |
134 | 133 |
|
135 |
| -export default Vue |
| 134 | +export default Vue; |
136 | 135 | ```
|
137 | 136 |
|
138 |
| -`function Vue (options) {`! We made it! This is the core Vue implementation. |
| 137 | +`function Vue (options) {`! Мы это сделали. Мы нашли реализацию ядра Vue. |
139 | 138 |
|
140 |
| -Below are five mixins, their names imply what they are. |
| 139 | +Ниже мы видим 5 миксин с говорящими именамию |
141 | 140 |
|
142 |
| -But why the core Vue function is such short? Only a `this._init`? |
| 141 | +Но почему основная функция Vue такая короткая? Только `this._init` ? |
143 | 142 |
|
144 |
| -Init process will be introduced in next article, now let's talk about how Vue is designed. |
| 143 | +Процесс инициализации будет описан в следующей части. Сейчас давайте немного поговорим о том как Vue устроен. |
145 | 144 |
|
146 |
| -Vue is a big open source project, which means it must be divided into many layers and parts. Let's start from the core and reverse the path to see how Vue is organized: |
| 145 | +Vue - это большой проект с открытым исходным кодом, что означает, что он должен быть разбит на множество слоев и частей. Давайте начнем с ядра и в обратном порядке посмотрим как организован Vue: |
147 | 146 |
|
148 |
| -- Core: the origin Vue function, calls `this._init()` |
149 |
| -- Mixins: five mixins, add init, state, events, lifecycle and render functions to core |
150 |
| -- Platform: add platform specific things to core, add patch and public mount functions |
151 |
| -- Entry: add configs and outmost $mount function to core |
| 147 | +- Ядро: собственно фукнция Vue, которая вызывает `this._init()` |
| 148 | +- Примеси (Миксины) - 5 миксин, добавляющие функции инициализации, управления состоянием, события, жизненнего цикла и функции отрисовки к ядру |
| 149 | +- Платфома - добавляет специфичные для окружения вещи к ядру, добавляет функции обновления и монтирования |
| 150 | +- Точка входа - добавляет к ядру конфигурции и внешнюю функцию `$mount` |
152 | 151 |
|
153 |
| -The entire Vue function is composited after four steps. |
| 152 | +Вся функция Vue состоит из 4х шагов. |
154 | 153 |
|
155 | 154 | 
|
156 | 155 |
|
157 |
| -This multiple layers pattern has many advantages: |
158 |
| - |
159 |
| -1. Decouple. Different layers focus on **different** things |
160 |
| -2. Encapsulate. Each layer **only** focus on itself |
161 |
| -2. Reuse. Closer to core, more **generic**. This makes Vue easy to compatible with different platforms and easy to build for different environment |
162 |
| - |
163 |
| -This layer pattern reminds me of OSI layer model, maybe Vue's author is inspired by that? |
| 156 | +Использование множествнных слоев имеет много преимуществ: |
164 | 157 |
|
165 |
| -## Next Step |
| 158 | +1. Развязка кода. Разные части отвечают за **разные** вещи. |
| 159 | +1. Инкапсуляция. Каждый слой сфокусирован только на себе |
| 160 | +1. Переиспользование. Чем ближе к ядру, тем больше обобщенного кода. Это делает Vue легко адаптируемым под разные платформы и разные окружения. |
166 | 161 |
|
167 |
| -Vue's core function just calls `this._init()`. What does it do? We will reveal it in next article. |
| 162 | +Этот подход со слоями напоминает модель OSI, может автор Vue вдохновлялся именно ей? |
168 | 163 |
|
169 |
| -Read next chapter: [Initialization](https://github.com/numbbbbb/read-vue-source-code/blob/master/03-init-introduction.md). |
| 164 | +## Следующий шаг |
170 | 165 |
|
171 |
| -## Practice |
| 166 | +Главная фукнция Vue просто вызывает `this._init()`. Что происходит дальше? Мы рассмотри это в следующей части. |
172 | 167 |
|
173 |
| -Find a friend and try to explain Vue's layer pattern to him/her. |
| 168 | +Следующая часть: [Инициализация](https://github.com/vvscode/tr--read-vue-source-code/blob/master/03-init-introduction.md). |
174 | 169 |
|
175 |
| -Nothing is perfect. Can you tell some disadvantages of this pattern? |
| 170 | +## Практика |
176 | 171 |
|
| 172 | +Возьмите приятеля и попробуйте объяснить ему/ей подход со слоями, который использован во Vue. |
177 | 173 |
|
| 174 | +Ничто не совершенно. Можете рассказать о недостатках такого подхода? |
0 commit comments