วิธีส่งข้อมูลระหว่างส่วนประกอบใน Vue.js

เผยแพร่แล้ว: 2022-03-10
สรุปอย่างรวดเร็ว ↬ ด้วยวิธีการต่างๆ มากมายในการแบ่งปันข้อมูลระหว่างส่วนประกอบต่างๆ คุณควรรู้ว่าเทคนิคใดดีที่สุดสำหรับสถานการณ์ของคุณ มาวิเคราะห์วิธีทั่วไปสามวิธีในการส่งข้อมูลใน VueJS

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

เว้นแต่ว่าคุณกำลังสร้างแอป Vue ทั้งหมดของคุณในองค์ประกอบเดียว (ซึ่งไม่สมเหตุสมผลเลย) คุณจะพบสถานการณ์ที่คุณต้องการแชร์ข้อมูลระหว่างส่วนประกอบต่างๆ

ในตอนท้ายของบทช่วยสอนนี้ คุณจะรู้สามวิธีในการทำสิ่งนี้ให้สำเร็จ

  • การใช้อุปกรณ์ประกอบฉากเพื่อแบ่งปันข้อมูลจากผู้ปกครองไปยังเด็ก
  • ปล่อยเหตุการณ์ที่กำหนดเองเพื่อแบ่งปันข้อมูลจากลูกไปยังผู้ปกครอง
  • การใช้ Vuex เพื่อสร้างสถานะแชร์ระดับแอป

โอเค - มาเริ่มกันเลย!

สร้างแอปด้วย Nuxt

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

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

1. การใช้อุปกรณ์ประกอบฉากเพื่อแบ่งปันข้อมูลจากผู้ปกครองถึงเด็ก

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

ตัวอย่างเช่น สมมติว่าเรากำลังดำเนินการในหน้าโปรไฟล์ผู้ใช้และต้องการให้องค์ประกอบย่อยยอมรับชื่อผู้ใช้ เราต้องการสององค์ประกอบ

  1. องค์ประกอบลูกที่ยอมรับพร็อพ ให้เรียกสิ่งนี้ว่า AccountInfo.vue
  2. องค์ประกอบหลักที่ส่งผ่าน prop ให้เรียก ProfilePage.vue นี้

ภายใน AccountInfo.vue เราสามารถประกาศอุปกรณ์ประกอบฉากที่ยอมรับโดยใช้ตัวเลือกอุปกรณ์ประกอบฉาก ดังนั้น ภายในตัวเลือกส่วนประกอบ เรามาทำให้มันมีลักษณะดังนี้

 // AccountInfo.vue <template> <div id='account-info'> {{username}} </div> </template> <script> export default { props: ['username'] } </script>

จากนั้น ในการส่งข้อมูลจากพาเรนต์ ( ProfilePage.vue ) เราส่งผ่านเหมือนแอตทริบิวต์ที่กำหนดเอง

 // ProfilePage.vue <account-info username='matt' />

ตอนนี้ หากเราโหลดหน้าเว็บ เราจะเห็นว่าองค์ประกอบ AccountInfo ของเราแสดงค่าที่ส่งผ่านโดยพาเรนต์อย่างถูกต้อง

เมื่อทำงานกับคำสั่ง VueJS อื่นๆ เราสามารถใช้ v-bind เพื่อส่งผ่านอุปกรณ์ประกอบฉากแบบไดนามิก ตัวอย่างเช่น สมมติว่าเราต้องการตั้งค่า username prop ให้เท่ากับตัวแปร เราสามารถทำได้โดยใช้ชวเลขสำหรับคำสั่ง v-bind (หรือเพียง : สำหรับระยะสั้น) รหัสจะมีลักษณะดังนี้:

 <template> <div> <account-info :username="user.username" /> </div> </template> <script> import AccountInfo from "@/components/AccountInfo.vue"; export default { components: { AccountInfo }, data() { return { user: { username: 'matt' } } } } </script>

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

เคล็ดลับ: ตรวจสอบอุปกรณ์ประกอบฉากของคุณเสมอ

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

สมมติว่าเราต้องการให้ชื่อผู้ใช้ของเรายอมรับสตริงเท่านั้น เราจะต้องแก้ไขวัตถุ props ของเราให้มีลักษณะดังนี้:

 export default { props: { username: String } }

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

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

เคล็ดลับ: ปฏิบัติตามอนุสัญญาการตั้งชื่อพร็อพ

ตามคู่มือสไตล์ VueJS วิธีที่ดีที่สุดในการตั้งชื่อพร็อพของคุณคือการใช้ camelCase เมื่อประกาศในสคริปต์และ kebab-case เมื่ออ้างอิงถึงพวกมันในโค้ดเทมเพลต

เหตุผลเบื้องหลังเรื่องนี้ค่อนข้างง่าย ใน Javascript นั้น camelCase เป็นรูปแบบการตั้งชื่อมาตรฐานและใน HTML มันคือ kebab-case

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

 // GOOD <account-info :my-username="user.username" /> props: { myUsername: String } // BAD <account-info :myUsername="user.username" /> props: { "my-username": String }

2. การปล่อยเหตุการณ์เพื่อแบ่งปันข้อมูลจากเด็กถึงผู้ปกครอง

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

ทุกอินสแตนซ์ของ Vue สามารถเรียกเมธอด .$emit(eventName) ที่ทริกเกอร์เหตุการณ์ได้ จากนั้น เราสามารถฟังเหตุการณ์นี้ในลักษณะเดียวกับงานอื่นๆ โดยใช้คำสั่ง v-on

การสร้างเหตุการณ์ที่กำหนดเอง

มาสร้างจากตัวอย่างโปรไฟล์ผู้ใช้ของเราโดยเพิ่มปุ่มที่เปลี่ยนชื่อผู้ใช้ ภายในองค์ประกอบลูกของเรา ( AccountInfo.vue ) มาสร้างปุ่มกัน

จากนั้น เมื่อคลิกปุ่มนี้ เราจะปล่อยเหตุการณ์ที่เรียกว่า changeUsername

 <template> <div id='account-info'> <button @click='changeUsername()'>Change Username</button> {{username}} </div> </template> <script> export default { props: { username: String }, methods: { changeUsername() { this.$emit('changeUsername') } } } </script>

ภายในพาเรนต์ เราจัดการเหตุการณ์นี้และเปลี่ยนตัวแปร user.username เช่นเดียวกับที่เราได้พูดคุยกันก่อนหน้านี้ เราสามารถฟังเหตุการณ์โดยใช้คำสั่ง v-on หรือ "@" สั้นๆ

 <template> <div> <account-info :username="user.username" @changeUsername="user.username = 'new name'"/> </div> </template>

มาลองดูกัน คุณควรเห็นว่าเมื่อคุณคลิกปุ่ม ชื่อผู้ใช้จะเปลี่ยนเป็น "ชื่อใหม่"

เคล็ดลับ: เหตุการณ์ที่กำหนดเองสามารถยอมรับอาร์กิวเมนต์ได้

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

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

สมมติว่าเราต้องการแก้ไขเหตุการณ์ changeUsername เพื่อให้เราสามารถส่งต่อค่าได้

วิธี $emit ใช้พารามิเตอร์ตัวที่สองที่เป็นทางเลือกสำหรับอาร์กิวเมนต์ สิ่งที่เราทำคือเพิ่มค่าชื่อผู้ใช้ใหม่ของเราหลังชื่อกิจกรรมของเรา

 this.$emit('changeUsername', 'mattmaribojoc')

จากนั้นในองค์ประกอบหลักของเรา เราสามารถเข้าถึงค่าเหล่านี้แบบอินไลน์โดยใช้ตัวแปรพิเศษ $event หรือเราสามารถเขียนวิธีจัดการที่ใช้พารามิเตอร์ได้

 <account-info :username="user.username" @changeUsername="user.username = $event"/> OR <account-info :username="user.username" @changeUsername="changeUsername($event)"/> export default { ... methods: { changeUsername (username) { this.user.username = username; } } }

3. การใช้ Vuex เพื่อสร้างสถานะแชร์ระดับแอปพลิเคชัน

โอเค เรารู้วิธีแชร์ข้อมูลระหว่างพ่อแม่/ลูก แล้วองค์ประกอบอื่นๆ ล่ะ เราต้องสร้างระบบลำดับชั้นที่ซับซ้อนอย่างยิ่งถ้าเราต้องการส่งข้อมูลหรือไม่?

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

ในวิธีที่เราใช้ก่อนหน้านี้ (props / emitting events) แต่ละองค์ประกอบมีสถานะข้อมูลของตัวเองที่เราแชร์ระหว่างส่วนประกอบ อย่างไรก็ตาม Vuex ช่วยให้เราดึงข้อมูลที่ใช้ร่วมกันทั้งหมดไว้ในสถานะเดียวที่แต่ละองค์ประกอบสามารถเข้าถึงได้ง่าย สถานะที่ใช้ร่วมกันนี้เรียกว่าร้านค้า

มาลองดูกัน

เนื่องจาก Vuex นั้นแยกจากโค้ดหลักของ Vue เราจึงต้องติดตั้งและนำเข้าไปยังโครงการของเราก่อน อันดับแรก เราจะต้องเรียกใช้ npm install vuex --save ภายในโครงการ CLI ของเรา

จากนั้น สร้างโฟลเดอร์ src/store ด้วยไฟล์ index.js ที่มีโค้ดต่อไปนี้

 // store/index.js import Vue from "vue"; import Vuex from "vuex"; Vue.use(Vuex); export default new Vuex.Store({ state: {}, getters: {}, mutations: {}, actions: {} });

ในการรวมสิ่งนี้ในอินสแตนซ์รูท Vue ของเรา เราต้องนำเข้าไฟล์ store/index.js และส่งผ่านไปยังตัวสร้าง Vue ของเรา

 // main.js import store from "./store"; new Vue({ store, ...

การเข้าถึง Vue Store Inside Components

เนื่องจากเราเพิ่มที่เก็บ Vuex ของเราลงในอินสแตนซ์รูท Vue จึงถูกฉีดเข้าไปในรายการย่อยของรูททั้งหมด หากเราต้องการเข้าถึงร้านค้าจากส่วนประกอบ เราสามารถทำได้ผ่าน this.$store

ตอนนี้ มาเจาะลึกรายละเอียดเฉพาะของแต่ละส่วนสี่ส่วนของร้าน Vuec

1. รัฐ

สถานะ Vuex เป็นอ็อบเจ็กต์ที่มีข้อมูลระดับแอปพลิเคชัน อินสแตนซ์ Vue ทั้งหมดจะสามารถเข้าถึงข้อมูลนี้ได้

สำหรับร้านค้าของเรา ให้สร้างวัตถุผู้ใช้ที่เก็บข้อมูลโปรไฟล์ผู้ใช้เพิ่มเติม

 export default new Vuex.Store({ state: { user: { username: 'matt', fullName: 'Matt Maribojoc' } }, getters: {}, mutations: {}, actions: {} });

เราสามารถเข้าถึงข้อมูลนี้ภายในองค์ประกอบอินสแตนซ์ใดๆ เช่นนี้

 mounted () { console.log(this.$store.state.user.username); },

2. Getters

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

ต่อจากสโตร์ก่อนหน้านี้ สมมติว่าเราต้องการสร้างวิธีการที่ส่งกลับชื่อจริงของผู้ใช้ตามแอตทริบิวต์ชื่อเต็ม

 getters: { firstName: state => { return state.user.fullName.split(' ')[0] } }

คุณสมบัติ Vuex getter พร้อมใช้งานสำหรับส่วนประกอบบนอ็อบเจ็กต์ store.getters

 mounted () { console.log(this.$store.getters.firstName); }

เคล็ดลับ: รู้จักอาร์กิวเมนต์ Getter เริ่มต้น

โดยค่าเริ่มต้น Vuex getters ยอมรับสองอาร์กิวเมนต์

  1. state — สถานะอ็อบเจ็กต์สำหรับแอปพลิเคชันของเรา
  2. getters — อ็อบเจ็กต์ store.getters หมายความว่าเราสามารถเรียก getters คนอื่นๆ ในร้านของเราได้

getter ทุกคนที่คุณประกาศจะต้องมีอาร์กิวเมนต์สถานะแรก และขึ้นอยู่กับว่าคุณออกแบบโค้ดอย่างไร getters ของคุณสามารถอ้างอิงถึงกันได้โดยใช้อาร์กิวเมนต์ 'getters' ที่สอง

มาสร้างตัวรับนามสกุลที่เพียงแค่ลบค่าชื่อของเราออกจากคุณสมบัติสถานะชื่อเต็มของเรา ตัวอย่างนี้จะต้องใช้ทั้งอ็อบเจ็กต์ state และ getters

 lastName (state, getters) { return state.user.fullName.replace(getters.firstName, ''); }

เคล็ดลับ: ส่งผ่านอาร์กิวเมนต์ที่กำหนดเองไปยัง Vuex Getters

คุณลักษณะที่ยอดเยี่ยมอีกประการหนึ่งของ getters คือเราสามารถส่งอาร์กิวเมนต์ที่กำหนดเองได้โดยทำให้ getter ส่งคืนวิธีการ

 prefixedName: (state, getters) => (prefix) => { return prefix + getters.lastName; } // in our component console.log(this.$store.getters.prefixedName("Mr."));

3. การกลายพันธุ์

การกลายพันธุ์เป็นวิธี เดียว ที่จะเปลี่ยนค่าของ state object ได้อย่างถูกต้อง รายละเอียดสำคัญที่ควรทราบคือการกลายพันธุ์ ต้องซิงโครนั

เช่นเดียวกับ getters การกลายพันธุ์จะยอมรับคุณสมบัติสถานะ Vuex เป็นอาร์กิวเมนต์แรกเสมอ พวกเขายังยอมรับอาร์กิวเมนต์ที่กำหนดเอง ซึ่งเรียกว่า payload เป็นอาร์กิวเมนต์ที่สอง

ตัวอย่างเช่น มาทำการกลายพันธุ์เพื่อเปลี่ยนชื่อของผู้ใช้เป็นค่าเฉพาะ

 mutations: { changeName (state, payload) { state.user.fullName = payload } },

จากนั้น เราสามารถเรียกวิธีนี้จากคอมโพเนนต์ของเราโดยใช้เมธอด store.commit โดยมีเพย์โหลดเป็นอาร์กิวเมนต์ที่สอง

 this.$store.commit("changeName", "New Name");

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

 changeName (state, payload) { state.user.fullName = payload.newName }

มีสองวิธีในการเรียกการกลายพันธุ์ด้วยเพย์โหลด

  1. คุณสามารถมีประเภทการกลายพันธุ์เป็นอาร์กิวเมนต์แรกและเพย์โหลดเป็นอาร์กิวเมนต์ที่สองได้
  2. คุณสามารถประกาศผ่านอ็อบเจ็กต์เดียว โดยมีคุณสมบัติหนึ่งสำหรับประเภทและอีกรายการสำหรับเพย์โหลด
 this.$store.commit("changeName", { newName: "New Name 1", }); // or this.$store.commit({ type: "changeName", newName: "New Name 2" });

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

4. การกระทำ

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

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

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

ต่อไปนี้คือตัวอย่างการดำเนินการของ Vuex ที่รอสองวินาทีแล้วส่งการกลายพันธุ์ของ changeName

 actions: { changeName (context, payload) { setTimeout(() => { context.commit("changeName", payload); }, 2000); } }

ภายในส่วนประกอบของเรา เราใช้เมธอด store.dispatch เพื่อเรียกใช้ฟังก์ชันของเรา เราส่งผ่านอาร์กิวเมนต์เหมือนกับที่เราทำกับการกลายพันธุ์ เราประกาศประเภทและเราส่งอาร์กิวเมนต์ที่กำหนดเองในอาร์กิวเมนต์ที่สอง

 this.$store.dispatch("changeName", { newName: "New Name from Action" });

ห่อ

ตอนนี้ คุณควรทราบสามวิธีในการแบ่งปันข้อมูลระหว่างส่วนประกอบต่างๆ ใน ​​VueJS: อุปกรณ์ประกอบฉาก เหตุการณ์ที่กำหนดเอง และร้านค้า Vuex

ฉันหวังว่าบทช่วยสอนนี้จะช่วยให้คุณเข้าใจมากขึ้นเกี่ยวกับวิธีการต่างๆ ของ Vue และแนวทางปฏิบัติที่ดีที่สุด แจ้งให้เราทราบว่าคุณได้นำไปใช้ในโครงการของคุณอย่างไร!

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

หากคุณสนใจที่จะเจาะลึกลงไปในด้านเทคนิค/ความสามารถของแต่ละเทคนิค ต่อไปนี้คือจุดเริ่มต้นที่ดี

  • เว็บไซต์คู่มืออย่างเป็นทางการของ Vuex
  • VueJS Docs สำหรับอุปกรณ์ประกอบฉากและเหตุการณ์ที่กำหนดเอง
  • “WTF คือ Vuex? คู่มือสำหรับผู้เริ่มต้นในการจัดเก็บข้อมูลแอปพลิเคชันของ Vue” Anthony Gore ผู้พัฒนา Vue.js