¿Cuándo desaparecerán los marcos de JavaScript?

El autor del material, cuya traducción publicamos hoy, un desarrollador web, dice que intenta revisar periódicamente el conjunto de herramientas que utiliza. Lo hace para comprender si puede prescindir de algunos de ellos resolviendo sus tareas habituales. Recientemente decidió llevar a cabo un experimento y crear una aplicación front-end sofisticada sin usar marcos JavaScript.

¿Qué es un marco?


Si intenta definir un marco de JavaScript sin entrar en detalles, resulta que esta es una herramienta que se puede utilizar para desarrollar aplicaciones web complejas, en particular aplicaciones de una sola página (SPA).

En los viejos tiempos, tales aplicaciones se construyeron en base a las capacidades de JavaScript puro y la biblioteca jQuery. Pero, con la creciente complejidad de las aplicaciones front-end, comenzaron a aparecer las herramientas correspondientes que hacen la vida más fácil para los programadores. Por ejemplo, estos son React, Angular y Vue.

Los marcos que son populares en estos días tienen algunas similitudes en común. Por lo tanto, la mayoría de los frameworks y bibliotecas front-end, en términos relativos, desde Vue hasta React, proporcionan al desarrollador una cierta combinación de las siguientes características:

  • Sincronización del estado y presentación visual de la aplicación.
  • Enrutamiento
  • Sistema de plantillas.
  • Componentes aptos para su reutilización.

¿Son necesarios los marcos para un desarrollador moderno?


La respuesta a la pregunta planteada en el título de esta sección depende de cómo se relacione con la idea de la "necesidad" de los marcos. Estoy seguro de que muchos pueden decir que los marcos front-end no son necesarios en el kit de herramientas para desarrolladores web, y nunca han sido necesarios. Aunque es indiscutible que estas son herramientas muy útiles.

En realidad, nuestra pregunta puede reformularse de la siguiente manera: "¿Son los marcos un poco como una" biblioteca jQuery moderna "? ¿Es posible resolver los problemas a los que se dirigen, por otros medios, por ejemplo, aquellos que aparecieron a disposición de los programadores durante el desarrollo de las API del navegador?


jQuery

De hecho, esta pregunta no es fácil de responder, pero podemos decir que el desarrollo de JavaScript, tecnologías para trabajar con componentes web y herramientas para crear proyectos ha hecho que el desarrollo de SPA sin el uso de marcos sea más fácil que nunca.

Para explorar esta idea, desarrollé una aplicación de una página usando solo JavaScript, componentes web estándar y el paquete de paquetes. En el proceso de trabajo, me encontré con algunos problemas y dificultades, observando que usted comienza a ver claramente las fortalezas de los marcos JS modernos.

Al mismo tiempo, tan pronto como lidié con los obstáculos iniciales, me sorprendió lo fácil que es crear una aplicación de una página en JavaScript puro.

Descripción general de la aplicación experimental


La aplicación en cuestión es bastante simple. Es una colección electrónica de recetas y permite al usuario crear, ver y editar recetas. El usuario, además, puede marcar recetas, lo que indica que le gustan, y también puede filtrar y eliminar entradas.


Página de inicio de la aplicación


Página de registro de recetas

Componentes web


- — . , , 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, .


, - . - , . , , - , .

- . , , , .

! -, ?

Source: https://habr.com/ru/post/439824/


All Articles