ล่าสุดฉันได้อ่านบทความ "แนวคิดใหม่ในการสร้างส่วนประกอบ UI ส่วนหน้า" ที่เขียนโดยลุงหยู ซึ่งทำให้ฉันนึกถึงบทความที่ฉันแชร์เมื่อปีที่แล้ว "รูปแบบการออกแบบ JS เพื่อการพัฒนาร่วมกันด้วยความรู้สึก" ซึ่งโดนใจเล็กน้อย.. .
ว่ากันว่าในโครงการแคชเชียร์เวอร์ชันใหม่ของ Alipay เมื่อปีที่แล้ว ฉันได้ลองใช้โมเดลการเขียนโค้ดส่วนประกอบนี้มาระยะหนึ่งแล้ว ต่อไปนี้คือประสบการณ์เล็กๆ น้อยๆ ที่จะแชร์กับคุณ:
เมื่อมองย้อนกลับไปในชั้นเรียนนามธรรมที่กล่าวถึงก่อนหน้านี้ นักเรียนที่รู้บางอย่างเกี่ยวกับรูปแบบการออกแบบอาจพบว่ามันคุ้นเคย ใช่ เมื่อมองแวบแรก มันดูเหมือนเป็นโรงงานนามธรรม แต่เมื่อรวมกับชั้นเรียนพื้นฐานต่อไปนี้ คุณจะพบว่าฉันไม่ได้แทนที่ getVessel, แสดง, ซ่อน และเมธอดอื่นๆ ในแต่ละคลาสพื้นฐาน แต่สืบทอดเมธอดเหล่านี้โดยตรงในคลาสนามธรรม จะต้องมีคนที่ไม่เข้าใจว่าทำไมพวกเขาถึงทำเช่นนี้ เพียงเพราะเป็น JS ไม่ใช่ JAVA ระดับการมีเพศสัมพันธ์ในระดับหนึ่งเพื่อแลกกับความยืดหยุ่นที่เพียงพอนั้นไม่ได้มากเกินไปในความคิดของฉัน ไม่ต้องพูดถึงว่าคลาสนามธรรมนี้จะต้องมั่นใจในความเสถียรที่สมบูรณ์ มันเป็นสิ่งจำเป็นที่จะไม่ได้รับอนุญาตให้แก้ไขตามความประสงค์หลังจากที่มันถูกสร้างขึ้น
ด้วยคลาสนามธรรมนี้ ฉันเชื่อมโยงออบเจ็กต์ผู้ติดต่อกับออบเจ็กต์คอนเทนเนอร์ และใช้การโต้ตอบที่ง่ายที่สุดระหว่างสิ่งเหล่านั้นผ่านวิธีดำเนินการ "วิธีที่ง่ายที่สุด" ไม่มีความหมายอะไรมากไปกว่าการแสดงหรือซ่อนการดำเนินการ ดังนั้นฉันจึงกำหนดวิธีการแสดงและซ่อนไว้ แน่นอนว่าพฤติกรรมการโต้ตอบที่ "ง่ายที่สุด" ไม่สามารถตอบสนองพฤติกรรมผู้ใช้ได้ 100% ดังนั้นฉันต้องตั้งค่าเมธอด setInterface และเพิ่มคลาสเอฟเฟกต์ให้กับคลาสที่ต้องใช้เอฟเฟกต์การโต้ตอบพิเศษ สุดท้ายนี้ หลีกเลี่ยงการสร้างอินสแตนซ์คลาสนามธรรมนี้โดยตรงเมื่อใช้งาน เตือนทุกคนในวิธีดำเนินการว่าหากคุณต้องการสร้างอินสแตนซ์ของการดำเนินการ โปรดไปที่คลาสการสืบทอดเฉพาะเพื่อแทนที่วิธีดำเนินการ
ด้วยคลาสนามธรรมนี้ เราสามารถสืบทอด aPop, dropDown, xbox, xTab และส่วนประกอบอื่นๆ ขั้นพื้นฐานที่สุดได้... สิ่งเหล่านี้ได้ถูกกล่าวถึงแล้วในบทความ p ก่อนหน้านี้ ฉันจะไม่ลงรายละเอียดที่นี่ ฉันจะเน้นที่การอธิบายเรื่องนั้น เมื่อคลาสพื้นฐานที่เขียนที่นี่ไม่สามารถตอบสนองความต้องการพิเศษได้ เราจะพัฒนาส่วนประกอบส่วนบุคคลได้อย่างรวดเร็วได้อย่างไร
ลองใช้ xTab เป็นตัวอย่าง เราสามารถใช้ส่วนประกอบนี้เพื่อสร้างเอฟเฟกต์การสลับพื้นฐานระหว่างจุดสัมผัสหลายจุดและคอนเทนเนอร์หลายจุดได้ แต่จะเกิดอะไรขึ้นถ้าเราจำเป็นต้องเพิ่มเอฟเฟกต์ภาพเคลื่อนไหวบางส่วนลงไป ก่อนอื่น มาดูโค้ดการใช้งานของแท็บคลาสที่สืบทอดมา:
พบว่าฉันดำเนินการวิธี setInterface หลังจากวิธีแสดง วิธีการที่มีชื่อเดียวกันในคลาสนามธรรมจะถูกเรียกตามค่าเริ่มต้น วิธีอินเทอร์เฟซนี้ได้รับการออกแบบเพื่อเพิ่มคลาสเอฟเฟกต์เชิงโต้ตอบเพิ่มเติมสำหรับบรรทัดโต้ตอบที่คล้ายกัน ตัวอย่างเช่น: ตอนนี้เราต้องการจัดการกับเอฟเฟกต์ของ SlideTab จากนั้นเราเพียงแค่ต้องสืบทอดคลาสแอปพลิเคชันตาม xTab แทนที่เมธอด setInterface และเพิ่มคลาสแอนิเมชั่นเพื่อให้ได้เอฟเฟกต์สไลด์ เท่านี้ก็เรียบร้อย!
AP.widget.animTab = AP.widget.xTab.extend({
setInterface:function(เป้าหมาย,เรือ){
this.parent (เป้าหมาย, เรือ);
this.anim (เรือ);
-
ภาพเคลื่อนไหว: ฟังก์ชั่น (เรือ) {
-
-
-
พูดตามตรง นี่เป็นแนวคิดการออกแบบที่หยาบมาก แต่มันช่วยให้เราคิดเกี่ยวกับโหมดการเขียนโค้ดของส่วนประกอบจากมุมที่แตกต่างกัน ข้างต้นเป็นเพียงความพยายามในการใช้งานแบบผิวเผิน และความตื่นเต้นจะดำเนินต่อไป...รอคุณอยู่!
AP.widget.xTab = AP.widget.basic.extend({
bindEvents:function(เป้าหมาย,เรือ){
E.on(เป้าหมาย,this.options.eventType,this.action,เป้าหมาย,นี้);
E.on(window,'load',this.oXtab,เป้าหมาย,สิ่งนี้);
-
การกระทำ: ฟังก์ชั่น (e เป้าหมาย) {
this.switchTab(e เป้าหมาย);
-
switchTab: ฟังก์ชั่น (e เป้าหมาย) {
-
สำหรับ(i=0,len=tabs.length;i<len;i++){
var hash = แท็บ[i].href.split("#")[1];
เรือ var = D.get (แฮช + 'ขยาย');
ถ้า(เรือ){
this.hide(เรือ);
-
D.removeClass(แท็บ[i].parentNode,'ปัจจุบัน');
ถ้า (target.href == แท็บ [i].href){
D.addClass(target.parentNode,'ปัจจุบัน');
ถ้า(เรือ){
this.show(เรือ);
-
//ตั้งค่าส่วนต่อประสานแอปพลิเคชันต่างๆ
this.setInterface (เป้าหมาย, เรือ);
-
E.preventDefault(e);
-
-
showTab: ฟังก์ชั่น (ดัชนี) {
-
-
// เริ่มต้นแท็บตำแหน่ง
oXtab:ฟังก์ชั่น(เป้าหมาย,e){
-
-
-
AP.widget.basic = AP.Class ใหม่ ({
setOptions: ฟังก์ชั่น (ตัวเลือก) {
//การตั้งค่าอินเทอร์เฟซ
-
เริ่มต้น: ฟังก์ชั่น (เป้าหมาย, ตัวเลือก) {
//วิธีการเริ่มต้น มีวัตถุประสงค์เพื่อสร้างความสัมพันธ์ระหว่างองค์ประกอบย่อยเป้าหมายและวิธีการ
-
getVessel: ฟังก์ชั่น (เป้าหมาย) {
//รับคอนเทนเนอร์ที่ตรงกับความสัมพันธ์ในการแมปเป้าหมาย
-
bindEvents:function(เป้าหมาย,เรือ){
//ผูกการกระทำทริกเกอร์ของเป้าหมายที่นี่
-
การกระทำ: ฟังก์ชั่น () {
//ฟังก์ชันการดำเนินการที่ถูกกระตุ้นโดยเหตุการณ์ที่เชื่อมโยงกับเป้าหมายประกอบด้วยตรรกะที่คุณต้องการดำเนินการ
-
แสดง: ฟังก์ชั่น () {
//แสดงคอนเทนเนอร์
-
ซ่อน:ฟังก์ชั่น(){
//ซ่อนคอนเทนเนอร์
-
setInterface:ฟังก์ชั่น(){
//ตั้งค่าอินเทอร์เฟซที่ใช้ร่วมกันโดยแต่ละองค์ประกอบ
-
-