فهرست منبع

feature(fluent access for store props)

Ryan Chandler 5 سال پیش
والد
کامیت
4c56ad1533
6فایلهای تغییر یافته به همراه115 افزوده شده و 1 حذف شده
  1. 17 0
      examples/index.html
  2. 2 1
      package.json
  3. 53 0
      src/index.js
  4. 19 0
      src/observable.js
  5. 19 0
      src/utils.js
  6. 5 0
      yarn.lock

+ 17 - 0
examples/index.html

@@ -0,0 +1,17 @@
+<html>
+    <head>
+        <script src="../dist/spruce.umd.js"></script>
+        <script src="https://cdn.jsdelivr.net/gh/alpinejs/alpine@v2.x.x/dist/alpine.min.js"></script>
+    </head>
+    <body>
+        <div x-data x-subscribe>
+            <input type="text" x-model="$store.dropdown.hello">
+            <span x-text="$store.dropdown.hello"></span>
+        </div>
+        <script>
+            Spruce.store('dropdown', {
+                hello: 'world'
+            })
+        </script>
+    </body>
+</html>

+ 2 - 1
package.json

@@ -17,6 +17,7 @@
         "watch": "microbundle watch"
     },
     "devDependencies": {
-        "microbundle": "^0.11.0"
+        "microbundle": "^0.11.0",
+        "observable-membrane": "^0.26.1"
     }
 }

+ 53 - 0
src/index.js

@@ -0,0 +1,53 @@
+import { domReady, buildInitExpression } from './utils'
+import { create } from './observable'
+
+const Spruce = {
+
+    stores: {},
+
+    subscribers: [],
+
+    start: async function () {
+        await domReady()
+
+        document.querySelectorAll('[x-subscribe]').forEach(el => {
+            el.setAttribute('x-init', buildInitExpression(el))
+            el.removeAttribute('x-subscribe')
+        })
+
+        this.stores = create(this.stores, (key, value) => {
+            this.updateSubscribers(key, value)
+        })
+    },
+
+    store: function (name, state = {}) {
+        if (! this.stores[name]) {
+            this.stores[name] = state
+        }
+    },
+
+    subscribe(el) {
+        this.subscribers.push(el)
+
+        return this.stores
+    },
+
+    updateSubscribers(key, value) {
+        this.subscribers.forEach(el => {
+            if (el.__x !== 'undefined') {
+                el.__x.$data.spruce = [key, value]
+            }
+        })
+    }
+}
+
+const deferrer = window.deferLoadingAlpine || function (callback) { callback() }
+
+window.deferLoadingAlpine = function (callback) {
+    window.Spruce = Spruce
+    window.Spruce.start()
+
+    deferrer(callback)
+}
+
+export default Spruce

+ 19 - 0
src/observable.js

@@ -0,0 +1,19 @@
+export const create = (target, callback) => {
+    Object.keys(target).forEach(key => {
+        if (Object.getPrototypeOf(target[key]) === Object.prototype) {
+            target[key] = create(target[key], callback)
+        }
+    })
+
+    return new Proxy(target, {
+        set(target, key, value) {
+            if (typeof value === 'object') {
+                value = create(value, callback)
+            }
+
+            callback(key, target[key] = value)
+
+            return true
+        }
+    })
+}

+ 19 - 0
src/utils.js

@@ -0,0 +1,19 @@
+export const domReady = () => {
+    return new Promise(resolve => {
+        if (document.readyState == "loading") {
+            document.addEventListener("DOMContentLoaded", resolve)
+        } else {
+            resolve()
+        }
+    })
+}
+
+export const buildInitExpression = el => {
+    let expression = "$store = Spruce.subscribe($el)"
+
+    if (el.hasAttribute('x-init')) {
+        expression = `${expression}; ${el.getAttribute('x-init')}`
+    }
+
+    return expression
+}

+ 5 - 0
yarn.lock

@@ -1970,6 +1970,11 @@ object.values@^1.1.0:
     function-bind "^1.1.1"
     has "^1.0.3"
 
+observable-membrane@^0.26.1:
+  version "0.26.1"
+  resolved "https://registry.yarnpkg.com/observable-membrane/-/observable-membrane-0.26.1.tgz#5619a7b2f4b0414d62b3e6cc2ea65734a08cce7a"
+  integrity sha512-fBxLHtd0pUFI/rKh6Dfn9fxjEgY4NkRIqlPEKa9fR28rC9CQDfQ5P+t292CtAArtXOQ1mF8Nq9m1cF52IdN8DA==
+
 once@^1.3.1, once@^1.4.0:
   version "1.4.0"
   resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1"