portaldacalheta.pt
  • หลัก
  • การจัดการวิศวกรรม
  • บุคลากรและทีมงานของผลิตภัณฑ์
  • อื่น ๆ
  • นวัตกรรม
ส่วนหลัง

การตรวจสอบแบบฟอร์ม Smart Node.js



หนึ่งในภารกิจพื้นฐานที่ต้องดำเนินการใน API คือการตรวจสอบข้อมูล ในบทความนี้ฉันต้องการแสดงวิธีเพิ่มการตรวจสอบความถูกต้องกันกระสุนสำหรับข้อมูลของคุณด้วยวิธีที่ส่งคืนข้อมูลในรูปแบบที่สวยงาม

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



การตรวจสอบฟอร์มใน Node.js ด้วย Datalize

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



ติดตั้ง

สามารถติดตั้ง Datalize ผ่าน npm:



npm install --save datalize

ในการแยกวิเคราะห์เนื้อหาของคำขอคุณควรใช้ห้องสมุดแยกต่างหาก หากคุณยังไม่ได้ใช้ฉันขอแนะนำ koa-body สำหรับ Koa หรือ ตัวแยกวิเคราะห์ร่างกาย สำหรับ Express.

สปริง mvc พร้อมสปริงบูต

คุณสามารถใช้บทช่วยสอนนี้กับเซิร์ฟเวอร์ HTTP API ที่ตั้งค่าไว้แล้วหรือใช้รหัสเซิร์ฟเวอร์ Koa HTTP แบบง่ายต่อไปนี้



const Koa = require('koa'); const bodyParser = require('koa-body'); const app = new Koa(); const router = new (require('koa-router'))(); // helper for returning errors in routes app.context.error = function(code, obj) { this.status = code; this.body = obj; }; // add koa-body middleware to parse JSON and form-data body app.use(bodyParser({ enableTypes: ['json', 'form'], multipart: true, formidable: { maxFileSize: 32 * 1024 * 1024, } })); // Routes... // connect defined routes as middleware to Koa app.use(router.routes()); // our app will listen on port 3000 app.listen(3000); console.log(' API listening on 3000');

อย่างไรก็ตามนี่ไม่ใช่การตั้งค่าการใช้งานจริง (คุณควรใช้ไฟล์ การบันทึก , บังคับใช้ การอนุญาต , ด้ามจับ ข้อผิดพลาด ฯลฯ ) แต่โค้ดสองสามบรรทัดนี้ใช้ได้ดีกับตัวอย่างที่ฉันจะแสดงให้คุณเห็น

หมายเหตุ: ตัวอย่างโค้ดทั้งหมดใช้ Koa แต่รหัสตรวจสอบข้อมูลจะใช้ได้กับ Express เช่นกัน ไลบรารี datalize ยังมีตัวอย่างสำหรับการใช้งานการตรวจสอบความถูกต้องของฟอร์ม Express



ตัวอย่างการตรวจสอบความถูกต้องของฟอร์ม Node.js พื้นฐาน

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

คุณสามารถเขียนตรรกะง่ายๆดังนี้:



/** * @api {post} / Create a user * ... */ router.post('/', (ctx) => { const data = ctx.request.body; const errors = {}; if (!String(data.name).trim()) { errors.name = ['Name is required']; } if (!(/^[-0-9a-zA-Z.+_] [email protected] [-0-9a-zA-Z.+_]+.[a-zA-Z]{2,}$/).test(String(data.email))) { errors.email = ['Email is not valid.']; } if (Object.keys(errors).length) { return ctx.error(400, {errors}); } const user = await User.create({ name: data.name, email: data.email, }); ctx.body = user.toJSON(); });

ตอนนี้เรามาเขียนโค้ดนี้ใหม่และตรวจสอบความถูกต้องของคำขอนี้โดยใช้ datalize:

const datalize = require('datalize'); const field = datalize.field; /** * @api {post} / Create a user * ... */ router.post('/', datalize([ field('name').trim().required(), field('email').required().email(), ]), (ctx) => { if (!ctx.form.isValid) { return ctx.error(400, {errors: ctx.form.errors}); } const user = await User.create(ctx.form); ctx.body = user.toJSON(); });

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



สถานะของวงการเพลง

กฎและตัวกรองจะดำเนินการตามลำดับเดียวกันกับที่กำหนดไว้ดังนั้นหากคุณต้องการตัดสตริงสำหรับช่องว่างก่อนจากนั้นตรวจสอบว่ามีค่าหรือไม่คุณต้องกำหนด .trim() ก่อนหน้า .required().

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



การจัดการข้อผิดพลาดอัตโนมัติ

หากเราไม่ต้องการตรวจสอบว่าแบบฟอร์มถูกต้องหรือไม่กับทุกคำขอเราสามารถเพิ่มมิดเดิลแวร์ส่วนกลางซึ่งจะยกเลิกคำขอได้หากข้อมูลไม่ผ่านการตรวจสอบความถูกต้อง

ในการทำเช่นนี้เราเพียงแค่เพิ่มโค้ดชิ้นนี้ในไฟล์ ไฟล์ bootstrap ที่เราสร้างอินสแตนซ์แอป Koa / Express

const datalize = require('datalize'); // set datalize to throw an error if validation fails datalize.set('autoValidate', true); // only Koa // add to very beginning of Koa middleware chain app.use(async (ctx, next) => { try { await next(); } catch (err) { if (err instanceof datalize.Error) { ctx.status = 400; ctx.body = err.toJSON(); } else { ctx.status = 500; ctx.body = 'Internal server error'; } } }); // only Express // add to very end of Express middleware chain app.use(function(err, req, res, next) { if (err instanceof datalize.Error) { res.status(400).send(err.toJSON()); } else { res.send(500).send('Internal server error'); } });

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

การตรวจสอบการสืบค้น

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

const datalize = require('datalize'); const field = datalize.field; /** * @api {get} / List users * ... */ router.post('/', datalize.query([ field('keywords').trim(), field('page').default(1).number(), field('perPage').required().select([10, 30, 50]), ]), (ctx) => { const limit = ctx.data.perPage; const where = { }; if (ctx.data.keywords) { where.name = {[Op.like]: ctx.data.keywords + '%'}; } const users = await User.findAll({ where, limit, offset: (ctx.data.page - 1) * limit, }); ctx.body = users; });

นอกจากนี้ยังมีวิธีการช่วยเหลือสำหรับการตรวจสอบพารามิเตอร์ .params() ข้อมูลแบบสอบถามและแบบฟอร์มสามารถตรวจสอบความถูกต้องร่วมกันได้โดยส่งข้อมูลกลางสองตัวของข้อมูลใน .post() ของเราเตอร์ วิธี.

องค์ประกอบการออกแบบคืออะไร

ฟิลเตอร์อาร์เรย์และออบเจ็กต์ที่ซ้อนกันมากขึ้น

จนถึงตอนนี้เราได้ใช้ข้อมูลง่ายๆในการตรวจสอบความถูกต้องของฟอร์ม Node.js ตอนนี้เรามาลองฟิลด์ที่ซับซ้อนมากขึ้นเช่นอาร์เรย์อ็อบเจ็กต์ที่ซ้อนกัน ฯลฯ :

const datalize = require('datalize'); const field = datalize.field; const DOMAIN_ERROR = 'Email's domain does not have a valid MX (mail) entry in its DNS record'; /** * @api {post} / Create a user * ... */ router.post('/', datalize([ field('name').trim().required(), field('email').required().email().custom((value) => { return new Promise((resolve, reject) => { dns.resolve(value.split('@')[1], 'MX', function(err, addresses) { if (err || !addresses || !addresses.length) { return reject(new Error(DOMAIN_ERROR)); } resolve(); }); }); }), field('type').required().select(['admin', 'user']), field('languages').array().container([ field('id').required().id(), field('level').required().select(['beginner', 'intermediate', 'advanced']) ]), field('groups').array().id(), ]), async (ctx) => { const {languages, groups} = ctx.form; delete ctx.form.languages; delete ctx.form.groups; const user = await User.create(ctx.form); await UserGroup.bulkCreate(groups.map(groupId => ({ groupId, userId: user.id, }))); await UserLanguage.bulkCreate(languages.map(item => ({ languageId: item.id, userId: user.id, level: item.level, )); });

หากไม่มีกฎในตัวสำหรับข้อมูลที่เราต้องตรวจสอบความถูกต้องเราสามารถสร้างกฎการตรวจสอบข้อมูลที่กำหนดเองโดยใช้ .custom() วิธีการ (ชื่อดีใช่มั้ย) และเขียนตรรกะที่จำเป็นที่นั่น สำหรับวัตถุที่ซ้อนกันจะมี .container() วิธีการที่คุณสามารถระบุรายการของเขตข้อมูลในลักษณะเดียวกับใน datalize() ฟังก์ชัน คุณสามารถซ้อนคอนเทนเนอร์ภายในคอนเทนเนอร์หรือเสริมด้วย .array() ตัวกรองซึ่งจะแปลงค่าเป็นอาร์เรย์ เมื่อ .array() ใช้ตัวกรองโดยไม่มีคอนเทนเนอร์กฎหรือตัวกรองที่ระบุจะถูกนำไปใช้กับทุกค่าในอาร์เรย์

ดังนั้น .array().select(['read', 'write']) จะตรวจสอบว่าทุกค่าในอาร์เรย์เป็น 'read' หรือไม่ หรือ 'write' และหากไม่มีก็จะแสดงรายการดัชนีทั้งหมดที่มีข้อผิดพลาด สวยดีใช่มั้ย?

PUT / PATCH

เมื่อพูดถึงการอัปเดตข้อมูลของคุณด้วย PUT / PATCH (หรือ POST) คุณไม่จำเป็นต้องเขียนตรรกะกฎและตัวกรองใหม่ทั้งหมด คุณเพียงแค่เพิ่มตัวกรองพิเศษเช่น .optional() หรือ .patch() ซึ่งจะลบฟิลด์ใด ๆ ออกจากอ็อบเจ็กต์บริบทหากไม่ได้กำหนดไว้ในคำขอ (.optional() จะทำให้เป็นทางเลือกเสมอในขณะที่ .patch() จะทำให้เป็นทางเลือกก็ต่อเมื่อวิธีการขอ HTTP คือ PATCH) คุณสามารถเพิ่มตัวกรองพิเศษนี้เพื่อให้ใช้ได้ทั้งการสร้างและการอัปเดต ข้อมูลในฐานข้อมูลของคุณ

const datalize = require('datalize'); const field = datalize.field; const userValidator = datalize([ field('name').patch().trim().required(), field('email').patch().required().email(), field('type').patch().required().select(['admin', 'user']), ]); const userEditMiddleware = async (ctx, next) => { const user = await User.findByPk(ctx.params.id); // cancel request here if user was not found if (!user) { throw new Error('User was not found.'); } // store user instance in the request so we can use it later ctx.user = user; return next(); }; /** * @api {post} / Create a user * ... */ router.post('/', userValidator, async (ctx) => { const user = await User.create(ctx.form); ctx.body = user.toJSON(); }); /** * @api {put} / Update a user * ... */ router.put('/:id', userEditMiddleware, userValidator, async (ctx) => { await ctx.user.update(ctx.form); ctx.body = ctx.user.toJSON(); }); /** * @api {patch} / Patch a user * ... */ router.patch('/:id', userEditMiddleware, userValidator, async (ctx) => { if (!Object.keys(ctx.form).length) { return ctx.error(400, {message: 'Nothing to update.'}); } await ctx.user.update(ctx.form); ctx.body = ctx.user.toJSON(); });

ด้วยตัวกลางง่ายๆสองตัวเราสามารถเขียนตรรกะส่วนใหญ่สำหรับทุกคน POST / PUT / PATCH วิธีการ userEditMiddleware() ฟังก์ชันตรวจสอบว่าระเบียนที่เราต้องการแก้ไขมีอยู่หรือไม่และแสดงข้อผิดพลาดเป็นอย่างอื่น แล้ว userValidator() ทำการตรวจสอบความถูกต้องสำหรับจุดสิ้นสุดทั้งหมด สุดท้าย .patch() ตัวกรองจะลบฟิลด์ใด ๆ ออกจาก .form ออบเจ็กต์หากไม่ได้กำหนดไว้และถ้าเมธอดของคำขอคือ PATCH

Node.js Form Validation Extras

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

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

const datalize = require('datalize'); const Field = datalize.Field; Field.prototype.date = function(format = 'YYYY-MM-DD') { return this.add(function(value) { const date = value ? moment(value, format) : null; if (!date || !date.isValid()) { throw new Error('%s is not a valid date.'); } return date.format(format); }); }; Field.prototype.dateTime = function(format = 'YYYY-MM-DD HH:mm') { return this.date(format); };

ด้วยตัวกรองที่กำหนดเองทั้งสองนี้คุณสามารถเชื่อมโยงฟิลด์ของคุณด้วย .date() หรือ .dateTime() ตัวกรองเพื่อตรวจสอบการป้อนวันที่

ไฟล์สามารถตรวจสอบความถูกต้องโดยใช้ datalize: มีตัวกรองพิเศษสำหรับไฟล์เช่น .file(), .mime() และ .size() คุณจึงไม่ต้องจัดการไฟล์แยกกัน

powerpivot ใน excel คืออะไร

เริ่มเขียน Better API ตอนนี้

ฉันใช้การตรวจสอบความถูกต้องของฟอร์ม datalize สำหรับ Node.js ในโปรเจ็กต์การผลิตหลายโครงการแล้วสำหรับทั้ง API ขนาดเล็กและขนาดใหญ่ ช่วยให้ฉันสามารถส่งมอบโปรเจ็กต์ที่ยอดเยี่ยมได้ตรงเวลาและมีความเครียดน้อยลงในขณะเดียวกันก็ทำให้สามารถอ่านและบำรุงรักษาได้มากขึ้น ในโครงการหนึ่งฉันเคยใช้มันเพื่อตรวจสอบข้อมูลสำหรับข้อความ WebSocket ด้วยการเขียน Wrapper แบบธรรมดารอบ ๆ Socket.IO และการใช้งานก็ค่อนข้างเหมือนกับการกำหนดเส้นทางใน Koa ดังนั้นมันก็ดี หากมีความสนใจเพียงพอฉันอาจเขียนบทช่วยสอนสำหรับสิ่งนั้นด้วย

ฉันหวังว่าบทช่วยสอนนี้จะช่วยคุณและฉันสร้าง API ที่ดีขึ้นใน Node.js ด้วยข้อมูลที่ผ่านการตรวจสอบอย่างสมบูรณ์แบบ ไม่มีปัญหาด้านความปลอดภัย หรือข้อผิดพลาดภายในเซิร์ฟเวอร์ และที่สำคัญที่สุดฉันหวังว่ามันจะช่วยคุณประหยัดเวลาได้มากพอที่จะต้องลงทุนในการเขียนฟังก์ชันพิเศษสำหรับการตรวจสอบแบบฟอร์มโดยใช้ JavaScript

ทำความเข้าใจพื้นฐาน

Node.js เป็น 'front end' หรือ 'back end'?

Node.js เป็นแพลตฟอร์มส่วนหลัง ตามความหมายของชื่อแอป Node.js จะเขียนด้วย JavaScript (JS) หรือภาษาใด ๆ ที่สามารถรวบรวมหรือแปลงไฟล์ได้

Node.js ไม่ดีสำหรับอะไร?

การคำนวณที่ใช้ CPU มากทำงานได้ไม่ดีกับ Node.js เพราะจะบล็อกการวนซ้ำของเหตุการณ์

วิธีการสร้างภาษาโปรแกรมของคุณเอง

การตรวจสอบแบบฟอร์มหมายความว่าอย่างไร

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

Express และ Node.js แตกต่างกันอย่างไร

Express เป็นเว็บเฟรมเวิร์กที่ใช้บน Node.js ในขณะที่ Node.js เป็นสภาพแวดล้อมของเซิร์ฟเวอร์สำหรับเรียกใช้ JavaScript ที่ส่วนหลัง

คุณใช้ Node.js เพื่ออะไร

Node.js มีกรณีการใช้งานมากมาย แต่เหมาะที่สุดสำหรับแอปแบบเรียลไทม์ (เช่นการแชทการสตรีมข้อมูลบริการการทำงานร่วมกัน) เว็บแอปที่แสดงผลฝั่งเซิร์ฟเวอร์ CLI และ API

เหตุใดจึงต้องมีการตรวจสอบแบบฟอร์ม

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

วิธีสร้างแอพ Android และ iOS ใน C # บน Mac

แบ็คเอนด์

วิธีสร้างแอพ Android และ iOS ใน C # บน Mac
อธิบายเอนโทรปีของซอฟต์แวร์: สาเหตุผลกระทบและการแก้ไข

อธิบายเอนโทรปีของซอฟต์แวร์: สาเหตุผลกระทบและการแก้ไข

การบริหารโครงการ

โพสต์ยอดนิยม
แหล่งข้อมูลสำหรับธุรกิจขนาดเล็กสำหรับ COVID-19: เงินกู้เงินช่วยเหลือและสินเชื่อ
แหล่งข้อมูลสำหรับธุรกิจขนาดเล็กสำหรับ COVID-19: เงินกู้เงินช่วยเหลือและสินเชื่อ
วิธีออกแบบประสบการณ์ที่ยอดเยี่ยมสำหรับอินเทอร์เน็ตในทุกสิ่ง
วิธีออกแบบประสบการณ์ที่ยอดเยี่ยมสำหรับอินเทอร์เน็ตในทุกสิ่ง
กลยุทธ์การสื่อสารที่มีประสิทธิภาพสำหรับนักออกแบบ
กลยุทธ์การสื่อสารที่มีประสิทธิภาพสำหรับนักออกแบบ
เรียนรู้ Markdown: เครื่องมือการเขียนสำหรับนักพัฒนาซอฟต์แวร์
เรียนรู้ Markdown: เครื่องมือการเขียนสำหรับนักพัฒนาซอฟต์แวร์
แนวโน้มต่อไปนี้: การแสดงความเคารพกับการลอกเลียนแบบการออกแบบ
แนวโน้มต่อไปนี้: การแสดงความเคารพกับการลอกเลียนแบบการออกแบบ
 
คู่มือสไตล์ Sass: บทช่วยสอน Sass เกี่ยวกับวิธีการเขียนโค้ด CSS ที่ดีขึ้น
คู่มือสไตล์ Sass: บทช่วยสอน Sass เกี่ยวกับวิธีการเขียนโค้ด CSS ที่ดีขึ้น
ทำลายกระบวนการคิดเชิงออกแบบ
ทำลายกระบวนการคิดเชิงออกแบบ
การออกแบบเว็บไซต์ CMS: คู่มือการใช้งานเนื้อหาแบบไดนามิก
การออกแบบเว็บไซต์ CMS: คู่มือการใช้งานเนื้อหาแบบไดนามิก
ทำคณิตศาสตร์: การปรับขนาดแอปพลิเคชันไมโครเซอร์วิสด้วย Orchestrators
ทำคณิตศาสตร์: การปรับขนาดแอปพลิเคชันไมโครเซอร์วิสด้วย Orchestrators
การปฏิวัติหุ่นยนต์เชิงพาณิชย์ที่กำลังจะเกิดขึ้น
การปฏิวัติหุ่นยนต์เชิงพาณิชย์ที่กำลังจะเกิดขึ้น
โพสต์ยอดนิยม
  • หลักสูตร c ++ ที่ดีที่สุด
  • เรียนเขียนโปรแกรมใน c
  • แนวทางปฏิบัติที่ดีที่สุดสำหรับการออกแบบเว็บบนมือถือ
  • ac กับ s corp ต่างกันอย่างไร
  • วีโอไอพี 2 บทช่วยสอนสำหรับนักพัฒนา
  • ไฟล์ .cpp คืออะไร
  • คุณสามารถทำอะไรกับ adobe xd
หมวดหมู่
  • การจัดการวิศวกรรม
  • บุคลากรและทีมงานของผลิตภัณฑ์
  • อื่น ๆ
  • นวัตกรรม
  • © 2022 | สงวนลิขสิทธิ์

    portaldacalheta.pt