”工欲善其事,必先利其器。“—孔子《论语.录灵公》
首页 > 编程 > 绑定和模板:Peasy-UI 系列的一部分

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

发布于2024-11-08
浏览:759

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]删除
最新教程 更多>
  • 可以在纯CS中将多个粘性元素彼此堆叠在一起吗?
    可以在纯CS中将多个粘性元素彼此堆叠在一起吗?
    [2这里: https://webthemez.com/demo/sticky-multi-header-scroll/index.html </main> <section> { display:grid; grid-template-...
    编程 发布于2025-07-14
  • 如何使用不同数量列的联合数据库表?
    如何使用不同数量列的联合数据库表?
    合并列数不同的表 当尝试合并列数不同的数据库表时,可能会遇到挑战。一种直接的方法是在列数较少的表中,为缺失的列追加空值。 例如,考虑两个表,表 A 和表 B,其中表 A 的列数多于表 B。为了合并这些表,同时处理表 B 中缺失的列,请按照以下步骤操作: 确定表 B 中缺失的列,并将它们添加到表的末...
    编程 发布于2025-07-14
  • 同实例无需转储复制MySQL数据库方法
    同实例无需转储复制MySQL数据库方法
    在同一实例上复制一个MySQL数据库而无需转储在同一mySQL实例上复制数据库,而无需创建InterMediate sqql script。以下方法为传统的转储和IMPORT过程提供了更简单的替代方法。 直接管道数据 MySQL手动概述了一种允许将mysqldump直接输出到MySQL clie...
    编程 发布于2025-07-14
  • 如何使用组在MySQL中旋转数据?
    如何使用组在MySQL中旋转数据?
    在关系数据库中使用mySQL组使用mySQL组进行查询结果,在关系数据库中使用MySQL组,转移数据的数据是指重新排列的行和列的重排以增强数据可视化。在这里,我们面对一个共同的挑战:使用组的组将数据从基于行的基于列的转换为基于列。 Let's consider the following ...
    编程 发布于2025-07-14
  • 为什么PYTZ最初显示出意外的时区偏移?
    为什么PYTZ最初显示出意外的时区偏移?
    与pytz 最初从pytz获得特定的偏移。例如,亚洲/hong_kong最初显示一个七个小时37分钟的偏移: 差异源利用本地化将时区分配给日期,使用了适当的时区名称和偏移量。但是,直接使用DateTime构造器分配时区不允许进行正确的调整。 example pytz.timezone(...
    编程 发布于2025-07-14
  • 如何正确使用与PDO参数的查询一样?
    如何正确使用与PDO参数的查询一样?
    在pdo 中使用类似QUERIES在PDO中的Queries时,您可能会遇到类似疑问中描述的问题:此查询也可能不会返回结果,即使$ var1和$ var2包含有效的搜索词。错误在于不正确包含%符号。通过将变量包含在$ params数组中的%符号中,您确保将%字符正确替换到查询中。没有此修改,PDO...
    编程 发布于2025-07-14
  • 为什么尽管有效代码,为什么在PHP中捕获输入?
    为什么尽管有效代码,为什么在PHP中捕获输入?
    在php ;?>" method="post">The intention is to capture the input from the text box and display it when the submit button is clicked.但是,输出...
    编程 发布于2025-07-14
  • 如何有效地选择熊猫数据框中的列?
    如何有效地选择熊猫数据框中的列?
    在处理数据操作任务时,在Pandas DataFrames 中选择列时,选择特定列的必要条件是必要的。在Pandas中,选择列的各种选项。选项1:使用列名 如果已知列索引,请使用ILOC函数选择它们。请注意,python索引基于零。 df1 = df.iloc [:,0:2]#使用索引0和1 c...
    编程 发布于2025-07-14
  • 如何在GO编译器中自定义编译优化?
    如何在GO编译器中自定义编译优化?
    在GO编译器中自定义编译优化 GO中的默认编译过程遵循特定的优化策略。 However, users may need to adjust these optimizations for specific requirements.Optimization Control in Go Compi...
    编程 发布于2025-07-14
  • C++20 Consteval函数中模板参数能否依赖于函数参数?
    C++20 Consteval函数中模板参数能否依赖于函数参数?
    [ consteval函数和模板参数依赖于函数参数在C 17中,模板参数不能依赖一个函数参数,因为编译器仍然需要对非contexexpr futcoriations contim at contexpr function进行评估。 compile time。 C 20引入恒定函数,必须在编译时进行...
    编程 发布于2025-07-14
  • CSS可以根据任何属性值来定位HTML元素吗?
    CSS可以根据任何属性值来定位HTML元素吗?
    靶向html元素,在CSS 中使用任何属性值,在CSS中,可以基于特定属性(如下所示)基于特定属性的基于特定属性的emants目标元素: 字体家庭:康斯拉斯(Consolas); } 但是,出现一个常见的问题:元素可以根据任何属性值而定位吗?本文探讨了此主题。的目标元素有任何任何属性值,属...
    编程 发布于2025-07-14
  • 为什么在我的Linux服务器上安装Archive_Zip后,我找不到“ class \” class \'ziparchive \'错误?
    为什么在我的Linux服务器上安装Archive_Zip后,我找不到“ class \” class \'ziparchive \'错误?
    class'ziparchive'在Linux Server上安装Archive_zip时找不到错误 commant in lin ins in cland ins in lin.11 on a lin.1 in a lin.11错误:致命错误:在... cass中找不到类z...
    编程 发布于2025-07-14
  • 为什么不````''{margin:0; }`始终删除CSS中的最高边距?
    为什么不````''{margin:0; }`始终删除CSS中的最高边距?
    在CSS 问题:不正确的代码: 全球范围将所有余量重置为零,如提供的代码所建议的,可能会导致意外的副作用。解决特定的保证金问题是更建议的。 例如,在提供的示例中,将以下代码添加到CSS中,将解决余量问题: body H1 { 保证金顶:-40px; } 此方法更精确,避免了由全局保证金重置引...
    编程 发布于2025-07-14
  • 如何使用Depimal.parse()中的指数表示法中的数字?
    如何使用Depimal.parse()中的指数表示法中的数字?
    在尝试使用Decimal.parse(“ 1.2345e-02”中的指数符号表示法表示的字符串时,您可能会遇到错误。这是因为默认解析方法无法识别指数符号。 成功解析这样的字符串,您需要明确指定它代表浮点数。您可以使用numbersTyles.Float样式进行此操作,如下所示:[&& && && ...
    编程 发布于2025-07-14
  • 如何在Java的全屏独家模式下处理用户输入?
    如何在Java的全屏独家模式下处理用户输入?
    Handling User Input in Full Screen Exclusive Mode in JavaIntroductionWhen running a Java application in full screen exclusive mode, the usual event ha...
    编程 发布于2025-07-14

免责声明: 提供的所有资源部分来自互联网,如果有侵犯您的版权或其他权益,请说明详细缘由并提供版权或权益证明然后发到邮箱:[email protected] 我们会第一时间内为您处理。

Copyright© 2022 湘ICP备2022001581号-3