瀏覽代碼

Bug - Components initialised twice (#2060)

* Add failing test

* Fix duplicate init
Simone Todaro 3 年之前
父節點
當前提交
c7077e996c
共有 2 個文件被更改,包括 15 次插入6 次删除
  1. 6 4
      packages/alpinejs/src/lifecycle.js
  2. 9 2
      tests/cypress/integration/directives/x-init.spec.js

+ 6 - 4
packages/alpinejs/src/lifecycle.js

@@ -20,7 +20,7 @@ export function start() {
         directives(el, attrs).forEach(handle => handle())
     })
 
-    let outNestedComponents = el => ! closestRoot(el.parentElement)
+    let outNestedComponents = el => ! closestRoot(el.parentElement, true)
     Array.from(document.querySelectorAll(allSelectors()))
         .filter(outNestedComponents)
         .forEach(el => {
@@ -44,14 +44,16 @@ export function allSelectors() {
 export function addRootSelector(selectorCallback) { rootSelectorCallbacks.push(selectorCallback) }
 export function addInitSelector(selectorCallback) { initSelectorCallbacks.push(selectorCallback) }
 
-export function closestRoot(el) {
+export function closestRoot(el, includeInitSelectors = false) {
     if (!el) return
 
-    if (rootSelectors().some(selector => el.matches(selector))) return el
+    const selectors = includeInitSelectors ? allSelectors() : rootSelectors()
+
+    if (selectors.some(selector => el.matches(selector))) return el
 
     if (! el.parentElement) return
 
-    return closestRoot(el.parentElement)
+    return closestRoot(el.parentElement, includeInitSelectors)
 }
 
 export function isRoot(el) {

+ 9 - 2
tests/cypress/integration/directives/x-init.spec.js

@@ -9,7 +9,6 @@ test('sets text on init',
     ({ get }) => get('span').should(haveText('baz'))
 )
 
-
 test('x-init can be used outside of x-data',
     html`
         <div x-init="$el.textContent = 'foo'"></div>
@@ -17,7 +16,6 @@ test('x-init can be used outside of x-data',
     ({ get }) => get('div').should(haveText('foo'))
 )
 
-
 test('changes made in x-init happen before the rest of the component',
     html`
         <div x-data="{ foo: 'bar' }" x-init="$refs.foo.innerText = 'yo'">
@@ -44,3 +42,12 @@ test('x-init will not evaluate expression if it is empty',
     `,
     ({ get }) => get('span').should(haveText('bar'))
 )
+
+test('component nested into x-init without x-data are not initialised twice',
+    html`
+        <div x-init="$el.setAttribute('attribute', 'value')">
+            <p x-data="{foo: 'foo'}" x-init="$el.textContent += foo"></p>
+        </div>
+    `,
+    ({ get }) => get('p').should(haveText('foo'))
+)