Caleb Porzio 2 年之前
父节点
当前提交
d2943ddfdd

+ 4 - 2
packages/alpinejs/src/alpine.js

@@ -1,11 +1,11 @@
 import { setReactivityEngine, disableEffectScheduling, reactive, effect, release, raw } from './reactivity'
 import { mapAttributes, directive, setPrefix as prefix, prefix as prefixed } from './directives'
-import { start, addRootSelector, addInitSelector, closestRoot, findClosest, initTree, interceptInit } from './lifecycle'
+import { start, addRootSelector, addInitSelector, closestRoot, findClosest, initTree, destroyTree, interceptInit } from './lifecycle'
 import { mutateDom, deferMutations, flushAndStopDeferringMutations, startObservingMutations, stopObservingMutations } from './mutation'
 import { mergeProxies, closestDataStack, addScopeToNode, scope as $data } from './scope'
 import { setEvaluator, evaluate, evaluateLater, dontAutoEvaluateFunctions } from './evaluator'
 import { transition } from './directives/x-transition'
-import { clone, skipDuringClone } from './clone'
+import { clone, skipDuringClone, onlyDuringClone } from './clone'
 import { interceptor } from './interceptor'
 import { getBinding as bound } from './utils/bind'
 import { debounce } from './utils/debounce'
@@ -33,6 +33,7 @@ let Alpine = {
     setReactivityEngine,
     closestDataStack,
     skipDuringClone,
+    onlyDuringClone,
     addRootSelector,
     addInitSelector,
     addScopeToNode,
@@ -44,6 +45,7 @@ let Alpine = {
     mergeProxies,
     findClosest,
     closestRoot,
+    destroyTree,
     interceptor, // INTERNAL: not public API and is subject to change without major release.
     transition, // INTERNAL
     setStyles, // INTERNAL

+ 1 - 0
packages/alpinejs/src/directives/index.js

@@ -4,6 +4,7 @@ import { warn } from '../utils/warn'
 import './x-transition'
 import './x-modelable'
 import './x-teleport'
+import './x-destroy'
 import './x-ignore'
 import './x-effect'
 import './x-model'

+ 6 - 0
packages/alpinejs/src/directives/x-destroy.js

@@ -0,0 +1,6 @@
+import { directive } from "../directives";
+import { skipDuringClone } from "../clone";
+
+directive('destroy', skipDuringClone((el, { expression }, { evaluate, cleanup }) => {
+    cleanup(() => evaluate(expression, {}, false))
+}))

+ 5 - 3
packages/alpinejs/src/lifecycle.js

@@ -73,10 +73,12 @@ let initInterceptors = []
 
 export function interceptInit(callback) { initInterceptors.push(callback) }
 
-export function initTree(el, walker = walk) {
+export function initTree(el, walker = walk, intercept = () => {}) {
     deferHandlingDirectives(() => {
         walker(el, (el, skip) => {
-            initInterceptors.forEach(i => i(el))
+            intercept(el, skip)
+
+            initInterceptors.forEach(i => i(el, skip))
 
             directives(el, el.attributes).forEach(handle => handle())
 
@@ -85,6 +87,6 @@ export function initTree(el, walker = walk) {
     })
 }
 
-function destroyTree(root) {
+export function destroyTree(root) {
     walk(root, el => cleanupAttributes(el))
 }

+ 2 - 2
packages/morph/src/morph.js

@@ -165,8 +165,8 @@ export function morph(from, toHtml, options) {
             }
 
             // Handle conditional markers (presumably added by backends like Livewire)...
-            let isIf = node => node.nodeType === 8 && node.textContent === ' __IF__ '
-            let isEnd = node => node.nodeType === 8 && node.textContent === ' __ENDIF__ '
+            let isIf = node => node.nodeType === 8 && node.textContent === ' __BLOCK__ '
+            let isEnd = node => node.nodeType === 8 && node.textContent === ' __ENDBLOCK__ '
 
             if (isIf(currentTo) && isIf(currentFrom)) {
                 let newFromChildren = []

+ 18 - 12
packages/navigate/src/index.js

@@ -9,9 +9,9 @@ import { getPretchedHtmlOr, prefetchHtml, storeThePrefetchedHtmlForWhenALinkIsCl
 import { restoreScrollPosition, storeScrollInformationInHtmlBeforeNavigatingAway } from "./scroll"
 
 let enablePrefetch = true
-let enablePersist = false
+let enablePersist = true
 let showProgressBar = false
-let restoreScroll = false
+let restoreScroll = true
 let autofocus = false
 
 export default function (Alpine) {
@@ -65,25 +65,29 @@ export default function (Alpine) {
     whenTheBackOrForwardButtonIsClicked((html) => {
         // @todo: see if there's a way to update the current HTML BEFORE
         // the back button is hit, and not AFTER:
-        // storeScrollInformationInHtmlBeforeNavigatingAway()
+        storeScrollInformationInHtmlBeforeNavigatingAway()
         // updateCurrentPageHtmlInHistoryStateForLaterBackButtonClicks()
 
         preventAlpineFromPickingUpDomChanges(Alpine, andAfterAllThis => {
-            swapCurrentPageWithNewHtml(html)
+            enablePersist && storePersistantElementsForLater()
 
-            hijackNewLinksOnThePage()
+            swapCurrentPageWithNewHtml(html, andThen => {
+                enablePersist && putPersistantElementsBack()
 
-            restoreScroll && restoreScrollPosition()
+                hijackNewLinksOnThePage()
 
-            fireEventForOtherLibariesToHookInto()
+                restoreScroll && restoreScrollPosition()
 
-            andAfterAllThis(() => {
-                autofocus && autofocusElementsWithTheAutofocusAttribute()
+                fireEventForOtherLibariesToHookInto()
 
-                nowInitializeAlpineOnTheNewPage(Alpine)
+                andAfterAllThis(() => {
+                    autofocus && autofocusElementsWithTheAutofocusAttribute()
+
+                    nowInitializeAlpineOnTheNewPage(Alpine)
+                })
             })
-        })
 
+        })
     })
 }
 
@@ -110,7 +114,9 @@ function fireEventForOtherLibariesToHookInto() {
 }
 
 function nowInitializeAlpineOnTheNewPage(Alpine) {
-    Alpine.initTree(document.body)
+    Alpine.initTree(document.body, undefined, (el, skip) => {
+        if (el._x_wasPersisted) skip()
+    })
 }
 
 function autofocusElementsWithTheAutofocusAttribute() {

+ 11 - 2
packages/navigate/src/page.js

@@ -1,3 +1,4 @@
+import Alpine from "alpinejs/src/alpine"
 
 export function swapCurrentPageWithNewHtml(html, andThen) {
     let newDocument = (new DOMParser()).parseFromString(html, "text/html")
@@ -9,20 +10,28 @@ export function swapCurrentPageWithNewHtml(html, andThen) {
 
     transitionOut(document.body)
 
-    setTimeout(() => {
+    // @todo: only setTimeout when applying transitions
+    // setTimeout(() => {
+        let oldBody = document.body
+
         document.body.replaceWith(newBody)
+
+        Alpine.destroyTree(oldBody)
+
         transitionIn(newBody)
 
         andThen()
-    }, 500)
+    // }, 0)
 }
 
 function transitionOut(body) {
+    return;
     body.style.transition = 'all .5s ease'
     body.style.opacity = '0'
 }
 
 function transitionIn(body) {
+    return;
     body.style.opacity = '0'
     body.style.transition = 'all .5s ease'
 

+ 11 - 1
packages/navigate/src/persist.js

@@ -1,3 +1,5 @@
+import Alpine from "alpinejs/src/alpine"
+
 let els = {}
 
 export function storePersistantElementsForLater() {
@@ -5,6 +7,10 @@ export function storePersistantElementsForLater() {
 
     document.querySelectorAll('[x-navigate\\:persist]').forEach(i => {
         els[i.getAttribute('x-navigate:persist')] = i
+
+        Alpine.mutateDom(() => {
+            i.remove()
+        })
     })
 }
 
@@ -12,6 +18,10 @@ export function putPersistantElementsBack() {
     document.querySelectorAll('[x-navigate\\:persist]').forEach(i => {
         let old = els[i.getAttribute('x-navigate:persist')]
 
-        i.replaceWith(old)
+        old._x_wasPersisted = true
+
+        Alpine.mutateDom(() => {
+            i.replaceWith(old)
+        })
     })
 }