Skip to content

Commit a7985a8

Browse files
committed
binding callback only call when value changes internally
1 parent fc7e99e commit a7985a8

File tree

5 files changed

+89
-2
lines changed

5 files changed

+89
-2
lines changed

src/compiler/compile/render_dom/index.ts

+2
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,7 @@ export default function dom(
8686
const set = (uses_props || uses_rest || writable_props.length > 0 || component.slots.size > 0)
8787
? x`
8888
${$$props} => {
89+
$$self.$$.skip_bound = true;
8990
${uses_props && renderer.invalidate('$$props', x`$$props = @assign(@assign({}, $$props), @exclude_internal_props($$new_props))`)}
9091
${uses_rest && !uses_props && x`$$props = @assign(@assign({}, $$props), @exclude_internal_props($$new_props))`}
9192
${uses_rest && renderer.invalidate('$$restProps', x`$$restProps = ${compute_rest}`)}
@@ -94,6 +95,7 @@ export default function dom(
9495
)}
9596
${component.slots.size > 0 &&
9697
b`if ('$$scope' in ${$$props}) ${renderer.invalidate('$$scope', x`$$scope = ${$$props}.$$scope`)};`}
98+
$$self.$$.skip_bound = false;
9799
}
98100
`
99101
: null;

src/runtime/internal/Component.ts

+3-2
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,8 @@ export function init(component, options, instance, create_fragment, not_equal, p
120120

121121
// everything else
122122
callbacks: blank_object(),
123-
dirty
123+
dirty,
124+
skip_bound: false
124125
};
125126

126127
let ready = false;
@@ -129,7 +130,7 @@ export function init(component, options, instance, create_fragment, not_equal, p
129130
? instance(component, prop_values, (i, ret, ...rest) => {
130131
const value = rest.length ? rest[0] : ret;
131132
if ($$.ctx && not_equal($$.ctx[i], $$.ctx[i] = value)) {
132-
if ($$.bound[i]) $$.bound[i](value);
133+
if (!$$.skip_bound && $$.bound[i]) $$.bound[i](value);
133134
if (ready) make_dirty(component, i);
134135
}
135136
return ret;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
<script>
2+
export let value = '';
3+
</script>
4+
5+
<input bind:value />
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
export default {
2+
html: `
3+
<input />
4+
<input />
5+
<div></div>
6+
`,
7+
8+
async test({ assert, component, target, window }) {
9+
let count = 0;
10+
component.callback = () => {
11+
count++;
12+
};
13+
14+
const [input1, input2] = target.querySelectorAll("input");
15+
16+
input1.value = "1";
17+
await input1.dispatchEvent(new window.Event("input"));
18+
19+
assert.htmlEqual(
20+
target.innerHTML,
21+
`
22+
<input />
23+
<input />
24+
<div>1</div>
25+
`
26+
);
27+
assert.equal(input1.value, "1");
28+
assert.equal(input2.value, "1");
29+
assert.equal(count, 1);
30+
31+
input2.value = "123";
32+
await input2.dispatchEvent(new window.Event("input"));
33+
34+
assert.htmlEqual(
35+
target.innerHTML,
36+
`
37+
<input />
38+
<input />
39+
<div>123</div>
40+
`
41+
);
42+
assert.equal(input1.value, "123");
43+
assert.equal(input2.value, "123");
44+
assert.equal(count, 2);
45+
46+
input1.value = "456";
47+
await input1.dispatchEvent(new window.Event("input"));
48+
49+
assert.htmlEqual(
50+
target.innerHTML,
51+
`
52+
<input />
53+
<input />
54+
<div>456</div>
55+
`
56+
);
57+
assert.equal(input1.value, "456");
58+
assert.equal(input2.value, "456");
59+
assert.equal(count, 3);
60+
},
61+
};
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
<script>
2+
import { writable } from 'svelte/store';
3+
import Input from './Input.svelte';
4+
5+
let value = writable({ value: '' });
6+
7+
export let callback = () => {};
8+
9+
value.subscribe(() => {
10+
callback();
11+
})
12+
</script>
13+
14+
<input bind:value={$value.value} />
15+
16+
<Input bind:value={$value.value}/>
17+
18+
<div>{$value.value}</div>

0 commit comments

Comments
 (0)