يقول مؤلف المادة ، التي ننشر ترجمتها اليوم ، وهو مطور ويب ، إنه يحاول مراجعة مجموعة الأدوات التي يستخدمها بانتظام. يفعل هذا من أجل فهم ما إذا كان يستطيع الاستغناء عن بعضها عن طريق حل مهامه المعتادة. قرر مؤخرًا إجراء تجربة وإنشاء تطبيق أمامي متطور دون استخدام أطر JavaScript.
ما هو الإطار؟
إذا حاولت تعريف إطار جافا سكريبت بدون الدخول في التفاصيل ، فقد تبيّن أن هذه أداة يمكن استخدامها لتطوير تطبيقات الويب المعقدة ، خاصة تطبيقات الصفحة الواحدة (SPA).
في الأيام الخوالي ، تم تصميم هذه التطبيقات استنادًا إلى إمكانيات JavaScript البحتة ومكتبة jQuery. ولكن مع التعقيد المتزايد للتطبيقات الأمامية ، بدأت تظهر الأدوات المقابلة التي تجعل الحياة أسهل للمبرمجين. على سبيل المثال ، هذه هي React و Angular و Vue.
الأطر الشائعة هذه الأيام لها بعض أوجه التشابه. لذلك ، فإن معظم الأُطُر الأمامية والمكتبات ، من الناحية النسبية ، من Vue إلى React ، توفر للمطور مجموعة معينة من الميزات التالية:
- تزامن الحالة والعرض المرئي للتطبيق.
- التوجيه
- نظام القالب.
- مكونات مناسبة لإعادة الاستخدام.
هل الأطر ضرورية للمطور الحديث؟
تعتمد إجابة السؤال المطروح في عنوان هذا القسم على مدى ارتباطك بفكرة "ضرورة" الأطر. أنا متأكد من أن الكثيرين يستطيعون القول إن أطر العمل الأمامية ليست ضرورية في مجموعة أدوات مطور الويب ، ولم تكن ضرورية أبدًا. على الرغم من أنه لا جدال في أن هذه أدوات مفيدة للغاية.
في الواقع ، يمكن إعادة صياغة سؤالنا على النحو التالي: "هل الأطر جزء من" مكتبة مسج الحديثة "؟ هل من الممكن حل المشكلات التي يستهدفونها ، من خلال وسائل أخرى ، على سبيل المثال ، تلك التي ظهرت تحت تصرف المبرمجين أثناء تطوير واجهات برمجة التطبيقات للمتصفح؟ "
مسجفي الواقع ، ليس من السهل الإجابة على هذا السؤال ، ولكن يمكننا القول أن تطوير جافا سكريبت ، وتقنيات العمل مع مكونات الويب وأدوات لبناء المشاريع قد جعل تطوير SPA دون استخدام الأطر أسهل من أي وقت مضى.
لاستكشاف هذه الفكرة ، قمت بتطوير تطبيق من صفحة واحدة باستخدام JavaScript ومكونات الويب القياسية وحزمة Parcel فقط. في هذه العملية ، واجهت بعض المشكلات والصعوبات ، حيث بدأت بوضوح في رؤية نقاط قوة أطر JS الحديثة.
في الوقت نفسه ، ما إن تعاملت مع العقبات الأولية ، فوجئت بمدى سهولة إنشاء تطبيق من صفحة واحدة في جافا سكريبت خالص.
نظرة عامة على التطبيق التجريبي
التطبيق المعني بسيط للغاية. إنها مجموعة إلكترونية من الوصفات وتتيح للمستخدم إنشاء وصفات وتحريرها. بالإضافة إلى ذلك ، يمكن للمستخدم تمييز الوصفات ، مشيرًا إلى أنه يحبها ، كما يمكنه تصفية وحذف الإدخالات.
صفحة التطبيق الرئيسيةوصفة سجل الصفحةمكونات الويب
- — . , ,
HTMLElement
(
HTMLParagraphElement
, ) .
, - , ,
connectedCallback
,
disconnectedCallback
,
attributeChangedCallback
.
recipe-item
, .
import template from './recipe.html'
import DATA_SERVICE from '../../utils/data'
export default class Recipe extends HTMLElement {
constructor () {
// DOM, recipe DATA_SERVICE()
super()
this._shadowRoot = this.attachShadow({ mode: 'open' })
this._recipe = null
this.ds = new DATA_SERVICE()
}
connectedCallback () {
// html-
this._shadowRoot.innerHTML = template
// delete
this._shadowRoot
.querySelector('.delete')
.addEventListener('click', () => this._delete())
}
_render (title) {
// ,
this._shadowRoot.querySelector('.recipe-title').innerHTML = title
this._shadowRoot.querySelector('.favorite').innerHTML = this._recipe
.favorite
? 'Unfavorite'
: 'Favorite'
}
_delete () {
//
try {
await this.ds.deleteRecipe(this._recipe.id)
} catch (e) {
console.error(e)
alert(
'Sorry, there was a problem deleting the recipe. Please, try again.'
)
}
}
get recipe () {
//
return this._recipe
}
set recipe (recipe = {}) {
// , render
this._recipe = recipe
this._render(this._recipe.title)
}
}
window.customElements.define('recipe-item', Recipe)
. , , .
, , npm- Vanilla JS Router. ,
API History, , - 100 . , - , (route guard).
import './components/error/error'
import content404 from './components/404/404.html'
import DATA_SERVICE from './utils/data'
const ds = new DATA_SERVICE()
// , SPA
const $el = document.getElementById('app')
//
const home = async () => {
await import('./components/recipe/recipe')
await import('./components/recipe-list/recipe-list')
await import('./components/modal/modal.js')
$el.innerHTML = `<recipe-list></recipe-list>`
}
const create = async () => {
await import('./components/create-recipe/create-recipe')
$el.innerHTML = `<create-recipe></create-recipe>`
}
const edit = async () => {
await import('./components/edit-recipe/edit-recipe')
$el.innerHTML = `<edit-recipe></edit-recipe>`
}
const error404 = async () => {
$el.innerHTML = content404
}
//
// id
const routes = {
'/': home,
'/create': create,
'/error': error404,
'/edit': async function (params) {
const id = params.get('id')
const recipe = await ds.getRecipe(id)
await edit()
$el.querySelector('edit-recipe').recipe = recipe
}
}
// onpopstate URL
// - /error
window.onpopstate = async () => {
const url = new URL(
window.location.pathname + window.location.search,
window.location.origin
)
if (routes[window.location.pathname]) {
await routes[window.location.pathname](url.searchParams)
} else routes['/error']()
}
//
let onNavItemClick = async pathName => {
const url = new URL(pathName, window.location.origin)
const params = url.searchParams
if (routes[url.pathname]) {
window.history.pushState({}, pathName, window.location.origin + pathName)
await routes[url.pathname](params)
} else {
window.history.pushState({}, '404', window.location.origin + '/404')
routes['/error']()
}
}
//
;(async () => {
const url = new URL(
window.location.pathname + window.location.search,
window.location.origin
)
if (routes[window.location.pathname]) {
await routes[window.location.pathname](url.searchParams)
} else routes['/error']()
})()
// onNavItemClick()
const router = {
onNavItemClick,
routes
}
export { router }
, . , , , — .
JS
, , . , JS-.
▍
-, , , , . , -
Fronteers Conference 2011. . . , HTML-
, .
▍
-. , —
skatejs ssr web-component-tester. . , -, .
▍
querySelector()- , , . Angular .
, — . , , , .
▍ Shadow DOM
Shadow DOM. . — , . , , , , , - . , . , ,
.
▍ DOM
Angular React , DOM. , .
Angular University: «Angular DOM, , HTML- ».
Angular, , jQuery, DOM. , HTML-, , DOM, . , HTML-. Virtual DOM , , .
JS . .
▍
-, JS, ( «») , , . , , , Angular-.
Angular-,▍
- CLI, , , . , , -. , , , , , , .
▍
, , . . — . , , , , , . , , , , DOM. .
, React Angular, , . . , - React
shouldUpdate()
onPush
Angular.
▍
— . , . . , , , . , .
Parcel. , , Webpack, , , ,
, Parcel , .
React, Vue Angular . «». , React «», Vue — « ».
Stencil Polymer? , , , , - , . , . , -.
, SPA - . , , , .
?
, - , , « ». , , , , , , . , , , , .
, — , , . « » . , , . , , , -.
, , , , , , , . — . , , , . — , -, , jQuery, .
, - . - , . , , - , .
- . , , , .
! -, ?