บริบทและตัวแปรใน Hugo Static Site Generator

เผยแพร่แล้ว: 2022-03-10
สรุปอย่างย่อ ↬ ในบทความนี้ เราจะมาดูหัวข้อบริบทและตัวแปรใน Hugo ซึ่งเป็นเครื่องมือสร้างไซต์สแตติกยอดนิยม คุณจะเข้าใจแนวคิดต่างๆ เช่น บริบทส่วนกลาง การควบคุมโฟลว์ และตัวแปรในเท็มเพลต Hugo ตลอดจนโฟลว์ข้อมูลจากไฟล์เนื้อหาผ่านเท็มเพลตไปยังเทมเพลทบางส่วนและฐาน

ในบทความนี้ เราจะมาดูกันว่าบริบททำงานอย่างไรในตัวสร้างไซต์คงที่ของ Hugo เราจะตรวจสอบว่าข้อมูลไหลจากเนื้อหาไปยังแม่แบบอย่างไร โครงสร้างบางอย่างเปลี่ยนแปลงข้อมูลที่มีอยู่อย่างไร และเราจะส่งข้อมูลนี้ไปยังแม่แบบบางส่วนและแม่แบบพื้นฐานได้อย่างไร

บทความนี้ ไม่ใช่การแนะนำ Hugo คุณอาจจะได้รับประโยชน์สูงสุดจากมัน หากคุณมีประสบการณ์กับ Hugo เนื่องจากเราจะไม่พูดถึงทุกแนวคิดตั้งแต่เริ่มต้น แต่ให้เน้นที่หัวข้อหลักของบริบทและตัวแปร อย่างไรก็ตาม หากคุณอ้างอิงถึงเอกสารของ Hugo ตลอด คุณอาจปฏิบัติตามได้โดยไม่ต้องมีประสบการณ์มาก่อน!

เราจะศึกษาแนวคิดต่างๆ โดยสร้างหน้าตัวอย่าง ไม่ใช่ทุกไฟล์ที่จำเป็นสำหรับไซต์ตัวอย่างจะครอบคลุมโดยละเอียด แต่โปรเจ็กต์ทั้งหมดมีอยู่ใน GitHub หากคุณต้องการเข้าใจว่าชิ้นส่วนต่างๆ เข้ากันได้ดีเพียงใด นั่นเป็นจุดเริ่มต้นที่ดี โปรดทราบว่าเราจะไม่ครอบคลุมถึงวิธีการ ตั้งค่า ไซต์ Hugo หรือเรียกใช้เซิร์ฟเวอร์การพัฒนา — คำแนะนำสำหรับการเรียกใช้ตัวอย่างอยู่ในที่เก็บ

ตัวสร้างไซต์แบบคงที่คืออะไร?

หากแนวคิดของเครื่องมือสร้างไซต์แบบคงที่เป็นแนวคิดใหม่สำหรับคุณ ต่อไปนี้คือข้อมูลแนะนำโดยย่อ! ตัวสร้างไซต์แบบคงที่อาจอธิบายได้ดีที่สุดโดยเปรียบเทียบกับไซต์แบบไดนามิก โดยทั่วไปแล้ว ไซต์แบบไดนามิกเช่น CMS จะประกอบหน้าตั้งแต่เริ่มต้นสำหรับการเข้าชมแต่ละครั้ง อาจดึงข้อมูลจากฐานข้อมูลและรวมเทมเพลตต่างๆ เข้าด้วยกัน ในทางปฏิบัติ การใช้แคชหมายความว่าหน้าเว็บไม่ได้ถูกสร้างขึ้นใหม่ค่อนข้างบ่อย แต่สำหรับวัตถุประสงค์ของการเปรียบเทียบนี้ เราสามารถคิดแบบนั้นได้ ไซต์ไดนามิกเหมาะสมกับ เนื้อหาแบบไดนามิก : เนื้อหาที่เปลี่ยนแปลงบ่อย เนื้อหาที่นำเสนอในการกำหนดค่าต่างๆ มากมาย ขึ้นอยู่กับอินพุต และเนื้อหาที่ผู้เข้าชมไซต์สามารถจัดการได้

ในทางตรงกันข้าม ไซต์จำนวนมากไม่ค่อยเปลี่ยนแปลง และยอมรับข้อมูลเล็กน้อยจากผู้เยี่ยมชม ส่วน "ความช่วยเหลือ" สำหรับแอปพลิเคชัน รายชื่อบทความ หรือ eBook อาจเป็นตัวอย่างของไซต์ดังกล่าว ในกรณีนี้ ควรประกอบหน้าสุดท้าย เพียงครั้งเดียว เมื่อเนื้อหาเปลี่ยนแปลง หลังจากนั้นจึงให้บริการหน้าเดียวกันแก่ผู้เยี่ยมชมทุกคนจนกว่าเนื้อหาจะเปลี่ยนแปลงอีกครั้ง

ไซต์แบบไดนามิกมีความยืดหยุ่นมากกว่า แต่มีความต้องการมากขึ้นบนเซิร์ฟเวอร์ที่พวกเขากำลังใช้งานอยู่ นอกจากนี้ยังอาจเป็นเรื่องยากที่จะกระจายตามภูมิศาสตร์ โดยเฉพาะอย่างยิ่งถ้าฐานข้อมูลเกี่ยวข้อง ตัว สร้างไซต์แบบคงที่ สามารถโฮสต์บนเซิร์ฟเวอร์ใดๆ ก็ได้ที่สามารถส่งไฟล์แบบคงที่ และแจกจ่ายได้ง่าย

วิธีแก้ปัญหาทั่วไปในปัจจุบัน ซึ่งผสมผสานแนวทางเหล่านี้เข้าด้วยกันคือ JAMstack “JAM” ย่อมาจาก JavaScript, APIs และ Markup และอธิบายการสร้างบล็อคของแอปพลิเคชัน JAMstack: ตัวสร้างไซต์แบบส แตติกสร้างไฟล์ สแตติกสำหรับส่งไปยังไคลเอนต์ แต่สแต็กมีองค์ประกอบแบบไดนามิกในรูปแบบของ JavaScript ที่ทำงานบนไคลเอนต์ — คอมโพเนนต์ไคลเอ็นต์นี้สามารถใช้ API เพื่อจัดเตรียมฟังก์ชันแบบไดนามิกให้กับผู้ใช้ได้

Hugo

Hugo เป็นโปรแกรมสร้างไซต์คงที่ยอดนิยม มันเขียนในภาษา Go และความจริงที่ว่า Go เป็นภาษาการเขียนโปรแกรมที่คอมไพล์แล้ว บ่งบอกถึงข้อดีและข้อเสียบางประการของ Hugos ประการหนึ่ง Hugo นั้นเร็วมาก หมายความว่ามันสร้างไซต์คงที่อย่างรวดเร็ว แน่นอนว่าสิ่งนี้ไม่มีผลต่อความเร็วหรือความช้าของเว็บไซต์ที่สร้างโดยใช้ Hugo สำหรับผู้ใช้ปลายทาง แต่สำหรับนักพัฒนาแล้ว การที่ Hugo รวบรวมเว็บไซต์ขนาดใหญ่ได้ในพริบตานั้นมีค่ามากทีเดียว

อย่างไรก็ตาม เนื่องจาก Hugo เขียนด้วยภาษาที่คอมไพล์ การขยายจึงเป็นเรื่องยาก เครื่องมือสร้างไซต์อื่นๆ บางตัวอนุญาตให้คุณแทรกโค้ดของคุณเอง — ในภาษาเช่น Ruby, Python หรือ JavaScript — ลงในกระบวนการคอมไพล์ ในการขยาย Hugo คุณจะต้อง เพิ่มโค้ดของคุณลงใน Hugo และคอมไพล์ใหม่ มิฉะนั้น คุณจะติดอยู่กับฟังก์ชันเทมเพลตที่ Hugo มาพร้อมกับอุปกรณ์ที่พร้อมใช้งานทันที

แม้ว่าจะมีฟังก์ชันที่หลากหลาย แต่ข้อเท็จจริงนี้อาจกลายเป็นข้อจำกัดได้ หากการสร้างหน้าเว็บของคุณเกี่ยวข้องกับตรรกะที่ซับซ้อนบางอย่าง ดังที่เราพบว่า การมีไซต์ที่พัฒนาบนแพลตฟอร์มไดนามิกแต่เดิมนั้น กรณีที่คุณได้นำความสามารถในการลดโค้ดที่กำหนดเองของคุณไปใช้งานมักจะกองพะเนินเทินทึก

ทีมงานของเราดูแลเว็บไซต์ต่างๆ ที่เกี่ยวข้องกับผลิตภัณฑ์หลักของเรา นั่นคือไคลเอนต์ Tower Git และเมื่อเร็ว ๆ นี้เราได้พิจารณาการย้ายไซต์เหล่านี้บางส่วนไปยังตัวสร้างไซต์แบบคงที่ หนึ่งในไซต์ของเรา ไซต์ "เรียนรู้" ดูเหมือนจะเหมาะสมเป็นอย่างยิ่งสำหรับโครงการนำร่อง ไซต์นี้มีสื่อการเรียนรู้ฟรีมากมาย รวมถึงวิดีโอ eBooks และคำถามที่พบบ่อยเกี่ยวกับ Git แต่ยังรวมถึงหัวข้อเทคโนโลยีอื่นๆ

เนื้อหาส่วนใหญ่เป็นแบบคงที่ และคุณลักษณะแบบโต้ตอบใดๆ ก็ตามที่มีอยู่ (เช่น การสมัครรับจดหมายข่าว) ได้รับการขับเคลื่อนโดย JavaScript แล้ว ณ สิ้นปี 2020 เรา แปลงไซต์นี้จาก CMS ก่อนหน้าของเราเป็น Hugo และวันนี้มันทำงานเป็นไซต์คงที่ โดยธรรมชาติแล้ว เราได้เรียนรู้มากมายเกี่ยวกับ Hugo ในระหว่างกระบวนการนี้ บทความนี้เป็นวิธีการแบ่งปันบางสิ่งที่เราได้เรียนรู้

ตัวอย่างของเรา

เนื่องจากบทความนี้เกิดขึ้นจากการทำงานของเราในการแปลงหน้าเว็บของเราเป็น Hugo ดูเหมือนว่าเป็นเรื่องปกติที่จะรวบรวมหน้า Landing Page สมมุติที่ง่ายขึ้น (มาก!) ไว้เป็นตัวอย่าง จุดสนใจหลักของเราคือเทมเพลตที่เรียกว่า "รายการ" ที่นำกลับมาใช้ใหม่ได้

กล่าวโดยย่อ Hugo จะใช้เทมเพลตรายการสำหรับหน้าใดๆ ที่มีหน้าย่อย ลำดับชั้นเทมเพลต Hugos มีมากกว่านั้น แต่คุณไม่จำเป็นต้องใช้ทุกเทมเพลตที่เป็นไปได้ เทมเพลตรายการเดียวไปไกล จะใช้ในสถานการณ์ใด ๆ ที่เรียกเทมเพลตรายการที่ไม่มีเทมเพลตเฉพาะอีกต่อไป

กรณีการใช้งานที่เป็นไปได้ ได้แก่ หน้าแรก ดัชนีบล็อก หรือรายการคำถามที่พบบ่อย เทมเพลตรายการ ที่ใช้ซ้ำได้ของเราจะอยู่ใน layouts/_default/list.html ในโครงการของเรา อีกครั้ง ไฟล์ที่เหลือที่จำเป็นในการรวบรวมตัวอย่างของเรามีอยู่ใน GitHub ซึ่งคุณสามารถดูได้ดียิ่งขึ้นว่าชิ้นส่วนต่างๆ เข้ากันได้อย่างไร ที่เก็บ GitHub ยังมาพร้อมกับเทมเพลต single.html — ตามชื่อที่แนะนำ เทมเพลตนี้ใช้สำหรับหน้าที่ไม่มีหน้าย่อย แต่ทำหน้าที่เป็นเนื้อหาชิ้นเดียวในสิทธิ์ของตนเอง

ตอนนี้เราได้ตั้งฉากและอธิบายว่าเราจะทำอะไร มาเริ่มกันเลย!

เพิ่มเติมหลังกระโดด! อ่านต่อด้านล่าง↓

บริบทหรือ "จุด"

ทุกอย่างเริ่มต้นด้วยจุด ในเทมเพลต Hugo วัตถุ . — “จุด” — หมายถึงบริบทปัจจุบัน สิ่งนี้หมายความว่า? ทุกเทมเพลตที่แสดงใน Hugo สามารถเข้าถึงชุดข้อมูล — บริบท ค่าเริ่มต้นนี้ถูกกำหนดให้เป็นอ็อบเจ็กต์ที่แสดงหน้าเว็บที่กำลังแสดงผล รวมถึงเนื้อหาและข้อมูลเมตาบางส่วน บริบทยังรวมถึงตัวแปรทั่วทั้งไซต์ เช่น ตัวเลือกการกำหนดค่าและข้อมูลเกี่ยวกับสภาพแวดล้อมปัจจุบัน คุณจะเข้าถึงช่องต่างๆ เช่น ชื่อเรื่องของหน้าปัจจุบันโดยใช้ .Title และเวอร์ชันของ Hugo ที่ใช้ผ่าน .Hugo.Version กล่าวคือ คุณกำลังเข้าถึง ช่องต่างๆ ของไฟล์ . โครงสร้าง.

ที่สำคัญ บริบทนี้สามารถเปลี่ยนแปลงได้ โดยการอ้างอิงเช่น `.Title' ด้านบนชี้ไปที่อย่างอื่น หรือแม้แต่ทำให้ไม่ถูกต้อง สิ่งนี้เกิดขึ้น ตัวอย่างเช่น เมื่อคุณวนรอบคอลเล็กชันบางชนิดโดยใช้ range หรือเมื่อคุณ แยกเทมเพลตออกเป็นบางส่วนและเทมเพลตพื้นฐาน เราจะดูรายละเอียดในภายหลัง!

Hugo ใช้แพ็คเกจ "เทมเพลต" ของ Go ดังนั้นเมื่อเราอ้างถึงเทมเพลต Hugo ในบทความนี้ เรากำลังพูดถึงเทมเพลต Go จริงๆ Hugo เพิ่มฟังก์ชันเทมเพลตจำนวนมากที่ไม่มีในเทมเพลต Go มาตรฐาน

ในความคิดของฉัน บริบทและความเป็นไปได้ที่จะรวมมันอีกครั้งเป็นหนึ่งในคุณสมบัติที่ดีที่สุดของ Hugos สำหรับฉัน มันสมเหตุสมผลมากที่จะมี "จุด" แทนวัตถุใดก็ตามที่เป็นโฟกัสหลักของเทมเพลตของฉัน ณ จุดใดจุดหนึ่ง โดยผูกซ้ำตามความจำเป็นในขณะที่ฉันดำเนินการ แน่นอนว่ามันเป็นไปได้ที่จะทำให้ตัวเองยุ่งเหยิงเช่นกัน แต่ฉันพอใจกับมันจนถึงตอนนี้ เท่าที่ฉันเริ่มขาดมันอย่างรวดเร็วในเครื่องมือสร้างไซต์คงที่อื่น ๆ ที่ฉันดู

ด้วยเหตุนี้ เราจึงพร้อมที่จะมองหาจุดเริ่มต้นเล็กๆ ของตัวอย่างของเรา — เทมเพลตด้านล่าง ซึ่งอยู่ในเลย์เอาต์สถานที่ตั้ง layouts/_default/list.html ในโครงการของเรา:

 <html> <head> <title>{{ .Title }} | {{ .Site.Title }}</title> <link rel="stylesheet" href="/css/style.css"> </head> <body> <nav> <a class="logo" href="{{ "/" | relURL }}"> <img src="/img/tower-logo.svg"> <img src="/img/tower-claim.svg"> </a> <ul> <li><a href="/">Home</a></li> </ul> </nav> <section class="content"> <div class="container"> <h1>{{ .Title }}</h1> {{ .Content }} </div> </section> </body> </html>

เทมเพลตส่วนใหญ่ประกอบด้วยโครงสร้าง HTML แบบเปล่าๆ พร้อมลิงก์สไตล์ชีต เมนูสำหรับการนำทาง และองค์ประกอบและคลาสพิเศษบางส่วนที่ใช้สำหรับการจัดสไตล์ สิ่งที่น่าสนใจอยู่ระหว่างเครื่องมือ จัดฟันแบบหยิก ซึ่งส่งสัญญาณให้ Hugo ก้าวเข้ามาและใช้เวทมนตร์ แทนที่สิ่งที่อยู่ระหว่างเหล็กจัดฟันด้วยผลลัพธ์ของการประเมินการแสดงออกและอาจจัดการบริบทด้วย

อย่างที่คุณอาจเดาได้ {{ .Title }} ในแท็กชื่อหมายถึงชื่อของหน้าปัจจุบัน ในขณะที่ {{ .Site.Title }} หมายถึงชื่อสำหรับทั้งเว็บไซต์ ซึ่งตั้งค่าไว้ในการกำหนดค่า Hugo . แท็กอย่าง {{ .Title }} บอกให้ Hugo แทนที่แท็กนั้นด้วยเนื้อหาของฟิลด์ Title ในบริบทปัจจุบัน

ดังนั้นเราจึงเข้าถึง ข้อมูล บางส่วนที่เป็นของเพจในเทมเพลต ข้อมูลนี้มาจากไหน? นั่นคือหัวข้อของส่วนต่อไปนี้

เนื้อหาและเบื้องหน้า

ตัวแปรบางตัวที่มีอยู่ในบริบทนั้นให้ Hugo โดยอัตโนมัติ อื่นๆ ถูกกำหนดโดยเรา ส่วนใหญ่อยู่ใน ไฟล์เนื้อหา นอกจากนี้ยังมีแหล่งข้อมูลอื่นๆ เช่น ไฟล์การกำหนดค่า ตัวแปรสภาพแวดล้อม ไฟล์ข้อมูล และแม้แต่ API ในบทความนี้เราจะเน้นที่ไฟล์เนื้อหาเป็นแหล่งข้อมูล

โดยทั่วไป ไฟล์เนื้อหาเดียวแสดงถึงหน้าเดียว ไฟล์เนื้อหาทั่วไปประกอบด้วยเนื้อหาหลักของหน้านั้น แต่ยังรวมถึงข้อมูลเมตาเกี่ยวกับหน้า เช่น ชื่อเรื่องหรือวันที่สร้าง Hugo รองรับหลายรูปแบบทั้งเนื้อหาหลักและข้อมูลเมตา ในบทความนี้ เราจะพูดถึงชุดค่าผสมที่พบบ่อยที่สุด: เนื้อหามีให้เป็น Markdown ในไฟล์ที่มีข้อมูลเมตาเป็นส่วนหน้าของ YAML

ในทางปฏิบัติ หมายความว่าไฟล์เนื้อหาเริ่มต้นด้วยส่วนที่คั่นด้วยบรรทัดที่มีขีดกลางสามขีดที่ปลายแต่ละด้าน ส่วนนี้ถือเป็น ส่วนหน้า และข้อมูลเมตาถูกกำหนดโดยใช้ key: value (ดังที่เราเห็นในเร็วๆ นี้ YAML รองรับโครงสร้างข้อมูลที่ซับซ้อนมากขึ้นด้วย) ส่วนหน้าตามด้วยเนื้อหาจริงที่ระบุโดยใช้ภาษามาร์กอัป Markdown

มาทำให้เป็นรูปธรรมมากขึ้นโดยดูตัวอย่าง นี่คือไฟล์เนื้อหาง่ายๆ ที่มีช่องเรื่องส่วนหน้าหนึ่งช่องและเนื้อหาหนึ่งย่อหน้า:

 --- title: Home --- Home page of the Tower Git client. Over 100,000 developers and designers use Tower to be more productive!

(ไฟล์นี้อยู่ที่ content/_index.md ในโครงการของเรา โดย _index.md หมายถึงไฟล์เนื้อหาสำหรับหน้าที่มีหน้าย่อย อีกครั้งที่ที่เก็บ GitHub ทำให้ชัดเจนว่าไฟล์ใดควรไปที่ใด)

แสดงผลโดยใช้เทมเพลตจากรุ่นก่อนหน้า พร้อมด้วยสไตล์และไฟล์ต่อพ่วงบางส่วน (ทั้งหมดที่พบใน GitHub) ผลลัพธ์ที่ได้จะมีลักษณะดังนี้:

หน้าแรกของไคลเอนต์ Tower Git
(ตัวอย่างขนาดใหญ่)

คุณอาจสงสัยว่าชื่อฟิลด์ในส่วนหน้าของไฟล์เนื้อหาของเราถูกกำหนดไว้ล่วงหน้าหรือไม่ หรือว่าเราสามารถเพิ่มฟิลด์ใดๆ ที่เราชอบได้หรือไม่ คำตอบคือ “ทั้งสอง” มีรายการของฟิลด์ที่กำหนดไว้ล่วงหน้า แต่เราสามารถเพิ่มฟิลด์อื่น ๆ ที่เราสามารถทำได้ อย่างไรก็ตาม ฟิลด์เหล่านี้มีการเข้าถึงแตกต่างกันเล็กน้อยในเทมเพลต ในขณะที่เข้าถึงฟิลด์ที่กำหนดไว้ล่วงหน้า เช่น title อย่างง่ายในชื่อ .Title ฟิลด์ที่กำหนดเอง เช่น author จะเข้าถึงได้โดยใช้ .Params.author .Title

(สำหรับการอ้างอิงอย่างรวดเร็วเกี่ยวกับฟิลด์ที่กำหนดไว้ล่วงหน้า ควบคู่ไปกับสิ่งต่างๆ เช่น ฟังก์ชัน พารามิเตอร์ของฟังก์ชัน และตัวแปรของเพจ โปรดดูเอกสารสรุป Hugo ของเรา!)

ตัวแปร .Content ใช้เพื่อเข้าถึงเนื้อหาหลักจากไฟล์เนื้อหาในเทมเพลตของคุณ เป็นตัวแปรพิเศษ Hugo มี คุณสมบัติ “ช อร์ตโค้ด” ให้คุณใช้แท็กพิเศษในเนื้อหา Markdown ของคุณได้ คุณยังสามารถกำหนดของคุณเอง ขออภัย รหัสย่อเหล่านี้จะใช้ได้เฉพาะกับตัวแปร .Content ในขณะที่คุณสามารถเรียกใช้ข้อมูลส่วนอื่นๆ ผ่านตัวกรอง Markdown ได้ การดำเนินการนี้จะไม่จัดการรหัสย่อในเนื้อหา

หมายเหตุเกี่ยวกับตัวแปรที่ไม่ได้กำหนดไว้ที่นี่: การเข้าถึงฟิลด์ที่กำหนดไว้ล่วงหน้า เช่น .Date ใช้งานได้เสมอ แม้ว่าคุณจะไม่ได้ตั้งค่าไว้ก็ตาม ในกรณีนี้ ค่าว่างจะถูกส่งคืน การเข้าถึงฟิลด์กำหนดเองที่ไม่ได้กำหนด เช่น .Params.thisHasNotBeenSet ก็ใช้งานได้เช่นกัน โดยคืนค่าว่าง อย่างไรก็ตาม การเข้าถึงฟิลด์ระดับบนสุดที่ไม่ได้กำหนดไว้ล่วงหน้า เช่น .thisDoesNotExist จะป้องกันไม่ให้ไซต์รวบรวม

ตามที่ระบุโดย .Params.author เช่นเดียวกับ .Hugo.version และ .Site.title ก่อนหน้านี้ สามารถใช้การเรียกใช้แบบลูกโซ่เพื่อเข้าถึงฟิลด์ที่ซ้อนอยู่ในโครงสร้างข้อมูลอื่นๆ เราสามารถกำหนดโครงสร้างดังกล่าวในส่วนหน้าของเรา มาดูตัวอย่างที่ เรากำหนดแผนที่ หรือพจนานุกรม ระบุคุณสมบัติบางอย่างสำหรับแบนเนอร์บนหน้าในไฟล์เนื้อหาของเรา นี่คือ content/_index.md :

 --- title: Home banner: headline: Try Tower For Free! subline: Download our trial to try Tower for 30 days --- Home page of the Tower Git client. Over 100,000 developers and designers use Tower to be more productive!

ตอนนี้ มาเพิ่มแบนเนอร์ในเทมเพลตของเรา โดยอ้างอิงข้อมูลแบนเนอร์โดยใช้ .Params ตามวิธีที่อธิบายข้างต้น:

 <html> ... <body> ... <aside> <h2>{{ .Params.banner.headline }}</h2> <p>{{ .Params.banner.subline}}</p> </aside> </body> </html>

เว็บไซต์ของเรามีลักษณะดังนี้:

หน้าแรกของไคลเอนต์ Tower Git ที่มีแบนเนอร์ว่า Try Tower For Free
(ตัวอย่างขนาดใหญ่)

ไม่เป็นอะไร! ในขณะนี้ เรากำลังเข้าถึงฟิลด์ของบริบทเริ่มต้นโดยไม่มีปัญหาใดๆ อย่างไรก็ตาม ตามที่กล่าวไว้ก่อนหน้านี้ บริบทนี้ไม่ได้รับการแก้ไข แต่สามารถเปลี่ยนแปลงได้

ลองดูว่ามันจะเกิดขึ้นได้อย่างไร

การควบคุมการไหล

คำสั่งควบคุมโฟลว์เป็นส่วนสำคัญของภาษาเทมเพลต ช่วยให้คุณทำสิ่งต่างๆ ได้หลากหลายขึ้นอยู่กับค่าของตัวแปร วนซ้ำข้อมูล และอื่นๆ เทมเพลต Hugo จัดเตรียมชุดโครงสร้างที่คาดไว้ รวมถึง if/else สำหรับตรรกะแบบมีเงื่อนไข และ range สำหรับการวนซ้ำ ในที่นี้ เราจะไม่ครอบคลุมถึงการควบคุมโฟลว์ใน Hugo โดยทั่วไป (สำหรับข้อมูลเพิ่มเติม โปรดดูเอกสารประกอบ) แต่เน้นว่าข้อความเหล่านี้ส่งผลต่อบริบทอย่างไร ในกรณีนี้ ข้อความที่น่าสนใจที่สุดคือ with และ range

มาเริ่มกัน with คำสั่งนี้จะตรวจสอบว่านิพจน์บางค่ามีค่า "ไม่ว่าง" หรือไม่ และถ้ามี จะรวม บริบทอีกครั้งเพื่ออ้างอิงถึงค่าของนิพจน์ นั้น แท็ก end ระบุจุดที่อิทธิพลของคำสั่ง with หยุดลง และบริบทจะย้อนกลับไปยังสิ่งที่เคยเป็นมาก่อน เอกสารประกอบ Hugo กำหนดค่าที่ไม่ว่างเปล่าเป็นเท็จ 0 และอาร์เรย์ สไลซ์ แผนที่ หรือสตริงที่มีความยาวเป็นศูนย์

ปัจจุบัน เทมเพลตรายการของเราไม่ได้แสดงรายการอะไรมาก เทมเพลตรายการอาจสมเหตุสมผลที่จะนำ เสนอหน้าย่อย บางหน้าในบางวิธี สิ่งนี้ทำให้เรามีโอกาสที่ดีในการดูตัวอย่างคำสั่งควบคุมการไหลของเรา

บางทีเราต้องการแสดงเนื้อหาเด่นที่ด้านบนสุดของหน้าของเรา นี่อาจเป็นเนื้อหาอะไรก็ได้ เช่น โพสต์บล็อก บทความช่วยเหลือ หรือสูตรอาหาร เป็นต้น ในตอนนี้ สมมติว่าไซต์ตัวอย่าง Tower ของเรามีหน้าเว็บบางหน้าที่เน้นคุณลักษณะ กรณีใช้งาน หน้าช่วยเหลือ หน้าบล็อก และหน้า "แพลตฟอร์มการเรียนรู้" ทั้งหมดนี้อยู่ในไดเร็กทอรี content/ เรากำหนดค่าเนื้อหาที่จะนำเสนอโดยการเพิ่มฟิลด์ในไฟล์เนื้อหาสำหรับหน้าแรกของเรา content/_index.md เพจถูกอ้างถึงโดยพาธ โดยถือว่าไดเร็กทอรีเนื้อหาเป็นรูท เช่น:

 --- title: Home banner: headline: Try Tower For Free! subline: Download our trial to try Tower for 30 days without limitations featured: /features.md ... --- ...

ต่อไป เทมเพลตรายการของเราจะต้องได้รับการแก้ไขเพื่อแสดงเนื้อหาชิ้นนี้ Hugo มีฟังก์ชันเทมเพลต . .GetPage ซึ่งจะช่วยให้เราสามารถอ้างถึงออบเจ็กต์ของหน้าอื่นที่ไม่ใช่หน้าที่เรากำลังแสดงผลอยู่ จำได้ว่าบริบทเป็น . เริ่มแรกถูกผูกไว้กับวัตถุที่แสดงถึงหน้าที่แสดงผลหรือไม่ การใช้ .GetPage และ with เราสามารถเชื่อมโยง บริบทใหม่กับหน้าอื่นชั่วคราว โดยอ้างอิงถึงฟิลด์ของหน้า นั้น เมื่อแสดงเนื้อหาเด่นของเรา:

 <nav> ... </nav> <section class="featured"> <div class="container"> {{ with .GetPage .Params.featured }} <article> <h2>{{ .Title }}</h2> {{ .Summary }} <p><a href="{{ .Permalink }}">Read more →</a></p> </article> {{ end }} </div> </section>

ในที่นี้ {{ .Title }} , {{ .Summary }} และ {{ .Permalink }} ระหว่าง with และ end tags จะอ้างอิงถึงฟิลด์เหล่านั้น ในหน้าแนะนำ ไม่ใช่ช่องหลักที่กำลังแสดงผล

นอกจากการมีเนื้อหาเด่นแล้ว เรามาลงรายการเนื้อหาเพิ่มเติมอีกสองสามรายการด้านล่าง เช่นเดียวกับเนื้อหาเด่น ส่วนเนื้อหาที่ระบุไว้จะถูกกำหนดใน content/_index.md ไฟล์เนื้อหาสำหรับหน้าแรกของเรา เราจะเพิ่มรายการเส้นทางเนื้อหาในส่วนหน้าของเราดังนี้ (ในกรณีนี้จะระบุพาดหัวของส่วนด้วย):

 --- ... listing_headline: Featured Pages listing: - /help.md - /use-cases.md - /blog/_index.md - /learn.md ---

เหตุผลที่หน้าบล็อกมีไดเร็กทอรีของตัวเองและไฟล์ _index.md ก็คือบล็อกจะมีหน้าย่อยของตัวเอง นั่นคือ โพสต์ในบล็อก

เพื่อแสดงรายการนี้ในเทมเพลตของเรา เราจะใช้ range ไม่น่าแปลกใจเลยที่คำสั่งนี้จะวนซ้ำในรายการ แต่จะรวมบริบทเข้ากับแต่ละองค์ประกอบของรายการในทางกลับกัน สะดวกมากสำหรับรายการเนื้อหาของเรา

โปรดทราบว่าจากมุมมองของ Hugo "listing" มีบางสตริงเท่านั้น สำหรับการวนซ้ำ "range" แต่ละครั้ง บริบทจะถูกผูกไว้กับหนึ่งในสตริงเหล่านั้น ในการเข้าถึงออบเจ็กต์เพจจริง เราใส่สตริงพาธ (ตอนนี้เป็นค่าของ . ) เป็นอาร์กิวเมนต์ของ . .GetPage จากนั้น เราจะใช้คำสั่ง with อีกครั้งเพื่อเชื่อมบริบทกับออบเจกต์เพจที่อยู่ในรายการอีกครั้ง แทนที่จะใช้สตริงพาธ ในตอนนี้ การแสดงเนื้อหาของแต่ละหน้าในรายการนั้นทำได้ง่ายๆ ดังนี้:

 <aside> ... </aside> <section class="listing"> <div class="container"> <h1>{{ .Params.listing_headline }}</h1> <div> {{ range .Params.listing }} {{ with $.GetPage . }} <article> <h2>{{ .Title }}</h2> {{ .Summary }} <p><a href="{{ .Permalink }}">Read more →</a></p> </article> {{ end }} {{ end }} </div> </div> </section>

นี่คือลักษณะของเว็บไซต์ ณ จุดนี้:

หน้าแรกของไคลเอนต์ Tower Git แสดงหน้าและแบนเนอร์เด่นสี่หน้า
(ตัวอย่างขนาดใหญ่)

แต่เดี๋ยวก่อน มีบางอย่างแปลก ๆ ในเทมเพลตด้านบน — แทนที่จะเรียก .GetPage เรากำลังเรียก $.GetPage คุณเดาได้ไหมว่าทำไม .GetPage จึงไม่ทำงาน

สัญกรณ์ .GetPage ระบุว่าฟังก์ชัน GetPage เป็นวิธีการของบริบทปัจจุบัน ในบริบทเริ่มต้น มีวิธีการดังกล่าว แต่เราเพิ่งดำเนินการและ เปลี่ยนบริบท ! เมื่อเราเรียก .GetPage บริบทจะถูกผูกไว้กับสตริง ซึ่งไม่มีเมธอดนั้น วิธีที่เราแก้ไขคือหัวข้อของหัวข้อถัดไป

บริบทโลก

ตามที่เห็นด้านบน มีบางสถานการณ์ที่บริบทมีการเปลี่ยนแปลง แต่เรายังต้องการเข้าถึงบริบทดั้งเดิม นี่เป็นเพราะเราต้องการเรียกวิธีการที่มีอยู่ในบริบทดั้งเดิม — สถานการณ์ทั่วไปอีกอย่างหนึ่งคือเมื่อเราต้องการเข้าถึงคุณสมบัติบางอย่างของหน้าหลักที่กำลังแสดงผล ไม่มีปัญหา มีวิธีง่ายๆ ในการทำเช่นนี้

ในเทมเพลต Hugo $ หรือที่รู้จักในชื่อ global context หมายถึงค่าดั้งเดิมของบริบท — บริบทเหมือนเมื่อตอนที่การประมวลผลเทมเพลตเริ่มต้นขึ้น ในส่วนก่อนหน้านี้ มันถูกใช้เพื่อเรียกเมธอด .GetPage แม้ว่าเราจะรีบาวด์บริบทเป็นสตริงแล้วก็ตาม ตอนนี้ เรายังจะใช้มันเพื่อเข้าถึงฟิลด์ของเพจที่กำลังแสดงผล

ในตอนต้นของบทความนี้ ฉันได้กล่าวถึงเทมเพลตรายการของเราที่สามารถนำมาใช้ซ้ำได้ จนถึงตอนนี้ เราเคยใช้สำหรับหน้าแรกเท่านั้น โดยแสดงไฟล์เนื้อหาที่อยู่ที่ content/_index.md ในที่เก็บตัวอย่าง มีไฟล์เนื้อหาอื่นซึ่งจะแสดงผลโดยใช้เทมเพลตนี้: content/blog/_index.md นี่คือหน้าดัชนีสำหรับบล็อก และเช่นเดียวกับหน้าแรก จะแสดงเนื้อหาเด่นและแสดงรายการโพสต์บล็อกอื่นๆ อีกสองสามรายการ ในกรณีนี้

ในตอนนี้ สมมติว่าเราต้องการแสดงเนื้อหาที่แสดงในรายการ แตกต่างกันเล็กน้อยบนโฮมเพจ — ไม่เพียงพอที่จะรับประกันเทมเพลตที่แยกจากกัน แต่มีบางอย่างที่เราสามารถทำได้ด้วยคำสั่งแบบมีเงื่อนไขในตัวเทมเพลตเอง ตัวอย่างเช่น เราจะแสดงเนื้อหาที่อยู่ในตารางแบบสองคอลัมน์ แทนที่จะเป็นรายการแบบคอลัมน์เดียว หากเราตรวจพบว่าเรากำลังแสดงหน้าแรก

Hugo มาพร้อมกับวิธีการของหน้า . .IsHome ซึ่งมีฟังก์ชันการทำงานที่เราต้องการอย่างแท้จริง เราจะจัดการกับการเปลี่ยนแปลงที่เกิดขึ้นจริงในการนำเสนอโดยการเพิ่มชั้นเรียนให้กับเนื้อหาแต่ละส่วนเมื่อเราพบว่าเราอยู่ในหน้าแรก โดยให้ไฟล์ CSS ของเราจัดการส่วนที่เหลือ

แน่นอน เราสามารถเพิ่มคลาสให้กับองค์ประกอบเนื้อหาหรือบางส่วนที่มีองค์ประกอบแทนได้ แต่นั่นจะไม่ช่วยให้สามารถสาธิตบริบททั่วโลกได้ดีเท่ากับ เมื่อเราเขียน HTML สำหรับเนื้อหาที่อยู่ในรายการ . หมายถึงหน้าที่แสดงรายการ แต่จำเป็นต้องเรียก IsHome บนหน้าหลักที่กำลังแสดงผล บริบทระดับโลกเข้ามาช่วยเหลือเรา:

 <section class="listing"> <div class="container"> <h1>{{ .Params.listing_headline }}</h1> <div> {{ range .Params.listing }} {{ with $.GetPage . }} <article{{ if $.IsHome }} class="home"{{ end }}> <h2>{{ .Title }}</h2> {{ .Summary }} <p><a href="{{ .Permalink }}">Read more →</a></p> </article> {{ end }} {{ end }} </div> </div> </section>

ดัชนีบล็อกดูเหมือนกับหน้าแรกของเรา แม้ว่าจะมีเนื้อหาต่างกัน:

หน้าแรกของไคลเอนต์ Tower Git แสดงสี่หน้าเด่นและแบนเนอร์ที่มีเนื้อหาต่างกัน
(ตัวอย่างขนาดใหญ่)

…แต่ตอนนี้หน้าแรกของเราแสดงเนื้อหาเด่นในตาราง:

หน้าแรกของไคลเอนต์ Tower Git แสดงหน้าเด่นสี่หน้าในสองแถวสองคอลัมน์และไม่ใช่ทั้งสี่หน้าเหมือนเดิม
(ตัวอย่างขนาดใหญ่)

แม่แบบบางส่วน

เมื่อสร้างเว็บไซต์จริง การแบ่งเทมเพลตของคุณเป็นส่วนๆ จะเป็นประโยชน์อย่างรวดเร็ว บางทีคุณอาจต้องการนำบางส่วนของเทมเพลตกลับมาใช้ใหม่ หรือบางทีคุณอาจต้องการแยกเทมเพลตขนาดใหญ่และเทอะทะออกเป็นชิ้นที่เชื่อมโยงกัน เพื่อจุดประสงค์นี้ เทมเพลตบางส่วนของ Hugo เป็นวิธีที่จะไป

จากมุมมองของบริบท สิ่งสำคัญในที่นี้คือเมื่อเรารวมเทมเพลตบางส่วน เรา จะส่งต่อบริบทที่ เราต้องการให้ใช้งานได้อย่างชัดเจน แนวทางปฏิบัติทั่วไปคือการส่งต่อบริบทเช่นเดียวกับเมื่อรวม partial ไว้ดังนี้: {{ partial "my/partial.html" . }} {{ partial "my/partial.html" . }} . หากจุดที่นี่หมายถึงหน้าที่แสดงผล นั่นคือสิ่งที่จะถูกส่งต่อไปยังบางส่วน ถ้าบริบทถูกสะท้อนกลับไปเป็นอย่างอื่น นั่นคือสิ่งที่ส่งต่อลงมา

แน่นอน คุณสามารถรวมบริบทอีกครั้งในเทมเพลตบางส่วนได้เหมือนกับในเทมเพลตปกติ ในกรณีนี้ บริบทส่วนกลาง $ อ้างอิงถึงบริบทดั้งเดิมที่ส่งผ่านไปยังบางส่วน ไม่ใช่หน้าหลักที่กำลังแสดงผล (เว้นแต่นั่นคือสิ่งที่ส่งผ่านเข้ามา)

หากเราต้องการให้เทมเพลตบางส่วนสามารถเข้าถึงข้อมูลบางส่วนได้ เราอาจประสบปัญหาหากเราส่งต่อข้อมูลนี้ไปยังบางส่วนเท่านั้น จำปัญหาของเราก่อนหน้านี้ด้วยการเข้าถึงเมธอดของเพจหลังจากเชื่อมโยงบริบทใหม่หรือไม่ เช่นเดียวกันสำหรับ partials แต่ในกรณีนี้บริบทส่วนกลางไม่สามารถช่วยเราได้ ถ้าเราส่งผ่านเข้าไป เช่น สตริงไปยังเทมเพลตบางส่วน บริบทส่วนกลางในบางส่วนจะอ้างอิงถึงสตริงนั้น และเราชนะ ไม่สามารถเรียกวิธีการที่กำหนดไว้ในบริบทของหน้า

วิธีแก้ปัญหานี้อยู่ใน การส่งผ่านข้อมูลมากกว่าหนึ่งชิ้น เมื่อรวมบางส่วน อย่างไรก็ตาม เราได้รับอนุญาตให้ระบุอาร์กิวเมนต์ได้เพียงอาร์กิวเมนต์เดียวสำหรับการเรียกบางส่วนเท่านั้น อย่างไรก็ตาม เราสามารถทำให้อาร์กิวเมนต์นี้เป็นชนิดข้อมูลแบบรวมได้ โดยทั่วไปแล้วจะเป็นแผนที่ (เรียกว่าพจนานุกรมหรือแฮชในภาษาโปรแกรมอื่นๆ)

ในแผนที่นี้ เราสามารถตั้งค่าคีย์ Page เป็นออบเจกต์ของเพจปัจจุบัน พร้อมกับคีย์อื่นๆ สำหรับข้อมูลที่กำหนดเองเพื่อส่งผ่าน ออบเจ็กต์ของเพจจะพร้อมใช้งานเป็น .Page ในบางส่วน และอื่นๆ ค่าของแผนที่สามารถเข้าถึงได้ในทำนองเดียวกัน แผนที่ถูกสร้างขึ้นโดยใช้ฟังก์ชันเทมเพลต dict ซึ่งรับอาร์กิวเมนต์เป็นจำนวนคู่ ตีความสลับกันเป็นคีย์ ค่าของคีย์ คีย์ ค่าของมัน และอื่นๆ

ในเทมเพลตตัวอย่าง ให้ย้ายโค้ดสำหรับเนื้อหาเด่นและเนื้อหาที่อยู่ในรายการเป็นส่วนย่อย สำหรับเนื้อหาเด่น แค่ส่งผ่านในออบเจ็กต์หน้าเด่น อย่างไรก็ตาม เนื้อหาที่อยู่ในรายการต้องการเข้าถึงเมธอด .IsHome นอกเหนือจากเนื้อหาที่แสดงในรายการที่กำลังแสดงผล ตามที่กล่าวไว้ก่อนหน้านี้ แม้ว่า .IsHome จะมีอยู่ในออบเจ็กต์เพจสำหรับเพจที่อยู่ในรายการเช่นกัน ซึ่งจะไม่ให้คำตอบที่ถูกต้องแก่เรา — เราต้องการทราบว่า เพจหลัก ที่แสดงผลเป็นโฮมเพจหรือไม่

เราสามารถส่งต่อชุดบูลีนไปยังผลลัพธ์ของการเรียก .IsHome ได้ แต่บางทีบางส่วนอาจจำเป็นต้องเข้าถึงเมธอดของเพจอื่นๆ ในอนาคต ไป ที่ออบเจ็กต์เพจหลักและออบเจ็กต์เพจ ที่อยู่ในรายการ ในตัวอย่างของเรา หน้าหลักจะอยู่ใน $ และหน้าที่แสดง . ใน . ดังนั้น ในแผนที่ที่ส่งไปยังบางส่วนที่ listed ในรายการ Page คีย์จะได้รับค่า $ ในขณะที่คีย์ "Listed" . รับค่า . นี่คือเทมเพลตหลักที่อัปเดต:

 <body> <nav> <a class="logo" href="{{ "/" | relURL }}"> <img src="/img/tower-logo.svg"> <img src="/img/tower-claim.svg"> </a> <ul> <li><a href="/">Home</a></li> <li><a href="/blog/">Blog</a></li> </ul> </nav> <section class="featured"> <div class="container"> {{ with .GetPage .Params.featured }} {{ partial "partials/featured.html" . }} {{ end }} </div> </section> <section class="content"> <div class="container"> <h1>{{ .Title }}</h1> {{ .Content }} </div> </section> <aside> <h2>{{ .Params.banner.headline }}</h2> <p>{{ .Params.banner.subline}}</p> </aside> <section class="listing"> <div class="container"> <h1>{{ .Params.listing_headline }}</h1> <div> {{ range .Params.listing }} {{ with $.GetPage . }} {{ partial "partials/listed.html" (dict "Page" $ "Listed" .) }} {{ end }} {{ end }} </div> </div> </section> </body>

เนื้อหาของส่วน "แนะนำ" ของเราจะไม่เปลี่ยนแปลงเมื่อเทียบกับเมื่อเป็นส่วนหนึ่งของเทมเพลตรายการ:

 <article> <h2>{{ .Title }}</h2> {{ .Summary }} <p><a href="{{ .Permalink }}">Read more →</a></p> </article>

อย่างไรก็ตาม บางส่วนของเราสำหรับเนื้อหาที่อยู่ในรายการ สะท้อนให้เห็นถึงความจริงที่ว่าขณะนี้พบวัตถุหน้าต้นฉบับใน . .Page ในขณะที่พบชิ้นส่วนของเนื้อหาที่อยู่ในรายการ . .Listed :

 <article{{ if .Page.IsHome }} class="home"{{ end }}> <h2>{{ .Listed.Title }}</h2> {{ .Listed.Summary }} <p><a href="{{ .Listed.Permalink }}">Read more →</a></p> </article>

Hugo ยังมีฟังก์ชันเทมเพลตพื้นฐานซึ่งช่วยให้คุณ ขยายเทมเพลตพื้นฐานทั่วไป แทนที่จะรวมเทมเพลตย่อย ในกรณีนี้ บริบทจะทำงานในลักษณะเดียวกัน: เมื่อขยายเทมเพลตฐาน คุณจะต้องให้ข้อมูลที่จะประกอบเป็นบริบทดั้งเดิมในเทมเพลตนั้น

ตัวแปรที่กำหนดเอง

นอกจากนี้ยังสามารถกำหนดและกำหนดตัวแปรที่กำหนดเองใหม่ในเทมเพลต Hugo ได้อีกด้วย สิ่งเหล่านี้จะพร้อมใช้งานในเทมเพลตที่มีการประกาศ แต่จะไม่เข้าสู่เทมเพลตบางส่วนหรือพื้นฐานใด ๆ เว้นแต่เราจะส่งต่ออย่างชัดเจน ตัวแปรที่กำหนดเองที่ ประกาศภายใน "บล็อก" เช่นเดียวกับที่ระบุโดยคำสั่ง if จะมีเฉพาะในบล็อกนั้น - หากเราต้องการอ้างถึงภายนอกบล็อก เราต้องประกาศภายนอกบล็อก แล้วแก้ไขภายใน บล็อกได้ตามต้องการ

ตัวแปรที่กำหนดเองมีชื่อ นำหน้า ด้วยเครื่องหมายดอลลาร์ ( $ ) หากต้องการประกาศตัวแปรและกำหนดค่าพร้อมกัน ให้ใช้ตัวดำเนินการ := การกำหนดตัวแปรภายหลังให้ใช้ตัวดำเนินการ = (ไม่มีเครื่องหมายทวิภาค) ไม่สามารถกำหนดตัวแปรให้ก่อนที่จะประกาศได้ และไม่สามารถประกาศตัวแปรได้โดยไม่ต้องให้ค่า

กรณีการใช้งานหนึ่งสำหรับตัวแปรที่กำหนดเองทำให้การเรียกใช้ฟังก์ชันแบบยาวง่ายขึ้นโดยกำหนดผลลัพธ์ระดับกลางให้กับตัวแปรที่มีชื่ออย่างเหมาะสม ตัวอย่างเช่น เราสามารถกำหนดออบเจกต์เพจเด่นให้กับตัวแปรชื่อ $featured แล้วส่งตัวแปรนี้ให้ with คำสั่ง with นอกจากนี้เรายังสามารถใส่ข้อมูลที่จะจัดหาให้กับบางส่วน "ที่อยู่ในรายการ" ในตัวแปรและมอบให้กับการเรียกบางส่วน

เทมเพลตของเราจะมีลักษณะดังนี้เมื่อมีการเปลี่ยนแปลงเหล่านั้น:

 <section class="featured"> <div class="container"> {{ $featured := .GetPage .Params.featured }} {{ with $featured }} {{ partial "partials/featured.html" . }} {{ end }} </div> </section> <section class="content"> ... </section> <aside> ... </aside> <section class="listing"> <div class="container"> <h1>{{ .Params.listing_headline }}</h1> <div> {{ range .Params.listing }} {{ with $.GetPage . }} {{ $context := (dict "Page" $ "Listed" .) }} {{ partial "partials/listed.html" $context }} {{ end }} {{ end }} </div> </div> </section>

จากประสบการณ์ของฉันกับ Hugo ฉันขอแนะนำให้ ใช้ตัวแปรที่กำหนดเองอย่างเสรี ทันทีที่คุณพยายามใช้ตรรกะที่เกี่ยวข้องมากกว่านี้ในเทมเพลต แม้ว่าการพยายามทำให้โค้ดของคุณกระชับเป็นเรื่องปกติ แต่ก็อาจทำให้สิ่งต่างๆ มีความชัดเจนน้อยกว่าที่ควรจะเป็น ซึ่งทำให้คุณและคนอื่นๆ สับสน

ให้ใช้ ตัวแปรที่มีชื่ออธิบาย สำหรับแต่ละขั้นตอนแทน และไม่ต้องกังวลกับการใช้สองบรรทัด (หรือสามหรือสี่ ฯลฯ) ในที่ๆ หนึ่งจะทำ

.เกา

สุดท้าย มาปิดกลไก . .Scratch กันดีกว่า ใน Hugo เวอร์ชันก่อนหน้า สามารถกำหนดตัวแปรที่กำหนดเองได้เพียงครั้งเดียว ไม่สามารถกำหนดตัวแปรที่กำหนดเองใหม่ได้ ทุกวันนี้ ตัวแปรที่กำหนดเองสามารถกำหนดใหม่ได้ ซึ่งทำให้ .Scratch มีความสำคัญน้อยลง แม้ว่าจะยังคงมีประโยชน์อยู่ก็ตาม

กล่าวโดยย่อ . .Scratch เป็นพื้นที่เริ่มต้นที่ให้คุณ ตั้งค่าและแก้ไขตัวแปรของคุณเอง ได้ เช่น ตัวแปรที่กำหนดเอง ต่างจากตัวแปรที่กำหนดเอง . .Scratch เป็นของบริบทของหน้า ดังนั้นการส่งต่อบริบทนั้นไปยังบางส่วน เช่น จะนำตัวแปร scratch ไปพร้อมกับตัวแปรโดยอัตโนมัติ

คุณสามารถตั้งค่าและรับตัวแปรบน .Scratch ได้โดยการเรียกเมธอด Set and Get มีวิธีการมากกว่านี้ เช่น การตั้งค่าและอัปเดตประเภทข้อมูลแบบผสม แต่สองวิธีนี้จะเพียงพอสำหรับความต้องการของเราที่นี่ Set รับ พารามิเตอร์สองตัว : คีย์และค่าสำหรับข้อมูลที่คุณต้องการตั้งค่า Get เพียงอันเดียว: กุญแจสำหรับข้อมูลที่คุณต้องการดึง

ก่อนหน้านี้ เราใช้ dict เพื่อสร้างโครงสร้างข้อมูลแผนที่เพื่อส่งข้อมูลหลายชิ้นไปยังบางส่วน สิ่งนี้ทำขึ้นเพื่อให้บางส่วนของเพจที่แสดงรายการจะสามารถเข้าถึงทั้งบริบทของเพจดั้งเดิมและออบเจกต์เพจที่แสดงในรายการนั้น ๆ การใช้ .Scratch ไม่จำเป็นต้องเป็นวิธีที่ดีกว่าหรือแย่กว่านั้นเสมอไป แล้วแต่กรณีที่ต้องการอาจขึ้นอยู่กับสถานการณ์

มาดูกันว่าเทมเพลตรายการของเราจะเป็นอย่างไรเมื่อใช้ .Scratch แทน dict เพื่อส่งข้อมูลไปยังบางส่วน เราเรียก $.Scratch.Get (อีกครั้งโดยใช้บริบทส่วนกลาง) เพื่อตั้งค่าตัวแปร scratch "listed" เป็น . — ในกรณีนี้คืออ็อบเจ็กต์เพจที่อยู่ในรายการ จากนั้นเราส่งเฉพาะวัตถุหน้า $ ไปยังบางส่วน ตัวแปรเริ่มต้นจะตามมาโดยอัตโนมัติ

 <section class="listing"> <div class="container"> <h1>{{ .Params.listing_headline }}</h1> <div> {{ range .Params.listing }} {{ with $.GetPage . }} {{ $.Scratch.Set "listed" . }} {{ partial "partials/listed.html" $ }} {{ end }} {{ end }} </div> </div> </section>

สิ่งนี้จะต้องมีการแก้ไขบางส่วนกับ listed.html บางส่วนเช่นกัน — บริบทของหน้าดั้งเดิมพร้อมใช้งานเป็น “จุด” ในขณะที่ดึงหน้าที่แสดงในรายการจากอ็อบเจ็กต์ . .Scratch เราจะใช้ตัวแปรที่กำหนดเองเพื่อลดความซับซ้อนในการเข้าถึงหน้าที่แสดงรายการ:

 <article{{ if .IsHome }} class="home"{{ end }}> {{ $listed := .Scratch.Get "listed" }} <h2>{{ $listed.Title }}</h2> {{ $listed.Summary }} <p><a href="{{ $listed.Permalink }}">Read more →</a></p> </article>

อาร์กิวเมนต์หนึ่งสำหรับการทำสิ่งนี้ในลักษณะนี้คือความสม่ำเสมอ เมื่อใช้ .Scratch คุณสามารถสร้างนิสัยที่จะส่งต่อออบเจ็กต์ของเพจปัจจุบันไปยังบางส่วนได้เสมอ โดยเพิ่มข้อมูลพิเศษใดๆ เป็นตัวแปรการขีดข่วน จากนั้น เมื่อใดก็ตามที่คุณเขียนหรือแก้ไขส่วนย่อยของคุณ คุณจะรู้ . เป็นวัตถุหน้า แน่นอน คุณสามารถสร้างแบบแผนสำหรับตัวคุณเองโดยใช้แผนที่ที่ส่งผ่านเข้ามาเช่นกัน เช่น ส่งออบ .Page กต์ของเพจเป็น .Page เสมอ

บทสรุป

เมื่อพูดถึงบริบทและข้อมูล เครื่องมือสร้างไซต์แบบคงที่มีทั้งข้อดีและข้อจำกัด ในแง่หนึ่ง การดำเนินการที่ไม่มีประสิทธิภาพเกินไปเมื่อเรียกใช้สำหรับการเยี่ยมชมเพจทุกครั้งอาจสมบูรณ์แบบเมื่อเรียกใช้เพียงครั้งเดียวในขณะที่เพจถูกคอมไพล์ ในทางกลับกัน อาจทำให้คุณประหลาดใจว่าการเข้าถึงบางส่วนของคำขอเครือข่ายจะมีประโยชน์เพียงใด แม้จะอยู่ในไซต์แบบสแตติกส่วนใหญ่ก็ตาม

ในการ จัดการพารามิเตอร์สตริงการสืบค้น ตัวอย่างเช่น บนไซต์สแตติก คุณจะต้องหันไปใช้ JavaScript หรือโซลูชันที่เป็นกรรมสิทธิ์บางอย่าง เช่น การเปลี่ยนเส้นทางของ Netlify ประเด็นคือในขณะที่การกระโดดจากไดนามิกไปยังไซต์สแตติกนั้นเป็นเรื่องง่ายในทางทฤษฎี แต่ก็เปลี่ยนความคิด ในช่วงเริ่มต้น คุณสามารถถอยกลับไปใช้นิสัยเดิม ๆ ได้ง่าย แต่การฝึกฝนจะทำให้สมบูรณ์แบบ

ด้วยเหตุนี้ เราจึงสรุปลักษณะการจัดการข้อมูลในตัวสร้างไซต์แบบคงที่ของ Hugo Even though we focused only on a narrow sector of its functionality, there are certainly things we didn't cover that could have been included. Nevertheless, I hope this article gave you some added insight into how data flows from content files, to templates, to subtemplates and how it can be modified along the way.

Note : If you already have some Hugo experience, we have a nice resource for you, quite appropriately residing on our aforementioned, Hugo-driven “Learn” site! When you just need to check the order of the arguments to the replaceRE function, how to retrieve the next page in a section, or what the “expiration date” front matter field is called, a cheat sheet comes in handy. We've put together just such a reference, so download a Hugo cheat sheet, in a package also featuring a host of other cheat sheets on everything from Git to the Visual Studio Code editor.

อ่านเพิ่มเติม

If you're looking for more information on Hugo, here are some nice resources:

  • The official Hugo documentation is always a good place to start!
  • A great series of in-depth posts on Hugo on Regis Philibert's blog.