New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

@pardnchiu/quickui

Package Overview
Dependencies
Maintainers
0
Versions
9
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@pardnchiu/quickui - npm Package Compare versions

Comparing version 0.6.2 to 0.6.3

8

package.json
{
"name": "@pardnchiu/quickui",
"version": "0.6.2",
"version": "0.6.3",
"description": "A web frontend framework that supports conditional and loop rendering, data binding, monitoring data changes, and automatic rendering. Previously known as QuickUI.",

@@ -29,8 +29,8 @@ "main": "dist/QuickUI.js",

"front-end-framework",
"quickui",
"UI-framework",
"data-binding",
"virtual-DOM",
"loop-rendering",
"conditional-rendering"
"conditional-rendering",
"邱敬幃",
"pardnchiu"
],

@@ -37,0 +37,0 @@ "author": {

@@ -1,7 +0,10 @@

<img src="./dist/logo.png" width=80>
<img src="https://quickui.pardn.io/static/image/logo.png" width=80>
# QuickUI
# QuickUI: Lightweight Frontend Framework
(Formerly known as PDQuickUI, renamed to QuickUI starting from version `0.6.0`)
> [!NOTE]
> (Formerly known as PDQuickUI, renamed to QuickUI starting from version `0.6.0`)
> QuickUI is a front-end rendering framework built with pure JavaScript. By integrating virtual DOM technology, it enhances rendering performance, achieving rapid data responsiveness and automatic updates.
![tag](https://img.shields.io/badge/tag-JavaScript%20Library-bb4444)

@@ -14,817 +17,162 @@ ![size](https://img.shields.io/github/size/pardnchiu/QuickUI/dist%2FQuickUI.js)<br>

`QuickUI` is a front-end rendering framework derived from [PDRenderKit](https://github.com/pardnchiu/PDRenderKit), focusing on enhancing front-end framework features.<br>
By integrating a virtual DOM, it rewrites the rendering logic to improve rendering efficiency, enabling faster data observation and automatic updates.<br>
This project removes the `prototype` extensions from `PDRenderKit` to ensure compatibility and performance, making it suitable for complex applications.<br>
It provides both `module` and non-`module` versions and changes the license from `GPL-3.0` in `PDRenderKit` to `MIT`.
## Features
- **Clear Architecture**: Separates UI from data logic, making it easier to maintain.
- **Code Simplicity**: Reduces redundant code and enhances readability.
- **Automatic Rendering**: Monitors data changes and updates automatically, minimizing manual operations.
- **Lightweight**: Maintains full functionality within a file size of less than `20kb`.
### Efficient Virtual DOM
- Precise diffing algorithm for efficient DOM updates
- Smart attribute patching system that updates only changed values
- Intelligent child node comparison for minimal DOM manipulation
## Installation
### Reactive Data Handling
- Deep data monitoring system for immediate state tracking
- Automatic UI updates on data changes, no manual operation needed
- Smart caching system to prevent unnecessary re-renders
- Support for nested data structures with reactive handling
- **Install from npm**
```bash
npm i @pardnchiu/quickui
```
- **Include from CDN**
- **Directly include `QuickUI`**
```html
<!-- Version 0.6.0 and above -->
<script src="https://cdn.jsdelivr.net/npm/@pardnchiu/quickui@[VERSION]/dist/QuickUI.js"></script>
### Advanced Template Features
- Built-in internationalization (i18n) support for easy localization
- Dynamic template loading with asynchronous processing
- Powerful expression system supporting calculations, dates, and text processing
- Comprehensive directive system for flexible DOM manipulation
<!-- Version 0.5.4 and below -->
<script src="https://cdn.jsdelivr.net/npm/pdquickui@[VERSION]/dist/PDQuickUI.js"></script>
```
- **Module Version**
```javascript
// Version 0.6.0 and above
import { QUI } from "https://cdn.jsdelivr.net/npm/@pardnchiu/quickui@[VERSION]/dist/QuickUI.esm.js";
// Version 0.5.4 and below
import { QUI } from "https://cdn.jsdelivr.net/npm/pdquickui@[VERSION]/dist/PDQuickUI.module.js";
```
### Performance Optimizations
- Lazy loading for images and SVG content to improve load times
- Minimal file size with zero external dependencies
- Smart event delegation and resource cleanup for optimized memory usage
## Usage
## Documentation
- Initialize `QUI`
```Javascript
const app = new QUI({
id: "", // Specify rendering element
data: {
// Custom DATA
},
event: {
// Custom EVENT
},
when: {
before_render: function () {
// Stop rendering
},
rendered: function () {
// Rendered
},
before_update: function () {
// Stop updating
},
updated: function () {
// Updated
},
before_destroy: function () {
// Stop destruction
},
destroyed: function () {
// Destroyed
}
}
});
```
- Website: [quickui.pardn.io](https://quickui.pardn.io)
- Documentation: [quickui.pardn.io/doc.html](https://quickui.pardn.io/doc.html)
## Overview
Automatic Rendering: Automatically reloads when data changes are detected.
## Installation
<details>
<summary>Attributes Overview</summary>
### Install via npm
```bash
npm i @pardnchiu/quickui
```
| Attribute | Description |
| --- | --- |
| `{{value}}` | Inserts text into HTML tags and automatically updates with data changes. |
| `:path` | Used with the `temp` tag to load HTML fragments from external files into the current page. |
| `:html` | Replaces the element's `innerHTML` with text. |
| `:for` | Supports formats like `item in items`, `(item, index) in items`, `(key, value) in object`. Iterates over data collections to generate corresponding HTML elements. |
| `:if`<br>`:else-if`<br>`:elif`<br>`:else` | Displays or hides elements based on specified conditions, enabling branching logic. |
| `:model` | Binds data to form elements (e.g., `input`), updating data automatically when input changes. |
| `:hide` | Hides elements based on specific conditions. |
| `:animation` | Specifies transition effects for elements, such as `fade-in` or `expand`, to enhance user experience. |
| `:mask` | Controls block loading animations, supporting `true\|false\|1\|0`, to enhance dynamic visual effects during loading. |
| `:[attr]` | Sets element attributes, such as `ID`, `class`, image source, etc.<br>Examples: `:id`/`:class`/`:src`/`:alt`/`:href`... |
| `:[css]` | Sets element CSS, such as margin, padding, etc. Examples: `:background-color`, `:opacity`, `:margin`, `:top`, `:position`... |
| `@[event]` | Adds event listeners that trigger specified actions upon activation.<br>Examples: `@click`/`@input`/`@mousedown`... |
### Include via CDN
</details>
#### Include the `QuickUI` library
```html
<!-- Version 0.6.0 and above -->
<script src="https://cdn.jsdelivr.net/npm/@pardnchiu/quickui@[VERSION]/dist/QuickUI.js"></script>
<details>
<summary>Text Replacement</summary>
<!-- Version 0.5.4 and below -->
<script src="https://cdn.jsdelivr.net/npm/pdquickui@[VERSION]/dist/PDQuickUI.js"></script>
```
### `{{value}}`
#### Module version
```javascript
// Version 0.6.0 and above
import { QUI } from "https://cdn.jsdelivr.net/npm/@pardnchiu/quickui@[VERSION]/dist/QuickUI.esm.js";
- index.html
```HTML
<h1>{{ title }}</h1>
<script>
const app = new QUI({
id: "app",
data: {
title: "test"
}
});
</script>
```
- Result
```HTML
<body id="app">
<h1>test</h1>
</body>
```
// Version 0.5.4 and below
import { QUI } from "https://cdn.jsdelivr.net/npm/pdquickui@[VERSION]/dist/PDQuickUI.module.js";
```
***
## How to use
### `:html`
- index.html
```HTML
<section :html="html"></section>
<script>
const app = new QUI({
id: "app",
data: {
html: "<b>innerHtml</b>"
}
});
</script>
```
- Result
```HTML
<body id="app">
<section>
<b>innerHtml</b>
</section>
</body>
```
</details>
<details>
<summary>Insert Block</summary>
> [!NOTE]
> Ensure to disable local file restrictions in your browser or use a live server when testing.
### `:path`
- test.html
```html
<h1>path heading</h1>
<p>path content</p>
```
- index.html
```html
<body id="app">
<temp :path="./test.html"></temp>
</body>
<script>
const app = new QUI({
id: "app"
});
</script>
```
- Result
```html
<body id="app">
<!-- Directly inserted PATH content -->
<h1>path heading</h1>
<p>path content</p>
</body>
```
</details>
<details>
<summary>Loop Rendering</summary>
### `:for`
- index.html
```html
<body id="app">
<ul>
<li :for="(item, index) in ary" :id="item" :index="index">{{ item }} {{ CALC(index + 1) }}</li>
</ul>
</body>
<script>
const app = new QUI({
id: "app",
data: {
ary: ["test1", "test2", "test3"]
}
});
</script>
```
- Result
```html
<body id="app">
<li id="test1" index="0">test1 1</li>
<li id="test2" index="1">test2 2</li>
<li id="test3" index="2">test3 3</li>
</body>
```
***
### 巢狀迴圈
- index.html
```html
<body id="app">
<ul>
<li :for="(key, val) in obj">
{{ key }}: {{ val.name }}
<ul>
<li :for="item in val.ary">
{{ item.name }}
<ul>
<li :for="(item1, index1) in item.ary1">
{{ CALC(index1 + 1) }}. {{ item1.name }} - ${{ item1.price }}
</li>
</ul>
</li>
</ul>
</li>
</ul>
</body>
<script>
const app = new QUI({
id: "app",
data: {
obj: {
food: {
name: "Food",
ary: [
{
name: 'Snacks',
ary1: [
{ name: 'Potato Chips', price: 10 },
{ name: 'Chocolate', price: 8 }
]
},
{
name: 'Beverages',
ary1: [
{ name: 'Juice', price: 5 },
{ name: 'Tea', price: 3 }
]
}
]
},
home: {
name: 'Home',
ary: [
{
name: 'Furniture',
ary1: [
{ name: 'Sofa', price: 300 },
{ name: 'Table', price: 150 }
]
},
{
name: 'Decorations',
ary1: [
{ name: 'Picture Frame', price: 20 },
{ name: 'Vase', price: 15 }
]
}
]
}
}
}
});
</script>
```
- Result
```html
<body id="app">
<ul>
<li>food: Food
<ul>
<li>Snacks
<ul>
<li>1. Potato Chips - $10</li>
<li>2. Chocolate - $8</li>
</ul>
</li>
<li>Beverages
<ul>
<li>1. Juice - $5</li>
<li>2. Tea - $3</li>
</ul>
</li>
</ul>
</li>
<li>home: Home
<ul>
<li>Furniture
<ul>
<li>1. Sofa - $300</li>
<li>2. Table - $150</li>
</ul>
</li>
<li>Decorations
<ul>
<li>1. Picture Frame - $20</li>
<li>2. Vase - $15</li>
</ul>
</li>
</ul>
</li>
</ul>
</body>
```
</details>
<details>
<summary>Conditional Rendering</summary>
- index.html
```html
<body id="app">
<h1 :if="heading == 1">{{ title }} {{ heading }}</h1>
<h2 :else-if="isH2">{{ title }} {{ heading }}</h2>
<h3 :else-if="heading == 3">{{ title }} {{ heading }}</h3>
<h4 :else>{{ title }} {{ heading }}</h4>
</body>
<script>
const app = new QUI({
id: "app",
data: {
heading: [Number|null],
isH2: [Boolean|null],
title: "test"
}
});
</script>
```
- Result: `heading = 1`
```html
<body id="app">
<h1>test 1</h1>
</body>
```
- Result: `heading = null && isH2 = true`
```html
<body id="app">
<h2>test </h2>
</body>
```
- Result: `heading = 3 && isH2 = null`
```html
<body id="app">
<h3>test 3</h3>
</body>
```
- Result: `heading = null && isH2 = null`
```html
<body id="app">
<h4>test </h4>
</body>
```
</details>
<details>
<summary>Template Rendering</summary>
- index.html
```HTML
<body id="app"></body>
<script>
const test = new QUI({
id: "app",
data: {
hint: "hint 123",
title: "test 123"
},
render: () => {
return `
"{{ hint }}",
h1 {
style: "background: red;",
children: [
"{{ title }}"
]
}`
}
})
</script>
```
- result
```HTML
<body id="app">
hint 123
<h1 style="background: red;">test 123</h1>
</body>
```
</details>
<details>
<summary>Binding</summary>
```html
<body id="app">
<input type="password" :model="password">
<button @click="show">test</button>
</body>
<script>
const app = new QUI({
id: "app",
data: {
password: null,
### Initialize `QUI`
```Javascript
const app = new QUI({
id: "", // Specify rendering element
data: {
// Custom DATA
},
event: {
// Custom EVENT
},
when: {
before_render: function () {
// Stop rendering
},
event: {
show: function(e){
alert("Password:", app.data.password);
}
rendered: function () {
// Rendered
},
before_update: function () {
// Stop updating
},
updated: function () {
// Updated
},
before_destroy: function () {
// Stop destruction
},
destroyed: function () {
// Destroyed
}
});
</script>
}
});
```
</details>
<details>
<summary>Event</summary>
## Overview
```html
<body id="app">
<button @click="test">test</button>
</body>
<script>
const app = new QUI({
id: "app",
event: {
test: function(e){
alert(e.target.innerText + " clicked");
}
}
});
</script>
```
</details>
### Text & Content
| Attribute | Use Case | Example |
|-----------|----------|---------|
| `{{value}}` | Dynamic text content | `<p>{{ userName }}</p>` displays user's name |
| `:html` | Raw HTML insertion | `<div :html="richContent"></div>` renders formatted content |
<details>
<summary>CSS</summary>
### Template Loading
| Attribute | Use Case | Example |
|-----------|----------|---------|
| `:path` | External template loading | `<temp :path="./templates/header.html"></temp>` loads header component |
> [!NOTE]
> Supports simple settings using :[CSS property], directly binding data to style attributes.
### List & Iteration
| Attribute | Use Case | Example |
|-----------|----------|---------|
| `:for` | Array/Object iteration | `<li :for="item in items">{{ item.name }}</li>` renders list items |
- index.html
```html
<body id="app">
<button :width="width" :backdround-color="color">test</button>
</body>
<script>
const app = new QUI({
id: "app",
data: {
width: "100px",
color: "red"
}
});
</script>
```
- Result:
```html
<body id="app">
<button style="width: 100px; backdround-color: red;">test</button>
</body>
```
### Conditional Rendering
| Attribute | Use Case | Example |
|-----------|----------|---------|
| `:if` | Conditional display | `<div :if="isLoggedIn">Welcome!</div>` |
| `:else-if`/`:elif` | Secondary conditions | `<div :elif="isPending">Loading...</div>` |
| `:else` | Fallback content | `<div :else>Please log in</div>` |
</details>
### Form Binding
| Attribute | Use Case | Example |
|-----------|----------|---------|
| `:model` | Two-way data binding | `<input :model="userInput">` syncs with data |
<details>
<summary>Functions</summary>
### Styling & Animation
| Attribute | Use Case | Example |
|-----------|----------|---------|
| `:animation` | Transition effects | `<div :animation="fade-in">Content</div>` |
| `:[css]` | Dynamic styling | `<div :background-color="bgColor">Styled content</div>` |
### `LENGTH()`
### Dynamic Attributes
| Attribute | Use Case | Example |
|-----------|----------|---------|
| `:[attr]` | Dynamic attributes | `<img :src="imageUrl" :alt="imageDesc">` |
- index.html
```HTML
<body id="app">
<p>Total: {{ LENGTH(array) }}</p>
</body>
<script>
const app = new QUI({
id: "app",
data: {
array: [1, 2, 3, 4]
}
});
</script>
```
- result
```HTML
<body id="app">
<p>Total: 4</p>
</body>
```
### Event Handling
| Attribute | Use Case | Example |
|-----------|----------|---------|
| `@[event]` | Event listeners | `<button @click="handleClick">Click me</button>` |
***
## License
### `CALC()`
Similar to MIT License but provides obfuscated code only:
- Same as MIT: Free to use, modify and redistribute, including commercial use
- Main difference: Provides obfuscated code by default, source code available for purchase
- License terms: Must retain original copyright notice (same as MIT)
- index.html
```HTML
<body id="app">
<p>calc: {{ CALC(num * 10) }}</p>
</body>
<script>
const app = new QUI({
id: "app",
data: {
num: 1
}
});
</script>
```
- result
```HTML
<body id="app">
<p>calc: 10</p>
</body>
```
For detailed terms and conditions, please see the [Software Usage Agreement](https://github.com/pardnchiu/QuickUI/blob/main/LICENSE).
***
### `UPPER()` / `LOWER()`
- index.html
```HTML
<body id="app">
<p>{{ UPPER(test1) }} {{ LOWER(test2) }}</p>
</body>
<script>
const app = new QUI({
id: "app",
data: {
test1: "upper",
test2: "LOWER"
}
});
</script>
```
- result
```HTML
<body id="app">
<p>UPPER lower</p>
</body>
```
***
### `DATE(num, format)`
- index.html
```HTML
<body id="app">
<p>{{ DATE(now, YYYY-MM-DD hh:mm:ss) }}</p>
</body>
<script>
const app = new QUI({
id: "app",
data: {
now: Math.floor(Date.now() / 1000)
}
});
</script>
```
- result
```HTML
<body id="app">
<p>2024-08-17 03:40:47</p>
</body>
```
</details>
<details>
<summary>Lazyload</summary>
### `:lazyload`
- index.html
```html
<body id="app">
<img :lazyload="image">
</body>
<script>
const app = new QUI({
id: "app",
data: {
image: "test.jpg"
},
option: {
lazyload: true // Enable image lazy loading: true|false (default: true)
}
});
</script>
```
- result
```html
<body id="app">
<img src="test.jpg">
</body>
```
***
### `SVG` 替換
- test.svg
```XML
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<line x1="18" y1="6" x2="6" y2="18" stroke="black" stroke-width="2" stroke-linecap="round"/>
<line x1="6" y1="6" x2="18" y2="18" stroke="black" stroke-width="2" stroke-linecap="round"/>
</svg>
```
- index.html
```html
<body id="app">
<temp-svg :src="svg"></temp-svg>
</body>
<script>
const app = new QUI({
id: "app",
data: {
svg: "test.svg",
},
option: {
svg: true // Enable SVG file transformation: true|false (default: true)
}
});
</script>
```
- result
```html
<body id="app">
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<line x1="18" y1="6" x2="6" y2="18" stroke="black" stroke-width="2" stroke-linecap="round">
<line x1="6" y1="6" x2="18" y2="18" stroke="black" stroke-width="2" stroke-linecap="round">
</svg>
</body>
```
</details>
<details>
<summary>i18n</summary>
> [!NOTE]
> If the format is an object, the multilingual content is directly configured.
> If the format is a string, the language file is dynamically loaded via fetch.
- en.json
```JSON
{
"greeting": "Hello",
"username": "Username"
}
```
- index.html
```html
<body id="app">
<h1>{{ i18n.greeting }}, {{ i18n.username }}: {{ username }}</h1>
<button @click="change" data-lang="zh">切換至中文</button>
<button @click="change" data-lang="en">Switch to English</button>
</body>
<script>
const app = new QUI({
id: "app",
data: {
username: "Pardn"
},
i18n: {
zh: {
greeting: "你好",
username: "用戶名"
},
en: "en.json",
},
i18nLang: "zh | en", // Select the displayed language
event: {
change: e => {
const _this = e.target;
const lang = _this.dataset.lang;
app.lang(lang);
},
}
});
</script>
```
- result `i18nLang = zh`
```html
<body id="app">
<h1>你好, 用戶名: Pardn</h1>
<button data-lang="zh">切換至中文</button>
<button data-lang="en">Switch to English</button>
</body>
```
- result `i18nLang = en`
```html
<body id="app">
<h1>Hello, Username: Pardn</h1>
<button data-lang="zh">切換至中文</button>
<button data-lang="en">Switch to English</button>
</body>
```
</details>
<details>
<summary>Lifecycle Hooks</summary>
```html
<body id="app"></body>
<script>
const app = new QUI({
id: "app",
when: {
before_render: function () {
// Stop rendering
// retuen false
},
rendered: function () {
// Rendered
},
before_update: function () {
// Stop updating
// retuen false
},
updated: function () {
// Updated
},
before_destroy: function () {
// Stop destruction
// retuen false
},
destroyed: function () {
// Destroyed
}
}
});
</script>
```
</details>
<details>
<summary>Data Retrieval</summary>
```html
<body id="app">
<input type="text" :model="test">
<button @click="get">Test</button>
</body>
<script>
const app = new QUI({
id: "app",
data: {
// Value bound to the input
test: 123
},
event: {
get: _ => {
// Show an alert with the value of test on button click
alert(app.data.test);
},
set: _ => {
let dom = document.createElement("button");
// Assign the button click event to the get function
dom.onclick = app.event.get;
app.body.append(dom);
}
}
});
</script>
```
</details>
## Creator
<img src="https://avatars.githubusercontent.com/u/25631760" align="left" width="96" height="96" style="margin-right: 0.5rem;" />
<img src="https://avatars.githubusercontent.com/u/25631760" align="left" width="96" height="96" style="margin-right: 0.5rem;">
<h4 style="padding-top: 0">邱敬幃 Pardn Chiu</h4>
[![](https://pardn.io/image/mail.svg)](mailto:dev@pardn.io) [![](https://skillicons.dev/icons?i=linkedin)](https://linkedin.com/in/pardnchiu)
<a href="mailto:dev@pardn.io" target="_blank">
<img src="https://pardn.io/image/email.svg" width="48" height="48">
</a> <a href="https://linkedin.com/in/pardnchiu" target="_blank">
<img src="https://pardn.io/image/linkedin.svg" width="48" height="48">
</a>
## License
This project is licensed under a **Proprietary License**.
You may use, install, and run this software only under the terms specified in the [End-User License Agreement (EULA)](https://github.com/pardnchiu/QuickUI/blob/main/LICENSE).
## Obtain Complete Source Code
[Contact me](mailto:dev@pardn.io) for the complete unobfuscated source code.<br>
Feel free to modify and use for commercial purposes with the following licensing options:
- Must retain `Powered by @pardnchiu/quickui` copyright notice: $7,500.
- Fully autonomous, no copyright notice required: $10,000.
***
©️ 2024 [邱敬幃 Pardn Chiu](https://www.linkedin.com/in/pardnchiu)
©️ 2024 [邱敬幃 Pardn Chiu](https://pardn.io)

@@ -1,7 +0,10 @@

<img src="./dist/logo.png" width=80>
<img src="https://quickui.pardn.io/static/image/logo.png" width=80>
# QuickUI
# QuickUI: 輕量化前端框架
*(原名:PDQuickUI,自 `0.6.0` 版本起更名為 QuickUI)*
> [!NOTE]
> (原名:PDQuickUI,自 `0.6.0` 版本起更名為 QuickUI)
> QuickUI 是一個純 JavaScript 開發的前端渲染框架。通過整合虛擬 DOM 技術提升渲染效能,實現快速的數據響應和自動更新。
![tag](https://img.shields.io/badge/tag-JavaScript%20Library-bb4444)

@@ -14,816 +17,162 @@ ![size](https://img.shields.io/github/size/pardnchiu/QuickUI/dist%2FQuickUI.js)<br>

`QuickUI` 是從 [PDRenderKit](https://github.com/pardnchiu/PDRenderKit) 中獨立出來的前端渲染框架,專注於強化前端框架功能。<br>
透過引入虛擬 DOM 概念重寫渲染邏輯,提升渲染效能,並實現更高效的數據監聽和自動更新。<br>
## 核心特色
本專案移除了 `PDRenderKit` 中針對 `prototype` 的擴展,確保兼容性與效能,適合用於複雜的應用場景。<br>
提供 `module` 和非 `module` 版本,授權從 `PDRenderKit` 的 `GPL-3.0` 更改為 `MIT`。<br>
### 高效虛擬 DOM
- 透過精準的差異比對算法實現高效 DOM 更新
- 智慧屬性更新系統,只更新發生變化的值
- 智能子節點對比機制,最小化 DOM 操作
## 特點
### 響應式數據處理
- 深度數據監控系統,確保數據變更即時反映
- 數據變更時自動更新 UI,無需手動操作
- 智慧緩存系統避免不必要的重複渲染
- 支援巢狀數據結構的響應式處理
- **清晰的架構**:UI 和資料邏輯分離,維護方便。
- **代碼簡潔**:減少重複代碼,提升可讀性。
- **自動渲染**:監控資料變動並自動更新,減少手動操作。
- **輕量化**:使用原生 JS 和內建 API 撰寫,無任何外部依賴。
### 進階模板功能
- 內建多語系(i18n)支援,輕鬆實現國際化
- 支援動態載入模板並非同步處理
- 強大的表達式系統,支援計算、日期和文字處理
- 完整的指令系統實現靈活的 DOM 操作
## 安裝方式
### 效能優化設計
- 圖片和 SVG 內容採用懶加載技術,提升載入速度
- 極小的檔案體積且無外部依賴
- 智慧事件委派和資源清理機制,優化記憶體使用
- 從 npm 安裝
```bash
npm i @pardnchiu/quickui
```
## 文件
- 從 CDN 引入
- **引入 `QuickUI` 套件**
```html
<!-- Version 0.6.0 and above -->
<script src="https://cdn.jsdelivr.net/npm/@pardnchiu/quickui@[VERSION]/dist/QuickUI.js"></script>
- 網站: [nanomd.pardn.io](https://nanomd.pardn.io)
- 說明文件: [nanomd.pardn.io/doc.html](https://nanomd.pardn.io/doc.html)
<!-- Version 0.5.4 and below -->
<script src="https://cdn.jsdelivr.net/npm/pdquickui@[VERSION]/dist/PDQuickUI.js"></script>
```
- **Module 版本**
```javascript
// Version 0.6.0 and above
import { QUI } from "https://cdn.jsdelivr.net/npm/@pardnchiu/quickui@[VERSION]/dist/QuickUI.esm.js";
// Version 0.5.4 and below
import { QUI } from "https://cdn.jsdelivr.net/npm/pdquickui@[VERSION]/dist/PDQuickUI.module.js";
```
## 使用方法
## 安裝方式
- **初始化 `QUI`**
```Javascript
const app = new QUI({
id: "", // 指定渲染元素
data: {
// 自訂 DATA
},
event: {
// 自訂 EVENT
},
when: {
before_render: function () {
// 停止渲染
},
rendered: function () {
// 已渲染
},
before_update: function () {
// 停止更新
},
updated: function () {
// 已更新
},
before_destroy: function () {
// 停止銷毀
},
destroyed: function () {
// 已銷毀
}
}
});
```
### 從 npm 安裝
```shell
npm i @pardnchiu/quickui
```
## 功能介紹
自動渲染:加載自動渲染在檢測到資料變更時自動重新渲染。
### 從 CDN 引入
<details>
<summary>屬性概覽</summary>
#### 引入 `QuickUI` 套件
```html
<!-- 0.6.0 版本以上 -->
<script src="https://cdn.jsdelivr.net/npm/@pardnchiu/quickui@[VERSION]/dist/QuickUI.js"></script>
| 屬性 | 描述 |
| --- | --- |
| `{{value}}` | 將文字插入到 HTML 標籤中,並隨資料變更自動更新。 |
| `:path` | 搭配 `temp` 標籤,用於將外部文件中的 HTML 片段加載到當前頁面。 |
| `:html` | 使用文本替換元素的 `innerHTML`。 |
| `:for` | 支援 `item in items`、`(item, index) in items`、`(key, value) in object` 格式,遍歷資料集合,生成對應的 HTML 元素。 |
| `:if`<br>`:else-if`<br>`:elif`<br>`:else` | 根據條件顯示或隱藏元素,實現分支邏輯。 |
| `:model` | 將資料綁定到表單元素(如 `input`),當輸入變更時自動更新資料。 |
| `:hide` | 根據特定條件隱藏元素。 |
| `:effect` | 用於指定元素的過渡效果,如 `fade-in` 或 `expand`,以增強用戶體驗。 |
| `:mask` | 控制區塊載入時的動畫效果,支援 `true\|false\|1\|0`,提升載入動態視覺效果。 |
| `:[attr]` | 設定元素屬性,例如 `ID`、`class`、圖像來源等。<br>範例:`:id`、`:class`、`:src`、`:alt`、`:href`... |
| `:[css]` | 設定元素CSS,例如 `margin`、`padding` 等。<br>範例:`:background-color`、`:opacity`、`:margin`、`:top`、`:position`... |
| `@[event]` | 添加事件監聽器,當事件觸發時執行指定操作。<br>範例:`@click`、`@input`、`@mousedown`... |
<!-- 0.5.4 版本以下 -->
<script src="https://cdn.jsdelivr.net/npm/pdquickui@[VERSION]/dist/PDQuickUI.js"></script>
```
</details>
#### Module 版本
```javascript
// 0.6.0 版本以上
import { QUI } from "https://cdn.jsdelivr.net/npm/@pardnchiu/quickui@[VERSION]/dist/QuickUI.esm.js";
<details>
<summary>文字替換</summary>
// 0.5.4 版本以下
import { QUI } from "https://cdn.jsdelivr.net/npm/pdquickui@[VERSION]/dist/PDQuickUI.module.js";
```
## 使用方法
### `{{value}}`
- index.html
```HTML
<h1>{{ title }}</h1>
<script>
const app = new QUI({
id: "app",
data: {
title: "test"
}
});
</script>
```
- Result
```HTML
<body id="app">
<h1>test</h1>
</body>
```
***
### `:html`
- index.html
```HTML
<section :html="html"></section>
<script>
const app = new QUI({
id: "app",
data: {
html: "<b>innerHtml</b>"
}
});
</script>
```
- Result
```HTML
<body id="app">
<section>
<b>innerHtml</b>
</section>
</body>
```
</details>
<details>
<summary>插入區塊</summary>
> [!NOTE]
> 確保測試時已禁用瀏覽器中的本地文件限制或使用實時服務器。
### `:path`
- test.html
```html
<h1>path heading</h1>
<p>path content</p>
```
- index.html
```html
<body id="app">
<temp :path="./test.html"></temp>
</body>
<script>
const app = new QUI({
id: "app"
});
</script>
```
- Result
```html
<body id="app">
<!-- 直接插入 PATH 內容 -->
<h1>path heading</h1>
<p>path content</p>
</body>
```
</details>
<details>
<summary>迴圈渲染</summary>
### `:for`
- index.html
```html
<body id="app">
<ul>
<li :for="(item, index) in ary" :id="item" :index="index">{{ item }} {{ CALC(index + 1) }}</li>
</ul>
</body>
<script>
const app = new QUI({
id: "app",
data: {
ary: ["test1", "test2", "test3"]
}
});
</script>
```
- Result
```html
<body id="app">
<li id="test1" index="0">test1 1</li>
<li id="test2" index="1">test2 2</li>
<li id="test3" index="2">test3 3</li>
</body>
```
***
### 巢狀迴圈
- index.html
```html
<body id="app">
<ul>
<li :for="(key, val) in obj">
{{ key }}: {{ val.name }}
<ul>
<li :for="item in val.ary">
{{ item.name }}
<ul>
<li :for="(item1, index1) in item.ary1">
{{ CALC(index1 + 1) }}. {{ item1.name }} - ${{ item1.price }}
</li>
</ul>
</li>
</ul>
</li>
</ul>
</body>
<script>
const app = new QUI({
id: "app",
data: {
obj: {
food: {
name: "Food",
ary: [
{
name: 'Snacks',
ary1: [
{ name: 'Potato Chips', price: 10 },
{ name: 'Chocolate', price: 8 }
]
},
{
name: 'Beverages',
ary1: [
{ name: 'Juice', price: 5 },
{ name: 'Tea', price: 3 }
]
}
]
},
home: {
name: 'Home',
ary: [
{
name: 'Furniture',
ary1: [
{ name: 'Sofa', price: 300 },
{ name: 'Table', price: 150 }
]
},
{
name: 'Decorations',
ary1: [
{ name: 'Picture Frame', price: 20 },
{ name: 'Vase', price: 15 }
]
}
]
}
}
}
});
</script>
```
- Result
```html
<body id="app">
<ul>
<li>food: Food
<ul>
<li>Snacks
<ul>
<li>1. Potato Chips - $10</li>
<li>2. Chocolate - $8</li>
</ul>
</li>
<li>Beverages
<ul>
<li>1. Juice - $5</li>
<li>2. Tea - $3</li>
</ul>
</li>
</ul>
</li>
<li>home: Home
<ul>
<li>Furniture
<ul>
<li>1. Sofa - $300</li>
<li>2. Table - $150</li>
</ul>
</li>
<li>Decorations
<ul>
<li>1. Picture Frame - $20</li>
<li>2. Vase - $15</li>
</ul>
</li>
</ul>
</li>
</ul>
</body>
```
</details>
<details>
<summary>條件渲染</summary>
- index.html
```html
<body id="app">
<h1 :if="heading == 1">{{ title }} {{ heading }}</h1>
<h2 :else-if="isH2">{{ title }} {{ heading }}</h2>
<h3 :else-if="heading == 3">{{ title }} {{ heading }}</h3>
<h4 :else>{{ title }} {{ heading }}</h4>
</body>
<script>
const app = new QUI({
id: "app",
data: {
heading: [Number|null],
isH2: [Boolean|null],
title: "test"
}
});
</script>
```
- Result: `heading = 1`
```html
<body id="app">
<h1>test 1</h1>
</body>
```
- Result: `heading = null && isH2 = true`
```html
<body id="app">
<h2>test </h2>
</body>
```
- Result: `heading = 3 && isH2 = null`
```html
<body id="app">
<h3>test 3</h3>
</body>
```
- Result: `heading = null && isH2 = null`
```html
<body id="app">
<h4>test </h4>
</body>
```
</details>
<details>
<summary>模板渲染</summary>
- index.html
```HTML
<body id="app"></body>
<script>
const test = new QUI({
id: "app",
data: {
hint: "hint 123",
title: "test 123"
},
render: () => {
return `
"{{ hint }}",
h1 {
style: "background: red;",
children: [
"{{ title }}"
]
}`
}
})
</script>
```
- result
```HTML
<body id="app">
hint 123
<h1 style="background: red;">test 123</h1>
</body>
```
</details>
<details>
<summary>雙向綁定</summary>
```html
<body id="app">
<input type="password" :model="password">
<button @click="show">test</button>
</body>
<script>
const app = new QUI({
id: "app",
data: {
password: null,
### 初始化 `QUI`
```Javascript
const app = new QUI({
id: "", // 指定渲染元素
data: {
// 自訂 DATA
},
event: {
// 自訂 EVENT
},
when: {
before_render: function () {
// 停止渲染
},
event: {
show: function(e){
alert("Password:", app.data.password);
}
rendered: function () {
// 已渲染
},
before_update: function () {
// 停止更新
},
updated: function () {
// 已更新
},
before_destroy: function () {
// 停止銷毀
},
destroyed: function () {
// 已銷毀
}
});
</script>
}
});
```
</details>
<details>
<summary>事件偵測</summary>
### 屬性概覽
```html
<body id="app">
<button @click="test">test</button>
</body>
<script>
const app = new QUI({
id: "app",
event: {
test: function(e){
alert(e.target.innerText + " clicked");
}
}
});
</script>
```
</details>
#### 文字與內容
| 屬性 | 使用場景 | 範例 |
|-----------|----------|---------|
| `{{ value }}` | 動態文字內容 | `<p>{{ userName }}</p>` 顯示使用者名稱 |
| `:html` | 原始 HTML 插入 | `<div :html="richContent"></div>` 渲染格式化內容 |
<details>
<summary>CSS設置</summary>
#### 模板載入
| 屬性 | 使用場景 | 範例 |
|-----------|----------|---------|
| `:path` | 外部模板載入 | `<temp :path="'./templates/header.html'"></temp>` 載入頁首元件 |
> [!NOTE]
> 支援 `:[CSS屬性]` 的簡易設定方式,直接將資料綁定到樣式屬性。
#### 列表與迭代
| 屬性 | 使用場景 | 範例 |
|-----------|----------|---------|
| `:for` | 陣列/物件迭代 | `<li :for="item in items">{{ item.name }}</li>` 渲染列表項目 |
- index.html
```html
<body id="app">
<button :width="width" :backdround-color="color">test</button>
</body>
<script>
const app = new QUI({
id: "app",
data: {
width: "100px",
color: "red"
}
});
</script>
```
- Result:
```html
<body id="app">
<button style="width: 100px; backdround-color: red;">test</button>
</body>
```
#### 條件渲染
| 屬性 | 使用場景 | 範例 |
|-----------|----------|---------|
| `:if` | 條件顯示 | `<div :if="isLoggedIn">歡迎!</div>` |
| `:else-if`/`:elif` | 次要條件 | `<div :elif="isPending">載入中...</div>` |
| `:else` | 預設內容 | `<div :else>請登入</div>` |
</details>
#### 表單綁定
| 屬性 | 使用場景 | 範例 |
|-----------|----------|---------|
| `:model` | 雙向資料綁定 | `<input :model="userInput">` 與資料同步 |
<details>
<summary>可用函式</summary>
#### 樣式與動畫
| 屬性 | 使用場景 | 範例 |
|-----------|----------|---------|
| `:animation` | 過渡效果 | `<div :animation="fade-in">內容</div>` |
| `:[css]` | 動態樣式 | `<div :background-color="bgColor">樣式內容</div>` |
### `LENGTH()`
#### 動態屬性
| 屬性 | 使用場景 | 範例 |
|-----------|----------|---------|
| `:[attr]` | 動態屬性 | `<img :src="imageUrl" :alt="imageDesc">` |
- index.html
```HTML
<body id="app">
<p>Total: {{ LENGTH(array) }}</p>
</body>
<script>
const app = new QUI({
id: "app",
data: {
array: [1, 2, 3, 4]
}
});
</script>
```
- result
```HTML
<body id="app">
<p>Total: 4</p>
</body>
```
#### 事件處理
| 屬性 | 使用場景 | 範例 |
|-----------|----------|---------|
| `@[event]` | 事件監聽器 | `<button @click="handleClick">點擊我</button>` |
***
## 授權條款
### `CALC()`
本專案採用類 MIT 授權,但僅提供混淆後的程式碼:
- 與 MIT 相同:可自由使用、修改、再散布,包含商業用途
- 主要差異:預設僅提供混淆版程式碼,原始碼需另外購買
- 授權內容:必須保留原始版權聲明 (與 MIT 相同)
- index.html
```HTML
<body id="app">
<p>calc: {{ CALC(num * 10) }}</p>
</body>
<script>
const app = new QUI({
id: "app",
data: {
num: 1
}
});
</script>
```
- result
```HTML
<body id="app">
<p>calc: 10</p>
</body>
```
詳細條款與條件請參閱[軟體使用協議](https://github.com/pardnchiu/QuickUI/blob/main/LICENSE)。
***
### `UPPER()` / `LOWER()`
- index.html
```HTML
<body id="app">
<p>{{ UPPER(test1) }} {{ LOWER(test2) }}</p>
</body>
<script>
const app = new QUI({
id: "app",
data: {
test1: "upper",
test2: "LOWER"
}
});
</script>
```
- result
```HTML
<body id="app">
<p>UPPER lower</p>
</body>
```
***
### `DATE(num, format)`
- index.html
```HTML
<body id="app">
<p>{{ DATE(now, YYYY-MM-DD hh:mm:ss) }}</p>
</body>
<script>
const app = new QUI({
id: "app",
data: {
now: Math.floor(Date.now() / 1000)
}
});
</script>
```
- result
```HTML
<body id="app">
<p>2024-08-17 03:40:47</p>
</body>
```
</details>
<details>
<summary>懶加載</summary>
### `:lazyload`
- index.html
```html
<body id="app">
<img :lazyload="image">
</body>
<script>
const app = new QUI({
id: "app",
data: {
image: "test.jpg"
},
option: {
lazyload: true, // 圖片延遲加載: true|false (預設: true)
}
});
</script>
```
- result
```html
<body id="app">
<img src="test.jpg">
</body>
```
***
### `SVG` 替換
- test.svg
```XML
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<line x1="18" y1="6" x2="6" y2="18" stroke="black" stroke-width="2" stroke-linecap="round"/>
<line x1="6" y1="6" x2="18" y2="18" stroke="black" stroke-width="2" stroke-linecap="round"/>
</svg>
```
- index.html
```html
<body id="app">
<temp-svg :src="svg"></temp-svg>
</body>
<script>
const app = new QUI({
id: "app",
data: {
svg: "test.svg",
},
option: {
svg: true // SVG 檔案轉換: true|false (預設: true)
}
});
</script>
```
- result
```html
<body id="app">
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<line x1="18" y1="6" x2="6" y2="18" stroke="black" stroke-width="2" stroke-linecap="round">
<line x1="6" y1="6" x2="18" y2="18" stroke="black" stroke-width="2" stroke-linecap="round">
</svg>
</body>
```
</details>
<details>
<summary>多國語言</summary>
> [!NOTE]
> 若為物件格式,直接配置多語言內容。
> 若為字串格式,會透過 `fetch` 動態載入語言檔案。
- en.json
```JSON
{
"greeting": "Hello",
"username": "Username"
}
```
- index.html
```html
<body id="app">
<h1>{{ i18n.greeting }}, {{ i18n.username }}: {{ username }}</h1>
<button @click="change" data-lang="zh">切換至中文</button>
<button @click="change" data-lang="en">Switch to English</button>
</body>
<script>
const app = new QUI({
id: "app",
data: {
username: "帕登"
},
i18n: {
zh: {
greeting: "你好",
username: "用戶名"
},
en: "en.json",
},
i18nLang: "zh | en", // 選擇顯示語言
event: {
change: e => {
const _this = e.target;
const lang = _this.dataset.lang;
app.lang(lang);
},
}
});
</script>
```
- result `i18nLang = zh`
```html
<body id="app">
<h1>你好, 用戶名: 帕登</h1>
<button data-lang="zh">切換至中文</button>
<button data-lang="en">Switch to English</button>
</body>
```
- result `i18nLang = en`
```html
<body id="app">
<h1>Hello, Username: 帕登</h1>
<button data-lang="zh">切換至中文</button>
<button data-lang="en">Switch to English</button>
</body>
```
</details>
<details>
<summary>生命週期</summary>
```html
<body id="app"></body>
<script>
const app = new QUI({
id: "app",
when: {
before_render: function () {
// 停止渲染
// retuen false
},
rendered: function () {
// 已掛載
},
before_update: function () {
// 停止更新
// retuen false
},
updated: function () {
// 已更新
},
before_destroy: function () {
// 停止銷毀
// retuen false
},
destroyed: function () {
// 已銷毀
}
}
});
</script>
```
</details>
<details>
<summary>資料獲取</summary>
```html
<body id="app">
<input type="text" :model="test">
<button @click="get">測試</button>
</body>
<script>
const app = new QUI({
id: "app",
data: {
// 給 input 綁定的值
test: 123
},
event: {
get: _ => {
// 點擊時彈出內容為 test 值的通知
alert(app.data.test);
},
set: _ => {
let dom = document.createElement("button");
// 按鈕點按事件設置為 get 函式
dom.onclick = app.event.get;
app.body.append(dom);
}
}
});
</script>
```
</details>
## 開發者
<img src="https://avatars.githubusercontent.com/u/25631760" align="left" width="96" height="96" style="margin-right: 0.5rem;" />
<img src="https://avatars.githubusercontent.com/u/25631760" align="left" width="96" height="96" style="margin-right: 0.5rem;">
<h4 style="padding-top: 0">邱敬幃 Pardn Chiu</h4>
[![](https://pardn.io/image/mail.svg)](mailto:dev@pardn.io) [![](https://skillicons.dev/icons?i=linkedin)](https://linkedin.com/in/pardnchiu)
<a href="mailto:dev@pardn.io" target="_blank">
<img src="https://pardn.io/image/email.svg" width="48" height="48">
</a> <a href="https://linkedin.com/in/pardnchiu" target="_blank">
<img src="https://pardn.io/image/linkedin.svg" width="48" height="48">
</a>
## 授權條款
本專案採用 **專有授權**。
更多詳細資訊,請參閱本倉庫中的 [最終使用者授權協議(EULA)](https://github.com/pardnchiu/QuickUI/blob/main/LICENSE)。
## 獲取完整原始碼
[聯絡我](mailto:dev@pardn.io) 獲取完整未混淆源碼<br>
可隨意修改、商業使用,根據需求選擇授權版本:
- 需保留 `Powered by @pardnchiu/quickui` 的版權聲明:$7,500
- 完全自主,無需添加版權聲明:$10,000
***
©️ 2024 [邱敬幃 Pardn Chiu](https://www.linkedin.com/in/pardnchiu)
©️ 2023 [邱敬幃 Pardn Chiu](https://www.linkedin.com/in/pardnchiu)

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc