Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

元素虚拟DOM也有updater #79

Closed
RubyLouvre opened this issue Nov 22, 2017 · 3 comments
Closed

元素虚拟DOM也有updater #79

RubyLouvre opened this issue Nov 22, 2017 · 3 comments

Comments

@RubyLouvre
Copy link
Owner

组件虚拟DOM会产生 CompositeUpdater
元素虚拟DOM会产生 DOMUpdater

它们至少用于控制ref的执行

@RubyLouvre
Copy link
Owner Author

RubyLouvre commented Dec 5, 2017

 *   元素: 元素虚拟DOM产生updater, 放入列队
 *         插入其孩子的所有DOM, 收集�孩子中的组件updater, resolve
 *   组件: 元素虚拟DOM产生instance与updater, 执行 willMount,
 *         立即调用render,目的是能让子级组件立即 willMount
 *   <App /> ==> <p ref={refFn}>{this.state.xxx}</p>
 *  container
 * 
 * 
 *  元素的render,用于添加子节点,收集它们的updater
 *  元素的resolve, 用于设置属性与可控属性,执行它们的ref
 * 
 *  组件的render, 用于执行它们的render, diffChildren 
 *  元素的resolve, 执行生命周期钩子与ref与处理异常
 * 
 *  <App><A /><A /><span>xxx</span></App>
 * 
 *   children.forEach(function(){ el.render() })
 *   children.
 * 
 *   VNode.prototype.render = function(p, queue){
 *      var el = this
 *      if(el.vtype < 1){
 *          el.stateNode = toDOM(el, p)
 *       }else if(el.vtype === 1){
 *          el.stateNode = toDOM(el, p)
 *          for(var i in children){
 *            var a = children[i]
 *            a.render(el, queue)
 *          }
 *          queue.push(el)
 *       } else {
 *          var c = el.stateNode = toComponent(el, p, queue)
 *          el.render() //组件
 *          queue.push(el.updater)
 *       }
 *   }
 *   Vnode.prototype.append = function(parentNode){
 *      var p = this.stateNode, children = this.children
 *      if(this.vtype === 1){
 *          for(var i in children){
 *              var el = children[i]
 *              if(el.vtype < 1){
 *                 p.appendChild(el.stateNode)
 *                
 *              }else if(el.vtype === 1){
 * 
 *                  el.append(p)
 *                  el.resolve()
 *              }else if(el.vtype > 1){
 *                 el.append(p)
 *                 el.resolve()
 *              }
 *          }
 *      }
 *    }
 *    

@RubyLouvre
Copy link
Owner Author

RubyLouvre commented Dec 7, 2017

batchUpdate(lastChildren, nextChildren, debug) {//子节点主动让父节点来更新其孩子 Fragment []
          var vnode = this.vnode;
        var parentNode = vnode.stateNode,
            newLength = nextChildren.length,
            oldLength = lastChildren.length,
            unique = createUnique();
        var fullNodes = toArray(parentNode.childNodes);
        var startIndex = fullNodes.indexOf(lastChildren[0]);
        var insertPoint = fullNodes[startIndex] || null;
        for (let i = 0; i < newLength; i++) {//Set
            let child = nextChildren[i];
            let last = lastChildren[i];
            if (last === child) {
                //如果相同
            } else if (last && !unique.has(last)) {
                parentNode.replaceChild(child, last); //如果这个位置有DOM,并且它不在新的nextChildren之中
            } else if (insertPoint) {
                parentNode.insertBefore(child, insertPoint.nextSibling);
            } else {
                parentNode.appendChild(child);
            }
            insertPoint = child;
            unique.add(child);
        }
        if (newLength < oldLength) {
            for (let i = newLength; i < oldLength; i++) {
                if (!unique.has(lastChildren[i])) {
                    removeElement(lastChildren[i]);
                }
            }
        }
    },

@RubyLouvre
Copy link
Owner Author

export function collectAndResolve(children, resolve, debug) {
    var ret = [];
    for (var i in children) {
        var child = children[i];
        var inner = child.stateNode;
        if (child._disposed) {
            continue;
        }
        if (child.vtype < 2) {
            //  console.log(inner, debug);
            ret.push(inner);
        } else {
            var updater = inner.updater;
            if (updater.cache) {
                ret.push.apply(ret, updater.cache);
            } else {
                if (child.child) {
                    var args = collectAndResolve(updater.children, resolve, debug);
                    updater.cache = args;
                    ret.push.apply(ret, args);
                }
            }

            if (resolve) {
                updater.addJob("resolve");
                resolve.push(updater); //先执行内围的,再执行外围的
            }
        }
    }
    return ret;
}
export function createUnique() {
    return typeof Set === "function" ? new Set() : new InnerSet();
}
function InnerSet() {
    this.elems = [];
}
InnerSet.prototype = {
    add: function(el) {
        this.elems.push(el);
    },
    has: function(el) {
        return this.elems.indexOf(el) !== -1;
    }
};

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant