portaldacalheta.pt
  • Põhiline
  • Tooteinimesed Ja Meeskonnad
  • Ux Disain
  • Protsess Ja Tööriistad
  • Andmeteadus Ja Andmebaasid
Tagumine Ots

ActiveResource.js: kiire JSON API jaoks võimsa JavaScripti SDK loomine



Teie ettevõte käivitas just oma API ja soovib nüüd selle ümber ehitada kasutajate kogukonna. Teate, et enamik teie kliente töötab JavaScripti , kuna teie API pakutavad teenused muudavad klientide jaoks lihtsamaks veebirakenduste loomise, selle asemel et kõik ise kirjutada - Twilio on selle hea näide.

Teate ka, et see on sama lihtne kui teie RESTful API võib olla, kasutajad soovivad langeda JavaScripti paketti see teeb nende jaoks kogu raske tõste. Nad ei taha teie API-d õppida ja iga vajaminevat taotlust ise koostada.



Nii et teete oma API ümber raamatukogu. Või kirjutate võib-olla lihtsalt oma sisemise API-ga suhtleva veebirakenduse olekusüsteemi.



Mõlemal juhul ei soovi te ennast korrata iga kord, kui teete oma API-ressurssidele halba, või mis veelgi hullem, CRUD-i nende ressurssidega seotud ressurssi. See pole hea kasvava SDK haldamiseks pikas perspektiivis ega ole ka teie aja hea kasutamine.



kuidas pythonit rahanduses kasutatakse

Selle asemel võite kasutada ActiveResource.js , JavaScripti ORM-süsteem API-dega suhtlemiseks. Lõin selle projekti vajaduse täitmiseks: JavaScripti SDK loomiseks võimalikult vähestel ridadel. See võimaldas nii meie kui ka meie arendajate kogukonna jaoks maksimaalset efektiivsust.

See põhineb Ruby on Railsi lihtsa ActiveRecord ORM-i põhimõtetel.



JavaScripti SDK põhimõtted

ActiveResource.js kujundamisel juhindub kahest Ruby on Rails ideest:

  1. „Konfiguratsiooni kokkulepe:” Tehke mõned eeldused API lõpp-punktide olemuse kohta. Näiteks kui teil on Product ressurss, vastab see /products lõpp-punkt. Nii ei kuluta aega korduvalt teie SDK kõigi taotluste konfigureerimist teie API-le. Arendajad saavad teie kasvavasse SDK-sse lisada uusi keerukate CRUD-päringutega API-ressursse minutite, mitte tundide jooksul.
  2. 'Ülenda ilusat koodi:' Rails ’looja DHH ütles seda kõige paremini - selle enda jaoks on ilusas koodis lihtsalt midagi suurepärast. ActiveResource.js mähib mõnikord koledad taotlused kauni välisküljega. Te ei pea enam filtrite ja lehekülgede lisamiseks lisama kohandatud koodi ja lisama seoseid pesitsevad seosed GET-päringutele. Samuti ei pea te koostama POST ja PATCH päringuid, mis muudavad objekti atribuute ja saadavad need värskendamiseks serverisse. Selle asemel helistage lihtsalt meetodile ActiveResource'is: soovitud päringu saamiseks ei pea enam JSON-iga mängima, vaid peate järgmise taotluse jaoks uuesti tegema.

Enne alustamist

Oluline on märkida, et selle kirjutamise ajal töötab ActiveResource.js ainult API-dega, mis on kirjutatud vastavalt JSON: API standard .



Kui te pole JSON: API-ga tuttav ja soovite kaasa minna, siis neid on palju häid raamatukogusid JSON: API serveri loomiseks.

See tähendab, et ActiveResource.js on pigem DSL kui ümbris ühe konkreetse API standardi jaoks. Kasutajaliidest, mida ta kasutab teie API-ga suhtlemiseks, saab laiendada, nii et tulevased artiklid võiksid käsitleda ActiveResource.js-i kasutamist kohandatud API-ga.



Asjade seadistamine

Alustuseks installige active-resource oma projektis:

yarn add active-resource

Esimene samm on luua ResourceLibrary teie API jaoks. Panen kõik oma ActiveResource s src/resources kaust:



// /src/resources/library.js import { createResourceLibrary } from 'active-resource'; const library = createResourceLibrary('http://example.com/api/v1'); export default library;

Ainus nõutav parameeter createResourceLibrary on teie API juur-URL.

Mida me loome

Loome sisuhaldussüsteemi API jaoks JavaScripti SDK kogu. See tähendab, et seal on kasutajaid, postitusi, kommentaare ja märguandeid.



Kasutajad saavad postitusi lugeda, luua ja redigeerida; lugeda, lisada ja kustutada kommentaare (postituste või muude kommentaaride jaoks) ning saada teateid uute postituste ja kommentaaride kohta.

Ma ei hakka vaate (React, Angular jne) ega oleku (Redux jne) haldamiseks kasutama ühtegi konkreetset teeki, selle asemel, et õpetust abstraktselt kasutada, et suhelda ainult teie API-ga ActiveResource s kaudu.

Esimene ressurss: kasutajad

Alustame User loomisega ressurss CMS-i kasutajate haldamiseks.

Kõigepealt loome User ressursiklassi attributes:

// /src/resources/User.js import library from './library'; class User extends library.Base { static define() { this.attributes('email', 'userName', 'admin'); } } export default library.createResource(User);

Oletame praegu, et teil on autentimise lõpp-punkt, mis pärast kasutaja e-posti aadressi ja parooli esitamist tagastab juurdepääsuloa ja kasutaja ID. Seda lõpp-punkti haldab mõni funktsioon requestToken Kui olete saanud autentitud kasutajatunnuse, soovite laadida kõik kasutaja andmed.

import library from '/src/resources/library'; import User from '/src/resources/User'; async function authenticate(email, password) { let [accessToken, userId] = requestToken(email, password); library.headers = { Authorization: 'Bearer ' + accessToken }; return await User.find(userId); }

Seadsin library.headers omada Authorization päis koos accessToken nii et kõik minu ResourceLibrary tulevased taotlused on volitatud.

Hilisemas jaotises käsitletakse, kuidas kasutajat autentida ja pääsuluba seadistada, kasutades ainult User ressursside klass.

authenticate. Viimane samm on taotlus User.find(id). See taotleb /api/v1/users/:id ja vastus võib välja näha umbes:

{ 'data': { 'type': 'users', 'id': '1', 'attributes': { 'email': ' [email protected] ', 'user_name': 'user1', 'admin': false } } }

authenticate Vastus on User eksemplar klass. Siit saate juurde pääseda autentitud kasutaja erinevatele atribuutidele, kui soovite neid kuskil rakenduses kuvada.

let user = authenticate(email, password); console.log(user.id) // '1' console.log(user.userName) // user1 console.log(user.email) // [email protected] console.log(user.attributes()) /* { email: ' [email protected] ', userName: 'user1', admin: false } */

Kõik atribuutide nimed muutuvad camelCasediks, et need sobiksid JavaScripti tüüpiliste standarditega. Igaüks neist saab otse user omadustena objekti või hankige kõik atribuudid, helistades user.attributes()

Ressursiindeksi lisamine

Enne kui lisame veel ressursse, mis on seotud User klassi, näiteks teatised, peaksime lisama faili src/resources/index.js, mis indekseerib kõik meie ressursid. Sellel on kaks eelist:

  1. See puhastab meie impordi, võimaldades meil hävitada src/resources mitme ressursi jaoks ühes impordilauses, selle asemel et kasutada mitut impordilauset.
  2. See lähtestab kõik ressursid ResourceLibrary -s loome helistades library.createResource igaühel, mis on vajalik ActiveResource.js jaoks suhete loomiseks.
// /src/resources/index.js import User from './User'; export { User };

Seotud ressursi lisamine

Nüüd loome seotud ressursi User, a Notification Kõigepealt looge Notification klass, mis belongsTo User klass:

// /src/resources/Notification.js import library from './library'; class Notification extends library.Base { static define() { this.belongsTo('user'); } } export default library.createResource(Notification);

Seejärel lisame selle ressursside indeksisse:

// /src/resources/index.js import Notification from './Notification'; import User from './User'; export { Notification, User };

Seejärel seostage teatised User -ga klass:

// /src/resources/User.js class User extends library.Base { static define() { /* ... */ this.hasMany('notifications'); } }

Nüüd, kui oleme kasutaja tagasi teenusest authenticate tagasi saanud, saame kõik selle märguanded laadida ja kuvada:

let notifications = await user.notifications().load(); console.log(notifications.map(notification => notification.message));

Autentitud kasutaja algsesse taotlusse võime lisada ka teatised:

async function authenticate(email, password) { /* ... */ return await User.includes('notifications').find(userId); }

See on üks paljudest DSL-is pakutavatest võimalustest.

DSL-i ülevaatamine

Vaatame nüüd juba kirjutatud koodist selle, mida on juba võimalik taotleda.

Võite esitada päringu kasutajate kogu või ühe kasutaja kohta.

let users = await User.all(); let user = await User.first(); user = await User.last(); user = await User.find('1'); user = await User.findBy({ userName: 'user1' });

Päringut saate muuta aheldatavate relatsioonimeetodite abil:

// Query and iterate over all users User.each((user) => console.log(user)); // Include related resources let users = await User.includes('notifications').all(); // Only respond with user emails as the attributes users = await User.select('email').all(); // Order users by attribute users = await User.order({ email: 'desc' }).all(); // Paginate users let usersPage = await User.page(2).perPage(5).all(); // Filter users by attribute users = await User.where({ admin: true }).all(); users = await User .includes('notifications') .select('email', { notifications: ['message', 'createdAt'] }) .order({ email: 'desc' }) .where({ admin: false }) .perPage(10) .page(3) .all(); let user = await User .includes('notification') .select('email') .first();

Pange tähele, et saate päringu koostada mis tahes hulga aheldatud modifikaatorite abil ja saate päringu lõpetada .all(), .first(), .last() või .each().

Saate kasutaja üles ehitada kohapeal või luua selle serverisse:

let user = User.build(attributes); user = await User.create(attributes);

Kui teil on püsiv kasutaja, saate selle muudatused saata serverisse salvestamiseks:

user.email = ' [email protected] '; await user.save(); /* or */ await user.update({ email: ' [email protected] ' });

Samuti saate selle serverist kustutada:

await user.destroy();

See põhiline DSL laieneb ka seotud ressurssidele, nagu demonstreerin ülejäänud juhendaja jooksul. Nüüd saame rakenduse ActiveResource.js kiiresti ülejäänud CMS-i loomiseks rakendada: postitused ja kommentaarid.

Postituste loomine

Looge ressursi klass Post jaoks ja seostage see User -ga klass:

// /src/resources/Post.js import library from './library'; class Post extends library.Base { static define() { this.belongsTo('user'); } } export default library.createResource(Post); // /src/resources/User.js class User extends library.Base { static define() { /* ... */ this.hasMany('notifications'); this.hasMany('posts'); } }

Lisa Post ka ressursside indeksisse:

// /src/resources/index.js import Notification from './Notification'; import Post from './Post'; import User from './User'; export { Notification, Post, User };

Seejärel siduge Post ressurss vormi, kus kasutajad saavad postitusi luua ja redigeerida. Kui kasutaja külastab esimest korda uue postituse loomise vormi, kuvatakse a Post ressurss ehitatakse ja iga kord, kui vormi muudetakse, rakendame muudatuse Post

import Post from '/src/resources/Post'; let post = Post.build({ user: authenticatedUser }); onChange = (event) => { post.content = event.target.value; };

Järgmisena lisage onSubmit vormi tagasihelistamine postituse serverisse salvestamiseks ja vigade käsitsemiseks, kui salvestamise katse ebaõnnestub:

onSubmit = async () => { try { await post.save(); /* successful, redirect to edit post form */ } catch { post.errors().each((field, error) => { console.log(field, error.message) }); } }

Postituste muutmine

Kui postitus on salvestatud, lingitakse see teie serveris oleva ressursina teie API-ga. Kui ressurss on serveris püsinud, saate teada helistades persisted

if (post.persisted()) { /* post is on server */ }

Püsivate ressursside korral toetab ActiveResource.js määrdunud atribuute, et saaksite kontrollida, kas ressursi mõnda atribuuti on serveris selle väärtusest muudetud.

kuidas kasutada node js-i

Kui helistate save() püsiva ressursi korral teeb see PATCH päring, mis sisaldab ainult ressursis tehtud muudatusi, selle asemel, et kogu ressursi atribuutide ja seoste komplekt asjatult serverile edastada.

Jälgitud atribuute saate ressursile lisada, kasutades attributes deklaratsioon. Jälgime muudatusi post.content

// /src/resources/Post.js class Post extends library.Base { static define() { this.attributes('content'); /* ... */ } }

Nüüd saame serveri püsiva postitusega postitust muuta ja kui nupul Esita klõpsatakse, salvestage muudatused serverisse. Saame ka nupu Esita keelata, kui muudatusi pole veel tehtud:

onEdit = (event) => { post.content = event.target.value; } onSubmit = async () => { try { await post.save(); } catch { /* display edit errors */ } } disableSubmitButton = () => { return !post.changed(); }

Ainsuse seose haldamiseks on meetodeid, näiteks post.user(), kui soovisime postitusega seotud kasutajat muuta:

await post.updateUser(user);

See on samaväärne järgmisega:

await post.update({ user });

Kommentaariallikas

Nüüd looge ressursside klass Comment ja seostage see Post -ga. Pidage meeles meie nõuet, et kommentaarid võivad olla vastus postitusele või mõnele muule kommentaarile, nii et kommentaari asjakohane ressurss on polümorfne:

// /src/resources/Comment.js import library from './library'; class Comment extends library.Base { static define() { this.attributes('content'); this.belongsTo('resource', { polymorphic: true, inverseOf: 'replies' }); this.belongsTo('user'); this.hasMany('replies', { as: 'resource', className: 'Comment', inverseOf: 'resource' }); } } export default library.createResource(Comment);

Lisage kindlasti Comment kuni /src/resources/index.js samuti.

Peame Post juurde lisama rea klass ka:

// /src/resources/Post.js class Post extends library.Base { static define() { /* ... */ this.hasMany('replies', { as: 'resource', className: 'Comment', inverseOf: 'resource' }); } }

inverseOf valik edastati hasMany mõiste replies määratlus näitab, et see seos on polümorfse belongsTo pöördväärtus mõiste resource määratlus. inverseOf suhete omadusi kasutatakse suhete vaheliste toimingute tegemisel sageli. Tavaliselt määratakse see omadus automaatselt klassi nime kaudu, kuid kuna polümorfsed seosed võivad olla üks mitmest klassist, peate määratlema inverseOf Polümorfsete seoste funktsionaalsus on tavaline.

Postituste kommentaaride haldamine

Sama DSL, mis kehtib ressursside kohta, kehtib ka seotud ressursside haldamise kohta. Nüüd, kui oleme postituste ja kommentaaride vahelised suhted loonud, on selle suhte haldamiseks mitmeid viise.

Postitusele saate lisada uue kommentaari:

onSubmitComment = async (event) => { let comment = await post.replies().create({ content: event.target.value, user: user }); }

Kommentaarile saate lisada vastuse:

onSubmitReply = async (event) => { let reply = await comment.replies().create({ content: event.target.value, user: user }); }

Kommentaari saate muuta:

onEditComment = async (event) => { await comment.update({ content: event.target.value }); }

Saate postitusest kommentaari eemaldada:

onDeleteComment = async (comment) => { await post.replies().delete(comment); }

Postituste ja kommentaaride kuvamine

SDK-d saab kasutada lehitsetud postituste loendi kuvamiseks ja kui postitusel klõpsatakse, laaditakse postitus uuele lehele koos kõigi selle kommentaaridega:

import { Post } from '/src/resources'; let postsPage = await Post .order({ createdAt: 'desc' }) .select('content') .perPage(10) .all();

Ülaltoodud päring toob välja 10 viimast postitust ja optimeerimiseks on ainus laaditav atribuut nende content.

Kui kasutaja klõpsab postituste järgmisele lehele liikumiseks nuppu, otsib muudatuste käitleja järgmise lehe. Siin keelame ka nupu, kui järgmisi lehti pole.

onClickNextPage = async () => { postsPage = await postsPage.nextPage(); if (!postsPage.hasNextPage()) { /* disable next page button */ } };

Kui klõpsatakse postituse lingil, avame uue lehe, laadides ja kuvades postituse koos kõigi selle andmetega, sealhulgas selle kommentaarid - tuntud kui vastused - ja vastused neile vastustele:

import { Post } from '/src/resources'; onClick = async (postId) => { let post = await Post.includes({ replies: 'replies' }).find(postId); console.log(post.content, post.createdAt); post.replies().target().each(comment => { console.log( comment.content, comment.replies.target().map(reply => reply.content).toArray() ); }); }

Helistamine .target() kohta hasMany suhe nagu post.replies() tagastab ActiveResource.Collection kommentaare, mis on kohapeal laaditud ja salvestatud.

See eristamine on oluline, sest post.replies().target().first() tagastab esimese laaditud kommentaari. Seevastu post.replies().first() tagastab lubaduse GET /api/v1/posts/:id/replies -lt küsitud ühe kommentaari eest.

Samuti võite taotleda postituse vastuseid eraldi postituse päringust, mis võimaldab teil oma päringut muuta. Saate aheldada modifikaatoreid nagu order, select, includes, where, perPage, page päringu tegemisel hasMany ressursside päringuid.

import { Post } from '/src/resources'; onClick = async (postId) => { let post = await Post.find(postId); let userComments = await post.replies().where({ user: user }).perPage(3).all(); console.log('Your comments:', userComments.map(comment => comment.content).toArray()); }

Ressursside muutmine pärast nende taotlemist

Mõnikord soovite enne kasutamist andmeid serverist võtta ja neid muuta. Näiteks võite pakkida post.createdAt aastal moment() objekt, et saaksite kuvada kasutaja jaoks kasutajasõbraliku kuupäeva postituse loomise ajast:

// /src/resources/Post.js import moment from 'moment'; class Post extends library.Base { static define() { /* ... */ this.afterRequest(function() { this.createdAt = moment(this.createdAt); }); } }

Muutmatus

Kui töötate olekuhaldussüsteemiga, mis soosib muutumatuid objekte, saab ActiveResource.js-is kogu käitumise muuta ressursside kogu konfigureerimisel muutumatuks:

// /src/resources/library.js import { createResourceLibrary } from 'active-resource'; const library = createResourceLibrary( 'http://example.com/api/v1', { immutable: true } ); export default library;

Ringiga tagasi: autentimissüsteemi linkimine

Kokkuvõtteks näitan teile, kuidas integreerida oma kasutaja autentimissüsteem oma User ActiveResource.

Teisaldage oma luba autentimissüsteem API lõpp-punkti /api/v1/tokens Kui sellele lõpp-punktile saadetakse kasutaja e-posti aadress ja parool, saadetakse vastuseks autentitud kasutaja andmed koos autoriseerimisloaga.

Looge Token ressursside klass, mis kuulub User:

// /src/resources/Token.js import library from './library'; class Token extends library.Base { static define() { this.belongsTo('user'); } } export default library.createResource(Token);

Lisa Token kuni /src/resources/index.js.

Seejärel lisage staatiline meetod authenticate teie User ressursiklassi ja seostada User kuni Token:

// /src/resources/User.js import library from './library'; import Token from './Token'; class User { static define() { /* ... */ this.hasOne('token'); } static async authenticate(email, password) { let user = this.includes('token').build({ email, password }); let authUser = await this.interface().post(Token.links().related, user); let token = authUser.token(); library.headers = { Authorization: 'Bearer ' + token.id }; return authUser; } }

See meetod kasutab resourceLibrary.interface(), mis on antud juhul JSON: API liides, kasutaja saatmiseks /api/v1/tokens. See kehtib: JSON-i lõpp-punkt: API ei nõua, et sinna ja sealt postitataks ainult tüüpe, mille järgi see on nime saanud. Seega on taotlus järgmine:

{ 'data': { 'type': 'users', 'attributes': { 'email': ' [email protected] ', 'password': 'password' } } }

Vastuseks saab autentitud kasutaja, kelle autentimiskood sisaldab:

{ 'data': { 'type': 'users', 'id': '1', 'attributes': { 'email': ' [email protected] ', 'user_name': 'user1', 'admin': false }, 'relationships': { 'token': { 'data': { 'type': 'tokens', 'id': 'Qcg6yI1a5qCxXgKWtSAbZ2MIHFChHAq0Vc1Lo4TX', } } } }, 'included': [{ 'type': 'tokens', 'id': 'Qcg6yI1a5qCxXgKWtSAbZ2MIHFChHAq0Vc1Lo4TX', 'attributes': { 'expires_in': 3600 } }] }

Siis kasutame token.id meie raamatukogu Authorization seadmiseks päise ja tagastab kasutaja, mis on sama, mis kasutajalt User.find() nagu me enne tegime.

Nüüd, kui helistate User.authenticate(email, password), saate vastuseks autentitud kasutaja ja kõik tulevased taotlused autoriseeritakse juurdepääsuloa abil.

ActiveResource.js lubab JavaScripti kiire SDK-arenduse

Selles õpetuses uurisime võimalusi, kuidas ActiveResource.js aitab teil kiiresti luua JavaScripti SDK teie API-ressursside ja nende erinevate, mõnikord keeruliste seotud ressursside haldamiseks. Kõiki neid ja rohkem dokumenteeritud funktsioone näete saidil README for ActiveResource.js .

Loodan, et teile on meeldinud nende toimingute lihtsus ja et kasutate (ja võib-olla isegi panustate) minu kogu oma tulevaste projektide jaoks, kui see sobib teie vajadustega. Avatud lähtekoodiga vaimus on PR-id alati teretulnud!

Põhitõdede mõistmine

Mida SDK tähistab?

SDK tähistab tarkvaraarenduskomplekti, mis JavaScripti kontekstis tähendab sageli raamatukogu konkreetse REST API-ga suhtlemiseks.

Mida tähendab lühend ORM?

ORM tähistab „objektide-relatsioonide kaardistamist“ - tehnikat objektidega töötamiseks, ilma et peaksime mõtlema, kust need pärinevad või kuidas neid hoitakse. Näiteks võib ORM-i teek eraldada API või vajaduse SQL-teadmiste järele, olenevalt sellest, millises kihis seda kasutatakse.

Mis on CRUD-teenus?

CRUD teenus, nt. põhiline REST API on see, mis pakub liidese toimingute „loomine, lugemine, värskendamine ja kustutamine” teostamiseks. Teisisõnu võimaldab see andmete salvestamise põhitoiminguid, mis vastavad SQL-i käskudele INSERT, SELECT, UPDATE ja DELETE ning HTTP-verbidele POST, GET, PUT / PATCH ja DELETE.

Mida API teeb?

API pakub teenuse abstraktsiooni, hõlbustades sellega töötamist, eesmärgiga pääseda juurde laiemale programmeerijate rühmale. Näiteks võimaldab Trello API teil programmipõhiselt luua uusi Trello kaarte HTTP-päringute kaudu.

Milleks kasutatakse API võtit?

API-võti on taotluste sõnastamiseks kasutatav salajane märgis, mis võimaldab API-teenuse pakkujal taotlejat positiivselt tuvastada, eeldades, et see jääb saladuseks.

Mida tähendab sisuhaldus?

Sisuhaldus viitab üldiselt sisevõrgus või Internetis avaldatava tekstisisu loomisele ja korrastamisele. Viimase paari aasta jooksul on kõige populaarsem sisuhaldussüsteem (CMS) WordPress.

Mis on ORM-i andmebaas?

See on mõistete kokkuvõte, kuid viitab tõenäoliselt RDBMS-ile, nt SQL Server, MySQL või PostgreSQL. ORM-i tööriistad aitavad mõnikord objekte SQL-i back-endi kaardistada. ActiveResource.js võtab kokku teise kihi, kaardistades objektid REST API lõpp-punktidega.

Google'i pilveallika hoidlad vs Bitbucket vs GitHub: kas väärt alternatiiv?

Tagumine Ots

Google'i pilveallika hoidlad vs Bitbucket vs GitHub: kas väärt alternatiiv?
Tasuta e-raamatud, mida iga disainer peaks lugema

Tasuta e-raamatud, mida iga disainer peaks lugema

Kujundusprotsess

Lemmik Postitused
Äriplaani anatoomia
Äriplaani anatoomia
Ladina-Ameerika ühinemiste ja ühinemiste parimad tavad
Ladina-Ameerika ühinemiste ja ühinemiste parimad tavad
Tarkvara kulude hindamine agiilses projektijuhtimises
Tarkvara kulude hindamine agiilses projektijuhtimises
Andekus pole kaup
Andekus pole kaup
Veebi juurdepääsetavus: miks W3C standardeid sageli eiratakse
Veebi juurdepääsetavus: miks W3C standardeid sageli eiratakse
 
Bränding on surnud, CX Design on kuningas
Bränding on surnud, CX Design on kuningas
Chatbot UX - disaininõuanded ja kaalutlused
Chatbot UX - disaininõuanded ja kaalutlused
Uus ettevõtluslaine
Uus ettevõtluslaine
Optimeeritud järjestikune keskmine kvantimise teisendus
Optimeeritud järjestikune keskmine kvantimise teisendus
Kasutajauuringute väärtus
Kasutajauuringute väärtus
Lemmik Postitused
  • riskikapitali terminilehe näide
  • kui nõudluse hinnaelastsus mõõdab 2, tähendab see, et tarbijad seda teeksid
  • rahavoogude aruande koostamine
  • mis on serverisõlm
  • kristall (programmeerimiskeel)
Kategooriad
  • Tooteinimesed Ja Meeskonnad
  • Ux Disain
  • Protsess Ja Tööriistad
  • Andmeteadus Ja Andmebaasid
  • © 2022 | Kõik Õigused Kaitstud

    portaldacalheta.pt