ICSI301 Төсөл 5: Нэг хуудаст апп
Энэ төслөөр фото зураг хуваалцдаг вэб аппыг эхлэлийг хийхэд React сангийн Material UI компоненттой хамтад нь ашиглана. Төслийн хоёрдахь хэсэгт өгөгдлийг серверээс авах талаар судлах болно.
Тохиргоо
Та өөрийн систем дээрээ Node.js болон npm модуль менежерийг суулгасан байх ёстой. Хэрэв үгүй бол, суулгах зааврыг дагаж одоо суулгаарай.
project5 нэрээр хавтас үүсгэж
энэ файлыг дотор нь задалж хуулаарай. Энэ zip файл энэ даалгаварт ашиглах гарааны файлуудыг агуулж байгаа.
Энэ даалгаварт Node.js-ийн 20.19, 22.13 эсвэл 24-өөс дээш хувилбар шаардлагатай.
Мөн хэд хэдэн node модуль хэрэгтэй. Жишээ нь, Vite нь
React аппын JSX файлуудыг ЖаваСкрипт болгон хөрвүүлж багцалдаг (build) багаж,
ESLint нь кодыг шалгах багаж,
ExpressJS нь веб аппыг веб хөтчид өгч үйлчлэх энгийн Node.js веб сервер үүсгэхэд хэрэглэгдэнэ.
Мөн React Router болон React компонент, CSS загварыг (stylesheet) агуулсан
Material UI модулийг татаж авна.
Эдгээр модулийг project5 хавтас дотроос дараах командыг
ажиллуулж суулгана:
npm installReact болон Material UI компонентууд
node_modules дэд хавтас дотор суух ч гэсэн
тэдгээрийг бид Node.js-ээр биш, веб хөтчид дуудаж ашиглах болно.
Төслийн бүтэц нь Төсөл 4-ийн адил Vite-ийн стандарт бүтэц дээр суурилсан. Аппын бүх эх код
src хавтаст, аппыг ачаалах index.html хуудас төслийн үндсэн хавтаст,
зургууд public/images хавтаст байрлана.
package.json файлын "scripts" шинжид байгаа дараах npm скриптүүдийг ажиллуулах боломжтой:
npm run lint- ESLint багажийг төслийн бүх ЖаваСкрипт файлд ажиллуулна. Даалгавраар илгээх таны код чинь ESLint програмыг ямар нэг санамжгүйгээр (warnings) давсан байх ёстой.npm run build-vite.config.jsфайлд байгаа тохиргоогоор аппын бүх JSX файлуудыг багцалжdistхавтас дотор ЖаваСкрипт багц (bundle) файлууд үүсгэнэ.npm run build:w-npm run buildкомандтай адил, гэхдээ --watch горимоор ажиллана. Ингэснээр эх кодын файлуудыг хянаж, аль нэгийг нь өөрчилж хадгалах бүрт багцыг дахин үүсгэнэ. Шинэ багцыг харахын тулд веб хөтчийн хуудсаа сэргээнэ (refresh).npm start-webServer.jsвеб серверийг асаана.
Бүх даалгаварыг гүйцэтгэсэн кодууд project5 хавтас дотор байх ёстой.
Энэ төсөлд Төсөл 4-ийн Vite хөгжүүлэлтийн серверийн (npm run dev) оронд бидний өгч буй
webServer.js веб серверийг ашиглана. Учир нь Даалгавар 2-т апп өгөгдлөө энэ серверээс авна.
Сервер нь dist хавтсыг үйлчилдэг тул эхлээд багцаа үүсгэх хэрэгтэй.
project5 хавтас дотроос командын мөрийн хоёр цонх нээж, нэгд нь:
npm run build:w
npm start
Ctrl+C дарна.
Даалгавар 1: Фото хуваалцдаг апп үүсгэх (40 оноо)
Таны үүсгэх PhotoApp-д зориулж бид суурь бүтцэт (skeleton) гарааны кодыг өгсөн байгаа:
index.html хуудас нь src/main.jsx-ийг ачаалж, тэр нь
src/photoShare.jsx доторх PhotoShare компонентыг рендерлэнэ.
Үүнийг
http://localhost:3000 URL-ээр хандаж ажиллуулна.
Энэ суурь код:
-
Хичээлээр заасан мастер-деталь хэвийг хэрэгжүүлсэн Material UI ашигладаг
React веб аппыг дууддаг. Энэ апп
дээд хэсэгтээ
Material UI App Bar
, зүүн хажуудаа
UserList, контент талбайдааUserDetailэсвэлUserPhotosкомпонентийг байршуулсан байгаа. -
Нэг хуудаст аппд гүн холбоосыг (deep linking) бий болгохын тулд
React Router-ийн declarative горимоор
дараах гурван компонентийг заах замыг тохируулсан.
-
/usersньsrc/components/UserList/UserList.jsxдоторхUserListкомпонентийг заана. -
/users/:userIdньsrc/components/UserDetail/UserDetail.jsxдоторхUserDetailкомпонентийг заана. -
/photos/:userIdньsrc/components/UserPhotos/UserPhotos.jsxдоторхUserPhotosкомпонентийг заана.
src/photoShare.jsxдотор BrowserRouter,Routes,Routeболон Outlet компонентийг хэрхэн хэрэглэж байгаагаас харж болно. Замын бүх компонент ньPhotoShareLayoutхүрээний дэд зам (nested route) бөгөөд контент талбай дахь<Outlet />байрлалд рендерлэгдэнэ. -
-
src/components/*хавтас дотор байгаа компонент бүрт хоосон CSS файл болон юу хийх, модель өгөгдлийг хэрхэн хэрэглэх тухай тайлбартай энгийн функц компонентыг тодорхойлж өгсөн.
Энэ даалгаврын хувьд бид өөрсдийн шидэт
icsi301models моделийг ашиглана. Энэ нь урьдаас бэлдсэн мэдээллийг дэлгэцлэхэд
модель өгөгдөл болох юм. Төсөл 4-ийн адил моделийг ЖаваСкрипт модулиас импортлож хандана:
import icsi301models from '../../modelData/photoApp';
src/modelData/photoApp.js файлд байгаа бөгөөд схемийг доор тайлбарласан болно.
Таны даалгавар бол өгсөн хоосон-програмыг (skeleton) хуурмаг модель өгөгдөл дээр ажилладаг болгох юм.
Энэ програмд хэдийнэ
UserList, UserDetail, болон
UserPhotos зэрэг компонентийг холбож өгсөн байгаа. Энэ нь
React Router компонентод шаардлагатай параметрүүд холбож өгсөн бөгөөд компонентийг үүсгэх
ихэнх ажлуудыг хийчихсэн.
Эдгээрийг дараах шаардлагын дагуу хөгжүүлнэ:
-
UserListкомпонент системд байгаа бүх хэрэглэгчийн дэлгэрэнгүй мэдээллийг харуулахын тулд хэрэглэгчдийг жагсааж харуулдаг байна. Компонент нь хажуу хэсэгт (side bar) байрлах ба хэрэглэгчийн нэрсийн жагсаалтыг дэлгэцлэнэ. Хэрэглэгчийн нэр дээр дарахад тухайн хэрэглэгчийн дэлгэрэнгүй мэдээллийг үндсэн хэсэгт (content area) дэлгэцэлдэг байна. -
UserDetailкомпонент нь URL-ийнuserIdпараметрийг React Router-ийн useParams() hook-оор авна. Энэ харагдац нь хэрэглэгчийн дэлгэрэнгүйг харуулах бөгөөд тухайн хэрэглэгчийн оруулсан зургуудыг харуулахUserPhotosкомпонентруу заах линктэй байна. -
UserPhotosкомпонент мөнuserId-ийгuseParams()hook-оор авна. Сонгосон хэрэглэгчийн бүх зургийг харуулна. Тухайн хэрэглэгчтэй холбоотой бүх зургийг дэлгэцлэх ёстой. Зураг бүрийн хувьд бичсэн сэтгэгдлүүдийг харуулна. Сэтгэгдэл нэг бүрийн бичсэн огноо, тухайн сэтгэгдлийг бичсэн хэрэглэгч болон сэтгэгдлийн бичвэрийг харуулдаг байна. Тухайн сэтгэгдлийг бичсэн хэрэглэгчийн нэр нь линк байх ба дарахад тухайн хэрэлэгчийн дэлгэрэнгүй мэдээллийг үзүүлнэ.
Эдгээр компонентоос гадна src/components/TopBar/TopBar.jsx дотор байгаа
TopBar компонентийг дараах шаардлагын дагуу шинэчлэнэ:
-
TopBar-ын зүүн талд таны нэр байна. -
TopBar-ын баруун талд аппын агуулгыг үндсэн хэсэгт юу үзүүлж байгаагаас хамаарч гаргана. Жишээ нь, үндсэн хэсэгт хэрэглэгчийн дэлгэрэнгүй мэдээллийг харуулж байвалTopBarнь хэрэглэгчийн нэрийг, хэрэв хэрэглэгчийн зургийг үзүүлж байвал "Зургууд: " гээд араас нь хэрэглэгчийн нэрийг залгаж харуулдаг байна.TopBarнь<Routes>-ээс гадна рендерлэгддэг тулuseParams()ажиллахгүй. Оронд нь useLocation() эсвэл useMatch() hook-ийг ашиглаж болно.
Энэ хоосон-програмд React Router ашиглан аппын ялгаатай харагдац бүрт
гүн-холбоос (deep-linking) үүсгэж өгсөн. Таны үүсгэх компонент энэ боломжийг
эвдэхгүй байх ёстой. Энэ нь веб хөтчийг сэргээх (refresh) үед өмнө үзэж байснаараа
гардаг байх боломжийг олгож байгаа юм. BrowserRouter нь /users/:userId
гэх мэт жинхэнэ URL ашигладаг тул сэргээх үед ийм хүсэлт серверт ирдэг. Үүнд зориулж
webServer.js нь өөр замд тохироогүй бүх хүсэлтэд аппын index.html-ийг буцаадаг. Бидний компонент үүсгэдэг стандарт арга нь
гүн-холбоосыг автоматаар тохируулдаг. Компонентууд хооронд объектыг дамжуулахад
үүнийг анхаарч байх ёстой. Хэрэв ямар нэг зүйл эвдсэн байвал харагдац бүр дээр
сэргээх туршилт хийгээд үзээрэй.
Харагдах байдлын хувьд цаг их зарцуулах хэрэггүй, энэ нь аятайхан, ойлгомжтой байх ёстой. Мэдээллийг дэлгэцлэх зохиомж нь цэвэр байна (Жишээ нь, зураг бүрийн хувьд холбогдох комментууд нь ойлгомжтой байх).
Фото апп модель өгөгдөл
Энэ даалгаврын хувьд бид src/modelData/photoApp.js модулиас
импортолдог шидэт модель өгөгдлийг ашиглана. Модель нь дөрвөн төрлийн объекттой.
Эдгээр нь user, photo, comment, болон
SchemaInfo төрөл.
-
Фото хуваалцдаг сайт дээрх фотонуудыг хэрэглэгчээр нь зохион байгуулсан.
Бид хэрэглэгчийг
userобъектоор илэрхийлэх ба дараах шинжүүдтэй:_id: Хэрэглэгчийн ID. first_name: Хэрэглэгчийн өөрийн нэр. last_name: Хэрэглэгчийн овог. location: Хэрэглэгчийн байршил. description: Хэрэглэгчийн талаарх товч тайлбар. occupation: Хэрэглэгчийн ажил мэргэжил. icsi301models.userModel(user_id)функц нь хэрэглэгчийнuser_idID-аарuserобъектыг буцаадаг. Харинicsi301models.userListModel()функц нь аппын бүх хэрэглэгчийнuserобъекыг буцаадаг. -
Хэрэглэгч бүр олон фото серверт хуулах боломжтой. Хэрэглэгчийн нэг зургийг
photoобъектоор, дараах шинжтэйгээр илэрхийлдэг:_id: Фото зургийн ID. user_id: Фото зургийг үүсгэсэн хэрэглэгчийн userID.date_time: Фото зургийг өгөгдлийн санд нэмсэн огноо ба цаг. file_name: Фото зургийг агуулж байгаа файлын нэр ( project5/public/imagesхавтас доторх; хөтчөөс/images/<file_name> замаар хандана).comments: Фото зургийн бүх сэтгэгдлийг commentsхадгалсан объектон хүснэгтэн хувьсагч, Нэгcommentнь тухайн фото зураг дээр бичигдсэн сэтгэгдэл.icsi301models.photoOfUserModel(user_id)функц нь хэрэглэгчийнuser_id-д холбогдохphotoобъектуудыг агуулсан хүснэгтэн хувьсагчийг буцаадаг. -
Фото бүр олон сэтгэгдэлтэй байж болно (ямар ч хэрэглэгч ямар ч фото зурагт сэтгэгдэл бичиж болно).
Сэтгэгдэл
commentобъект дараах шинжүүдтэй:_id: Сэтгэгдлийн ID. photo_id: Сэтгэгдэл харгалзах photoфото зургийн ID.user: Сэтгэгдэл бичсэн хэрэглэгчийн userобъект.date_time: Сэтгэгдлийг бичсэн огноо ба цаг. comment: Сэтгэгдлийн бичвэр. -
Турших зорилгоор
SchemaInfoобъектыг дараах шинжээр үүсгэсэн:_id: SchemaInfo схемийн ID. __v: SchemaInfo объектын хувилбарын дугаар. load_date_time: SchemaInfo ачаалах үеийн огноо ба цаг. Нэг тэмдэгт мөр.
Даалгавар 2: Веб серверээс моделийн өгөгдлийг авах (20 оноо)
Даалгавар 1-ийг гүйцэтгэсэний дараа манай фото аппын front-end бодит апп шиг харагдах ёстой. Гол асуудал нь хуурмаг модель өгөгдлийг аппын ЖаваСкрипт багц дотор шууд импортолж ачаалсан байсан. Даалгавар 2-ын хувьд, бид энэ арга залийг хаяад бодит апптай ижил серверээс модель өгөгдөл авдаг болгоно.
Энэ төслөөр өгсөн webServer.js нь Даалгавар 1-д импортолж
ашигласан icsi301models-ийг ExpressJS
чиглүүлэгч (route) ашиглан серверээс өгөгдөл авах боломжийг олгож байгаа.
Энэ API-ыг webServer.js-ээр гаргаж байгаа ба харгалзах URL хаягаар
HTTP GET хүсэлт явуулахад icsi301models моделиудаас өгөгдлийг буцааж өгдөг.
Эдгээр GET хүсэлтэд хариулах HTTP хариулт нь JSON форматтай байна. Энэ API бол:
/test/info-icsi301models.schemaInfo()объектыг буцаана. Энэ нь URL нь модель дуудаж турших зориулалттай./user/list-icsi301models.userListModel() функцийг дуудаж буцаана../user/:id-icsi301models.userModel(id) функцийг дуудаж буцаана./photosOfUser/:id-icsi301models.photoOfUserModel(id) функцийг дуудаж буцаана..
Дээрх URL-ийг веб хөтөчийн хаягийн мөр дээрээ бичээд бодитоор хэрхэн ажиллаж байгааг харж болно. Жишээ нь, http://localhost:3000/test/info болон http://localhost:3000/user/list линк нь веб хөтчийн цонх дээр моделийн өгөгдлийг JSON форматаар харуулна.
Веб сервер дээрээс моделийг авдаг болгож програмаа хөрвүүлэхийн тулд
src/lib/fetchModelData.js файлд байгаа fetchModel функцийг хөгжүүлэх ёстой.
Энэ функцийг дараах тодорхойлолтын дагуу хөгжүүлнэ:
/**
* fetchModel - Веб серверээс моделийг авдаг
*
* @param {string} url GET хүсэлт явуулах URL
*
* @returns GET хүсэлтийн хариултад ирэх JSON объектоор дүүргэсэн Promise буцаана.
* Өгөгдөл нь нэг объектын "data" нэртэй шинжэд байна.
* Хэрэв хүсэлт явуулахад алдаа гарвал Promise нь дараах шинжүүдийг агуулсан объектыг буцаана.
* {number} status HTTP хариултын төлөв
* {string} statusText xhr хүсэлтээр ирсэн өгөгдөл
*/
Хэдийгээр энэ функцийг олон янзын бэлэн хөгжүүлсэн модуль ашиглан хийж болох ч
та AJAX-ийн доод түвшний мэдлэгт суралцах хэрэгтэй. Та fetchModel
функцийг кодлохдоо өөр бусад санг ашиглахгүй байх; XMLHttpRequest DOM объектыг
үүсгэх болон түүний үзэгдлийг барьж авч хэрэглэх ЖаваСкрипт кодыг бичээрэй.
Таны код олон fetchModel хүсэлтүүдийг хүлээн авч хариулдаг байх ёстой.
Өөрийн fetchModel функцийг ажиллаж байгаа эсэхийг харахын тулд
http://localhost:3000
хаягаар орж үзээрэй. Энэ нь http://localhost:3000/test/info
хаягруу хүсэлт явуулаад буцаж ирэх хувилбарын дугаарыг дэлгэцэлдэг юм. Хувилбарын дугаарыг
өөрийн аппынхаа TopBar компонентод дэлгэцэлдэг байна.
src/lib/fetchModelData.js файлд fetchModel функцийг амжилттай
кодлосны дараа та дараах файлуудын кодыг өөрчлөөрэй.
src/components/UserDetail/UserDetail.jsxsrc/components/UserList/UserList.jsxsrc/components/UserPhotos/UserPhotos.jsx
fetchModel функц нь серверээс өгөгдлийг авах хүсэлт тавьдаг.
Таны компонентуудад icsi301models-ийг шууд дуудаж
ашиглах код байх ёсгүй. Өөрөөр хэлбэл, src/components доторх аль ч файлд
дараах мөр байх ёсгүй (webServer.js үүнийг импортлох нь зөв):import icsi301models from '../../modelData/photoApp';
Загвар (5 оноо)
Энэ оноог MVC загварын зөвлөмжийг дагаж зөв зохион байгуулсан тохиолдолд өгнө. Нэмж хэлэхэд, таны код болон компонент цэвэрхэн, уншууртай байх ёстой ба таны апп ядаж"тодорхой хэмжээнд гоё" харагддаг, хэрэглэгддэг байна.
Бид Material UI гэх Гүүглээс гаргасан Material Design зөвлөмжийг хэрэгжүүлсэн React компонентийг ашиглана. Хичээл дээр ярьсан Master-Detail загварыг хэрэгжүүлэхэд Material UI-ийн Grid component ашиглаж харуулсан. Мөн App Bar компонентоор аппын толгой хэсгийг хийсэн байгаа. Хэдийгээр Material Design загварт бүрэн нийцсэн апп хөгжүүлэхийг шаардахгүй ч боломжтой бол Material UI элементүүдийг аль болох ашиглаж хийгээрэй.
Бас илгээхээсээ өмнө ESLint ажиллуулахаа мартуузай. ESLint ямар нэг алдаа өгөхгүй ёсгүй.
Нэмэлт оноо (5 оноо)
userPhotos компонент нь хэрэглэгчийн бүх зургаас гадна
зурагт бичсэн комментуудыг харуулах ёстой. Энэ арга нь маш олон зурагтай
хэрэглэгчийн хувьд тийм ч сайн ажиллахгүй. Нэмэлт онооны даалгавраар
нэг зургийг комменттой нь харуулдаг болгож хөгжүүлэх ба өмнөх болон
дараах гэсэн механизмыг (жишээ нь, stepper буюу алхамт байдлаар) хэрэгжүүлж
хэрэглэгчийн зургийг дэлгэцэлдэг байна.
Энэ даалгаврт нэмэлт оноо авахын тулд таны шийдэл дараах шиг байна:
-
Фото аппдаа "Нэмэлт сонголт" ойлголтыг оруулж ирнэ. Апп эхлэж ажиллахад
энэ сонголт нь үргэлж идэвхгүй байна.
TopBarкомпонент "Нэмэлт сонголтыг" идэвхжүүлэх чагтлах товлууртай (checkbox) байх үүнийг чагталсан тохиолдолд "Нэмэлт сонголт" идэвхтэй болно. Эсрэг тохиолдолд идэвхгүй болно. Чагтлах товчлуур дарснаар сонголтыг идэвхтэй/идэвхгүй болгоно. - Таны апп "Нэмэлт сонголт"-ыг идэвхжүүлээгүй бол зураг үздэг ердийн харагдацаа ашигладаг байх юм. Хэрэв идэвхжсэн бол зургуудыг нэг нэгээр нь алхамт байдлаар харуулдаг байна.
- Алхамаар харуулах хэрэглэгчийн интерфэйс нь хэрэглэгч зургуудын хамгийн эхнийхийг үзэж байвал бол өмнөх зурагруу, хамгийн сүүлд очсон бол дараах зурагруу шилжих боломжгүй учир үүнийг маш ойлгомжтой (жишээ нь, товчлуурыг идэвхгүй болгох) харуулдаг байна.
- Таны апп тухайн нэг зургийн URL хаягийг веб хөтчийн хаягийн мөрөөс хуулж шэйрлэх болон тэмдэглэж авах (bookmark) боломжийг олгодог байна. Веб хөтчийн өмнөх болон дараах шилжих товч нь өмнөхрүү буцах, эргэж буцах гээд хийдэг үйлдлээ хийдэг байна. Тухайн зургийг заах гүн холбоосоор аппруу орох үед алхамт байдлаар харуулах үүргээрээ ажилладаг байна.
Санамж: Энэ нэмэлт онооны даалгаврыг хийх нь төслөөр хийсэн нэмэлт онооны бус бусад даалгавруудын хэд хэдэн хэсэгт өөрчлөх шаардлага гарна. Онцлог чагтлах (feature flag) товчлуураар ийм боломжийг хийх нь веб аппликейшнд нийтлэг практик байдаг. Гэхдээ нэмэлт онооны бус бусад даалгавруудаа эвдэж нэмэлт оноо авах гэж байгад илүү их оноо алдах эрсдэл бий. Болгоомжтой байгаарай.
Хүлээлгэн өгөх үр дүн
Ердийн Даалгавар илгээх
зааврын дагуу аппаа бүхэлд нь (project5
хавтас доторх бүгд) илгээнэ. Илгээхээсээ өмнө зааврын дагуу
төслийн хавтасаа цэвэрлээрэй. Ялангуяа, 180MB хэмжээтэй
node_modules/ хавтсыг дэмий хадгалахыг хүсэхгүй байна.
dist/ хавтсаа ч бас устгахаа мартуузай.