ส่วนประกอบต่างๆมีอยู่ใน Angular ตั้งแต่เริ่มต้น อย่างไรก็ตามหลายคนยังพบว่าตัวเองใช้ส่วนประกอบไม่ถูกต้อง ในงานของฉันฉันเคยเห็นคนไม่ได้ใช้เลยสร้างส่วนประกอบแทนคำสั่งแอตทริบิวต์และอื่น ๆ สิ่งเหล่านี้เป็นประเด็นที่รุ่นน้องและรุ่นพี่ นักพัฒนาเชิงมุม มีแนวโน้มที่จะสร้างตัวเองเหมือนกัน ดังนั้นโพสต์นี้มีไว้สำหรับคนอย่างฉันเมื่อฉันเรียน Angular เนื่องจากไม่มีเอกสารอย่างเป็นทางการหรือเอกสารที่ไม่เป็นทางการเกี่ยวกับส่วนประกอบที่อธิบายด้วยกรณีการใช้งานว่าจะใช้ส่วนประกอบอย่างไรและเมื่อใด
ในบทความนี้ฉันจะระบุวิธีที่ถูกต้องและไม่ถูกต้องในการใช้ส่วนประกอบเชิงมุมพร้อมตัวอย่าง โพสต์นี้ควรให้แนวคิดที่ชัดเจนเกี่ยวกับ:
ก่อนที่เราจะข้ามไปสู่การใช้ส่วนประกอบเชิงมุมที่ถูกต้องฉันต้องการสัมผัสสั้น ๆ เกี่ยวกับหัวข้อส่วนประกอบโดยทั่วไป โดยทั่วไปแล้วแอปพลิเคชัน Angular แต่ละตัวจะมีองค์ประกอบอย่างน้อยหนึ่งองค์ประกอบตามค่าเริ่มต้นนั่นคือ root component
จากนั้นขึ้นอยู่กับเราว่าจะออกแบบแอปพลิเคชันของเราอย่างไร โดยปกติคุณจะสร้างคอมโพเนนต์สำหรับเพจแยกกันจากนั้นแต่ละเพจจะมีรายการคอมโพเนนต์แยกกัน ตามหลักการทั่วไปส่วนประกอบต้องเป็นไปตามเกณฑ์ต่อไปนี้:
ลองนึกภาพสถานการณ์ที่เรามีแอปพลิเคชันซึ่งมีสองหน้า: งานที่จะเกิดขึ้น และ งานที่เสร็จสมบูรณ์ . ใน งานที่จะเกิดขึ้น เราสามารถดูงานที่จะเกิดขึ้นทำเครื่องหมายเป็น 'เสร็จสิ้น' และสุดท้ายเพิ่มงานใหม่ ในทำนองเดียวกันในไฟล์ งานที่เสร็จสมบูรณ์ เราสามารถดูงานที่เสร็จสมบูรณ์และทำเครื่องหมายว่า 'เลิกทำ' ได้ สุดท้ายเรามีลิงก์การนำทางซึ่งช่วยให้เราสามารถไปยังหน้าต่างๆได้ ดังที่กล่าวมาเราสามารถแบ่งหน้าต่อไปนี้ออกเป็นสามส่วน: องค์ประกอบราก, หน้า, ส่วนประกอบที่ใช้ซ้ำได้
จากภาพหน้าจอด้านบนเราจะเห็นได้อย่างชัดเจนว่าโครงสร้างของแอปพลิเคชันจะมีลักษณะดังนี้:
── myTasksApplication ├── components │ ├── header-menu.component.ts │ ├── header-menu.component.html │ ├── task-list.component.ts │ └── task-list.component.html ├── pages │ ├── upcoming-tasks.component.ts │ ├── upcoming-tasks.component.html │ ├── completed-tasks.component.ts │ └── completed-tasks.component.html ├── app.component.ts └── app.component.html
มาเชื่อมโยงไฟล์คอมโพเนนต์กับองค์ประกอบจริงบนโครงร่างด้านบน:
header-menu.component
และ task-list.component
เป็นส่วนประกอบที่ใช้ซ้ำได้ซึ่งแสดงด้วยเส้นขอบสีเขียวในภาพหน้าจอโครงร่างupcoming-tasks.component
และ completed-tasks.component
คือหน้าต่างๆที่แสดงด้วยเส้นขอบสีเหลืองในภาพหน้าจอโครงร่างด้านบน และapp.component
คือองค์ประกอบรากซึ่งแสดงด้วยเส้นขอบสีแดงในภาพหน้าจอโครงร่างดังที่กล่าวไปแล้วเราสามารถระบุตรรกะและการออกแบบแยกกันสำหรับแต่ละองค์ประกอบได้ จากโครงร่างด้านบนเรามีสองหน้าที่นำองค์ประกอบหนึ่งมาใช้ใหม่ - task-list.component
คำถามจะเกิดขึ้น - เราจะระบุได้อย่างไรว่าเราควรแสดงข้อมูลประเภทใดในหน้าใดหน้าหนึ่ง โชคดีที่เราไม่ต้องกังวลเกี่ยวกับเรื่องนี้เพราะเมื่อคุณสร้างส่วนประกอบคุณสามารถระบุได้ อินพุต และ เอาต์พุต ตัวแปร
ความแตกต่างระหว่าง ac และ s corp
ตัวแปรอินพุตถูกใช้ภายในคอมโพเนนต์เพื่อส่งผ่านข้อมูลบางส่วนจากคอมโพเนนต์หลัก ในตัวอย่างข้างต้นเราสามารถมีพารามิเตอร์อินพุตสองตัวสำหรับ task-list.component
- tasks
และ listType
. ดังนั้น tasks
จะเป็นรายการสตริงที่จะแสดงแต่ละสตริงในแถวที่แยกจากกันในขณะที่ listType
จะเป็นอย่างใดอย่างหนึ่ง กำลังจะเกิดขึ้น หรือ เสร็จสมบูรณ์ ซึ่งจะระบุว่ามีการเลือกช่องทำเครื่องหมายหรือไม่ ด้านล่างนี้คุณจะพบข้อมูลโค้ดขนาดเล็กที่แสดงลักษณะของส่วนประกอบจริง
// task-list.component.ts import { Component, Input } from '@angular/core'; @Component({ selector: 'app-task-list', templateUrl: 'task-list.component.html' }) export class TaskListComponent { @Input() tasks: string[] = []; // List of tasks which should be displayed. @Input() listType: 'upcoming' | 'completed' = 'upcoming'; // Type of the task list. constructor() { } }
เช่นเดียวกับตัวแปรอินพุตตัวแปรเอาต์พุตยังสามารถใช้เพื่อส่งผ่านข้อมูลบางอย่างระหว่างคอมโพเนนต์ แต่คราวนี้ไปยังคอมโพเนนต์หลัก ตัวอย่างเช่นสำหรับ task-list.component
เราสามารถมีตัวแปรเอาต์พุต itemChecked
มันจะแจ้งส่วนประกอบหลักหากมีการตรวจสอบหรือไม่เลือกรายการ ตัวแปรเอาต์พุตต้องเป็น ตัวปล่อยเหตุการณ์ . ด้านล่างนี้คุณจะพบข้อมูลโค้ดขนาดเล็กที่แสดงให้เห็นว่าคอมโพเนนต์จะมีลักษณะอย่างไรด้วยตัวแปรเอาต์พุต
// task-list.component.ts import { Component, Input, Output } from '@angular/core'; @Component({ selector: 'app-task-list', templateUrl: 'task-list.component.html' }) export class TaskListComponent { @Input() tasks: string[] = []; // List of tasks which should be displayed. @Input() listType: 'upcoming' | 'completed' = 'upcoming'; // Type of the task list. @Output() itemChecked: EventEmitter = new EventEmitter(); @Output() tasksChange: EventEmitter = new EventEmitter(); constructor() { } /** * Is called when an item from the list is checked. * @param selected---Value which indicates if the item is selected or deselected. */ onItemCheck(selected: boolean) { this.itemChecked.emit(selected); } /** * Is called when task list is changed. * @param changedTasks---Changed task list value, which should be sent to the parent component. */ onTasksChanged(changedTasks: string[]) { this.taskChange.emit(changedTasks); } }
เป็นไปได้ task-list.component.ts
เนื้อหาหลังจากเพิ่มตัวแปรเอาต์พุตมาดูวิธีใช้ส่วนประกอบนี้ภายในองค์ประกอบหลักและวิธีการเชื่อมโยงตัวแปรประเภทต่างๆ ใน Angular มีสองวิธีในการผูกตัวแปรอินพุต - การผูกทางเดียวซึ่งหมายความว่าคุณสมบัติต้องถูกห่อด้วยวงเล็บเหลี่ยม []
และการโยงสองทางซึ่งหมายความว่าคุณสมบัตินั้นจะต้องถูกรวมไว้ภายในสี่เหลี่ยม และวงเล็บกลม [()]
. ดูตัวอย่างด้านล่างและดูวิธีต่างๆในการส่งผ่านข้อมูลระหว่างส่วนประกอบต่างๆ
เป็นไปได้ upcoming-tasks.component.html
เนื้อหามาดูพารามิเตอร์แต่ละตัวกัน:
tasks
พารามิเตอร์ถูกส่งผ่านโดยใช้การรวมสองทาง นั่นหมายความว่าในกรณีที่พารามิเตอร์งานมีการเปลี่ยนแปลงภายในคอมโพเนนต์ลูกคอมโพเนนต์พาเรนต์จะสะท้อนการเปลี่ยนแปลงเหล่านั้นบน upcomingTasks
ตัวแปร. ในการอนุญาตการเชื่อมโยงข้อมูลสองทางคุณต้องสร้างพารามิเตอร์เอาต์พุตซึ่งตามหลังเทมเพลต“ [inputParameterName] Change” ในกรณีนี้ tasksChange
listType
พารามิเตอร์ถูกส่งผ่านโดยใช้การรวมทางเดียว ซึ่งหมายความว่าสามารถเปลี่ยนแปลงได้ภายในองค์ประกอบย่อย แต่จะไม่ปรากฏในองค์ประกอบหลัก โปรดทราบว่าฉันสามารถกำหนดค่า 'upcoming'
ได้ ไปยังพารามิเตอร์ภายในส่วนประกอบและส่งผ่านสิ่งนั้นไปแทนซึ่งจะไม่สร้างความแตกต่างitemChecked
พารามิเตอร์เป็นฟังก์ชั่นผู้ฟังและจะถูกเรียกเมื่อใดก็ตาม onItemCheck ถูกดำเนินการบน task-list.component
. หากมีการตรวจสอบรายการ $event
จะเก็บค่า true
แต่ถ้าไม่เลือกก็จะเก็บค่า false
อย่างที่คุณเห็นโดยทั่วไป Angular เป็นวิธีที่ยอดเยี่ยมในการส่งผ่านและแบ่งปันข้อมูลระหว่างส่วนประกอบต่างๆดังนั้นคุณไม่ควรกลัวที่จะใช้ เพียงตรวจสอบให้แน่ใจว่าใช้อย่างชาญฉลาดและไม่ใช้มากเกินไป
ตามที่กล่าวไว้ก่อนหน้านี้คุณไม่ควรกลัวที่จะใช้ส่วนประกอบเชิงมุม แต่คุณควรใช้อย่างชาญฉลาด
ดังนั้นเมื่อ คุณควร สร้างส่วนประกอบเชิงมุม?
task-list.component
เราเรียกพวกเขาว่า ส่วนประกอบที่ใช้ซ้ำได้ .กฎทั้งสามนี้ช่วยให้ฉันระบุได้ว่าฉันจำเป็นต้องสร้างองค์ประกอบใหม่หรือไม่และกฎเหล่านี้ทำให้ฉันมีวิสัยทัศน์ที่ชัดเจนเกี่ยวกับบทบาทขององค์ประกอบนั้นโดยอัตโนมัติ ตามหลักการแล้วเมื่อคุณสร้างส่วนประกอบคุณควรรู้อยู่แล้วว่าจะมีบทบาทอย่างไรในแอปพลิเคชัน
แบบสอบถามสื่อ css ออกแบบตอบสนอง
เนื่องจากเราได้ดูการใช้งานของ ส่วนประกอบที่ใช้ซ้ำได้ มาดูการใช้งานของ ส่วนประกอบขององค์กรรหัส . สมมติว่าเรามีแบบฟอร์มการลงทะเบียนและที่ด้านล่างของแบบฟอร์มเรามีช่อง ข้อกำหนดและเงื่อนไข . โดยปกติ Legalese มักจะมีขนาดใหญ่มากและใช้พื้นที่มากในกรณีนี้คือในเทมเพลต HTML ลองดูตัวอย่างนี้แล้วดูว่าเราจะเปลี่ยนแปลงได้อย่างไร
ในตอนแรกเรามีองค์ประกอบเดียวคือ registration.component
- ซึ่งเก็บทุกอย่างรวมถึงแบบฟอร์มการลงทะเบียนและข้อกำหนดในการให้บริการ
รหัสที่ได้รับการทดสอบแล้วและใช้งานในสถานการณ์ต่างๆ เรียกว่า ____
Registration
Username
Password
Text with very long terms and conditions. Registrate
สถานะเริ่มต้นก่อนแยกregister.componentเป็นหลายองค์ประกอบตอนนี้เทมเพลตดูเล็ก แต่ลองนึกดูว่าเราจะเปลี่ยนไหม 'ข้อความที่มีข้อกำหนดและเงื่อนไขที่ยาวมาก' ด้วยข้อความจริงที่มีมากกว่า 1,000 คำจะทำให้การแก้ไขไฟล์ยุ่งยากและไม่สะดวก เรามีวิธีแก้ปัญหาอย่างรวดเร็ว - เราสามารถคิดค้นส่วนประกอบใหม่ terms-and-conditions.component
ซึ่งจะเก็บทุกอย่างที่เกี่ยวข้องกับข้อกำหนดและเงื่อนไข ลองมาดูไฟล์ HTML สำหรับ terms-and-conditions.component
Text with very long terms and conditions.
สร้างขึ้นใหม่Terms-and-Conditions.componentเทมเพลต HTMLและตอนนี้เราสามารถปรับ registration.component
และใช้ terms-and-conditions.component
อยู่ภายใน.
Registration
Username
Password
Registrate
อัปเดตแล้วregister.component.tsแม่แบบที่มีองค์ประกอบขององค์กรรหัสยินดีด้วย! เราเพิ่งลดขนาดของ registration.component
หลายร้อยบรรทัดและทำให้ง่ายต่อการอ่านโค้ด ในตัวอย่างข้างต้นเราได้ทำการเปลี่ยนแปลงแม่แบบของส่วนประกอบ แต่หลักการเดียวกันนี้สามารถนำไปใช้กับตรรกะของส่วนประกอบได้
สุดท้ายสำหรับ ส่วนประกอบการเพิ่มประสิทธิภาพ ฉันขอแนะนำอย่างยิ่งให้คุณผ่านไป โพสต์นี้ เนื่องจากจะให้ข้อมูลทั้งหมดที่จำเป็นในการทำความเข้าใจกับการตรวจจับการเปลี่ยนแปลงและกรณีเฉพาะที่คุณสามารถนำไปใช้ได้ คุณไม่ได้ใช้บ่อยนัก แต่อาจมีบางกรณีและหากคุณสามารถข้ามการตรวจสอบองค์ประกอบหลาย ๆ อย่างเป็นประจำได้เมื่อไม่จำเป็นก็เป็นผลดีต่อประสิทธิภาพ
ตามที่กล่าวมาเราไม่ควรสร้างส่วนประกอบแยกกันเสมอไปดังนั้นมาดูกันว่าเมื่อใดที่คุณควรหลีกเลี่ยงการสร้างส่วนประกอบแยกต่างหาก
มีสามประเด็นหลักตามที่ฉันแนะนำให้สร้างองค์ประกอบเชิงมุมแยกต่างหาก แต่มีบางกรณีที่ฉันจะหลีกเลี่ยงการสร้างองค์ประกอบแยกเช่นกัน
อีกครั้งมาดูหัวข้อย่อยซึ่งจะช่วยให้คุณเข้าใจได้ง่ายเมื่อคุณ ไม่ควร สร้างส่วนประกอบแยกต่างหาก
ตอนนี้เรามาดูอย่างละเอียดและดูทั้งสองกรณีในตัวอย่าง สมมติว่าเราต้องการมีปุ่มที่บันทึกข้อความเมื่อมีการคลิก สิ่งนี้อาจผิดพลาดและอาจมีการสร้างส่วนประกอบแยกต่างหากสำหรับฟังก์ชันการทำงานเฉพาะนี้ซึ่งจะมีปุ่มและการดำเนินการเฉพาะ ก่อนอื่นให้ตรวจสอบวิธีการที่ไม่ถูกต้อง:
// log-button.component.ts import { Component, Input, Output } from '@angular/core'; @Component({ selector: 'app-log-button', templateUrl: 'log-button.component.html' }) export class LogButtonComponent { @Input() name: string; // Name of the button. @Output() buttonClicked: EventEmitter = new EventEmitter(); constructor() { } /** * Is called when button is clicked. * @param clicked - Value which indicates if the button was clicked. */ onButtonClick(clicked: boolean) { console.log('I just clicked a button on this website'); this.buttonClicked.emit(clicked); } }
ตรรกะขององค์ประกอบที่ไม่ถูกต้อง log-button.component.ts
ดังนั้นองค์ประกอบนี้จึงมาพร้อมกับมุมมอง html ต่อไปนี้
{{ name }}
เทมเพลตของส่วนประกอบที่ไม่ถูกต้อง log-button.component.html
อย่างที่คุณเห็นตัวอย่างข้างต้นใช้ได้ผลและคุณสามารถใช้องค์ประกอบข้างต้นตลอดการดูของคุณ มันจะทำในสิ่งที่คุณต้องการในทางเทคนิค แต่วิธีแก้ไขที่ถูกต้องคือการใช้คำสั่ง ซึ่งจะช่วยให้คุณไม่เพียง แต่ลดจำนวนโค้ดที่คุณต้องเขียน แต่ยังเพิ่มความเป็นไปได้ในการนำฟังก์ชันนี้ไปใช้กับองค์ประกอบที่คุณต้องการไม่ใช่แค่ปุ่มเท่านั้น
ผลกระทบของสีที่มีต่อวิธีคิดและความรู้สึกของเรา
import { Directive } from '@angular/core'; @Directive({ selector: '[logButton]', hostListeners: { 'click': 'onButtonClick()', }, }) class LogButton { constructor() {} /** * Fired when element is clicked. */ onButtonClick() { console.log('I just clicked a button on this website'); } }
logButton
คำสั่งซึ่งสามารถกำหนดให้กับองค์ประกอบใดก็ได้ตอนนี้เมื่อเราสร้างคำสั่งของเราแล้วเราสามารถใช้มันในแอปพลิเคชันของเราและกำหนดให้กับองค์ประกอบที่เราต้องการ ตัวอย่างเช่นเราจะนำ registration.component
ของเรากลับมาใช้ใหม่
Registration
Username
Password
Registrate
logButton
คำสั่งที่ใช้กับปุ่มแบบฟอร์มการลงทะเบียนตอนนี้เราสามารถดูกรณีที่สองซึ่งเราไม่ควรสร้างส่วนประกอบแยกต่างหากและนั่นคือสิ่งที่ตรงกันข้ามกับ ส่วนประกอบการเพิ่มประสิทธิภาพรหัส . หากองค์ประกอบที่สร้างขึ้นใหม่ทำให้โค้ดของคุณซับซ้อนและมีขนาดใหญ่ขึ้นก็ไม่จำเป็นต้องสร้างขึ้นมา ลองมาเป็นตัวอย่าง registration.component
ของเรา หนึ่งในกรณีเช่นนี้คือการสร้างส่วนประกอบแยกต่างหากสำหรับป้ายกำกับและช่องป้อนข้อมูลที่มีพารามิเตอร์อินพุตจำนวนมาก มาดูแนวทางปฏิบัติที่ไม่ดีนี้กัน
// form-input-with-label.component.ts import { Component, Input} from '@angular/core'; @Component({ selector: 'app-form-input-with-label', templateUrl: 'form-input-with-label.component.html' }) export class FormInputWithLabelComponent { @Input() name: string; // Name of the field @Input() id: string; // Id of the field @Input() label: string; // Label of the field @Input() type: 'text' | 'password'; // Type of the field @Input() model: any; // Model of the field constructor() { } }
ตรรกะของ form-input-with-label.component
และนี่อาจเป็นมุมมองของส่วนประกอบนี้
{{ label }}
มุมมองของ form-input-with-label.component
แน่นอนว่าจำนวนโค้ดจะลดลงใน registration.component
แต่มันทำให้ตรรกะโดยรวมของโค้ดเข้าใจและอ่านง่ายขึ้นหรือไม่? ฉันคิดว่าเราเห็นได้ชัดว่ามันทำให้โค้ดซับซ้อนขึ้นกว่าเดิมโดยไม่จำเป็น
สรุป: อย่ากลัวที่จะใช้ส่วนประกอบต่างๆ เพียงตรวจสอบให้แน่ใจว่าคุณมีวิสัยทัศน์ที่ชัดเจนเกี่ยวกับสิ่งที่คุณต้องการบรรลุ สถานการณ์ที่ฉันได้ระบุไว้ข้างต้นเป็นสถานการณ์ที่พบบ่อยที่สุดและฉันถือว่าเป็นสถานการณ์ที่สำคัญและพบบ่อยที่สุด อย่างไรก็ตามสถานการณ์ของคุณอาจไม่เหมือนใครและขึ้นอยู่กับคุณในการตัดสินใจอย่างชาญฉลาด ฉันหวังว่าคุณจะได้เรียนรู้มากพอที่จะตัดสินใจได้ดี
หากคุณต้องการเรียนรู้เพิ่มเติมเกี่ยวกับกลยุทธ์การตรวจจับการเปลี่ยนแปลงของ Angular และกลยุทธ์ OnPush ขอแนะนำให้อ่าน การตรวจจับการเปลี่ยนแปลงเชิงมุมและกลยุทธ์ OnPush . มีความเกี่ยวข้องอย่างใกล้ชิดกับส่วนประกอบและตามที่ฉันได้กล่าวไปแล้วในโพสต์สามารถปรับปรุงประสิทธิภาพของแอปพลิเคชันได้อย่างมาก
เนื่องจากส่วนประกอบเป็นเพียงส่วนหนึ่งของคำสั่งที่ Angular มีให้ดังนั้นจึงเป็นการดีที่จะทำความรู้จัก คำสั่งแอตทริบิวต์ และ คำสั่งโครงสร้าง . การทำความเข้าใจคำสั่งทั้งหมดมักจะทำให้โปรแกรมเมอร์เขียนโค้ดได้ดีขึ้นโดยสิ้นเชิง
มีคำสั่งส่วนประกอบคำสั่งแอตทริบิวต์และคำสั่งโครงสร้าง
ตัวเลือกคือวิธีการเรียกส่วนประกอบในเทมเพลต เป็นตัวระบุเฉพาะสำหรับส่วนประกอบ
ใช้หลักการออกแบบภาพและองค์ประกอบอย่างไร
คอมโพเนนต์คือคำสั่งที่มีเทมเพลตที่อนุญาตให้มีการสร้าง UI ในแอปพลิเคชัน Angular ส่วนประกอบมักจะมีเทมเพลตตัวเลือกและอาจมีหรือไม่มีสไตล์แยกกัน ส่วนประกอบถูกประกาศโดยใช้ @Component
เทมเพลตเชิงมุมกำหนด UI ของส่วนประกอบ
คำสั่งแอตทริบิวต์เปลี่ยนวิธีที่องค์ประกอบ DOM ปรากฏหรือทำงาน แอตทริบิวต์ไม่มีเทมเพลตและประกาศโดยใช้ @Directive
Angular เป็นแพลตฟอร์มที่ช่วยให้ผู้ใช้สร้างเว็บแอปพลิเคชันได้อย่างง่ายดาย มันขึ้นอยู่กับ TypeScript
TypeScript เป็นภาษาสคริปต์ซึ่งมีต้นกำเนิดมาจากและเป็นส่วนเหนือของ JavaScript