」工欲善其事,必先利其器。「—孔子《論語.錄靈公》
首頁 > 程式設計 > 綁定和模板:Peasy-UI 系列的一部分

綁定和模板:Peasy-UI 系列的一部分

發佈於2024-11-08
瀏覽:166

Bindings and Templates: Part f the Peasy-UI series

Table of Contents

  1. Introduction
  2. Bindings and the Template
  3. Text Bindings
    • Basic Binding
    • Conditional Boolean Text Binding
    • One-time Text bindings
  4. Attribute Bindings
    • Bindings for element attributes
    • Bindings for events
    • Binding whole elements to data model
    • Binding for Rendering
    • Binding for Arrays
    • Bindings for Components
  5. Getters
  6. More information
  7. Conclusion

Introduction

Today we are going to dive a layer deeper into the Peasy-UI library. We are going to explain the different types of bindings that are available in the library, and how you can incorporate them into the string literal template that you provide to the library to be rendered to the DOM. For this article all examples are provided using TypeScript, but the library works with vanilla JavaScript perfectly fine.

If you missed the introduction article for Peasy-UI, you can read it
here, and it can provide the overview for the library, and even introduces upcoming topics in the series.

Bindings and the Template

I quick recap of what bindings are, what the template is, and how they work with the library to give you control of what gets rendered to the DOM.

Peasy-UI is a library that injects content into DOM elements that you specify. The content that gets injected is dictated by a string literal template that provides HTML markup that represents the content to be injected.

const template = `
  
Render Me
`;

This is an example of the string literal template that you pass to Peasy-UI and it will render it into the targeted DOM element.

Bindings provide a means to control that template dynamically. For example, let's do a Hello World example.

const model = {
  name: "Bob",
};

const template = `
Hello: \${name}!!!!
`; await UI.create(document.body, model, template).attached;

This code creates the data store (model), that is bound to the html in the string literal template. UI.create() takes the model, template, and the targeted DOM element to inject into as parameters. In your JavaScript code, you can change model.name to whatever string you'd like, and it will dynamically re-render the new text into the DOM. Side note: the await in the UI.create() method pauses the execution of subsequent logic until Peasy-UI attaches the content into the DOM. This way you can prevent trying to make changes or access DOM content that isn't rendered yet.

Text bindings

There are two types of bindings in Peasy-UI, text bindings and attribute bindings, and we will explore both types. One thing to note is that since we are providing a string literal to Peasy-UI, we use the backslash escape character to designate it as a binding.

Basic binding

The most basic binding is simply injecting data into the DOM as text. The Hello World above is a prime example of this. Use cases for this binding can include manipulating the inner text or inner HTML content inside a DOM element, such as changing a name. I've also used this for changing CSS properties inside a CSS string.

BINDING: ${propertyName}

As in the example above, we can use this:

const model = {
  name: "Bob",
};

const template = `
Hello: \${name}!!!!
`;

The binding maps the 'name' property to the tag in the HTML and replaces name with the name content from the model.

Conditional boolean text binding

In order to control if a binding is active, we can leverage some conditional bindings.

BINDING: ${'value' = propertyName}

BINDING: ${'value' ! propertyName}

An example of this would be:

const model = {
  darkMode: true,
};

const template = `
I am using \${'Dark mode' = darkMode} \${'Light mode' ! darkMode} now!
`;

Based on the truthy status of the darkMode property in the model, different text renders. If true, the div will say I am using Dark mode now! and if its set to false, it will render I am using Light mode now!.

One-time text bindings

The previous bindings get constantly evaluated with respect to RequestAnimationFrame(). However, sometimes you may only want to evaluate it one-time, like on initialization. Peasy-UI provides one-time bindings.

BINDING: ${|'value' = prop}

BINDING: ${|'value' ! prop}

The same example above can be reused, the only difference is that the evaluation of the darkMode property will only be done on the first rendering cycle. Please take note of the pipe character in the binding, as that is what designates it as a one-time binding.

Attribute Bindings

Attribute bindings use either \${ } or the pui attribute within an element tag to affect the behaviour of the element. For the sake of this article we will continue using the \${ } nomenclature. We will explore the different methods of assigning bindings in a future article.

Bindings for element attributes

Peasy-UI gives us the power to access element attributes and allows us to monitor and control those values easily.

There are four basic element attribute bindings:

BINDING: ${attribute

BINDING: ${attribute

BINDING: ${attribute ==> propertyName} bind in one direction, from the element to the model

BINDING: ${attribute propertyName} bi-directional, or two-way, between the element and the model

Let's look at some examples of this:

const model = {
  color: "red",
};

const template = `
color}>Red color}>Green
`;

In this example you are binding a custom attribute on each element 'red' and 'green' to the color property in the model. When the radio button in this group is selected, it changes the data in the model property 'color'.

Another simple example:

const model = {
  userName: "",
};

const template = `
userName}>
`;

This is a one way binding from the text field, that sets the data model value of userName to whatever is entered into the input field.

Let's look at a bidirectional example:

const model = {
  userName: "Bob",
};

const template = `
userName}>\${userName}
`;

The magic that exists here is that you can set username in the data model programmatically, and it will automatically change the rendered text in the input field. Or, you can type into the input field and it will dynamically change the value in the data model.

Bindings for events

So what if want to render a drop down select input, or a button? Peasy-UI gives you access to mapping the event listeners automatically and tying them into the data model.

BINDING: ${ event @=> callbackName}

Buttons provide easy examples for this, but all DOM events can be used.

const model = {
  clickHandler: (event: HTMLEvent, model: any, element: HTMLElement, eventType: string, object: any) => {
    window.alert("I got clicked");
  },
};

const template = `
`;

Okay, there is a bit to unpack here. First lets focus on the binding, you can bind any HTML DOM event, such as change, input, click, mouseenter, etc... as an event binding, and then you provide the 'handler' callback which exists IN the data model.

Peasy passes 5 standard parameters into the handler for your convenience. The first parameter is the HTMLEvent that actually is fired.The second parameter is the 'localized' data model that is bound to the element. This CAN be tricky, because depending on your nesting of elements, it maybe be a localized data model for just that element, or if it is a top level binding, it will be the standard data model. We will get into nesting a bit later, but just know that another option is provided to help with this.

The third parameter is the target element that fired the event, so you can access any attributes nested in the element. The fourth element is the string representation of the event, such as 'click' or 'change' and this helps in case you bind multiple events to the same callback, you can distinguish which event triggered this callback. The final parameter is the overarching data model. Inside this object, regardless of how nested your binding is, will be an object that contains the model property, and you can navigate that object to have access to ANY property in the data model.

Binding whole elements to data model

Do you know how annoying it is to have to perform a documement.getElementById('myElement'); in your Javascript? Yeah, Peasy-UI makes that a bit easier.

BINDING: ${ ==> propertyName}

Let's look at this timesaver example:

const model = {
  myInputElement: undefined as HTMLElement | undefined,
};

const template = `
myInputElement} />
`;

What this binding does is maps the DOM elements rendered and binds their reference inside the model. In this example, instead of having to do the getElementById() method, model.myInputElement is that reference after the first rendering cycle. The element has to render 'first' then the reference to it gets captured in the data model. This is why its set to undefined by default, then gets set to the element reference after the HTML gets injected into the DOM. So now to have access to the element value, i can just access model.myInputElement.value or any attribute in that element that I'd like access to.

Binding for rendering

What if you want to be selective about what gets rendered and maybe have portions of your template not rendered under certain conditions. Yup, Peasy-UI allows you to control overall rendering as well.

BINDING: ${=== propertyName}

BINDING: ${!== propertyName}

Let's looke at the example of this binding:

const model = {
  isDog: true,
};

const template = `
I am a Dog
I am a Cat

In this example you will only see one of the bound div's being rendered, and by toggling between true and false in the data model.isDog, you can control which div is being rendered.

Binding for arrays

Sometimes you need to list things out in the DOM. Examples may be forum posts, options in a select input, or list items in a nav bar. Peasy-UI gives you an iterable renderer, so you can translate a list or array in the data model to multiple element renderings.

BINDING: ${ item

Let's give a simple example:

const model = {
  myItems: [{text: 'one', value: '1'},{text: 'one', value: '1'},{text: 'one', value: '1'}],
};

const template = `

So this use case iterates over the 'myItems' property array in the data model, and renders a separate option element in the select tag.

Each rendered option tag has its own model scope as you can see, with opt.text and opt.value.

Bindings for components

So with larger projects, there is a desire to organize a code base and utilize code splitting to keep aspects of a project manageable. Peasy-UI allows for component based design. We will 'lightly' touch on this topic in this article as the overall component feature will get its own article for properly exploring its capabilities.

A component in Peasy-UI is any JavaScript object which contains a static, public template property and a static create method.

BINDING: ${ComponentName === state}

Let's look at one basic example, with more to follow in future article:

class MyComponent{
  public static template = `
  
Hello \${name}
My count is: \${count}
`; constructor(public name: string,public count:number){} static create( state: {name:string, count:number}){ return new MyComponent(state.name, state.count) } } const model = { MyComponent, componentData:{ name: 'bob', count: 10, } }; const template = `

So the MyComponent class must have a static create method that accepts incoming state, and a public static template. What Peasy-UI will do is set the local class properties as the internal state for each component, and will inject the class template into the overall project template.

This can let you break a larger project down into smaller pieces. There is a lot more you can do with components, and it warrants its own article to explore further.

Getters

The final binding idea to be covered is the usage of getters in the data model and what they bring to the table. Sometimes a simple primitive just doesn't cut it in the data model, and getters provide a means of providing more complicated logic and the return value will be the binding value to the binding. There's no unique binding tag to cover here, just an example:

const model = {
  val1: 1,
  val2: 3,
  get myGetter(){
      return this.val1   this.val2;
  },
};

const template = `
My getter value is: \${myGetter}

The nice part of using a getter is that it gets re-evaluated every rendering loop. So if any values change within its own logic, it will get updated.

More information

More information can be found in the GitHub repo for Peasy-Lib, you also will find all the other companion packages there too. Also, Peasy has a Discord server where we hang out and discuss Peasy and help each other out.

The author's twitter: Here

The author's itch: Here

Github Repo: Here

Discord Server: Here

Conclusion

So this article covered all the basics of the Peasy-UI library's data bindings, which is the magic that powers how the library is used to render essentially anything you need in the DOM. We discussed Text Bindings and Attribute Bindings. For each we covered the binding syntax, and how it can be used in examples.

In the next article we will dive deeper into events.

版本聲明 本文轉載於:https://dev.to/jyoung4242/bindings-and-templates-part-2-of-the-peasy-ui-series-k44?1如有侵犯,請聯絡[email protected]刪除
最新教學 更多>
  • 如何解決 Windows 上 PHP 中的 SSL 套接字傳輸問題?
    如何解決 Windows 上 PHP 中的 SSL 套接字傳輸問題?
    解決PHP 中的SSL Socket 傳輸問題在Windows 系統上使用PHP 時,開發人員可能會遇到錯誤「無法連線到ssl: //...”由於啟用“ssl”套接字傳輸存在困難。本文將指導您排除故障並解決此問題,並介紹您迄今為止已採取的具體步驟。 故障排除步驟檢查PHP 設定:確保php_open...
    程式設計 發佈於2024-11-08
  • 為什麼類比滑鼠懸停在 Chrome 中不會觸發 CSS 懸停?
    為什麼類比滑鼠懸停在 Chrome 中不會觸發 CSS 懸停?
    在JavaScript 中模擬滑鼠懸停:澄清差異並實現手動控制嘗試在Chrome 中模擬滑鼠懸停事件時,您可能遇到了一個有趣的問題問題。儘管“mouseover”事件監聽器已成功激活,但相應的CSS“hover”聲明並未生效。此外,嘗試在滑鼠懸停偵聽器中使用 classList.add("...
    程式設計 發佈於2024-11-08
  • 你能衡量 MySQL 索引的有效性嗎?
    你能衡量 MySQL 索引的有效性嗎?
    了解 MySQL 索引效能優化 MySQL 查詢對於高效的資料庫處理至關重要。索引是提高搜尋效能的關鍵技術,但監控其有效性也同樣重要。本文解決了是否可以評估 MySQL 索引效能的問題並提供了解決方案。 識別查詢效能決定查詢是否使用索引,執行下列查詢:EXPLAIN EXTENDED SELECT ...
    程式設計 發佈於2024-11-08
  • 如何自訂 PDF.js
    如何自訂 PDF.js
    PDF.js 是一個很棒的開源項目,它經常更新並且不斷添加新功能,但是從外觀上看它很醜陋,或者可以說它看起來已經過時了。從 PDF.js 取得最新的 PDF 功能和修復,但在演示方面擁有流暢的外觀怎麼樣? PdfJsKit 的pdf 檢視器並不引人注目,它不會直接更改PDF.js 的程式碼,它只是...
    程式設計 發佈於2024-11-08
  • 即將推出大事
    即將推出大事
    我決定從頭開始建立全端 Web 開發人員課程,從 HID 一直到伺服器和可擴展性。所有需要知道的,都將免費涵蓋免費! 以下是涵蓋的內容: 網際網路 互聯網是如何運作的? 什麼是HTTP? 瀏覽器及其運作方式? DNS 及其運作方式? 什麼是網域名稱? 什麼是託管? ...
    程式設計 發佈於2024-11-08
  • HTML 頁面的剖析
    HTML 頁面的剖析
    程式設計 發佈於2024-11-08
  • 設計有效資料庫的終極指南(說真的,我們是認真的)
    設計有效資料庫的終極指南(說真的,我們是認真的)
    Alright, you’ve got a shiny new project. Maybe it's a cutting-edge mobile app or a massive e-commerce platform. Whatever it is, behind all that glitz ...
    程式設計 發佈於2024-11-08
  • 使用 html css 和 javascript 的圖像輪播旋轉幻覺
    使用 html css 和 javascript 的圖像輪播旋轉幻覺
    程式碼 旋轉影像輪播 身體 { 顯示:柔性; 調整內容:居中; 對齊項目:居中; 高度:100vh; 保證金:0; 背景顏色:#0d0d0d; 溢出:隱藏; ...
    程式設計 發佈於2024-11-08
  • 如何開始 Web 開發
    如何開始 Web 開發
    介绍 Web 开发是当今最受欢迎的职业之一,对于那些对 前端(用户看到的内容)和 后端(服务器逻辑)感兴趣的人来说)。如果您刚刚起步,想知道从哪里开始或者作为开发者可以赚多少钱,本指南将为您提供清晰的入门路径和资源。 什么是网页开发? 网络开发分为两大区域: 前端:...
    程式設計 發佈於2024-11-08
  • 如何在不使用 Composer 本身的情況下安裝 Composer PHP 套件?
    如何在不使用 Composer 本身的情況下安裝 Composer PHP 套件?
    如何在沒有Composer 的情況下安裝Composer PHP 軟體包在本文中,我們將解決在沒有Composer 工具的情況下安裝Composer PHP 軟體包的挑戰本身。當您遇到 Composer 對於您的工作流程不可用或不切實際的情況時,此方法非常有用。 識別依賴關係第一步是識別包所需的依賴...
    程式設計 發佈於2024-11-08
  • 如何在 Matplotlib 中繪製不同顏色的線條?
    如何在 Matplotlib 中繪製不同顏色的線條?
    繪製不同顏色的線在 matplotlib 中,可以透過多種方法來繪製具有不同顏色段的線。選擇取決於要繪製的線段數量。 線段數量較少如果只需要幾條線段,如繪製軌跡,請考慮以下事項:import numpy as np import matplotlib.pyplot as plt # Generate...
    程式設計 發佈於2024-11-08
  • 為什麼 Safari 無法處理「2010-11-29」格式的日期?
    為什麼 Safari 無法處理「2010-11-29」格式的日期?
    Safari 的日期解析怪癖為什麼Safari 在遇到“2010-11-29”等格式的日期時會拋出“無效日期”錯誤',而其他瀏覽器處理這些日期沒有問題?這種不一致的行為可能會讓 Web 開發人員感到沮喪。 問題的根源在於 Safari 對日期字串中破折號 (-) 的解釋。雖然大多數瀏覽器將破...
    程式設計 發佈於2024-11-08
  • 我應該使用哪些工具來進行 Python 套件管理? Distutils、Setuptools、Distribute 和 Distutils2 指南。
    我應該使用哪些工具來進行 Python 套件管理? Distutils、Setuptools、Distribute 和 Distutils2 指南。
    探索Distribute、Distutils、Setuptools 和Distutils2 之間的區別Python 套件管理隨著時間的推移不斷發展,引入了各種用於不同目的的工具。了解這些工具之間的細微差別對於高效的軟體分發和安裝至關重要。 Distutils:標準函式庫遺產Distutils 已合併...
    程式設計 發佈於2024-11-08
  • 如何在沒有 syscall 或 scrypt 的情況下安全地在 Golang/App Engine 中對密碼進行雜湊處理?
    如何在沒有 syscall 或 scrypt 的情況下安全地在 Golang/App Engine 中對密碼進行雜湊處理?
    在Golang/App Engine 中安全地散列密碼,無需系統調用或scrypt雖然bcrypt 和scrypt 通常用於密碼散列,但它們可能不是由於系統調用可訪問性,適合App Engine。作為替代方案,請考慮利用 go.crypto 程式庫進行安全密碼雜湊。 go.crypto 套件提供對 ...
    程式設計 發佈於2024-11-08
  • 使用 JDK 記錄促進 Spring 開發的真實範例
    使用 JDK 記錄促進 Spring 開發的真實範例
    In this article, we'll explore the various scenarios where JDK 14 Records prove to be a game-changer. Unlocking the Power of JDK 14 Records: A Simplif...
    程式設計 發佈於2024-11-08

免責聲明: 提供的所有資源部分來自互聯網,如果有侵犯您的版權或其他權益,請說明詳細緣由並提供版權或權益證明然後發到郵箱:[email protected] 我們會在第一時間內為您處理。

Copyright© 2022 湘ICP备2022001581号-3