ICSI301 Төсөл 5: Нэг хуудаст апп
Энэ төслөөр фото зураг хуваалцдаг вэб аппыг эхлэлийг хийхэд ReactJS фрэймвөркийг Material-UI компоненттой хамтад нь ашиглана. Төслийн хоёрдахь хэсэгт өгөгдлийг серверээс авах талаар судлах болно.
Тохиргоо
Та өөрийн систем дээрээ Node.js болон npm модуль менежерийг суулгасан байх ёстой. Хэрэв үгүй бол, суулгах зааврыг дагаж одоо суулгаарай.
project5 нэрээр хавтас үүсгэж
энэ файлыг дотор нь задалж хуулаарай. Энэ zip файл энэ даалгаварт ашиглах гарааны файлуудыг агуулж байгаа.
Энэ даалгаварт нэлээд олон node модулийг ашиглана. Жишээ нь,
Webpack,
Babel,
ESLint. Эдгээр багаж
ReactJS веб апп босгох (build), мөн веб аппыг веб хөтчид өгч үйчлэх
энгийн Node.js веб сервер (ExpressJS)
үүсгэхэд хэрэг болно. Энэ нь бас Material-UI модулийг татаж авах бөгөөд энэ модуль
React компонент болон CSS загварыг (stylesheet) агуулна.
Эдгээр модулийг project5 хавтас дотроос дараах командыг
ажиллуулж суулгана:
npm installReactJS болон Material-UI компонентууд
node_modules дэд хавтас дотор суух ч гэсэн үүнийг бид Node.js-ээр биш, веб хөтчид
дуудаж ашиглах болно.
Өмнөх төслийн адил npm командыг татаж авсан эдгээр багажийг ажиллуулахад хэрэглэнэ.
package.json файлд байгаа дараах npm скриптийг ажиллуулах боломжтой:
npm run lint- ESLint багажийг төслийн бүх ЖаваСкрипт файлд ажиллуулна. Даалгавраар илгээх таны код чинь ESLint програмыг ямар нэг санамжгүйгээр (warnings) давсан байх ёстой.npm run build- Webpack багажийгwebpack.config.jsфайлд байгаа тохиргоогоор ажиллуулж төсөлд байгаа бүх JSX файлуудыг багцалжcompiledхавтас дотор нэг ширхэг ЖаваСкрипт багц (bundle) файл үүсгэнэ.npm run build:w-npm run buildкомандтай адил, гэхдээ --watch горимоор Webpack багажийг ажиллуулна. Ингэснээр React компонентийг хянах, хэрэв тэдгээрийн аль нэгийг нь өөрчилбөл дахин шинэчилж үүсгэдэг.
Бүх даалгаварыг гүйцэтгэсэн кодууд project5 хавтас дотор байх ёстой.
Өмнөх төслөөр гүйцэтгэсэнтэй адил бидний өгч буй веб серверийг project5 хавтас дотроос
дараах командыг ажиллуулж асаана.
node webServer.js
Мөн өмнөхтэй адил дараах командаар:
node webServer.js & npm run build:w
Даалгавар 1: Фото хуваалцдаг апп үүсгэх (40 оноо)
Таны үүсгэх PhotoApp-д зориулж бид суурь бүтцэт (skeleton)
(photoShare.jsx-ийг дууддаг photo-share.html) гарааны кодыг өгсөн байгаа.
Үүнийг
http://localhost:3000/photo-share.html URL-ээр хандаж ажиллуулна.
Энэ суурь код:
-
Хичээлээр заасан мастер-деталь хэвийг хэрэгжүүлсэн Material-UI ашигладаг
ReactJS веб аппыг дууддаг. Энэ апп
дээд хэсэгтээ
Material-UI App Bar
, зүүн хажуудаа
UserList, контент талбайдааUserDetailэсвэлUserPhotosкомпонентийг байршуулсан байгаа. -
Нэг хуудаст аппд гүн холбоосыг (deep linking) бий болгохын тулд
React Router компонентоор
дараах гурван компонентийг заах замыг тохируулсан.
-
/usersньcomponents/userList/хавтас доторхUserListкомпонентийг заана. -
/users/:userIdньcomponents/userDetail/хавтас доторхUserDetailкомпонентийг заана. -
/photos/:userIdньcomponents/userPhotos/хавтас доторхUserPhotosкомпонентийг заана.
photoShare.jsxдотор HashRouter, болон Route компонентийг хэрхэн хэрэглэж байгаагаас харж болно.components/*хавтас дотор байгаа компонент бүрт хоосон CSS файл болон энгийн render функцийг юу хийх, модель өгөгдлийг хэрхэн хэрэглэх тухай тайлбарын хамт тодорхойлж өгсөн. -
Энэ даалгаврын хувьд би өөрсдийн шидэт
ICSI301models моделийг ашиглана. Энэ нь урьдаас бэлдсэн мэдээллийг дэлгэцлэхэд
модель өгөгдөл болох юм. Өмнө нь ийм модельд
window.ICSI301Models ашиглан хандаж байсныг санаж байгаа байх. Моделийн схемийг доор тайлбарласан болно.
Таны даалгавар бол өгсөн хоосон-програмыг (skeleton) хуурмаг модель өгөгдөл дээр ажилладаг болгох юм.
Энэ програмд хэдийнэ
UserList, UserDetail, болон
UserPhotos зэрэг компонентийг холбож өгсөн байгаа. Энэ нь
React Router компонентод шаардлагатай параметрүүд холбож өгсөн бөгөөд компонентийг үүсгэх
ихэнх ажлуудыг хийчихсэн.
Эдгээрийг дараах шаардлагын дагуу хөгжүүлнэ:
-
components/userListкомпонент системд байгаа бүх хэрэглэгчийн дэлгэрэнгүй мэдээллийг харуулахын тулд хэрэглэгчдийг жагсааж харуулдаг байна. Компонент нь хажуу хэсэгт (side bar) байрлах ба хэрэглэгчийн нэрсийн жагсаалтыг дэлгэцлэнэ. Хэрэглэгчийн нэр дээр дарахад тухайн хэрэглэгчийн дэлгэрэнгүй мэдээллийг үндсэн хэсэгт (content area) дэлгэцэлдэг байна. -
components/userDetailкомпонентод React Router-ийнprops.matchшинжээрuserId-ийг дамжуулна. Энэ харагдац нь хэрэглэгчийн дэлгэрэнгүйг харуулах бөгөөд тухайн хэрэглэгчийн оруулсан зургуудыг харуулахUserPhotosкомпонентруу заах линктэй байна. -
components/userPhotosкомпонентодuserId-ийг дамжуулна. Сонгосон хэрэглэгчийн бүх зургийг харуулна. Тухайн хэрэглэгчтэй холбоотой бүх зургийг дэлгэцлэх ёстой. Зураг бүрийн хувьд бичсэн сэтгэгдлүүдийг харуулна. Сэтгэгдэл нэг бүрийн бичсэн огноо, тухайн сэтгэгдлийг бичсэн хэрэглэгч болон сэтгэгдлийн бичвэрийг харуулдаг байна. Тухайн сэтгэгдлийг бичсэн хэрэглэгчийн нэр нь линк байх ба дарахад тухайн хэрэлэгчийн дэлгэрэнгүй мэдээллийг үзүүлнэ.
Эдгээр компонентоос гадна components/topBar дотор байгаа
TopBar компонентийг дараах шаардлагын дагуу шинэчлэнэ:
-
TopBar-ын зүүн талд таны нэр байна. -
TopBar-ын баруун талд аппын агуулгыг үндсэн хэсэгт юу үзүүлж байгаагаас хамаарч гаргана. Жишээ нь, үндсэн хэсэгт хэрэглэгчийн дэлгэрэнгүй мэдээллийг харуулж байвалTopBarнь хэрэглэгчийн нэрийг, хэрэв хэрэглэгчийн зургийг үзүүлж байвал "Photos of " гээд араас нь хэрэглэгчийн нэрийг залгаж харуулдаг байна.
Энэ хоосон-програмд React Router ашиглан аппын ялгаатай харагдац бүрт гүн-холбоос (deep-linking) үүсгэж өгсөн. Таны үүсгэх компонент энэ боломжийг эвдэхгүй байх ёстой. Энэ нь веб хөтчийг сэргээх (refresh) үед өмнө үзэж байснаараа гардаг байх боломжийг олгож байгаа юм. Бидний компонент үүсгэдэг стандарт арга нь гүн-холбоосыг автоматаар тохируулдаг. Компонентууд хооронд объектыг дамжуулахад үүнийг анхаарч байх ёстой. Хэрэв ямар нэг зүйл эвдсэн байвал харагдац бүр дээр сэргээх туршилт хийгээд үзээрэй.
Харагдах байдлын хувьд цаг их зарцуулах хэрэггүй, энэ нь аятайхан, ойлгомжтой байх ёстой. Мэдээллийг дэлгэцлэх зохиомж нь цэвэр байна (Жишээ нь, зураг бүрийн хувьд холбогдох комментууд нь ойлгомжтой байх).
Фото апп модель өгөгдөл
Энэ даалгаврын хувьд бид өмнөх даалгавраар ашигласан, нөгөө DOM-д
ачаалсан шидэт модель өгөгдлийг ашиглана. Модель нь дөрвөн төрлийн объекттой.
Эдгээр нь user, photo, comment, болон
SchemaInfo төрөл.
-
Фото хуваалцдаг сайт дээрх фотонуудыг хэрэглэгчээр нь зохион байгуулсан.
Бид хэрэглэгчийг
userобъектоор илэрхийлэх ба дараах шинжүүдтэй:_id: Хэрэглэгчийн ID. first_name: Хэрэглэгчийн өөрийн нэр. last_name: Хэрэглэгчийн овог. location: Хэрэглэгчийн байршил. description: Хэрэглэгчийн талаарх товч тайлбар. occupation: Хэрэглэгчийн ажил мэргэжил. window.ICSI301models.userModel(user_id)DOM функц нь хэрэглэгчийнuser_idID-аарuserобъектыг буцаадаг. Харинwindow.ICSI301models.userListModel()DOM функц нь аппын бүх хэрэглэгчийнuserобъекыг буцаадаг. -
Хэрэглэгч бүр олон фото серверт хуулах боломжтой. Хэрэглэгчийн нэг зургийг
photoобъектоор, дараах шинжтэйгээр илэрхийлдэг:_id: Фото зургийн ID. user_id: Фото зургийг үүсгэсэн хэрэглэгчийн userID.date_time: Фото зургийг өгөгдлийн санд нэмсэн огноо ба цаг. file_name: Фото зургийг агуулж байгаа файлын нэр ( project5/imagesхавтас доторх).comments: Фото зургийн бүх сэтгэгдлийг commentsхадгалсан объектон хүснэгтэн хувьсагч, Нэгcommentнь тухайн фото зураг дээр бичигдсэн сэтгэгдэл.window.ICSI301models.photoOfUserModel(user_id)DOM функц нь хэрэглэгчийн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 бодит апп шиг харагдах ёстой. Гол асуудал нь ЖаваСкрипт болон DOM-ыг ашиглаад хуурмаг модель өгөгдлийг ачаалсан байсан. Даалгавар 2-ын хувьд, бид энэ арга залийг хаяад бодит апптай ижил серверээс модель өгөгдөл авдаг болгоно.
Энэ төслөөр өгсөн webServer.js нь Даалгавар 1-д DOM-д ачаалж
ашигласан 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 форматаар харуулна.
Веб сервер дээрээс моделийг авдаг болгож програмаа хөрвүүлэхийн тулд
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/photo-share.html
хаягаар орж үзээрэй. Энэ нь http://localhost:3000/test/info
хаягруу хүсэлт явуулаад буцаж ирэх хувилбарын дугаарыг дэлгэцэлдэг юм. Хувилбарын дугаарыг
өөрийн аппынхаа TopBar компонентод дэлгэцэлдэг байна.
lib/fetchModelData.js файлд fetchModel функцийг амжилттай
кодлосны дараа та дараах файлуудын кодыг өөрчлөөрэй.
components/userDetail/UserDetail.jsxcomponents/userList/UserList.jsxcomponents/userPhotos/UserPhotos.jsx
fetchModel функц нь серверээс өгөгдлийг авах хүсэлт тавьдаг.
Таны кодод window.ICSI301models хувьсагчийг шууд дуудаж
ашиглах код байх ёсгүй бөгөөд таны аппын
photo-share.html файлд дараах мөр байх ёсгүй:<script src="modelData/photoApp.js"><script>
Загвар (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) товчлуураар ийм боломжийг хийх нь веб аппликейшнд нийтлэг практик байдаг. Гэхдээ нэмэлт онооны бус бусад даалгавруудаа эвдэж нэмэлт оноо авах гэж байгад илүү их оноо алдах эрсдэл бий. Болгоомжтой байгаарай.
Хүлээлгэн өгөх үр дүн
Ердийн Даалгавар илгээх
зааврын дагуу аппаа бүхэлд нь (project4
хавтас доторх бүгд) илгээнэ. Илгээхээсээ өмнө зааврын дагуу
төслийн хавтасаа цэвэрлээрэй. Ялангуяа, 180MB хэмжээтэй
node_modules/ хавтсыг дэмий хадгалахыг хүсэхгүй байна.
compiled/ хавтсаа ч бас устгахаа мартуузай.