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.5.4

Published

PDQuickUI contains a lightweight front-end framework designed to separate the front-end user interface and data logic.

Downloads

720

Readme

PDQuickUI

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

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

特點

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

安裝方式

  • 從 npm 安裝
    npm i pdquickui
  • 從 CDN 引入
    • 引入 PDQuickUI 套件
      <script src="https://cdn.jsdelivr.net/npm/pdquickui@[VERSION]/dist/PDQuickUI.js"></script>
    • Module 版本
      import { QUI } from "https://cdn.jsdelivr.net/npm/pdquickui@[VERSION]/dist/PDQuickUI.module.js";

功能介紹

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

| 屬性 | 描述 | | --- | --- | | {{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 | 根據特定條件隱藏元素。 | | :animation | 用於指定元素的過渡效果,如 fade-inexpand,以增強用戶體驗。 | | :mask | 控制區塊載入時的動畫效果,支援 true|false|1|0,提升載入動態視覺效果。 | | :[attr] | 設定元素屬性,例如 IDclass、圖像來源等。範例::id:class:src:alt:href... | | @[event] | 添加事件監聽器,當事件觸發時執行指定操作。範例:@click@input@mousedown... |

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

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

  • 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>
  • 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">
        <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>
  • index.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>

:padding, :margin, :border, :border-radius, :outline, :box-sahdow, :bg-image, :bg-attachment, :bg-blend-mode, :bg-clip, :bg-origin, :bg-position, :bg-position-x, :bg-position-y, :bg-repeat, :bg-size, :bg-color, :color

  • 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>
<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);
            }
        }
    });
</script>
  • 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"></body>
<script>
    const app = new QUI({
        id: "app",
        when: {
            before_mount: function () {
                // 停止渲染
                // retuen false 
            },
            mounted: function () {
                console.log("已掛載");
            },
            before_update: function () {
                // 停止更新
                // retuen false 
            },
            updated: function () {
                console.log("已更新");
            },
            before_destroy: function () {
                // 停止銷毀
                // retuen false 
            },
            destroyed: function () {
                console.log("已銷毀");
            }
        }
    });
</script>
  • 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="test.svg"></temp-svg>
        <temp-svg src="svg"></temp-svg>
        <img :lazyload="image">
        <img lazyload="test.jpg">
    </body>
    <script>
        const app = new QUI({
            id: "app",
            data: {
                svg: "test.svg",
                image: "test.jpg"
            },
            option: {
                lazyload: true, // 圖片延遲加載: true|false (預設: true)
                svg: true       // SVG 檔案轉換: true|false (預設: true)
            }
        });
    </script>
  • result
    <body id="app">
        <!-- 直接插入 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>
        <!-- 會在元素進入畫面時讀取 -->
        <img src="test.jpg">
    </body>

範例

開發者

授權條款

本專案依據 MIT 授權使用。


©️ 2024 邱敬幃 Pardn Chiu