{"id":19427986,"url":"https://github.com/hellof2e/gluang","last_synced_at":"2025-04-24T17:31:52.554Z","repository":{"id":203275331,"uuid":"665985260","full_name":"hellof2e/gluang","owner":"hellof2e","description":"Simple shared app state management for Quarkc.（Quarkc 全局状态管理工具）","archived":false,"fork":false,"pushed_at":"2023-12-19T07:20:51.000Z","size":201,"stargazers_count":9,"open_issues_count":0,"forks_count":1,"subscribers_count":4,"default_branch":"main","last_synced_at":"2025-04-14T15:49:50.781Z","etag":null,"topics":["gluang","quarkc","store","webcomponents"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"lgpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/hellof2e.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null}},"created_at":"2023-07-13T12:48:44.000Z","updated_at":"2024-03-29T08:19:03.000Z","dependencies_parsed_at":null,"dependency_job_id":"0e6c4e13-085d-401e-ad85-d49514b5bcb4","html_url":"https://github.com/hellof2e/gluang","commit_stats":null,"previous_names":["hellof2e/gluang"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hellof2e%2Fgluang","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hellof2e%2Fgluang/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hellof2e%2Fgluang/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hellof2e%2Fgluang/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/hellof2e","download_url":"https://codeload.github.com/hellof2e/gluang/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":250674392,"owners_count":21469214,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["gluang","quarkc","store","webcomponents"],"created_at":"2024-11-10T14:13:27.926Z","updated_at":"2025-04-24T17:31:52.264Z","avatar_url":"https://github.com/hellof2e.png","language":"TypeScript","readme":"# Gluang\n\n```gluang （音同：gluon /ˈɡluː ɒn/ 格鲁昂）[物理学] 胶子。用于链接夸克形成强子，构成基本粒子。```\n\n\u003e It also can be used in Lit.\n\n### Simple shared app state management for Quarkc.\n\nGluang automatically re-renders your Quarkc components, when a shared app\nstate variable they use changes. It's like Quarkc's\n[properties](https://quarkc.hellobike.com/#/zh-CN/docs/reactive), but\nthen shared over multiple components.\n\n\n## Installation\n\n```\nnpm install gluang\n```\n\n\n## Basic idea\n\nYou keep your shared state in a `Gluang` derived class. This class contains\n`stateVar` variables that contain the state. This class can also contain helper\nfunctions that modify the state. Decorate your `Quarkc` classes with the\n`connectStore()` mixin. This makes your components automatically re-render\nwhenever a `stateVar` they use changes.\n\n\n## Usage\n\n### 1. Create a `Gluang` object:\n\n```javascript\n// my-store.js\n\nimport { createGluang, stateVar } from 'gluang';\n\nclass MyState extends createGluang {\n    static get stateVars() {\n        return {\n            counter: 0\n        };\n    }\n}\n\nexport const myState = new MyState();\n```\n\n### 2. Make your component aware of your state:\n\nBy using the `connectStore()` mixin on your `Quarkc component` class and then just\nusing the `stateVar` variables in your render method:\n\n```javascript\n// my-components\n\nimport { QuarkElement, customElement } from \"quarkc\";\nimport { connectStore } from 'gluang';\nimport { myState } from './my-state.js';\n\n@customElement({ tag: \"my-component\"})\nclass MyComponent extends connectStore(QuarkElement) {\n\n    render() {\n        return (\n            \u003ch1\u003eCounter: {myState.counter}\u003c/h1\u003e\n            \u003cbutton onClick={() =\u003e myState.counter++}\u003e\u003c/button\u003e\n        )\n    }\n\n}\n```\n\nThe components that read `myState.counter` will automatically re-render when\nany (other) component updates it.\n\nIn more technical words:\n\nA component using the `connectStore()` mixin will re-render when any\n`stateVar` - which it read in the last render cycle - changes.\n\n\n## Docs\n\nFor more information about how to use Gluang, check the\n\nTODO: [docs](https://TODO).\n\n\n## How does this work?\n\n\n### Basics\n\nWhen you define a `stateVar` variable, Gluang will observe those variables\nwhenever they're get or set. When using the `connectStore()` mixin on a\ncomponent, during the render of that component, there is a recorder active that\nrecords any `stateVar` that is accessed during the render of that component. At\nthe end of the render, the recorded `stateVar` variables are collected and\nwhenever one of them changes, the component will be re-rendered. If the\nre-render uses different `stateVar` variables, they are again recorded and\nobserved for possible rerenders.\n\n\n### Implementation details\n\nTo re-render the component, the `connectStore()` mixin calls Quarkc's\n`this.update()`. This will enqueue an update request for the component. The\ncomponent will re-render at the end of the execution queue.\n`this.update()` can be called multiple times during a particular\nJavaScript event (like a click), and it will only update the component once, at\nthe end of the execution queue. So it doesn't matter when it is called multiple\ntimes when multiple `stateVar` variables are changed during a JavaScript event.\nThis is an optimization feature built-in in Quarkc. Quarkc uses this\noptimization for it's own\n[properties](https://quarkc.hellobike.com/#/zh-CN/docs/reactive). This\noptimization works in the same way for Gluang's `stateVar` variables.\n\n\n## Notes\n\n### You can create and use multiple `Gluang` classes at the same time.\n\nIt is even encouraged to keep things separate. You can of course have one big\n`Gluang` derived class which contains all global app state variables. But it\nis probably cleaner if you categorize it into multiple smaller `Gluang`\nderived classes. For example, you can put each state class in a separate file,\ncollected in a `state/` folder, and import them at the places you need.\n\n\n### You can nest states\n\nIf your state requires more hierarchy, you can also nest states. It doesn't\nmatter to your components how your state is structured, as long as it uses the\ncorrect references to your `stateVar` variables. Refer to the\n[docs](TODO: #state-handling/nested-states/)\nfor more information about nesting states.\n\n\n### Only new assigns trigger a re-render. Updating an object/array won't trigger a re-render.\n\nJust like Quarkc's\n[properties](https://quarkc.hellobike.com/#/zh-CN/docs/reactive), only a\nnew assign of the `stateVar` triggers a re-render. For example if you have a\nstate like this:\n\n```javascript\nMyState extends Gluang {\n    @stateVar() myObj = {myKey: 'myValue'};\n    @stateVar() myArray = ['one', 'two', 'three'];\n}\n```\n\nThen this won't trigger a re-render:\n\n```javascript\nmyState = new MyState();\nmyState.myObj.mykey = 'newValue';\nmyState.myArray.push('four');\n```\n\nYou'll instead need to assign a new object to the `stateVar`:\n\n```javascript\nmyState.myObj = {...myState.myObj, myKey: 'newValue'};\nmyState.myArray = [...myState.myArray, 'four'];\n```\n\nWatching for changes inside objects is very complex matter and would make\nGluang way more complicated than desirable. If you are interested in this\nkind of thing, check out\n[observable-slim](https://github.com/ElliotNB/observable-slim).\n\n\n## Extra features\n\n### Custom `stateVar` variables\n\nYou can easily extend Gluang with a custom `stateVar` handler. An example of\nthis is the [asyncStateVar](TODO: async-state-var),\nwhich is a `stateVar` variation that makes handling with asynchronous data\neasy. To make a custom `stateVar` yourself, create a class that extends from\n`StateVar`, exported by Gluang.\n[Check out the documentation on this.](TODO: #advanced-usage/state-var-handler/)\n\n\n## FAQ\n\n\n### Why should I use shared state for my components? Doesn't that oppose the concept of web components?\n\nThe big feature of web components is that they are encapsulated through the\n[Shadow DOM](https://developer.mozilla.org/en-US/docs/Web/Web_Components/Using_shadow_DOM).\nThat means that their internal state isn't affected by state from the outside.\nAnd also that the component's internal state doesn't affect other elements on\nthe page. This makes web components great for creating reusable elements.\nReusable elements should have no side-effects, meaning that they shouldn't\nchange state outside of themselves.\n\nReusable elements are great and we should use them a lot. When you're building\na full application however, it is also desirable to have application-specific\ncomponents that have application-specific side-effects. For example, changing\nthe global app state. And it is of course desirable, that when this global app\nstate changes, the components that use this global app state are synchronized\nwith it.\n\nAnd you can also have a reusable component that has several internal\nsub-components. They all might need to share some common internal state.\n\nGluang is created for these use cases, and is meant to make it as simple as\npossible for the developer.\n\n\n## Notes\n\nGluang is fork from [lit-state](https://github.com/gitaarik/lit-state) and I rewrote it to work with Quarkc.\n\n###### Changes in this fork\n- Renamed to Gluang - so you can use npx gluang directly.\n- Add `this.update()` in connectStore in order to it can work with quarkc.\n- Remove connectedCallback，disconnectedCallback function in observerState(connectStore),\nBecause there is no these functions in Quarkc.\n- Renamed some functions' name. Also made some changes to the readme.\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhellof2e%2Fgluang","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fhellof2e%2Fgluang","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhellof2e%2Fgluang/lists"}