npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

pdquickui

v0.6.1

Published

A web frontend framework that supports conditional and loop rendering, data binding, monitoring data changes, and automatic rendering. Previously known as QuickUI.

Downloads

185

Readme

QuickUI

(原名:PDQuickUI,自 0.6.0 版本起更名為 QuickUI)

tag size license npm download jsdeliver

QuickUI 是從 PDRenderKit 中獨立出來的前端渲染框架,專注於強化前端框架功能。 透過引入虛擬 DOM 概念重寫渲染邏輯,提升渲染效能,並實現更高效的數據監聽和自動更新。

本專案移除了 PDRenderKit 中針對 prototype 的擴展,確保兼容性與效能,適合用於複雜的應用場景。 提供 module 和非 module 版本,授權從 PDRenderKitGPL-3.0 更改為 MIT

特點

  • 清晰的架構:UI 和資料邏輯分離,維護方便。
  • 代碼簡潔:減少重複代碼,提升可讀性。
  • 自動渲染:監控資料變動並自動更新,減少手動操作。
  • 輕量化:使用原生 JS 和內建 API 撰寫,無任何外部依賴。

安裝方式

  • 從 npm 安裝

    npm i @pardnchiu/quickui
  • 從 CDN 引入

    • 引入 QuickUI 套件
      <!-- Version 0.6.0 and above -->
      <script src="https://cdn.jsdelivr.net/npm/@pardnchiu/quickui@[VERSION]/dist/QuickUI.js"></script>
      
      <!-- Version 0.5.4 and below -->
      <script src="https://cdn.jsdelivr.net/npm/pdquickui@[VERSION]/dist/PDQuickUI.js"></script>
    • Module 版本
      // 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
    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 () {
                // 已銷毀
            }
        }
    });

功能介紹

自動渲染:加載自動渲染在檢測到資料變更時自動重新渲染。

| 屬性 | 描述 | | --- | --- | | {{value}} | 將文字插入到 HTML 標籤中,並隨資料變更自動更新。 | | :path | 搭配 temp 標籤,用於將外部文件中的 HTML 片段加載到當前頁面。 | | :html | 使用文本替換元素的 innerHTML。 | | :for | 支援 item in items(item, index) in items(key, value) in object 格式,遍歷資料集合,生成對應的 HTML 元素。 | | :if:else-if:elif:else | 根據條件顯示或隱藏元素,實現分支邏輯。 | | :model | 將資料綁定到表單元素(如 input),當輸入變更時自動更新資料。 | | :hide | 根據特定條件隱藏元素。 | | :effect | 用於指定元素的過渡效果,如 fade-inexpand,以增強用戶體驗。 | | :mask | 控制區塊載入時的動畫效果,支援 true|false|1|0,提升載入動態視覺效果。 | | :[attr] | 設定元素屬性,例如 IDclass、圖像來源等。範例::id:class:src:alt:href... | | :[css] | 設定元素CSS,例如 marginpadding 等。範例::background-color:opacity:margin:top:position... | | @[event] | 添加事件監聽器,當事件觸發時執行指定操作。範例:@click@input@mousedown... |

{{value}}

  • index.html
    <h1>{{ title }}</h1>
    <script>
        const app = new QUI({
            id: "app",
            data: {
                title: "test"
            }
        });
    </script>
  • Result
    <body id="app">
        <h1>test</h1>
    </body>

:html

  • index.html
    <section :html="html"></section>
    <script>
        const app = new QUI({
            id: "app",
            data: {
                html: "<b>innerHtml</b>"
            }
        });
    </script>
  • Result
    <body id="app">
        <section>
            <b>innerHtml</b>
        </section>
    </body>

[!NOTE] 確保測試時已禁用瀏覽器中的本地文件限制或使用實時服務器。

:path

  • test.html
    <h1>path heading</h1>
    <p>path content</p>
  • index.html
    <body id="app">
        <temp :path="./test.html"></temp>
    </body>
    <script>
        const app = new QUI({
            id: "app"
        });
    </script>
  • Result
    <body id="app">
        <!-- 直接插入 PATH 內容 -->
        <h1>path heading</h1>
        <p>path content</p>
    </body>

:for

  • index.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
    <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
    <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
    <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>
  • index.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
    <body id="app">
        <h1>test 1</h1>
    </body>
  • Result: heading = null && isH2 = true
    <body id="app">
        <h2>test </h2>
    </body>
  • Result: heading = 3 && isH2 = null
    <body id="app">
        <h3>test 3</h3>
    </body>
  • Result: heading = null && isH2 = null
    <body id="app">
        <h4>test </h4>
    </body>
  • index.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
    <body id="app">
        hint 123
        <h1 style="background: red;">test 123</h1>
    </body>
<body id="app">
    <input type="password" :model="password">
    <button @click="show">test</button>
</body>
<script>
    const app = new QUI({
        id: "app",
        data: {
            password: null,
        },
        event: {
            show: function(e){
                alert("Password:", app.data.password);
            }
        }
    });
</script>
<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>

[!NOTE] 支援 :[CSS屬性] 的簡易設定方式,直接將資料綁定到樣式屬性。

  • index.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:
    <body id="app">
        <button style="width: 100px; backdround-color: red;">test</button>
    </body>

LENGTH()

  • index.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
    <body id="app">
        <p>Total: 4</p>
    </body>

CALC()

  • index.html
    <body id="app">
        <p>calc: {{ CALC(num * 10) }}</p>
    </body>
    <script>
        const app = new QUI({
            id: "app",
            data: {
                num: 1
            }
        });
    </script>
  • result
    <body id="app">
        <p>calc: 10</p>
    </body>

UPPER() / LOWER()

  • index.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
    <body id="app">
        <p>UPPER lower</p>
    </body>

DATE(num, format)

  • index.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
    <body id="app">
        <p>2024-08-17 03:40:47</p>
    </body>

:lazyload

  • index.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
    <body id="app">
        <img src="test.jpg">
    </body>

SVG 替換

  • test.svg
    <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
    <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
    <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>

[!NOTE] 若為物件格式,直接配置多語言內容。 若為字串格式,會透過 fetch 動態載入語言檔案。

  • en.json
    {
        "greeting": "Hello",
        "username": "Username"
    }
  • index.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
    <body id="app">
        <h1>你好, 用戶名: 帕登</h1>
        <button data-lang="zh">切換至中文</button>
        <button data-lang="en">Switch to English</button>
    </body>
  • result i18nLang = en
    <body id="app">
        <h1>Hello, Username: 帕登</h1>
        <button data-lang="zh">切換至中文</button>
        <button data-lang="en">Switch to English</button>
    </body>
<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>
<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>

開發者

授權條款

本專案依據 MIT 授權使用。

獲取完整原始碼

聯絡我 獲取完整未混淆源碼 可隨意修改、商業使用,根據需求選擇授權版本:

  • 需保留 Powered by @pardnchiu/quickui 的版權聲明:$7,500
  • 完全自主,無需添加版權聲明:$10,000

©️ 2024 邱敬幃 Pardn Chiu