Przeglądaj źródła

fix whitespace vnode identity breaking patch (fix #3043)

Evan You 10 lat temu
rodzic
commit
a53d54aa8a

+ 1 - 1
examples/tree/index.html

@@ -40,7 +40,7 @@
             v-for="model in model.children"
             :model="model">
           </item>
-          <li @click="addChild">+</li>
+          <li class="add" @click="addChild">+</li>
         </ul>
       </li>
     </script>

+ 1 - 1
src/core/instance/lifecycle.js

@@ -31,7 +31,7 @@ export function lifecycleMixin (Vue: Class<Component>) {
     const vm: Component = this
     vm.$el = el
     if (!vm.$options.render) {
-      vm.$options.render = () => emptyVNode
+      vm.$options.render = emptyVNode
       if (process.env.NODE_ENV !== 'production') {
         /* istanbul ignore if */
         if (vm.$options.template) {

+ 1 - 1
src/core/instance/render.js

@@ -70,7 +70,7 @@ export function renderMixin (Vue: Class<Component>) {
           vm
         )
       }
-      vnode = emptyVNode
+      vnode = emptyVNode()
     }
     // set parent
     vnode.parent = _parentVnode

+ 1 - 1
src/core/vdom/create-element.js

@@ -46,7 +46,7 @@ export function renderElement (
   }
   if (!tag) {
     // in case of component :is set to falsy value
-    return emptyVNode
+    return emptyVNode()
   }
   if (typeof tag === 'string') {
     let Ctor

+ 2 - 9
src/core/vdom/helpers.js

@@ -3,8 +3,6 @@
 import { isPrimitive } from '../util/index'
 import VNode from './vnode'
 
-const whitespace = new VNode(undefined, undefined, undefined, ' ')
-
 export function normalizeChildren (children: any): Array<VNode> {
   // invoke children thunks.
   // components always receive their children as thunks so that they
@@ -23,13 +21,8 @@ export function normalizeChildren (children: any): Array<VNode> {
       if (Array.isArray(c)) {
         res.push.apply(res, normalizeChildren(c))
       } else if (isPrimitive(c)) {
-        // optimize whitespace
-        if (c === ' ') {
-          res.push(whitespace)
-        } else {
-          // convert primitive to vnode
-          res.push(new VNode(undefined, undefined, undefined, c))
-        }
+        // convert primitive to vnode
+        res.push(new VNode(undefined, undefined, undefined, c))
       } else if (c instanceof VNode) {
         res.push(c)
       }

+ 1 - 1
src/core/vdom/patch.js

@@ -250,6 +250,7 @@ export function createPatchFunction (backend) {
   }
 
   function patchVnode (oldVnode, vnode, insertedVnodeQueue) {
+    if (oldVnode === vnode) return
     let i, hook
     if (isDef(i = vnode.data) && isDef(hook = i.hook) && isDef(i = hook.prepatch)) {
       i(oldVnode, vnode)
@@ -257,7 +258,6 @@ export function createPatchFunction (backend) {
     const elm = vnode.elm = oldVnode.elm
     const oldCh = oldVnode.children
     const ch = vnode.children
-    if (oldVnode === vnode) return
     if (isDef(vnode.data)) {
       for (i = 0; i < cbs.update.length; ++i) cbs.update[i](oldVnode, vnode)
       if (isDef(hook) && isDef(i = hook.update)) i(oldVnode, vnode)

+ 1 - 1
src/core/vdom/vnode.js

@@ -48,4 +48,4 @@ export default class VNode {
   }
 }
 
-export const emptyVNode = new VNode(undefined, undefined, undefined, '')
+export const emptyVNode = () => new VNode(undefined, undefined, undefined, '')

+ 31 - 6
test/e2e/specs/tree.js

@@ -4,20 +4,45 @@ module.exports = {
     .url('http://localhost:8080/examples/tree/')
       .waitForElementVisible('li', 1000)
       .assert.count('.item', 12)
+      .assert.count('.add', 4)
       .assert.count('.item > ul', 4)
       .assert.notVisible('#demo li ul')
       .assert.containsText('#demo li div span', '[+]')
 
+      // expand root
       .click('.bold')
       .assert.visible('#demo ul')
-      .assert.containsText('#demo li div span', '[-]')
-      .assert.containsText('#demo ul > .item:nth-child(1)', 'hello')
-      .assert.containsText('#demo ul > .item:nth-child(2)', 'wat')
-      .assert.containsText('#demo ul > .item:nth-child(3)', 'child folder')
-      .assert.containsText('#demo ul > .item:nth-child(3)', '[+]')
       .assert.evaluate(function () {
         return document.querySelector('#demo li ul').children.length === 4
       })
+      .assert.containsText('#demo li div span', '[-]')
+      .assert.containsText('#demo > .item > ul > .item:nth-child(1)', 'hello')
+      .assert.containsText('#demo > .item > ul > .item:nth-child(2)', 'wat')
+      .assert.containsText('#demo > .item > ul > .item:nth-child(3)', 'child folder')
+      .assert.containsText('#demo > .item > ul > .item:nth-child(3)', '[+]')
+
+      // add items to root
+      .click('#demo > .item > ul > .add')
+      .assert.evaluate(function () {
+        return document.querySelector('#demo li ul').children.length === 5
+      })
+      .assert.containsText('#demo > .item > ul > .item:nth-child(1)', 'hello')
+      .assert.containsText('#demo > .item > ul > .item:nth-child(2)', 'wat')
+      .assert.containsText('#demo > .item > ul > .item:nth-child(3)', 'child folder')
+      .assert.containsText('#demo > .item > ul > .item:nth-child(3)', '[+]')
+      .assert.containsText('#demo > .item > ul > .item:nth-child(4)', 'new stuff')
+
+      // add another item
+      .click('#demo > .item > ul > .add')
+      .assert.evaluate(function () {
+        return document.querySelector('#demo li ul').children.length === 6
+      })
+      .assert.containsText('#demo > .item > ul > .item:nth-child(1)', 'hello')
+      .assert.containsText('#demo > .item > ul > .item:nth-child(2)', 'wat')
+      .assert.containsText('#demo > .item > ul > .item:nth-child(3)', 'child folder')
+      .assert.containsText('#demo > .item > ul > .item:nth-child(3)', '[+]')
+      .assert.containsText('#demo > .item > ul > .item:nth-child(4)', 'new stuff')
+      .assert.containsText('#demo > .item > ul > .item:nth-child(5)', 'new stuff')
 
       .click('#demo ul .bold')
       .assert.visible('#demo ul ul')
@@ -34,7 +59,7 @@ module.exports = {
       .assert.containsText('#demo li div span', '[-]')
 
       .dblClick('#demo ul > .item div')
-      .assert.count('.item', 13)
+      .assert.count('.item', 15)
       .assert.count('.item > ul', 5)
       .assert.containsText('#demo ul > .item:nth-child(1)', '[-]')
       .assert.evaluate(function () {

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

@@ -77,7 +77,7 @@ describe('create-element', () => {
     const _e = bind(renderElement, vm)
     renderState.activeInstance = vm
     const vnode = _e(null, {})
-    expect(vnode).toEqual(emptyVNode)
+    expect(vnode).toEqual(emptyVNode())
   })
 
   it('render vnode with not string tag using renderElement', () => {