mirror of
https://github.com/marko-js/marko.git
synced 2026-02-01 16:07:13 +00:00
Fix for edge case bug when rerendering a child component that is a parent's root
This commit is contained in:
parent
e8c3c390d0
commit
7d32145f5b
@ -4,7 +4,6 @@
|
||||
var domInsert = require('../runtime/dom-insert');
|
||||
var marko = require('../');
|
||||
var componentsUtil = require('./util');
|
||||
var getComponentForEl = componentsUtil.$__getComponentForEl;
|
||||
var componentLookup = componentsUtil.$__componentLookup;
|
||||
var emitLifecycleEvent = componentsUtil.$__emitLifecycleEvent;
|
||||
var destroyComponentForEl = componentsUtil.$__destroyComponentForEl;
|
||||
@ -35,10 +34,23 @@ function removeListener(removeEventListenerHandle) {
|
||||
removeEventListenerHandle();
|
||||
}
|
||||
|
||||
function hasCompatibleComponent(componentsContext, existingComponent) {
|
||||
var id = existingComponent.id;
|
||||
var newComponentDef = componentsContext.$__componentsById[id];
|
||||
return newComponentDef && existingComponent.$__type == newComponentDef.$__component.$__type;
|
||||
function checkCompatibleComponent(componentsContext, el) {
|
||||
var component = el._w;
|
||||
while(component) {
|
||||
var id = component.id;
|
||||
var newComponentDef = componentsContext.$__componentsById[id];
|
||||
if (newComponentDef && component.$__type == newComponentDef.$__component.$__type) {
|
||||
break;
|
||||
}
|
||||
|
||||
var rootFor = component.$__rootFor;
|
||||
if (rootFor) {
|
||||
component = rootFor;
|
||||
} else {
|
||||
component.$__destroyShallow();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function handleCustomEventWithMethodListener(component, targetMethodName, args, extraArgs) {
|
||||
@ -488,7 +500,6 @@ Component.prototype = componentProto = {
|
||||
|
||||
function onBeforeElUpdated(fromEl, toEl) {
|
||||
var id = fromEl.id;
|
||||
var existingComponent;
|
||||
|
||||
if (componentsContext && id) {
|
||||
var preserved = componentsContext.$__preserved[id];
|
||||
@ -499,13 +510,10 @@ Component.prototype = componentProto = {
|
||||
// the morphing will take place when the reused component updates.
|
||||
return MORPHDOM_SKIP;
|
||||
} else {
|
||||
existingComponent = getComponentForEl(fromEl);
|
||||
if (existingComponent && !hasCompatibleComponent(componentsContext, existingComponent)) {
|
||||
// We found a component in an old DOM node that does not have
|
||||
// a compatible component that was rendered so we need to
|
||||
// destroy the old component
|
||||
existingComponent.$__destroyShallow();
|
||||
}
|
||||
// We may need to destroy a Component associated with the current element
|
||||
// if a new UI component was rendered to the same element and the types
|
||||
// do not match
|
||||
checkCompatibleComponent(componentsContext, fromEl);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,11 @@
|
||||
class {
|
||||
constructor() {
|
||||
this.state = {
|
||||
count: 0
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
<div.foo>
|
||||
count:${state.count}
|
||||
</div>
|
||||
@ -0,0 +1,7 @@
|
||||
class {
|
||||
}
|
||||
|
||||
<foo key="foo"/>
|
||||
|
||||
<div.root>
|
||||
</div>
|
||||
@ -0,0 +1,17 @@
|
||||
var expect = require('chai').expect;
|
||||
|
||||
module.exports = function(helpers) {
|
||||
|
||||
var component = helpers.mount(require('./index.marko'), {});
|
||||
|
||||
|
||||
var foo = component.getComponent('foo');
|
||||
expect(foo.el.innerHTML).to.contain('count:0');
|
||||
|
||||
foo.state.count++;
|
||||
foo.update();
|
||||
|
||||
expect(component.isDestroyed()).to.equal(false);
|
||||
expect(foo.isDestroyed()).to.equal(false);
|
||||
expect(foo.el.innerHTML).to.contain('count:1');
|
||||
};
|
||||
@ -0,0 +1,8 @@
|
||||
class {
|
||||
constructor() {
|
||||
this.isBar = true;
|
||||
}
|
||||
}
|
||||
|
||||
<div.bar>
|
||||
</div>
|
||||
@ -0,0 +1,8 @@
|
||||
class {
|
||||
constructor() {
|
||||
this.isFoo = true;
|
||||
}
|
||||
}
|
||||
|
||||
<div.foo>
|
||||
</div>
|
||||
@ -0,0 +1,16 @@
|
||||
class {
|
||||
onCreate() {
|
||||
this.state = {
|
||||
target: 'foo'
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
<div.root>
|
||||
<if(state.target === 'foo')>
|
||||
<foo key="child"/>
|
||||
</if>
|
||||
<else>
|
||||
<bar key="child"/>
|
||||
</else>
|
||||
</div>
|
||||
@ -0,0 +1,24 @@
|
||||
var expect = require('chai').expect;
|
||||
|
||||
module.exports = function(helpers) {
|
||||
|
||||
var component = helpers.mount(require('./index.marko'), {});
|
||||
|
||||
expect(component.el.innerHTML).to.contain('foo');
|
||||
expect(component.el.innerHTML).to.not.contain('bar');
|
||||
|
||||
|
||||
var foo = component.getComponent('child');
|
||||
expect(foo.isDestroyed()).to.equal(false);
|
||||
|
||||
component.state.target = 'bar';
|
||||
component.update();
|
||||
|
||||
expect(foo.isDestroyed()).to.equal(true);
|
||||
|
||||
var bar = component.getComponent('child');
|
||||
expect(bar.isDestroyed()).to.equal(false);
|
||||
|
||||
expect(component.el.innerHTML).to.not.contain('foo');
|
||||
expect(component.el.innerHTML).to.contain('bar');
|
||||
};
|
||||
Loading…
x
Reference in New Issue
Block a user