Skip to content

Commit f2bd882

Browse files
gebilaoxiongyyx990803
authored andcommitted
Fix: nested child elements can not be updated correctly, fix vuejs#5618 (vuejs#5627)
* fix:nested elements can not be updated correctly * add tests * ensure nestedIndex is always passed down
1 parent 5d965d5 commit f2bd882

File tree

4 files changed

+58
-3
lines changed

4 files changed

+58
-3
lines changed

src/core/instance/render-helpers/render-list.js

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/* @flow */
22

3-
import { isObject } from 'core/util/index'
3+
import { isObject, isDef } from 'core/util/index'
44

55
/**
66
* Runtime helper for rendering v-for lists.
@@ -28,5 +28,8 @@ export function renderList (
2828
ret[i] = render(val[key], key, i)
2929
}
3030
}
31+
if (isDef(ret)) {
32+
(ret: any)._isVList = true
33+
}
3134
return ret
3235
}

src/core/vdom/helpers/normalize-children.js

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
/* @flow */
22

33
import VNode, { createTextVNode } from 'core/vdom/vnode'
4-
import { isFalse, isDef, isUndef, isPrimitive } from 'shared/util'
4+
import { isFalse, isTrue, isDef, isUndef, isPrimitive } from 'shared/util'
55

66
// The template compiler attempts to minimize the need for normalization by
77
// statically analyzing the template at compile time.
@@ -58,7 +58,10 @@ function normalizeArrayChildren (children: any, nestedIndex?: string): Array<VNo
5858
res[res.length - 1] = createTextVNode(last.text + c.text)
5959
} else {
6060
// default key for nested array children (likely generated by v-for)
61-
if (isDef(c.tag) && isUndef(c.key) && isDef(nestedIndex)) {
61+
if (isTrue(children._isVList) &&
62+
isDef(c.tag) &&
63+
isUndef(c.key) &&
64+
isDef(nestedIndex)) {
6265
c.key = `__vlist${nestedIndex}_${i}__`
6366
}
6467
res.push(c)

test/unit/features/component/component-slot.spec.js

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -639,4 +639,25 @@ describe('Component slot', () => {
639639
expect(vm.$el.textContent).toBe('2foo')
640640
}).then(done)
641641
})
642+
643+
it('the elements of slot should be updated correctly', done => {
644+
const vm = new Vue({
645+
data: { n: 1 },
646+
template: '<div><test><span v-for="i in n" :key="i">{{ i }}</span><input value="a"/></test></div>',
647+
components: {
648+
test: {
649+
template: '<div><slot></slot></div>'
650+
}
651+
}
652+
}).$mount()
653+
expect(vm.$el.innerHTML).toBe('<div><span>1</span><input value="a"></div>')
654+
const input = vm.$el.querySelector('input')
655+
input.value = 'b'
656+
vm.n++
657+
waitForUpdate(() => {
658+
expect(vm.$el.innerHTML).toBe('<div><span>1</span><span>2</span><input value="a"></div>')
659+
expect(vm.$el.querySelector('input')).toBe(input)
660+
expect(vm.$el.querySelector('input').value).toBe('b')
661+
}).then(done)
662+
})
642663
})

test/unit/modules/vdom/create-element.spec.js

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -152,4 +152,32 @@ describe('create-element', () => {
152152
}).$mount()
153153
expect('Avoid using observed data object as vnode data').toHaveBeenWarned()
154154
})
155+
156+
it('nested child elements should be updated correctly', done => {
157+
const vm = new Vue({
158+
data: { n: 1 },
159+
render (h) {
160+
const list = []
161+
for (let i = 0; i < this.n; i++) {
162+
list.push(h('span', i))
163+
}
164+
const input = h('input', {
165+
attrs: {
166+
value: 'a',
167+
type: 'text'
168+
}
169+
})
170+
return h('div', [[...list, input]])
171+
}
172+
}).$mount()
173+
expect(vm.$el.innerHTML).toBe('<span>0</span><input value="a" type="text">')
174+
const el = vm.$el.querySelector('input')
175+
el.value = 'b'
176+
vm.n++
177+
waitForUpdate(() => {
178+
expect(vm.$el.innerHTML).toBe('<span>0</span><span>1</span><input value="a" type="text">')
179+
expect(vm.$el.querySelector('input')).toBe(el)
180+
expect(vm.$el.querySelector('input').value).toBe('b')
181+
}).then(done)
182+
})
155183
})

0 commit comments

Comments
 (0)