only make component dirty if value has changed

pull/1864/head
Rich Harris 7 years ago
parent 05a4f5d7c8
commit 701af7f7fb

@ -145,33 +145,10 @@ export default function dom(
` `
: `@noop`; : `@noop`;
const body = [ const body = [];
deindent`
$$init($$make_dirty) {
${component.init_uses_self && `const $$self = this;`}
${should_add_css &&
`if (!document.getElementById("${component.stylesheet.id}-style")) @add_css();`}
${component.javascript || component.exports.map(x => `let ${x.name};`)}
${component.partly_hoisted.length > 0 && component.partly_hoisted.join('\n\n')}
return [
// TODO only what's needed by the template
() => ({ ${component.declarations.join(', ')} }),
${inject_props},
${inject_refs}
];
}
$$create_fragment(${component.alias('component')}, ctx) {
${block.getContents()}
}
`
];
const debug_name = `<${component.customElement ? component.tag : name}>`; const debug_name = `<${component.customElement ? component.tag : name}>`;
const not_equal = component.options.immutable ? `@not_equal` : `@safe_not_equal`;
if (component.options.dev) { if (component.options.dev) {
// TODO check no uunexpected props were passed, as well as // TODO check no uunexpected props were passed, as well as
@ -219,11 +196,35 @@ export default function dom(
}); });
builder.addBlock(deindent` builder.addBlock(deindent`
function $$create_fragment(${component.alias('component')}, ctx) {
${block.getContents()}
}
${component.module_javascript} ${component.module_javascript}
${component.fully_hoisted.length > 0 && component.fully_hoisted.join('\n\n')} ${component.fully_hoisted.length > 0 && component.fully_hoisted.join('\n\n')}
function $$init($$self, $$make_dirty) {
${should_add_css &&
`if (!document.getElementById("${component.stylesheet.id}-style")) @add_css();`}
${component.javascript || component.exports.map(x => `let ${x.name};`)}
${component.partly_hoisted.length > 0 && component.partly_hoisted.join('\n\n')}
return [
// TODO only what's needed by the template
() => ({ ${component.declarations.join(', ')} }),
${inject_props},
${inject_refs}
];
}
class ${name} extends ${superclass} { class ${name} extends ${superclass} {
constructor(options) {
super(options, $$init, $$create_fragment, ${not_equal});
}
${body.join('\n\n')} ${body.join('\n\n')}
} }
`); `);

@ -5,7 +5,7 @@ import { blankObject } from './utils.js';
import { children } from './dom.js'; import { children } from './dom.js';
export class $$Component { export class $$Component {
constructor(options) { constructor(options, init, create_fragment, not_equal) {
this.$$beforeRender = []; this.$$beforeRender = [];
this.$$onMount = []; this.$$onMount = [];
this.$$afterRender = []; this.$$afterRender = [];
@ -16,14 +16,15 @@ export class $$Component {
this.$$slotted = options.slots || {}; this.$$slotted = options.slots || {};
set_current_component(this); set_current_component(this);
const [get_state, inject_props, inject_refs] = this.$$init( const [get_state, inject_props, inject_refs] = init(
this,
key => { key => {
this.$$make_dirty(key); this.$$make_dirty(key);
if (this.$$bindings[key]) this.$$bindings[key](get_state()[key]); if (this.$$bindings[key]) this.$$bindings[key](get_state()[key]);
} }
); );
this.$$ = { get_state, inject_props, inject_refs }; this.$$ = { get_state, inject_props, inject_refs, not_equal };
this.$$refs = {}; this.$$refs = {};
@ -35,7 +36,7 @@ export class $$Component {
} }
run_all(this.$$beforeRender); run_all(this.$$beforeRender);
this.$$fragment = this.$$create_fragment(this, this.$$.get_state()); this.$$fragment = create_fragment(this, this.$$.get_state());
if (options.target) { if (options.target) {
intro.enabled = !!options.intro; intro.enabled = !!options.intro;
@ -63,8 +64,11 @@ export class $$Component {
$set(values) { $set(values) {
if (this.$$) { if (this.$$) {
const state = this.$$.get_state();
this.$$.inject_props(values); this.$$.inject_props(values);
for (const key in values) this.$$make_dirty(key); for (const key in values) {
if (this.$$.not_equal(state[key], values[key])) this.$$make_dirty(key);
}
} }
} }
@ -137,7 +141,7 @@ export class $$ComponentDev extends $$Component {
throw new Error(`'target' is a required option`); throw new Error(`'target' is a required option`);
} }
super(options); super(...arguments);
this.$$checkProps(); this.$$checkProps();
} }

@ -48,3 +48,11 @@ export function run_all(fns) {
export function is_function(thing) { export function is_function(thing) {
return typeof thing === 'function'; return typeof thing === 'function';
} }
export function safe_not_equal(a, b) {
return a != a ? b == b : a !== b || ((a && typeof a === 'object') || typeof a === 'function');
}
export function not_equal(a, b) {
return a != a ? b == b : a !== b;
}
Loading…
Cancel
Save