Rumah > Artikel > hujung hadapan web > Meneroka Bentuk Sudut: Alternatif Baharu dengan Isyarat
Dalam dunia Angular, borang adalah penting untuk interaksi pengguna, sama ada anda membuat halaman log masuk yang mudah atau antara muka profil pengguna yang lebih kompleks. Angular secara tradisinya menawarkan dua pendekatan utama: borang dipacu templat dan borang reaktif. Dalam siri terdahulu saya tentang Borang Reaktif Sudut, saya meneroka cara memanfaatkan kuasa borang reaktif untuk mengurus logik yang kompleks, mencipta borang dinamik dan membina kawalan borang tersuai.
Alat baharu untuk mengurus kereaktifan - isyarat - telah diperkenalkan dalam versi 16 Angular dan telah menjadi tumpuan penyelenggara Sudut sejak itu, menjadi stabil dengan versi 17. Isyarat membolehkan anda mengendalikan perubahan keadaan secara deklaratif, menawarkan alternatif menarik yang menggabungkan kesederhanaan bentuk dipacu templat dengan kereaktifan teguh bentuk reaktif. Artikel ini akan mengkaji cara isyarat boleh menambah kereaktifan kepada kedua-dua bentuk ringkas dan kompleks dalam Sudut.
Sebelum menyelami topik mempertingkatkan borang dipacu templat dengan isyarat, mari kita imbas kembali pendekatan bentuk tradisional Angular dengan cepat:
Borang Dipacu Templat: Ditakrifkan terus dalam templat HTML menggunakan arahan seperti ngModel, borang ini mudah disediakan dan sesuai untuk borang ringkas. Walau bagaimanapun, mereka mungkin tidak menyediakan kawalan terperinci yang diperlukan untuk senario yang lebih kompleks.
Berikut ialah contoh minimum borang dipacu templat:
<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); } } ```
Borang Reaktif: Diuruskan secara pengaturcaraan dalam kelas komponen menggunakan kelas FormGroup, FormControl dan FormArray Angular; borang reaktif menawarkan kawalan berbutir ke atas keadaan borang dan pengesahan. Pendekatan ini sangat sesuai untuk bentuk yang kompleks, seperti yang dibincangkan dalam artikel saya sebelum ini tentang Borang Reaktif Sudut.
Dan berikut ialah contoh minimum bentuk reaktif:
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 }); } }
Pendekatan ini berfungsi dengan baik untuk bentuk ringkas, tetapi dengan memperkenalkan isyarat, kami boleh mengekalkan kesederhanaan sambil menambah keupayaan reaktif:
// 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]; }); } }
Perhatikan bahawa medan phoneNumbers ditakrifkan sebagai isyarat bagi susunan isyarat. Struktur ini membolehkan kami menjejaki perubahan pada nombor telefon individu dan mengemas kini keadaan borang secara reaktif. Kaedah addPhoneNumber dan removePhoneNumber mengemas kini tatasusunan isyarat phoneNumbers, mencetuskan kemas kini kereaktifan dalam borang.
<!-- user-profile.component.html --> <borang> <blockquote> <p>Dalam templat, kami menggunakan tatasusunan isyarat phoneNumbers untuk memaparkan medan input nombor telefon secara dinamik. Kaedah addPhoneNumber dan removePhoneNumber membolehkan pengguna menambah atau mengalih keluar nombor telefon secara reaktif, mengemas kini keadaan borang. Perhatikan penggunaan fungsi trek, yang diperlukan untuk memastikan bahawa arahan ngFor menjejaki perubahan kepada tatasusunan phoneNumbers dengan betul.</p> </blockquote> <p>Berikut ialah demo StackBlitz bagi contoh bentuk kompleks untuk anda bermain-main dengan:</p> <h3> Mengesahkan Borang dengan Isyarat </h3> <p>Pengesahan adalah penting untuk sebarang bentuk, memastikan input pengguna memenuhi kriteria yang diperlukan sebelum penyerahan. Dengan isyarat, pengesahan boleh dikendalikan secara reaktif dan deklaratif. Dalam contoh bentuk kompleks di atas, kami telah melaksanakan isyarat yang dikira dipanggil formValid, yang menyemak sama ada semua medan memenuhi kriteria pengesahan tertentu.</p> <p>Logik pengesahan boleh disesuaikan dengan mudah untuk menampung peraturan yang berbeza, seperti menyemak format e-mel yang sah atau memastikan semua medan yang diperlukan diisi. Menggunakan isyarat untuk pengesahan membolehkan anda mencipta kod yang lebih boleh diselenggara dan boleh diuji, kerana peraturan pengesahan ditakrifkan dengan jelas dan bertindak balas secara automatik kepada perubahan dalam medan borang. Ia juga boleh disarikan ke dalam utiliti yang berasingan untuk menjadikannya boleh digunakan semula dalam bentuk yang berbeza.</p> <p>Dalam contoh borang yang kompleks, isyarat formValid memastikan semua medan yang diperlukan diisi dan mengesahkan format e-mel dan nombor telefon.</p> <p>Pendekatan untuk pengesahan ini agak mudah dan perlu disambungkan dengan lebih baik kepada medan borang sebenar. Walaupun ia akan berfungsi untuk banyak kes penggunaan, dalam sesetengah kes, anda mungkin perlu menunggu sehingga sokongan "bentuk isyarat" yang jelas ditambahkan pada Angular. Tim Deschryver mula melaksanakan beberapa abstraksi di sekitar bentuk isyarat, termasuk pengesahan dan menulis artikel mengenainya. Mari lihat sama ada sesuatu seperti ini akan ditambahkan pada Angular pada masa hadapan.</p> <h3> Mengapa Menggunakan Isyarat dalam Bentuk Sudut? </h3> <p>Penggunaan isyarat dalam Angular menyediakan cara baharu yang berkuasa untuk mengurus keadaan bentuk dan kereaktifan. Isyarat menawarkan pendekatan deklaratif yang fleksibel yang boleh memudahkan pengendalian borang yang kompleks dengan menggabungkan kekuatan borang dipacu templat dan bentuk reaktif. Berikut ialah beberapa faedah utama menggunakan isyarat dalam bentuk Sudut:</p> <ol> <li><p><strong>Pengurusan Negeri Deklaratif</strong>: Isyarat membolehkan anda mentakrifkan medan borang dan nilai yang dikira secara deklaratif, menjadikan kod anda lebih mudah diramal dan lebih mudah difahami.</p></li> <li><p><strong>Kereaktifan</strong>: Isyarat menyediakan kemas kini reaktif pada medan borang, memastikan perubahan kepada keadaan borang mencetuskan kemas kini reaktiviti secara automatik.</p></li> <li><p><strong>Kawalan Butiran</strong>: Isyarat membolehkan anda mentakrifkan medan borang pada tahap berbutir, membolehkan kawalan terperinci ke atas keadaan dan pengesahan borang.</p></li> <li><p><strong>Borang Dinamik</strong>: Isyarat boleh digunakan untuk mencipta borang dinamik dengan medan yang boleh ditambah atau dialih keluar secara dinamik, menyediakan cara yang fleksibel untuk mengendalikan senario bentuk yang kompleks.</p></li> <li><p><strong>Kesederhanaan</strong>: Isyarat boleh menawarkan cara yang lebih ringkas, lebih ringkas untuk mengurus keadaan bentuk berbanding bentuk reaktif tradisional, menjadikan pembinaan dan penyelenggaraan bentuk kompleks lebih mudah.</p></li> </ol> <h3> Kesimpulan </h3> <p>Dalam artikel saya sebelum ini, kami meneroka ciri hebat bentuk reaktif Sudut, daripada pembinaan bentuk dinamik kepada kawalan bentuk tersuai. Dengan pengenalan isyarat, pembangun Angular mempunyai alat baharu yang menggabungkan kesederhanaan borang dipacu templat dengan kereaktifan bentuk reaktif.</p> <p>Walaupun banyak kes penggunaan memerlukan Borang Reaktif, isyarat menyediakan alternatif baharu yang berkuasa untuk mengurus keadaan borang dalam aplikasi Sudut yang memerlukan pendekatan deklaratif yang lebih mudah. Memandangkan Angular terus berkembang, bereksperimen dengan ciri baharu ini akan membantu anda membina lebih banyak aplikasi yang boleh diselenggara dan berprestasi.</p> <p>Selamat pengekodan!</p>
Atas ialah kandungan terperinci Meneroka Bentuk Sudut: Alternatif Baharu dengan Isyarat. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!