组件挂载入口
Vue.prototype.$mount = function(el){
const vm = this;
const opt = vm.$options;
el = document.querySelector(el);
if(!opt.render){
let template = opt.template;
if(!template && el){
template = el.outerHTML;
}
if(template){
let render = complileToFunction(template);
opt.render = render;
}
}
mountComponent(vm, el);
}
组件挂载核心方法
export function mountComponent(vm, el){
console.log(vm, el)
vm.$el = el;
const updateComponent = () => {
vm._update(vm._render())
};
updateComponent();
}
render函数转换虚拟dom方法
export function lifecycleMixin(Vue){
Vue.prototype._c = function(){
return createElement(this, ...arguments);
}
Vue.prototype._v = function(){
return createTextNode(this, ...arguments);
}
Vue.prototype._s = function(value){
if(Object.prototype.toString.call(value) === '[object Object]'){
return JSON.stringify(value)
}
return value
}
Vue.prototype._render = function(){
const vm = this;
const render = vm.$options.render;
let vnode = render.call(vm);
return vnode;
}
Vue.prototype._update = function(vnode){
const vm = this;
const el = vm.$el;
vm.$el = patch(vm.$el, vnode);
}
}
创建虚拟dom
export function createElement(vm, tag, data={}, ...children){
return vnode(vm, tag, data, children, data.key, null);
}
export function createTextNode(vm, text){
return vnode(vm, null, null, null, null, text);
}
function vnode(vm, tag, data, children, key, text){
return {
vm,
tag,
data,
children,
key,
text,
}
}
创建真实dom
export function patch(oldVnode, vnode){
const isRealElement = oldVnode.nodeType;
if(isRealElement){
const oldEle = oldVnode;
const parentNode = oldEle.parentNode;
const el = createElm(vnode);
parentNode.insertBefore(el, oldEle.nextSibling);
parentNode.removeChild(oldEle);
}else{
}
}
function createElm(vnode){
let {tag, data, children, text} = vnode;
if(typeof tag === 'string'){
vnode.el = document.createElement(tag);
children.forEach(child => {
vnode.el.appendChild(createElm(child));
})
}else{
vnode.el = document.createTextNode(text);
}
return vnode.el;
}