瀏覽代碼

Merge pull request #479 from jonaskuske/$el-in-x-data

Expose $el in x-data
Caleb Porzio 5 年之前
父節點
當前提交
b3b4255ad7
共有 4 個文件被更改,包括 48 次插入2 次删除
  1. 2 0
      README.md
  2. 2 2
      src/component.js
  3. 32 0
      test/constructor.spec.js
  4. 12 0
      test/data.spec.js

+ 2 - 0
README.md

@@ -536,6 +536,8 @@ These behave exactly like VueJs's transition directives, except they have differ
 
 ### Magic Properties
 
+> With the exception of `$el`, magic properties are **not available within `x-data`** as the component isn't initialized yet.
+
 ---
 
 ### `$el`

+ 2 - 2
src/component.js

@@ -17,7 +17,7 @@ export default class Component {
         const dataExpression = dataAttr === '' ? '{}' : dataAttr
         const initExpression = this.$el.getAttribute('x-init')
 
-        this.unobservedData = seedDataForCloning ? seedDataForCloning : saferEval(dataExpression, {})
+        this.unobservedData = seedDataForCloning ? seedDataForCloning : saferEval(dataExpression, { $el: this.$el })
 
         /* IE11-ONLY:START */
             // For IE11, add our magic properties to the original data for access.
@@ -340,7 +340,7 @@ export default class Component {
                 if (! (closestParentComponent && closestParentComponent.isSameNode(this.$el))) continue
 
                 if (mutations[i].type === 'attributes' && mutations[i].attributeName === 'x-data') {
-                    const rawData = saferEval(mutations[i].target.getAttribute('x-data'), {})
+                    const rawData = saferEval(mutations[i].target.getAttribute('x-data'), { $el: this.$el })
 
                     Object.keys(rawData).forEach(key => {
                         if (this.$data[key] !== rawData[key]) {

+ 32 - 0
test/constructor.spec.js

@@ -279,6 +279,38 @@ test('auto-detect x-data property changes at run-time', async () => {
     await wait(() => { expect(document.querySelector('span').innerText).toEqual(1) })
 })
 
+test('can use $el when changing x-data property at run-time', async () => {
+    var runObservers = []
+
+    global.MutationObserver = class {
+        constructor(callback) { runObservers.push(callback) }
+        observe() {}
+    }
+
+    document.body.innerHTML = `
+        <div x-data="{ count: '0' }" data-count="1">
+            <span x-text="count"></span>
+        </div>
+    `
+
+    Alpine.start()
+
+    expect(document.querySelector('span').innerText).toEqual('0')
+
+    document.querySelector('div').setAttribute('x-data', '{ count: $el.dataset.count }')
+
+    runObservers[0]([
+        {
+            addedNodes: [],
+            type: 'attributes',
+            attributeName: 'x-data',
+            target: document.querySelector('div')
+        }
+    ])
+
+    await wait(() => { expect(document.querySelector('span').innerText).toEqual('1') })
+})
+
 test('nested components only get registered once on initialization', async () => {
     global.MutationObserver = class {
         constructor(callback) {}

+ 12 - 0
test/data.spec.js

@@ -48,6 +48,18 @@ test('x-data can use attributes from a reusable function', async () => {
     expect(document.querySelector('span').innerText).toEqual('bar')
 })
 
+test('x-data can use $el', async () => {
+    document.body.innerHTML = `
+        <div x-data="{ text: $el.dataset.text }" data-text="test">
+          <span x-text="text"></span>
+        </div>
+    `
+
+    Alpine.start()
+
+    expect(document.querySelector('span').innerText).toEqual('test')
+})
+
 test('functions in x-data are reactive', async () => {
     document.body.innerHTML = `
         <div x-data="{ foo: 'bar', getFoo() {return this.foo}}">