فهرست منبع

Fix x-on with both self and once (#4152)

* Fix x-on with both self and once

* Fix x-on with both outside and once
Benjamin Bock 1 سال پیش
والد
کامیت
95ae59032c
2فایلهای تغییر یافته به همراه49 افزوده شده و 8 حذف شده
  1. 9 8
      packages/alpinejs/src/utils/on.js
  2. 40 0
      tests/cypress/integration/directives/x-on.spec.js

+ 9 - 8
packages/alpinejs/src/utils/on.js

@@ -37,7 +37,14 @@ export default function on (el, event, modifiers, callback) {
 
     if (modifiers.includes('prevent')) handler = wrapHandler(handler, (next, e) => { e.preventDefault(); next(e) })
     if (modifiers.includes('stop')) handler = wrapHandler(handler, (next, e) => { e.stopPropagation(); next(e) })
-    if (modifiers.includes('self')) handler = wrapHandler(handler, (next, e) => { e.target === el && next(e) })
+
+    if (modifiers.includes("once")) {
+        handler = wrapHandler(handler, (next, e) => {
+            next(e);
+
+            listenerTarget.removeEventListener(event, handler, options);
+        });
+    }
 
     if (modifiers.includes('away') || modifiers.includes('outside')) {
         listenerTarget = document
@@ -57,13 +64,7 @@ export default function on (el, event, modifiers, callback) {
         })
     }
 
-    if (modifiers.includes('once')) {
-        handler = wrapHandler(handler, (next, e) => {
-            next(e)
-
-            listenerTarget.removeEventListener(event, handler, options)
-        })
-    }
+    if (modifiers.includes('self')) handler = wrapHandler(handler, (next, e) => { e.target === el && next(e) })
 
     // Handle :keydown and :keyup listeners.
     handler = wrapHandler(handler, (next, e) => {

+ 40 - 0
tests/cypress/integration/directives/x-on.spec.js

@@ -186,6 +186,27 @@ test('.self modifier',
     }
 )
 
+test(
+    ".self.once modifiers",
+    html`
+        <div x-data="{ foo: 'bar' }">
+            <h1 x-on:click.self.once="foo = 'baz'" id="selfTarget">
+                content
+                <button>click</button>
+                content
+            </h1>
+            <span x-text="foo"></span>
+        </div>
+    `,
+    ({ get }) => {
+        get("span").should(haveText("bar"));
+        get("button").click();
+        get("span").should(haveText("bar"));
+        get("h1").click();
+        get("span").should(haveText("baz"));
+    }
+);
+
 test('.prevent modifier',
     html`
         <div x-data="{}">
@@ -492,6 +513,25 @@ test('@click.away',
     }
 )
 
+test('@click.away.once works after clicking inside',
+    html`
+        <div x-data="{ foo: 'bar' }">
+            <h1 @click.away.once="foo = 'baz'">h1</h1>
+
+            <h2>h2</h2>
+
+            <span x-text="foo"></span>
+        </div>
+    `,
+    ({ get }) => {
+        get('span').should(haveText('bar'))
+        get('h1').click()
+        get('span').should(haveText('bar'))
+        get('h2').click()
+        get('span').should(haveText('baz'))
+    }
+)
+
 test('@click.away with x-show (prevent race condition)',
     html`
         <div x-data="{ show: false }">