Caleb Porzio 5 年之前
父節點
當前提交
aec5580046
共有 4 個文件被更改,包括 45 次插入9 次删除
  1. 20 5
      dist/alpine.js
  2. 13 3
      src/component.js
  3. 4 1
      src/directives/bind.js
  4. 8 0
      src/index.js

+ 20 - 5
dist/alpine.js

@@ -606,8 +606,9 @@
     var value = component.evaluateReturnExpression(el, expression, extraVars);
 
     if (attrName === 'value') {
-      // If nested model key is undefined, set the default value to empty string.
-      if (value === undefined && expression.match(/\./).length) {
+      if (Alpine.ignoreFocusedForValueBinding && document.activeElement.isSameNode(el)) return; // If nested model key is undefined, set the default value to empty string.
+
+      if (value === undefined && expression.match(/\./)) {
         value = '';
       }
 
@@ -1374,9 +1375,18 @@
       const dataAttr = this.$el.getAttribute('x-data');
       const dataExpression = dataAttr === '' ? '{}' : dataAttr;
       const initExpression = this.$el.getAttribute('x-init');
-      this.unobservedData = componentForClone ? componentForClone.getUnobservedData() : saferEval(dataExpression, {
+      let dataExtras = {
         $el: this.$el
+      };
+      let canonicalComponentElementReference = componentForClone ? componentForClone.$el : this.$el;
+      Object.entries(Alpine.magicProperties).forEach(([name, callback]) => {
+        Object.defineProperty(dataExtras, `$${name}`, {
+          get: function get() {
+            return callback(canonicalComponentElementReference);
+          }
+        });
       });
+      this.unobservedData = componentForClone ? componentForClone.getUnobservedData() : saferEval(dataExpression, dataExtras);
       // Construct a Proxy-based observable. This will be used to handle reactivity.
 
       let {
@@ -1400,9 +1410,8 @@
       this.unobservedData.$watch = (property, callback) => {
         if (!this.watchers[property]) this.watchers[property] = [];
         this.watchers[property].push(callback);
-      };
+      }; // Register custom magic properties.
 
-      let canonicalComponentElementReference = componentForClone ? componentForClone.$el : this.$el; // Register custom magic properties.
 
       Object.entries(Alpine.magicProperties).forEach(([name, callback]) => {
         Object.defineProperty(this.unobservedData, `$${name}`, {
@@ -1413,6 +1422,7 @@
       });
       this.showDirectiveStack = [];
       this.showDirectiveLastElement;
+      componentForClone || Alpine.onBeforeComponentInitializeds.forEach(callback => callback(this));
       var initReturnedCallback; // If x-init is present AND we aren't cloning (skip x-init on clone)
 
       if (initExpression && !componentForClone) {
@@ -1747,6 +1757,8 @@
     pauseMutationObserver: false,
     magicProperties: {},
     onComponentInitializeds: [],
+    onBeforeComponentInitializeds: [],
+    ignoreFocusedForValueBinding: false,
     start: async function start() {
       if (!isTesting()) {
         await domReady();
@@ -1828,6 +1840,9 @@
     },
     onComponentInitialized: function onComponentInitialized(callback) {
       this.onComponentInitializeds.push(callback);
+    },
+    onBeforeComponentInitialized: function onBeforeComponentInitialized(callback) {
+      this.onBeforeComponentInitializeds.push(callback);
     }
   };
 

+ 13 - 3
src/component.js

@@ -18,7 +18,17 @@ export default class Component {
         const dataExpression = dataAttr === '' ? '{}' : dataAttr
         const initExpression = this.$el.getAttribute('x-init')
 
-        this.unobservedData = componentForClone ? componentForClone.getUnobservedData() : saferEval(dataExpression, { $el: this.$el })
+        let dataExtras = {
+            $el: this.$el,
+        }
+
+        let canonicalComponentElementReference = componentForClone ? componentForClone.$el : this.$el
+
+        Object.entries(Alpine.magicProperties).forEach(([name, callback]) => {
+            Object.defineProperty(dataExtras, `$${name}`, { get: function () { return callback(canonicalComponentElementReference) } });
+        })
+
+        this.unobservedData = componentForClone ? componentForClone.getUnobservedData() : saferEval(dataExpression, dataExtras)
 
         /* IE11-ONLY:START */
             // For IE11, add our magic properties to the original data for access.
@@ -54,8 +64,6 @@ export default class Component {
             this.watchers[property].push(callback)
         }
 
-        let canonicalComponentElementReference = componentForClone ? componentForClone.$el : this.$el
-
         // Register custom magic properties.
         Object.entries(Alpine.magicProperties).forEach(([name, callback]) => {
             Object.defineProperty(this.unobservedData, `$${name}`, { get: function () { return callback(canonicalComponentElementReference) } });
@@ -64,6 +72,8 @@ export default class Component {
         this.showDirectiveStack = []
         this.showDirectiveLastElement
 
+        componentForClone || Alpine.onBeforeComponentInitializeds.forEach(callback => callback(this))
+
         var initReturnedCallback
         // If x-init is present AND we aren't cloning (skip x-init on clone)
         if (initExpression && ! componentForClone) {

+ 4 - 1
src/directives/bind.js

@@ -1,11 +1,14 @@
 import { arrayUnique, isBooleanAttr, convertClassStringToArray, camelCase } from '../utils'
+import Alpine from '../index'
 
 export function handleAttributeBindingDirective(component, el, attrName, expression, extraVars, attrType, modifiers) {
     var value = component.evaluateReturnExpression(el, expression, extraVars)
 
     if (attrName === 'value') {
+        if (Alpine.ignoreFocusedForValueBinding && document.activeElement.isSameNode(el)) return
+
         // If nested model key is undefined, set the default value to empty string.
-        if (value === undefined && expression.match(/\./).length) {
+        if (value === undefined && expression.match(/\./)) {
             value = ''
         }
 

+ 8 - 0
src/index.js

@@ -10,6 +10,10 @@ const Alpine = {
 
     onComponentInitializeds: [],
 
+    onBeforeComponentInitializeds: [],
+
+    ignoreFocusedForValueBinding: false,
+
     start: async function () {
         if (! isTesting()) {
             await domReady()
@@ -109,6 +113,10 @@ const Alpine = {
 
     onComponentInitialized: function (callback) {
         this.onComponentInitializeds.push(callback)
+    },
+
+    onBeforeComponentInitialized: function (callback) {
+        this.onBeforeComponentInitializeds.push(callback)
     }
 }