Глубокий анализ Vue3

внешний интерфейс Vue.js

предисловие

Прошло больше месяца с тех пор, как You Yuxi впервые выпустила исходный код Vue3 (vue-next). Цинби заметил, что во время только что выпущенного Национального дня появилось много статей, интерпретирующих исходный код Vue3. Конечно, многие из них подозреваются в погоне за ветром и игнорировании жары.В статье торопливо рассказывали о принципе отзывчивости, или просто делали какие-то высокоуровневые гайды, рассказывая читателям, куда сначала смотреть, а потом на что смотреть. Нельзя сказать, что эти статьи не имеют никакой ценности, они позволяют вам понять некоторые из наиболее важных «галантереи» Vue3 за короткий промежуток времени, не задумываясь слишком много. Но слишком сухой материал не всегда хорош. Поскольку сухая пища обычно является продуктом после пережевывания автором, большая часть питательных веществ на самом деле переваривается только автором. Читателю остаются лишь некоторые остатки, которые кажутся очень информативными, но на самом деле не питательными. Это как отбивная кость в кости. Такие статьи обычно подходят для распространения в СМИ и используются только для быстрого привлечения внимания. Но для профессиональной фронтенд-разработки, которая хочет детально разобраться в Vue3, этого явно недостаточно.

На самом деле это не первая статья Qingbi о Vue3. На пятый день после анонса Vue3, то есть 10 октября. Цинби не интерпретировал исходный код напрямую, но рассказал об инструментах построения и связанных технологиях, используемых для создания Vue3, с точки зрения желания разрабатывать проект Vue3 или участвовать в нем. В статье приводится не только итоговая «галантерея», но и приемы и приемы, используемые Цинби в процессе практики, включая каждую строчку, которая дает результат.shellкоманды, git трюки и т.д. Читатели могут получить те же результаты, что и Цинби, в зависимости от контекста статьи. Это связано с тем, что Цинби имеет многолетний опыт разработки программного обеспечения и настаивает на точке зрения, то есть «Технология используется не для просмотра, а для практической работы». Только когда вы сможете сделать это самостоятельно, вы сможете по-настоящему понять, что это такое, а это самый простой и эффективный способ научиться. Те, кто читает неясные, сложные и абстрактные концептуальные термины, на самом деле больше всего боятся практики, потому что, как только они столкнутся с читателем, практикующим Дафа, все его «запрещенные искусства» будут демонтированы, одно за другим.

Но если вы хотите избежать обходных путей и эффективно практиковаться, предпосылка заключается в том, что есть соответствующая статья.

Собрать vue3 с нуля

Эта статья по-прежнему придерживается такого принципа и предлагает вам изучить исходный код Vue3 с практической точки зрения. Вы также можете понимать это как «научите человека ловить рыбу, а не дайте ему рыбу».

Подготовка

Для успешного завершения практики. Убедитесь, что на вашем компьютере установлены следующие инструменты.

  1. git
  2. узел 10 и выше(LTS-версия)
  3. yarn
  4. lerna
  5. typescript

вlernaа такжеtypescriptУстановите глобально, используя npm. Способ установки следующий:

npm install -g lerna
npm install -g typescript

2. Будьте на шаг впереди и испытайте Vue3 для создания веб-приложений следующего поколения.

2.1 Composition API

Фактически, задолго до выпущенного исходного кода Vue3 был выпущен, Vue официально выявил новое использование интерфейса о том, что Vue3, представляющий следующее поколение технологии Vue. Этот новый способ называетсяComposition API(составленный API). Соответствующий классический API также известен как то, как мы используем Vue.Options API(вариант API) илиOptions-based API(API на основе опций).

в классикеOptions API, мы используемdata, methodsПодождите, пока JS-объект «options» определит страницу или компонент. Этот простой и прямой метод очень удобен и близок людям на ранней стадии приложения, когда код и бизнес-логика относительно просты, что также является фактором, по которому Vue широко любим разработчиками из-за его низкого порога обучения. Однако разработчики, разрабатывавшие крупномасштабные приложения Vue, должны знать его наизусть. По мере роста логики страницы наши компоненты будут становиться многословными и сложными. Много логики и кода, который можно было бы использовать повторно, и очень сложно использовать его так, чтобы это было очень удобно. Личная практика, в Vue2 наиболее распространенный способ повторного использования логики и кода компонентов — это смешиваниеmixin, это осуществимый способ, но этот путь, очевидно, тесно связан с самого рождения и фреймворком Vue. Когда вы хотите повторно использовать неразборчивую в кадре общую функцию JS или объект в компоненте, разработанном Vue2, вы обнаружите, что все так неэлегантно.

Основываясь на необходимости более элегантного повторного использования существующего кода при разработке крупномасштабных приложений Vue, Vue3Composition APIКажется, что он пользуется тенденцией, и это неизбежно.

vue-composition-api-rfc

2.2 Первое приложение Composition API

Согласно официальному представлению, официальный выпуск Vue3 состоится в первом квартале следующего года. Но это не влияет на наше использование заранееComposition APIРазработайте простое адаптивное веб-приложение.

И как источник интерпретации VUE3 перед шоу, мы будем прямыми практическими руками на последний исходный код (вы скоро выясните преимущества этого).

2.2.1 Клонирование исходного кода и инициализация

Для упрощения пространства все команды даны прямо здесь. Для получения более подробной информации я рекомендую другую колонку Qingbi"Создание vue3 с нуля", который имеет подробное объяснение соответствующих деталей.

# 克隆源码
git clone https://github.com/vuejs/vue-next.git
# 进入源码目录
cd vue-next
# 安装依赖
yarn
# 初次构建
yarn build
# 建立项目内部 packages 软链
lerna bootstrap

Что нужно упомянуть здесь, это последний шагlerna bootstrap, который на самом деле находится в корневом каталоге проектаnode_modulesсоздал символическую ссылку (или программную ссылку)vueИ область видимости@vue.

В macOS или других дистрибутивах Linux вы можете просмотреть ссылку с помощью следующей команды.

ls -l node_modules/ | grep vue
ls -l node_modules/@vue

можно увидетьvueа также@vueСледующие символические ссылки указывают на исходный каталог соответственноpackages/в соответствующем каталоге (папке).

Таким образом, мы можем напрямую использовать каждый пакет в исходном коде до того, как Vue3 будет официально выпущен для npm, что эквивалентно использованию других зависимостей, установленных из npm. А поскольку Vue3 написан на Typescript, все зависимости и конфигурации разработки, необходимые для написания Typescript, уже установлены и предоставлены. Поэтому мы можем писать программы на Typescript так же, как исходный код Vue3 в проекте исходного кода. Не волнуйтесь, даже если вы еще не знакомы с Typescript, продолжайте читать.

2.2.2 Написание первой веб-страницы Vue3 Composition API

Чтобы не загрязнять структуру исходных каталогов Vue3. Мы можем создать новую ветку.

git checkout -b examples

Создать в корневом каталогеexamplesКаталог для хранения примера кода.

mkdir examples

создать новый файл./examples/composition.html, добавьте следующее:

<html>
<head><title>vue3 - hello composition!</title></head>
<body>
    <div id="app"><p>{{ state.text }}</p></div>
    <script src="../node_modules/vue/dist/vue.global.js"></script>
    <script>
    const { createApp, reactive, onMounted } = Vue
    const state = reactive({ text: 'hello world!' })
    const App = {
        setup () {
            onMounted(() => {
                console.log('onMounted: hello world!')
            })
            return { state }
        }
    }
    createApp().mount(App, '#app')
    </script>
</body>
</html>

Используйте браузер Chrome, чтобы открыть файл html. В консоли можно получить доступ к глобальным переменным, которые мы определяемstate. может быть изменен произвольноstate.textзначение, вы увидите, что текст, отображаемый веб-страницей, изменяется с новым назначением.

поздравляю! вы успешно использовалиVue3 Composition APIНаписал адаптивное веб-приложение.

Вы можете увидеть уродливые определения компонентов, которые отличаются от API опций Vue2.Vue3 Composition APIПредоставьте ряд функций API и создайте отзывчивое веб-приложение Vue3 с помощью простой композиции (это также значение композиции), и все будет выглядеть так естественно и удобно. Как и ожидалось, с ростом популярности функционального программированияVue3 Composition APIОн обязательно станет предпочтительным и основным способом создания приложений Vue следующего поколения.

3. Исследование исходного кода

Прочитайте колонку зеленого пера"Создание vue3 с нуля"Читатели Vue3 должны знать, что исходный код Vue3 разделен на несколько разных частей.package, хранится в каталоге./packages/вниз и использоватьlernaуправлять большеpackageпроект.

packages/
├── compiler-core
├── compiler-dom
├── compiler-sfc
├── reactivity
├── runtime-core
├── runtime-dom
├── server-renderer
├── shared
└── vue

вcompiler-sfcэто реализация однофайлового компонента Vue (то есть файла .vue, который мы используем в Webpack),server-rendererЭто исходный код рендеринга на стороне сервера.Эти две части не были завершены на момент написания этой статьи;sharedкаждыйpackageОбщая библиотека утилит (эквивалентная утилитам, которые мы обычно используем), которая инкапсулирует некоторые общие функции, такие как оценка того, является ли это массивом, является ли это объектом или функцией, поэтому с точки зрения понимания исходного кода Vue3 вы можете игнорируй это;vueэто финальный релизVue3пакет, но с точки зрения исходного кода это только внешний экспорт внутреннего модуля, и его исходный код имеет только одинindex.tsфайл, благодаря которому мы можем узнать, что в конечном итогеVue3Какие интерфейсы предоставляются извне, то есть мы создали ранееComposition APIГлобальные объекты, используемые на веб-страницахVueФункции API, поддерживаемые в .

сужение нашего фокуса, составлениеVue3Ядро следующего пяти пакета:

  • reactivity
  • compiler-core
  • runtime-core
  • compiler-dom
  • runtime-dom

И первые 3 пакетаreactivity,compiler-core,runtime-coreОпять такиVue3Ядро внутри ядра (как следует из слова ядро). Можно сказать, что эти 3 пакета должны построить весьVue3проект и весьVue3Зависимость нижнего уровня и краеугольный камень экологии. Для того, чтобы более наглядно понять смысл этого предложения. Я представляю себе такую ​​картину.

Прохладным осенним днем ​​одноклассница Ю Юйси взяла свой 13-дюймовый MacBook Pro в свою самую посещаемую кофейню и заказала латте. Откройте VSCode и приготовьтесь писать код, и я вижу что-то под названием AngularJs. Внезапно мысль промелькнула в голове Ю. «Вокао, этот парень такой классный! Я тоже возьму его…». После периода тяжелых размышлений. «Benyou хочет сделать лучше не только для создания WEB-интерфейса, но и для создания любого клиентского интерфейса, такого как мобильное приложение, с использованием знакомого шаблона html во внешнем интерфейсе». Для достижения этого эффекта синтаксический анализ шаблона страницы (компиляция) и вывод рендеринга должны быть разделены во время проектирования. Поэтому вы создали новую папку с именемcompiler-core, для проведения реализации будем использоватьhtmlСкомпилированный шаблон компилируется в抽象语法树а также渲染桥接函数(используется для разделения реализации функции рендеринга(runtime-core, который используется для хранения абстракций создания приложений и средств визуализации приложений, которые также включают абстракции компонентов и узлов, составляющих приложение. На данный момент абстракция для построения интерфейса представления приложения из html-шаблона (строки) завершена, но для привязки содержимого, отображаемого представлением, к данным, когда данные изменяются, содержимое представления может быть изменены оперативно. Модуль, который реагирует на изменения данных, поэтому вы создали третью папку с именемreactivityПосле технического анализа вы думаете, что новые функции ES6 в настоящее время используютсяProxyЭто самый элегантный способ реализации ответа на данные, поэтому вы решили хранить и управлять всемиProxyОбернутые адаптивные модули. отличается от первых двухpackageявляется абстракцией платформы и среды,reactivityэто конкретная реализация, как мы использовали ранееComposition APIпостроенhello worldиспользуется на веб-страницахreactiveфункция получена изreactivity. На этом базовая модель абстракции и реактивных данных для построения любого пользовательского интерфейса завершена. До применения этого метода проектирования представления до конечного продукта, чтобы сделать абстрактную платформу неразличимой, еще далеко.compiler-coreа такжеruntime-coreреализация на уровне платформы. Однако для достижения рендеринга вида на всех платформах требуется немалый объем работы.Предпосылка заключается в том, что вам необходимо знать разработку интерфейса связанных платформ, например, разработку интерфейса приложения IOS или приложения Android. Kexi, Вы только веб-интерфейс изучили. Поэтому Вы начали с того, с чем были знакомы и добавили два модуля для рендеринга и выполнения приложений в среде браузера, а именноcompiler-domа такжеruntime-dom. «...Незаметно прошла еще одна осень». Вы, наконец, реализовали свое видение год назад в среде браузера, но до конечной цели еще далеко. Следующим приоритетом для вас является внедрение пакета компонентов с одним файлом и пакета рендеринга на стороне сервера для лучшей разработки приложений Vue3 в среде Webpack и приложений рендеринга на стороне сервера, требующих сценариев SEO.

Напоминание: этот сюжет является чисто вымышленным и даже немного забавным ^^!

Прочитав этот вымышленный сюжет, вы должны иметьVue3Четкое понимание 5 самых важных модулей в Наконец, используйте диаграмму, чтобы обобщить отношения между ними. Стрелки на картинке обозначают зависимости. На самом деле пакет vue, который мы в итоге использовали, работает под браузером, так что vue напрямую зависит отcompiler-domа такжеruntime-dom. и вью наreactiveВ зависимости используется пунктирная линия, поскольку vue не зависит напрямую отreactivity, но экспортируя всеruntime-domэкспорт, покаruntime-domэкспортировано всеruntime-core, которая включает в себяreactivityсоздавать реактивные объекты вreactiveфункция, которая косвенно экспортируется таким образомreactive, то есть предыдущийhello-worldФункции, используемые в веб-приложениях.

4. createApp

Мы уже знаем разделение труда и зависимости пяти пакетов, составляющих ядро ​​Vue3. Но как они «сотрудничают» друг с другом, чтобы завершить создание полноценного веб-приложения. Мы использовали ранееComposition APIсозданныйhello worldВозьмем в качестве примера веб-приложения. Следующий отрывок — это часть кода Javascript (написанная здесь с использованием синтаксиса ES6).

const { createApp, reactive, onMounted } = Vue
const state = reactive({ text: 'hello world!' })
const App = {
    setup () {
        onMounted(() => {
            console.log('onMounted: hello world!')
        })
        return { state }
    }
}
createApp().mount(App, '#app')

Мы видим последнюю строку кода, используяcreateAppФабричная функция создает экземпляр приложения Vue3 и затем будет использоватьComposition APIНаписанный корневой компонент приложенияAppКрепление к IDappЭлементы Дом на. Этот процессVue3Как проходит внутренне, или как пять пакетов, которые мы упомянули ранее, сотрудничаем, чтобы завершить создание этого приложения. Ниже приведена диаграмма такого связей вызова, обращается после промежуточного трассировки кода.

Части с добавленным цветом фона на рисунке — это части, которые сравнивают ключевые роли каждого пакета. Желтая часть — это API, экспортированный Vue3 в приложение; оранжевая часть — этоruntime-coreСоздайте средство визуализации во время выполнения в ; голубая частьcompiler-coreа такжеcompiler-domАбстрактное синтаксическое дерево и реализация рендеринга dom для компиляции строк шаблона в функции рендеринга; зеленая частьreactivityЭкспортируются два основных реактивных API,reactiveФункция используется для передачи неотзывчивого простого JS-объекта и возврата отзывчивого объекта данных, в то время какisReactiveФункция используется для определения того, является ли объект реактивным объектом.

5. Typescript

мы знаемVue3использоватьTypescriptзаписывать. Однако это не означает, что мы должныTypescriptУчитесь один раз, чтобы понятьVue3исходный код. Как мы все знаем, Javascript является слаботипизированным языком, преимущество которого заключается в уменьшении «шума» кода (грамматических компонентов, не имеющих ничего общего с реализуемой функцией), что позволяет разработчикам сосредоточиться на реализации бизнес-логики и пишите лаконичнее и понятнее.код но у всего есть плюсы и минусы.при написании масштабного софта с повышенными требованиями к стабильности и безопасности гибкость типов стала рассадником сложных багов. Так что естьTypescriptТакой строго типизированный язык, а это всего лишь надмножество Javascript, то есть любой легальныйJavascriptКод также является законнымTypescript.TypescriptядроJavascriptНа основе грамматики добавляются ограничения на типы данных, а также добавляются некоторые новые типы данных (такие как кортежи, перечисления, Any и т. д.) и типы интерфейса. при освоенииTypescriptНастоящая трудность заключается в выяснении того, как квалифицировать типы в различных сценариях. В частности, объявления переменных, параметры функции, возвращаемые значения функции, составные (Array, Set, Map, WeakSet, WeakMap) типы элементов, типы интерфейса и псевдонимы типов.

нижеприведенныйTypescriptСамый распространенный и самый простой тип использования.

// 变量申明
let num: number = 1
let str: string = 'hello'
// 函数参数类型与返回值类型
function sum(a: number, b: number): number {
    return a + b
}
// 复合元素类型
let arr: Array<number> = [1, 2, 3]
let set: Set<number> = new Set([1, 2, 2])
let map: Map<string, number> = new Map([['key1', 1], ['key2', 2]])
// 接口类型
interface Point {
    x: number
    y: number
}
const point: Point = { x: 10, y: 20 }
// 类型别名
type mathfunc = (a: number, b: number) => number
const product: mathfunc = (a, b) => a * b

console.log(num, str, arr, set, map, sum(1, 2), product(2, 3), point)

Приведенный выше пример также легко понять. Лично чувствовать больше всегоTypesriptСамый сложный тип для понимания, а такжеVue3Самым большим препятствием для чтения исходного кода является泛型(Generics). Generics — это компонент, основанный на типах (под компонентом здесь понимается многократно используемая единица кода, такая как функции и т. д.), механизм повторного использования, поэтому он несколько абстрактен, проще говоря, его можно понимать как переменную типа. Обычно используется для функций, эффект аналогичен объектно-ориентированному программированию.перегрузка функций.

Поскольку сказано, что общий тип похож на переменную типа в Typescript, как определить и использовать эту переменную, давайте приведем пример.

функцияidentity()Принимает параметр строкового типа и возвращает себя, также строкового типа.

function identity(arg: string): string {
    return arg
}

Теперь я не хочу, чтобы параметр и тип возвращаемого значения были зафиксированы как string , и в то же время я хочу ограничить тип.Лучший способ - сделать тип переменным или определить тип как переменную. Это называетсяДженерики. Итак, где определена эта «переменная типа», ответ состоит в том, чтобы вставить пару угловых скобок «» после имени функции и определить переменную в угловых скобках, а затем вы можете использовать эту «переменную типа» для следующие параметры и возвращаемые типы заменяют". следующим образом:

function identity<T>(arg: T): T {
    return arg
}

console.log(identity<string>('hello'))
console.log(identity<number>(100))
// 也可省略类型部分
console.log(identity('hello'))
console.log(identity(100))

хочу узнать большеДженерикисценарии использования см.официальная документация

Если вы освоите приведенное выше использование типа Typescript, вы можете в основном прочитать его.Vue3исходный код. Хотя перечисленные здесь функции относятся не ко всем функциям Typescript, остальные не повлияли на правильное понимание исходного кода и по сравнению с непосредственным чтением и освоением всех функций Typescript путем чтенияVue3Исходный код дает вам более быстрое понимание наиболее важных функций и рекомендаций, убивая двух зайцев одним выстрелом.

6. Практически понять основную часть исходного кода

Сказав так много, наконец, через 3 примера кода, попрактикуйтесь в обобщении и углубите пониманиеVue3Роль трех основных модулей заключается в конце текста.

6.1 reactivity

существует./examplesКаталог новый файлreactivity.ts, вставьте следующий код:

import { reactive, isReactive } from '@vue/reactivity'

const content = { text: 'hello' }
const state = reactive(content)

console.log('content is reactive: ', isReactive(content))
console.log('state is reactive: ', isReactive(state))

console.log('state ', state)
content.text = 'world'
console.log('state ', state)

Скомпилируйте и запустите:

tsc reactivity.ts && node reactivity.js

6.2 compiler-core

существует./examplesкаталог новый файлcompiler-core.ts, вставьте следующий код:

import { baseCompile as compile } from '@vue/compiler-core'

const template = '<p>{{ state.text }}</p>'
const { ast, code } = compile(template)

console.log('ast\n----')
console.log(ast)
console.log('code\n----')
console.log(code)

Скомпилируйте и запустите:

tsc compiler-core.ts && node compiler-core.js

6.3 runtime-core

существует./examplesкаталог новый файлruntime-core.ts, вставьте следующий код:

import { createRenderer } from '@vue/runtime-core'

const patchProp = function (el: Element, key: string, nextValue: any, prevValue: any, isSVG: boolean) {}
const nodeOps = {
  insert: (child: Node, parent: Node, anchor?: Node) => {},
  remove: (child: Node) => {},
  createElement: (tag: string, isSVG?: boolean) => {},
  createText: (text: string) => {},
  createComment: (text: string) => {},
  setText: (node: Text, text: string) => {},
  setElementText: (el: HTMLElement, text: string) => {},
  parentNode: (node: Node) => {},
  nextSibling: (node: Node) => {},
  querySelector: (selector: string) => {}
}

const { createApp } = createRenderer({
  patchProp,
  ...nodeOps
})

console.log(createApp())

Скомпилируйте и запустите:

tsc runtime-core.ts && node runtime-core.js

Суммировать

В этой статье используетсяVue3Первая часть создания первого отзывчивого веб-приложения с комбинированным API начинается от более мелкого к более глубокому и последовательно объясняет состав.Vue3Разделение труда и зависимости наиболее важных 5 пакетов, а также объяснение составаVue3и построитьVue3Экологические 3 пакета нижнего уровня и помогите читателям понять, придумав интересную историюVue3сущность. Для того, чтобы подметать читателя глубокое чтениеVue3Психологический барьер исходного кода увеличивает цельVue3Базовые знания Typescript необходимы для исходного кода. Наконец, написав вручную 3 примера кода, давVue3Отзывчивые данные, компиляция шаблонов и наиболее важный интерфейс для создания приложений среды выполнения помогают читателям отладитьVue3Основной код, чтобы действительно понятьVue3основной принцип.


если ты правVue3Заинтересованные исходным кодом и последними разработками, вы можетеСледите за автором в WeChat,Отвечать:vue, присоединитесь к «группе по обмену передовыми технологиями Vue3» и подробно обсудите с автором.


Следите за автором в WeChat

связанное предложение:"Создание vue3 с нуля"