国产av日韩一区二区三区精品,成人性爱视频在线观看,国产,欧美,日韩,一区,www.成色av久久成人,2222eeee成人天堂

首頁 web前端 js教程 探索角度形式:信號的新替代方案

探索角度形式:信號的新替代方案

Nov 08, 2024 am 07:03 AM

Exploring Angular Forms: A New Alternative with Signals

探索角度形式:信號的新替代方案

在 Angular 的世界中,無論您是在制作簡單的登錄頁面還是更復(fù)雜的用戶配置文件界面,表單對于用戶交互都是至關(guān)重要的。 Angular 傳統(tǒng)上提供兩種主要方法:模板驅(qū)動表單反應(yīng)式表單。在我之前的 Angular 反應(yīng)式表單系列中,我探索了如何利用反應(yīng)式表單的強(qiáng)大功能來管理復(fù)雜邏輯、創(chuàng)建動態(tài)表單以及構(gòu)建自定義表單控件。

用于管理反應(yīng)性的新工具 - 信號 - 已在 Angular 版本 16 中引入,此后一直是 Angular 維護(hù)人員關(guān)注的焦點(diǎn),并在版本 17 中變得穩(wěn)定。信號允許您處理狀態(tài)更改聲明性地,提供了一個令人興奮的替代方案,將模板驅(qū)動表單的簡單性與反應(yīng)表單的強(qiáng)大反應(yīng)性結(jié)合起來。本文將研究信號如何為 Angular 中的簡單和復(fù)雜形式添加反應(yīng)性。

回顧:角度形式方法

在深入探討使用信號增強(qiáng)模板驅(qū)動表單的主題之前,讓我們快速回顧一下 Angular 的傳統(tǒng)表單方法:

  1. 模板驅(qū)動表單:使用 ngModel 等指令直接在 HTML 模板中定義,這些表單易于設(shè)置,非常適合簡單表單。但是,它們可能無法提供更復(fù)雜場景所需的細(xì)粒度控制。

    這是模板驅(qū)動表單的最小示例:

    <form (ngSubmit)="onSubmit()">
      <label for="name">Name:</label>
      <input>
    
    </li>
    </ol>
    
    
    
    <pre class="brush:php;toolbar:false">```typescript
    import { Component } from '@angular/core';
    
    @Component({
      selector: 'app-root',
      templateUrl: './app.component.html'
    })
    export class AppComponent {
      name = '';
    
      onSubmit() {
        console.log(this.name);
      }
    }
    ```
    
    1. 反應(yīng)式表單:使用 Angular 的 FormGroup、FormControl 和 FormArray 類在組件類中以編程方式進(jìn)行管理;反應(yīng)式表單提供對表單狀態(tài)和驗(yàn)證的精細(xì)控制。正如我之前關(guān)于 Angular Reactive Forms 的文章所討論的那樣,這種方法非常適合復(fù)雜的表單。

      這是一個反應(yīng)式形式的最小示例:

      import { Component } from '@angular/core';
      import { FormGroup, FormControl } from '@angular/forms';
      
      @Component({
        selector: 'app-root',
        templateUrl: './app.component.html'
      })
      export class AppComponent {
        form = new FormGroup({
          name: new FormControl('')
        });
      
        onSubmit() {
          console.log(this.form.value);
        }
      }
      
    ```html
    <form [formGroup]="form" (ngSubmit)="onSubmit()">
      <label for="name">Name:</label>
      <input>
    
    
    
    <h2>
      
      
      Introducing Signals as a New Way to Handle Form Reactivity
    </h2>
    
    <p>With the release of Angular 16, signals have emerged as a new way to manage reactivity. Signals provide a declarative approach to state management, making your code more predictable and easier to understand. When applied to forms, signals can enhance the simplicity of template-driven forms while offering the reactivity and control typically associated with reactive forms.</p>
    
    <p>Let’s explore how signals can be used in both simple and complex form scenarios.</p>
    
    <h3>
      
      
      Example 1: A Simple Template-Driven Form with Signals
    </h3>
    
    <p>Consider a basic login form. Typically, this would be implemented using template-driven forms like this:<br>
    </p>
    
    <pre class="brush:php;toolbar:false"><!-- login.component.html -->
    <form name="form" (ngSubmit)="onSubmit()">
      <label for="email">E-mail</label>
      <input type="email">
    
    
    
    
    
    <pre class="brush:php;toolbar:false">// login.component.ts
    import { Component } from "@angular/core";
    
    @Component({
      selector: "app-login",
      templateUrl: "./login.component.html",
    })
    export class LoginComponent {
      public email: string = "";
      public password: string = "";
    
      onSubmit() {
        console.log("Form submitted", { email: this.email, password: this.password });
      }
    }
    

    這種方法適用于簡單的表單,但是通過引入信號,我們可以在添加反應(yīng)功能的同時保持簡單性:

    // login.component.ts
    import { Component, computed, signal } from "@angular/core";
    import { FormsModule } from "@angular/forms";
    
    @Component({
      selector: "app-login",
      standalone: true,
      templateUrl: "./login.component.html",
      imports: [FormsModule],
    })
    export class LoginComponent {
      // Define signals for form fields
      public email = signal("");
      public password = signal(""); // Define a computed signal for the form value
    
      public formValue = computed(() => {
        return {
          email: this.email(),
          password: this.password(),
        };
      });
    
      public isFormValid = computed(() => {
        return this.email().length > 0 && this.password().length > 0;
      });
    
      onSubmit() {
        console.log("Form submitted", this.formValue());
      }
    }
    
    <!-- login.component.html -->
    <form name="form" (ngSubmit)="onSubmit()">
      <label for="email">E-mail</label>
      <input type="email">
    
    
    
    <p>In this example, the form fields are defined as signals, allowing for reactive updates whenever the form state changes. The formValue signal provides a computed value that reflects the current state of the form. This approach offers a more declarative way to manage form state and reactivity, combining the simplicity of template-driven forms with the power of signals.</p>
    
    <p>You may be tempted to define the form directly as an object inside a signal. While such an approach may seem more concise, typing into the individual fields does not dispatch reactivity updates, which is usually a deal breaker. Here’s an example StackBlitz with a component suffering from such an issue:</p>
    
    <p>Therefore, if you'd like to react to changes in the form fields, it's better to define each field as a separate signal. By defining each form field as a separate signal, you ensure that changes to individual fields trigger reactivity updates correctly. </p>
    
    <h3>
      
      
      Example 2: A Complex Form with Signals
    </h3>
    
    <p>You may see little benefit in using signals for simple forms like the login form above, but they truly shine when handling more complex forms. Let's explore a more intricate scenario - a user profile form that includes fields like firstName, lastName, email, phoneNumbers, and address. The phoneNumbers field is dynamic, allowing users to add or remove phone numbers as needed.</p>
    
    <p>Here's how this form might be defined using signals:<br>
    </p>
    
    <pre class="brush:php;toolbar:false">// user-profile.component.ts
    import { JsonPipe } from "@angular/common";
    import { Component, computed, signal } from "@angular/core";
    import { FormsModule, Validators } from "@angular/forms";
    
    @Component({
      standalone: true,
      selector: "app-user-profile",
      templateUrl: "./user-profile.component.html",
      styleUrls: ["./user-profile.component.scss"],
      imports: [FormsModule, JsonPipe],
    })
    export class UserProfileComponent {
      public firstName = signal("");
      public lastName = signal("");
      public email = signal(""); 
      // We need to use a signal for the phone numbers, so we get reactivity when typing in the input fields
      public phoneNumbers = signal([signal("")]);
      public street = signal("");
      public city = signal("");
      public state = signal("");
      public zip = signal("");
    
      public formValue = computed(() => {
        return {
          firstName: this.firstName(),
          lastName: this.lastName(),
          email: this.email(), // We need to do a little mapping here, so we get the actual value for the phone numbers
          phoneNumbers: this.phoneNumbers().map((phoneNumber) => phoneNumber()),
          address: {
            street: this.street(),
            city: this.city(),
            state: this.state(),
            zip: this.zip(),
          },
        };
      });
    
      public formValid = computed(() => {
        const { firstName, lastName, email, phoneNumbers, address } = this.formValue(); // Regex taken from the Angular email validator
    
        const EMAIL_REGEXP = /^(?=.{1,254}$)(?=.{1,64}@)[a-zA-Z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-zA-Z0-9!#$%&'*+/=?^_`{|}~-]+)*@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/;
        const isEmailFormatValid = EMAIL_REGEXP.test(email);
    
        return (
          firstName.length > 0 &&
          lastName.length > 0 &&
          email.length > 0 &&
          isEmailFormatValid &&
          phoneNumbers.length > 0 && // Check if all phone numbers are valid
          phoneNumbers.every((phoneNumber) => phoneNumber.length > 0) &&
          address.street.length > 0 &&
          address.city.length > 0 &&
          address.state.length > 0 &&
          address.zip.length > 0
        );
      });
    
      addPhoneNumber() {
        this.phoneNumbers.update((phoneNumbers) => {
          phoneNumbers.push(signal(""));
          return [...phoneNumbers];
        });
      }
    
      removePhoneNumber(index: number) {
        this.phoneNumbers.update((phoneNumbers) => {
          phoneNumbers.splice(index, 1);
          return [...phoneNumbers];
        });
      }
    }
    

    請注意,phoneNumbers 字段被定義為信號數(shù)組中的一個信號。這種結(jié)構(gòu)使我們能夠跟蹤各個電話號碼的更改并反應(yīng)性地更新表單狀態(tài)。 addPhoneNumber 和removePhoneNumber 方法更新phoneNumbers 信號數(shù)組,觸發(fā)表單中的反應(yīng)性更新。

    <!-- user-profile.component.html -->
    
    
    
    
    <blockquote>
    <p>在模板中,我們使用phoneNumbers信號數(shù)組來動態(tài)渲染電話號碼輸入字段。 addPhoneNumber 和removePhoneNumber 方法允許用戶反應(yīng)性地添加或刪除電話號碼,從而更新表單狀態(tài)。請注意 track 函數(shù)的用法,這是確保 ngFor 指令正確跟蹤phoneNumbers 數(shù)組更改所必需的。</p>
    </blockquote>
    
    <p>這是復(fù)雜表單示例的 StackBlitz 演示,供您試用:</p>
    
    <h3>
      
      
      使用信號驗(yàn)證表單
    </h3>
    
    <p>驗(yàn)證對于任何表單都至關(guān)重要,確保用戶輸入在提交之前符合所需的標(biāo)準(zhǔn)。使用信號,可以以反應(yīng)性和聲明性的方式處理驗(yàn)證。在上面的復(fù)雜表單示例中,我們實(shí)現(xiàn)了一個名為 formValid 的計(jì)算信號,它檢查所有字段是否滿足特定的驗(yàn)證標(biāo)準(zhǔn)。</p>
    
    <p>可以輕松自定義驗(yàn)證邏輯以適應(yīng)不同的規(guī)則,例如檢查有效的電子郵件格式或確保填寫所有必填字段。使用信號進(jìn)行驗(yàn)證可以讓您創(chuàng)建更多可維護(hù)和可測試的代碼,因?yàn)轵?yàn)證規(guī)則被明確定義并自動對表單字段中的更改做出反應(yīng)。它甚至可以被抽象為一個單獨(dú)的實(shí)用程序,以使其可以在不同形式中重用。</p>
    
    <p>在復(fù)雜表單示例中,formValid 信號可確保填寫所有必填字段并驗(yàn)證電子郵件和電話號碼格式。</p>
    
    <p>這種驗(yàn)證方法有點(diǎn)簡單,需要更好地連接到實(shí)際的表單字段。雖然它適用于許多用例,但在某些情況下,您可能需要等到 Angular 中添加顯式“信號形式”支持。 Tim Deschryver 開始實(shí)現(xiàn)一些圍繞信號形式的抽象,包括驗(yàn)證,并寫了一篇關(guān)于它的文章。讓我們看看將來 Angular 中是否會添加這樣的東西。</p>
    
    <h3>
      
      
      為什么使用角度形式的信號?
    </h3>
    
    <p>Angular 中信號的采用提供了一種強(qiáng)大的新方法來管理表單狀態(tài)和反應(yīng)性。信號提供了一種靈活的聲明性方法,可以通過結(jié)合模板驅(qū)動表單和反應(yīng)式表單的優(yōu)勢來簡化復(fù)雜的表單處理。以下是使用 Angular 形式的信號的一些主要好處:</p>
    
    <ol>
    <li><p><strong>聲明式狀態(tài)管理</strong>:信號允許您以聲明方式定義表單字段和計(jì)算值,使您的代碼更可預(yù)測且更易于理解。</p></li>
    <li><p><strong>反應(yīng)性</strong>:信號為表單字段提供反應(yīng)性更新,確保表單狀態(tài)的更改自動觸發(fā)反應(yīng)性更新。</p></li>
    <li><p><strong>粒度控制</strong>:信號允許您在粒度級別定義表單字段,從而實(shí)現(xiàn)對表單狀態(tài)和驗(yàn)證的細(xì)粒度控制。</p></li>
    <li><p><strong>動態(tài)表單</strong>:信號可用于創(chuàng)建帶有可動態(tài)添加或刪除字段的動態(tài)表單,提供靈活的方式來處理復(fù)雜的表單場景。</p></li>
    <li><p><strong>簡單性</strong>:與傳統(tǒng)的反應(yīng)式表單相比,信號可以提供更簡單、更簡潔的方式來管理表單狀態(tài),使構(gòu)建和維護(hù)復(fù)雜表單變得更加容易。</p></li>
    </ol>
    
    <h3>
      
      
      結(jié)論
    </h3>
    
    <p>在我之前的文章中,我們探索了 Angular 反應(yīng)式表單的強(qiáng)大功能,從動態(tài)表單構(gòu)建到自定義表單控件。隨著信號的引入,Angular 開發(fā)人員擁有了一種新工具,它將模板驅(qū)動表單的簡單性與反應(yīng)式表單的反應(yīng)性融為一體。</p>
    
    <p>雖然許多用例都需要反應(yīng)式表單,但信號為需要更直接、聲明性方法的 Angular 應(yīng)用程序中的表單狀態(tài)管理提供了一種全新、強(qiáng)大的替代方案。隨著 Angular 的不斷發(fā)展,嘗試這些新功能將幫助您構(gòu)建更易于維護(hù)、性能更高的應(yīng)用程序。</p>
    
    <p>編碼愉快!</p>
    
    
              
    
                
            

以上是探索角度形式:信號的新替代方案的詳細(xì)內(nèi)容。更多信息請關(guān)注PHP中文網(wǎng)其他相關(guān)文章!

本站聲明
本文內(nèi)容由網(wǎng)友自發(fā)貢獻(xiàn),版權(quán)歸原作者所有,本站不承擔(dān)相應(yīng)法律責(zé)任。如您發(fā)現(xiàn)有涉嫌抄襲侵權(quán)的內(nèi)容,請聯(lián)系admin@php.cn

熱AI工具

Undress AI Tool

Undress AI Tool

免費(fèi)脫衣服圖片

Undresser.AI Undress

Undresser.AI Undress

人工智能驅(qū)動的應(yīng)用程序,用于創(chuàng)建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用于從照片中去除衣服的在線人工智能工具。

Clothoff.io

Clothoff.io

AI脫衣機(jī)

Video Face Swap

Video Face Swap

使用我們完全免費(fèi)的人工智能換臉工具輕松在任何視頻中換臉!

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費(fèi)的代碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

功能強(qiáng)大的PHP集成開發(fā)環(huán)境

Dreamweaver CS6

Dreamweaver CS6

視覺化網(wǎng)頁開發(fā)工具

SublimeText3 Mac版

SublimeText3 Mac版

神級代碼編輯軟件(SublimeText3)

熱門話題

Laravel 教程
1600
29
PHP教程
1500
276
如何在node.js中提出HTTP請求? 如何在node.js中提出HTTP請求? Jul 13, 2025 am 02:18 AM

在Node.js中發(fā)起HTTP請求有三種常用方式:使用內(nèi)置模塊、axios和node-fetch。1.使用內(nèi)置的http/https模塊無需依賴,適合基礎(chǔ)場景,但需手動處理數(shù)據(jù)拼接和錯誤監(jiān)聽,例如用https.get()獲取數(shù)據(jù)或通過.write()發(fā)送POST請求;2.axios是基于Promise的第三方庫,語法簡潔且功能強(qiáng)大,支持async/await、自動JSON轉(zhuǎn)換、攔截器等,推薦用于簡化異步請求操作;3.node-fetch提供類似瀏覽器fetch的風(fēng)格,基于Promise且語法簡單

JavaScript數(shù)據(jù)類型:原始與參考 JavaScript數(shù)據(jù)類型:原始與參考 Jul 13, 2025 am 02:43 AM

JavaScript的數(shù)據(jù)類型分為原始類型和引用類型。原始類型包括string、number、boolean、null、undefined和symbol,其值不可變且賦值時復(fù)制副本,因此互不影響;引用類型如對象、數(shù)組和函數(shù)存儲的是內(nèi)存地址,指向同一對象的變量會相互影響。判斷類型可用typeof和instanceof,但需注意typeofnull的歷史問題。理解這兩類差異有助于編寫更穩(wěn)定可靠的代碼。

JavaScript時間對象,某人構(gòu)建了一個eactexe,在Google Chrome上更快的網(wǎng)站等等 JavaScript時間對象,某人構(gòu)建了一個eactexe,在Google Chrome上更快的網(wǎng)站等等 Jul 08, 2025 pm 02:27 PM

JavaScript開發(fā)者們,大家好!歡迎閱讀本周的JavaScript新聞!本周我們將重點(diǎn)關(guān)注:Oracle與Deno的商標(biāo)糾紛、新的JavaScript時間對象獲得瀏覽器支持、GoogleChrome的更新以及一些強(qiáng)大的開發(fā)者工具。讓我們開始吧!Oracle與Deno的商標(biāo)之爭Oracle試圖注冊“JavaScript”商標(biāo)的舉動引發(fā)爭議。Node.js和Deno的創(chuàng)建者RyanDahl已提交請?jiān)笗?,要求取消該商?biāo),他認(rèn)為JavaScript是一個開放標(biāo)準(zhǔn),不應(yīng)由Oracle

什么是緩存API?如何與服務(wù)人員使用? 什么是緩存API?如何與服務(wù)人員使用? Jul 08, 2025 am 02:43 AM

CacheAPI是瀏覽器提供的一種緩存網(wǎng)絡(luò)請求的工具,常與ServiceWorker配合使用,以提升網(wǎng)站性能和離線體驗(yàn)。1.它允許開發(fā)者手動存儲如腳本、樣式表、圖片等資源;2.可根據(jù)請求匹配緩存響應(yīng);3.支持刪除特定緩存或清空整個緩存;4.通過ServiceWorker監(jiān)聽fetch事件實(shí)現(xiàn)緩存優(yōu)先或網(wǎng)絡(luò)優(yōu)先等策略;5.常用于離線支持、加快重復(fù)訪問速度、預(yù)加載關(guān)鍵資源及后臺更新內(nèi)容;6.使用時需注意緩存版本控制、存儲限制及與HTTP緩存機(jī)制的區(qū)別。

處理諾言:鏈接,錯誤處理和承諾在JavaScript中 處理諾言:鏈接,錯誤處理和承諾在JavaScript中 Jul 08, 2025 am 02:40 AM

Promise是JavaScript中處理異步操作的核心機(jī)制,理解鏈?zhǔn)秸{(diào)用、錯誤處理和組合器是掌握其應(yīng)用的關(guān)鍵。1.鏈?zhǔn)秸{(diào)用通過.then()返回新Promise實(shí)現(xiàn)異步流程串聯(lián),每個.then()接收上一步結(jié)果并可返回值或Promise;2.錯誤處理應(yīng)統(tǒng)一使用.catch()捕獲異常,避免靜默失敗,并可在catch中返回默認(rèn)值繼續(xù)流程;3.組合器如Promise.all()(全成功才成功)、Promise.race()(首個完成即返回)和Promise.allSettled()(等待所有完成)

利用Array.Prototype方法用于JavaScript中的數(shù)據(jù)操作 利用Array.Prototype方法用于JavaScript中的數(shù)據(jù)操作 Jul 06, 2025 am 02:36 AM

JavaScript數(shù)組內(nèi)置方法如.map()、.filter()和.reduce()可簡化數(shù)據(jù)處理;1).map()用于一對一轉(zhuǎn)換元素生成新數(shù)組;2).filter()按條件篩選元素;3).reduce()用于聚合數(shù)據(jù)為單一值;使用時應(yīng)避免誤用導(dǎo)致副作用或性能問題。

JS綜述:深入研究JavaScript事件循環(huán) JS綜述:深入研究JavaScript事件循環(huán) Jul 08, 2025 am 02:24 AM

JavaScript的事件循環(huán)通過協(xié)調(diào)調(diào)用棧、WebAPI和任務(wù)隊(duì)列來管理異步操作。1.調(diào)用棧執(zhí)行同步代碼,遇到異步任務(wù)時交由WebAPI處理;2.WebAPI在后臺完成任務(wù)后將回調(diào)放入相應(yīng)的隊(duì)列(宏任務(wù)或微任務(wù));3.事件循環(huán)檢查調(diào)用棧是否為空,若為空則從隊(duì)列中取出回調(diào)推入調(diào)用棧執(zhí)行;4.微任務(wù)(如Promise.then)優(yōu)先于宏任務(wù)(如setTimeout)執(zhí)行;5.理解事件循環(huán)有助于避免阻塞主線程并優(yōu)化代碼執(zhí)行順序。

了解事件在JavaScript DOM事件中冒泡和捕獲 了解事件在JavaScript DOM事件中冒泡和捕獲 Jul 08, 2025 am 02:36 AM

事件冒泡是從目標(biāo)元素向外傳播到祖先節(jié)點(diǎn),事件捕獲則是從外層向內(nèi)傳播到目標(biāo)元素。1.事件冒泡:點(diǎn)擊子元素后,事件依次向上觸發(fā)父級元素的監(jiān)聽器,例如點(diǎn)擊按鈕后先輸出Childclicked,再輸出Parentclicked。2.事件捕獲:設(shè)置第三個參數(shù)為true,使監(jiān)聽器在捕獲階段執(zhí)行,如點(diǎn)擊按鈕前先觸發(fā)父元素的捕獲監(jiān)聽器。3.實(shí)際用途包括統(tǒng)一管理子元素事件、攔截預(yù)處理和性能優(yōu)化。4.DOM事件流分為捕獲、目標(biāo)和冒泡三個階段,默認(rèn)監(jiān)聽器在冒泡階段執(zhí)行。

See all articles