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

feature: Value/Modifier based intersect (#1933)

* added base logic

* cleanup

* refactor

* Added tests

* Added change test

* Added docs

* cleanup

* remanme 'change' to 'changed'

* value base logic

* value base tests

* added docs

* removed dispatch from directive utils

* cleanup

* updated tests

* cleanup
Dede Muzaffer 3 лет назад
Родитель
Сommit
6f37ce0fcb

+ 22 - 0
packages/docs/src/en/plugins/intersect.md

@@ -75,6 +75,28 @@ For example, in the following snippet, `shown` will remain `false` until the ele
 </div>
 <!-- END_VERBATIM -->
 
+<a name="directives"></a>
+## Directives
+
+| Directive      | Description |
+| ---            | --- |
+| `:enter`       | Applied only entering phase. |
+| `:leave`       | Applied only leaving phase. |
+
+<a name="enter"></a>
+### :enter
+
+```html
+<div x-intersect:enter="shown = true">...</div>
+```
+
+<a name="leave"></a>
+### :leave
+
+```html
+<div x-intersect:leave="shown = false">...</div>
+```
+
 <a name="modifiers"></a>
 ## Modifiers
 

+ 2 - 2
packages/intersect/src/index.js

@@ -1,10 +1,10 @@
 export default function (Alpine) {
-    Alpine.directive('intersect', (el, { expression, modifiers }, { evaluateLater, cleanup }) => {
+    Alpine.directive('intersect', (el, { value, expression, modifiers }, { evaluateLater, cleanup }) => {
         let evaluate = evaluateLater(expression)
 
         let observer = new IntersectionObserver(entries => {
             entries.forEach(entry => {
-                if (entry.intersectionRatio === 0) return
+                if(!entry.isIntersecting && value === 'enter' || entry.isIntersecting && value === 'leave' || entry.intersectionRatio === 0 && !value) return
 
                 evaluate()
 

+ 49 - 11
tests/cypress/integration/plugins/intersect.spec.js

@@ -2,24 +2,63 @@ import { haveText, test, html } from '../../utils'
 
 test('can intersect',
     [html`
-    <div x-data="{ count: 0 }" x-init="setTimeout(() => count++, 300)">
+    <div x-data="{ count: 0 }">
         <span x-text="count"></span>
 
         <div x-intersect="count++" style="margin-top: 100vh;" id="1">hi</div>
     </div>
     `],
-    ({ get }, reload) => {
+    ({ get }) => {
         get('span').should(haveText('0'))
+        get('#1').scrollIntoView({duration: 100})
+        get('span').should(haveText('1'))
+        get('span').scrollIntoView({duration: 100})
         get('span').should(haveText('1'))
-        get('#1').scrollIntoView()
+        get('#1').scrollIntoView({duration: 100})
+        get('span').should(haveText('2'))
+    },
+)
+
+test('It should evaluate with ":enter" only when the component is intersected',
+    [html`
+    <div x-data="{ count: 0 }">
+        <span x-text="count"></span>
+
+        <div x-intersect:enter="count++" style="margin-top: 100vh;" id="1">hi</div>
+    </div>
+    `],
+    ({ get }) => {
+        get('span').should(haveText('0'))
+        get('#1').scrollIntoView({duration: 100})
         get('span').should(haveText('1'))
-        get('span').scrollIntoView()
+        get('span').scrollIntoView({duration: 100})
         get('span').should(haveText('1'))
-        get('#1').scrollIntoView()
+        get('#1').scrollIntoView({duration: 100})
         get('span').should(haveText('2'))
     },
 )
 
+test('It should evaluate with ":leave" only when the component is not intersected',
+    [html`
+    <div x-data="{ count: 0 }">
+        <span x-text="count"></span>
+
+        <div x-intersect:leave="count++" style="margin-top: 100vh;" id="1">hi</div>
+    </div>
+    `],
+    ({ get }) => {
+        get('span').should(haveText('1'))
+        get('#1').scrollIntoView({duration: 100})
+        get('span').should(haveText('1'))
+        get('span').scrollIntoView({duration: 100})
+        get('span').should(haveText('2'))
+        get('#1').scrollIntoView({duration: 100})
+        get('span').should(haveText('2'))
+        get('span').scrollIntoView({duration: 100})
+        get('span').should(haveText('3'))
+    },
+)
+
 test('.once',
     [html`
     <div x-data="{ count: 0 }" x-init="setTimeout(() => count++, 300)">
@@ -28,14 +67,13 @@ test('.once',
         <div x-intersect.once="count++" style="margin-top: 100vh;" id="1">hi</div>
     </div>
     `],
-    ({ get }, reload) => {
+    ({ get }) => {
         get('span').should(haveText('0'))
+        get('#1').scrollIntoView({duration: 100})
         get('span').should(haveText('1'))
-        get('#1').scrollIntoView()
-        get('span').should(haveText('1'))
-        get('span').scrollIntoView()
-        get('span').should(haveText('1'))
-        get('#1').scrollIntoView()
+        get('span').scrollIntoView({duration: 100})
         get('span').should(haveText('1'))
+        get('#1').scrollIntoView({duration: 100})
+        get('span').should(haveText('2'))
     },
 )