предисловие
В предыдущем разделе мы говорили о"Изучение исходного кода Vue (2)" вы не знаете - принцип компиляции шаблона, то есть шаблон преобразуется вrender函数所需格式
, то сегодня я расскажу вам, как Vue использует эту штуку для создания настоящего DOM и отображения его на странице.
код
Шаг
2. Инициализируйте Vue
const { initMixin } = require('./init')
const { lifecycleMixin } = require('./lifecycle')
const { renderMixin } = require("./render")
function Vue(options) {
this._init(options)
}
initMixin(Vue)
renderMixin(Vue)
lifecycleMixin(Vue)
3. Функция mountComponent (функция входа рендеринга)
// lifecycle.js
const { patch } = require('./vdom/patch')
function mountComponent (vm, el) {
vm.$el = el;
// 上一节讲到把模板编译成render函数渲染所需格式
// 那么这一节就需要执行_render函数,来调用render函数生成虚拟DOM
// 然后接收返回值虚拟DOM,调用_update函数把虚拟DOM转为真实DOM并渲染
vm._update(vm._render())
return vm
}
function lifecycleMixin(Vue) {
// 将_update挂在Vue原型上
Vue.prototype._update = function (vnode) {
const vm = this
// 执行patch函数,patch函数在下面有讲
vm.$el = patch(vm.$el, vnode) || vm.$el
}
}
module.exports = {
mountComponent,
lifecycleMixin
}
4. Функция _render (выполните функцию рендеринга, чтобы получить виртуальный DOM)
// render.js
const { createElement, createTextNode } = require('./vdom/index')
function renderMixin(Vue) {
// 将_render函数挂在Vue原型上
Vue.prototype._render = function() {
const vm = this
// 把上一节生成的render函数取出来
const { render } = vm.$options
// 执行render函数并获得虚拟DOM
const vnode = render.call(vm)
return vnode
}
// 创建元素节点虚拟DOM
Vue.prototype._c = function(...args) {
return createElement(...args)
}
// 创建文本节点虚拟DOM
Vue.prototype._v = function (text) {
return createTextNode(text)
}
// 对象的情况,把对象转成字符串
Vue.prototype._s = function (val) {
return val === null ? '' : typeof val === 'object' ? JSON.stringify(val) : val
}
}
module.exports = {
renderMixin
}
Ниже приведены конкретные функции и классы, необходимые для создания виртуального DOM.
// vdom/index.js
// 创建某一个节点的虚拟DOM
class Vnode {
constructor(tag, data, key, children, text) {
this.tag = tag
this.data = data
this.key = key
this.children = children
this.text = text
}
}
// 创建元素节点虚拟DOM
function createElement(tag, data= {}, ...children) {
const key = data.key
return new Vnode(tag, data, key, children)
}
// 创建文本节点虚拟DOM
function createTextNode(text) {
return new Vnode(undefined, undefined, undefined, undefined, text)
}
module.exports = {
createElement,
createTextNode
}
5. Функция исправления (преобразование виртуального DOM в реальный DOM и визуализация)
// vdom/patch.js
function patch(oldVnode, vnode) {
// 本节只讲初次渲染
// 初次渲染时oldVnode就是el节点,以后非初次渲染时,oldVnode就是上一次的虚拟DOM
// 判断oldVnode的类型
const isRealElement = oldVnode.nodeType
if (isRealElement) {
// 初次渲染
const oldElm = oldVnode
const parentElm = oldElm.parentNode
// 生成真实DOM对象
const el = createElm(vnode)
// 将生成的真实DOM。插入到el的下一个节点的前面
// 也就是插到el的后面
// 不直接appendChild是因为可能页面中有其他el同级节点,不能破坏顺序
parentElm.insertBefore(el, oldElm.nextSibling)
// 删除老el节点
parentElm.removeChild(oldVnode)
return el
}
}
// 虚拟DOM生成真实DOM
function createElm(vnode) {
const { tag, data, key, children, text } = vnode
// 判断是元素节点还是文本节点
if (typeof tag === 'string') {
// 创建标签
vnode.el = document.createElement(tag)
// 解析虚拟DOM属性
updateProperties(vnode)
// 递归,将子节点也生成真实DOM
children.forEach(child => {
return vnode.el.appendChild(createElm(child))
})
} else {
// 文本节点直接创建
vnode.el = document.createTextNode(text)
}
return vnode.el
}
// 解析虚拟DOM的属性
function updateProperties(vnode) {
const newProps = vnode.data || {}
const el = vnode.el
for(let key in newProps) {
if (key === 'style') {
// style的处理
for (let styleName in newProps.style) {
el.style[styleName] = newProps.style[styleName]
}
} else if (key === 'class') {
// class的处理
el.className = newProps.class
} else {
// 调用dom的setAttribute进行属性设置
el.setAttribute(key, newProps[key])
}
}
}
module.exports = {
patch
}
6. Конкретная блок-схема
Эпилог
Я не знаю, будет ли это кто-нибудь читать, в любом случае, я закончил писать! ! ! Ну давай же! ! !
- Хотите узнать принцип реализации Vuex?
- Вы действительно знаете, как слот "затыкается"?
- «Обучение исходного кода Vue (1)» вы не знаете - принцип ответа на данные
- "Изучение исходного кода Vue (2)" вы не знаете - принцип компиляции шаблона
- «Изучение исходного кода Vue (3)» вы не знаете — принцип начального рендеринга
Изучите группу, прикоснитесь к группе рыб, заходите, болтайте и смейтесь, хе-хе
пожалуйста, нажмите здесьСвязь