preface
- Article ideas article and implement article 】 【 】, in this paper, in order to achieve the first edition, at the end of the article is the second edition link, synchronous read advice to see two window, or please read – “the Vue | | article implementation ast
Implement template writing compatibility
Check whether there is el attribute during initialization, if there is, execute $mount method (to achieve user self-control mount timing)
init.js
Vue.prototype._init = function (options) {
const vm = this;
vm.$options = options;
// Initialize the data
initState(vm)
if(vm.$options.el){ vm.$mount(vm.$options.el); }}Copy the code
$mount = “render”
If there is no template, get the HTML string from EL and assign to template. Render function will be generated from template through compilerToFunction
Vue.prototype.$mount = function (el){
const vm = this;
const options = vm.$options;
el = document.querySelector(el);
if(! options.render){// If there is no render attribute, check whether there is a template
let template = options.template;
// If there is no template and el is present, the el content is assigned to template
if(! template && el){ template = el.outerHTML; }constrender = compilerToFunction(template); options.render = render; }}Copy the code
Implement the Render method
Define the VDOM structure{tag,data,key,children,text }
And a function to create a VDOM from that information
vdom/index.js
function createElement(tag,data={},... children) {
let key = data.key;
if(key){
delete data.key;
}
return vnode(tag,data,key,children);
}
function createTextVnode(text) {
return vnode(undefined.undefined.undefined.undefined,text)
}
// Generating virtual DOM differs from AST in that you can customize the data format
function vnode(tag,data,key,children,text) {
return {
tag,data,key,children,text
}
}
Copy the code
Pass _c to render and get the render function return value, which is a VDOM
vdom/index.js
Vue.prototype._c = function () { // Create the element
returncreateElement(... arguments); }Copy the code
Render pages with VDOM using deep traversal + DOM processing
- Generate the corresponding HTML structure through VNode, and pay attention to handling attributes
- Find the mount point via EL and replace it
Vue.prototype._update = function (vnode) {
console.log("= = = = = = = =",vnode);
const vm = this;
patch(vm.$el,vnode)
}
Copy the code
vdom/patch.js
Render page entry functions according to VNode
function patch(oldVnode,vnode){
// oldVnode is the real DOM corresponding to EL when first rendered
const isRealElement = oldVnode.nodeType;
if(isRealElement){
const oldElm = oldVnode;
const parentElm = oldElm.parentNode;
// Use vNode to generate the corresponding HTML structure
let el = createElm(vnode);
// Replace the mount point
parentElm.insertBefore(el,oldElm.nextSibling);
parentElm.removeChild(oldVnode)
returnel; }}Copy the code
Create a real DOM based on a VNode
function createElm(vnode){
let {tag,children,key,data,text} = vnode;
if(typeof tag === 'string'){
vnode.el = document.createElement(tag);
// Handle attributes
updateProperties(vnode);
children.forEach(child= > {
return vnode.el.appendChild(createElm(child));
});
}else{
vnode.el = document.createTextNode(text);
}
return vnode.el
}
Copy the code
Processing properties
function updateProperties(vnode){
let newProps = vnode.data || {}; // Get attributes in the current old node
let el = vnode.el; // The current real node
for(let key in newProps){
if(key === 'style') {for(let styleName in newProps.style){
el.style[styleName] = newProps.style[styleName]
}
}else if(key === 'class'){
el.className= newProps.class
}else{ // Add attribute values to this elementel.setAttribute(key,newProps[key]); }}}Copy the code
A link to the
- Vue – ast article second edition | | realizing ast/vnode and page rendering
- Vue | | article implementation ast