Просмотр исходного кода

Merge pull request #341 from SimoTod/bug/nexttick

nextTick runs before x-for finishes updating
Caleb Porzio 5 лет назад
Родитель
Сommit
e42b20791b
4 измененных файлов с 60 добавлено и 25 удалено
  1. 14 9
      dist/alpine-ie11.js
  2. 12 8
      dist/alpine.js
  3. 11 7
      src/component.js
  4. 23 1
      test/next-tick.spec.js

+ 14 - 9
dist/alpine-ie11.js

@@ -6699,11 +6699,8 @@
 
           el.__x = new Component(el);
         }.bind(this));
-        this.executeAndClearRemainingShowDirectiveStack(); // Walk through the $nextTick stack and clear it as we go.
-
-        while (this.nextTickStack.length > 0) {
-          this.nextTickStack.shift()();
-        }
+        this.executeAndClearRemainingShowDirectiveStack();
+        this.executeAndClearNextTickStack(rootEl);
       }
     }, {
       key: "initializeElement",
@@ -6736,10 +6733,18 @@
 
           el.__x = new Component(el);
         }.bind(this));
-        this.executeAndClearRemainingShowDirectiveStack(); // Walk through the $nextTick stack and clear it as we go.
-
-        while (this.nextTickStack.length > 0) {
-          this.nextTickStack.shift()();
+        this.executeAndClearRemainingShowDirectiveStack();
+        this.executeAndClearNextTickStack(rootEl);
+      }
+    }, {
+      key: "executeAndClearNextTickStack",
+      value: function executeAndClearNextTickStack(el) {
+        // Skip spawns from alpine directives
+        if (el === this.$el) {
+          // Walk through the $nextTick stack and clear it as we go.
+          while (this.nextTickStack.length > 0) {
+            this.nextTickStack.shift()();
+          }
         }
       }
     }, {

+ 12 - 8
dist/alpine.js

@@ -1395,11 +1395,8 @@
       }, el => {
         el.__x = new Component(el);
       });
-      this.executeAndClearRemainingShowDirectiveStack(); // Walk through the $nextTick stack and clear it as we go.
-
-      while (this.nextTickStack.length > 0) {
-        this.nextTickStack.shift()();
-      }
+      this.executeAndClearRemainingShowDirectiveStack();
+      this.executeAndClearNextTickStack(rootEl);
     }
 
     initializeElement(el, extraVars) {
@@ -1421,10 +1418,17 @@
       }, el => {
         el.__x = new Component(el);
       });
-      this.executeAndClearRemainingShowDirectiveStack(); // Walk through the $nextTick stack and clear it as we go.
+      this.executeAndClearRemainingShowDirectiveStack();
+      this.executeAndClearNextTickStack(rootEl);
+    }
 
-      while (this.nextTickStack.length > 0) {
-        this.nextTickStack.shift()();
+    executeAndClearNextTickStack(el) {
+      // Skip spawns from alpine directives
+      if (el === this.$el) {
+        // Walk through the $nextTick stack and clear it as we go.
+        while (this.nextTickStack.length > 0) {
+          this.nextTickStack.shift()();
+        }
       }
     }
 

+ 11 - 7
src/component.js

@@ -156,10 +156,7 @@ export default class Component {
 
         this.executeAndClearRemainingShowDirectiveStack()
 
-        // Walk through the $nextTick stack and clear it as we go.
-        while (this.nextTickStack.length > 0) {
-            this.nextTickStack.shift()()
-        }
+        this.executeAndClearNextTickStack(rootEl)
     }
 
     initializeElement(el, extraVars) {
@@ -185,9 +182,16 @@ export default class Component {
 
         this.executeAndClearRemainingShowDirectiveStack()
 
-        // Walk through the $nextTick stack and clear it as we go.
-        while (this.nextTickStack.length > 0) {
-            this.nextTickStack.shift()()
+        this.executeAndClearNextTickStack(rootEl)
+    }
+
+    executeAndClearNextTickStack(el) {
+        // Skip spawns from alpine directives
+        if (el === this.$el) {
+            // Walk through the $nextTick stack and clear it as we go.
+            while (this.nextTickStack.length > 0) {
+                this.nextTickStack.shift()()
+            }
         }
     }
 

+ 23 - 1
test/next-tick.spec.js

@@ -20,5 +20,27 @@ test('$nextTick', async () => {
 
     document.querySelector('button').click()
 
-    await wait(() => { expect(document.querySelector('span').innerText).toEqual('bob') })
+    await wait(() => expect(document.querySelector('span').innerText).toEqual('bob'))
+})
+
+test('nextTick wait for x-for to finish rendering', async () => {
+    document.body.innerHTML = `
+        <div x-data="{list: ['one', 'two'], check: 2}">
+            <template x-for="item in list">
+                <span x-text="item"></span>
+            </template>
+
+            <p x-text="check"></p>
+
+            <button x-on:click="list = ['one', 'two', 'three']; $nextTick(() => {check = document.querySelectorAll('span').length})"></button>
+        </div>
+    `
+
+    Alpine.start()
+
+    expect(document.querySelector('p').innerText).toEqual(2)
+
+    document.querySelector('button').click()
+
+    await wait(() => { expect(document.querySelector('p').innerText).toEqual(3) })
 })