На написание этой статьи меня вдохновил YouTube-канал Fireship, записывающий отличные видео о веб-разработке, крайне рекомендую их посмотреть, если вам интересна эта тема.

Вот видео с канала, в котором в 10 фреймворках создают todo-приложение:


Я решил, что не хочу тратить на это кучу времени, и в основном использовал статью как оправдание для изучения нескольких новых фреймворков, поэтому пять раз собрал одно и то же приложение. Я планирую создать простое приложение для добавления заметок, в котором пользователи могут писать текст и сохранять его как отдельные заметки. Некоторые из этих фреймворков я уже использовал для создания подобных приложений, а в других не делал ничего похожего, или даже не использовал их вообще, поэтому это будет чуть сложнее.

Создаём приложение


jQuery


Чтобы упростить создание приложения без фреймворка, я буду использовать jQuery. Начал я с создания базовой структуры файлов и открытия index.html. Если вам любопытно, структура файлов выглядит так:


По сути, у меня есть таблица стилей в SCSS, которую я скомпилирую в CSS, и на этом пока всё. Разметка html выглядит пока так, но в дальнейшем я её расширю:

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <link rel="stylesheet" href="./css/styles.css" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
    <title>Notes App</title>
</head>

<body>
    <div class="container">
        <header>
            <h1>Notes App</h1>
        </header>
        <main>
            <div class="note">
                <form>
                    <input required type="text" id="note-title" placeholder="Note Title" />
                    <textarea id="note-body" placeholder="Note Body"></textarea>
                    <input type="submit" id="note-submit" title="Add Note" />
                </form>
            </div>
        </main>
    </div>
</body>

</html>

Таблица стилей выглядит так:

body {
    height: 100%;
    width: 100%;
    margin: 0;
}

.container {
    width: 100%;
    height: auto;
    margin: 0;
    display: flex;
    flex-direction: column;

    header {
        display: flex;
        align-items: center;

        width: 100%;
        height: 56px;
        background-color: #4e78b8;
        color: white;

        h1 {
            margin-left: 6px;
        }
    }

    main {
        margin: 10px;
        display: grid;
        grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
        grid-gap: 1rem;
        align-items: center;

        .note {
            display: flex;
            flex-direction: column;

            padding: 10px;
            background-color: #a15fbb;
            border-radius: 5px;

            form {
                display: flex;
                flex-direction: column;

                textarea {
                    resize: none;
                }
            }
        }
    }
}

Далее я компилирую код при помощи sass scss/styles.scss:css/styles.css, после чего мы готовы писать JavaScript. По сути, нам достаточно добавить в DOM новый div с парой дочерних элементов для отправки формы и сохранение в локальное хранилище. Вот что у меня в результате получилось:

let notes = [];

$(document).ready(function () {
    if (localStorage.getItem("notes")) notes = JSON.parse(localStorage.getItem("notes"));
    setNotes();
});

$("#note-submit").click(function (e) { 
    let noteTitle = $("#note-title").val();
    let noteDesc = $("#note-body").val();
    let note = {
        title: noteTitle,
        desc: noteDesc
    }
    notes.push(note);
    console.log(notes);
    localStorage.setItem("notes", JSON.stringify(notes));
    setNotes();
});

function setNotes() {
    notes.forEach((note) => {
        $("main").prepend(`
            <div class="note">
                <h4>${note.title}</h4>
                <span>${note.desc}</span>
            </div>
        `);
    });
}

Вероятно, это не самый лучший код, но мне он показался логичным, к тому же я решил, что для этого проекта и не нужен идеальный код. Как бы то ни было, это было гораздо проще, чем я ожидал из предыдущего опыта, и мне это действительно понравилось. Вероятно, в других приложениях будет отличаться порядок заметок, потому что я не мог заморачиваться тем, чтобы они всегда добавлялись до формы, но после других заметок.

Angular


Забавен контраст между тем, сколько можно сделать с помощью Angular, и тем, что делаем мы. Вопреки впечатлению, которое могло сложиться по предыдущим постам, мне очень нравится Angular, просто я недолюбливают его недостаток модульности по сравнению с чем-то наподобие React. Впрочем, ладно, давайте сгенерируем проект:

$ ng new angular

И это буквально всё, что нужно для начала. Разве CLI Angular не великолепен? Для базовой структуры приложения я напишу, по сути, тот же код:

<div class="container">
  <header>
    <h1>Notes App</h1>
  </header>
  <main>
    <div class="note" *ngFor="let note of [0, 1, 2, 3]">
      <h4>Note Title</h4>
      <span>Note Body</span>
    </div>
    <div class="note">
      <form>
        <input required type="text" #noteTitle placeholder="Note Title" ngModel />
        <textarea #noteBody placeholder="Note Body" ngModel></textarea>
        <input type="submit" #noteSubmit title="Add Note" />
      </form>
    </div>
  </main>
</div>

Это может показаться вам спорным, но я собираюсь выполнять всю логику приложения в самом компоненте приложения, без дочерних компонентов. В целом это немного упростит работу, хотя на самом деле это необязательно. Давайте используем практически те же стили, что и раньше:

.container {
  width: 100%;
  height: auto;
  margin: 0;
  display: flex;
  flex-direction: column;

  header {
      display: flex;
      align-items: center;

      width: 100%;
      height: 56px;
      background-color: #4e78b8;
      color: white;

      h1 {
          margin-left: 6px;
      }
  }

  main {
      margin: 10px;
      display: grid;
      grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
      grid-gap: 1rem;
      align-items: center;

      .note {
          display: flex;
          flex-direction: column;

          padding: 10px;
          background-color: #a15fbb;
          border-radius: 5px;

          form {
              display: flex;
              flex-direction: column;

              textarea {
                  resize: none;
              }
          }
      }
  }
}

Теперь мы просто можем написать код, похожий на тот, что писали раньше:

import { Component } from '@angular/core';

type Note = {
  title: string;
  desc: string;
}

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.scss']
})
export class AppComponent {
  notes: Array<Note> = [];
  title!: string;
  body?: string;

  constructor() {
    const data = localStorage.getItem("notes");
    if (data) this.notes = JSON.parse(data);
  }

  submitForm() {
    let note: Note = {
      title: this.title,
      desc: this.body || ""
    }
    this.notes.push(note);
    localStorage.setItem("notes", JSON.stringify(this.notes));
  }
}

Сделав это, мы можем вернуться к шаблону и исправить логику заметок:

<div class="container">
  <header>
    <h1>Notes App</h1>
  </header>
  <main>
    <div class="note" *ngFor="let note of notes">
      <h4>{{note.title}}</h4>
      <span>{{note.desc}}</span>
    </div>
    <div class="note">
      <form #addNoteForm="ngForm">
        <input required type="text" placeholder="Note Title" [(ngModel)]="title" name="Title" />
        <textarea placeholder="Note Body" [(ngModel)]="body" name="Body"></textarea>
        <input type="submit" #noteSubmit title="Add Note" (click)="submitForm()" />
      </form>
    </div>
  </main>
</div>

Вот и всё, ребята!

React


Думаю, здесь всё будет сложнее необходимого из-за природы React. React спроектирован так, чтобы быть более модульным и лёгким, чем другие фреймворки, но в каком-то смысле из-за своей структуры для мелких приложений он сложнее. Я начал генерацию своего react-приложения с собственного шаблона sammy-libraries:

$ yarn create react-app react-app --template sammy-libraries

У меня время от времени возникает баг: node sass (который я использую обычно, потому что dart sass, по моему опыту, имеет более медленное время компиляции для React) отказывается компилировать мой код sass, поэтому я просто удалил node_modules и yarn.lock, а затем снова запустил yarn, и всё заработало идеально. Вот что я сделал: я начал с создания index.scss, аналогичного styles.scss из первого приложения, а затем в своём компоненте App воссоздал базовую структуру приложения:

import React, { useEffect, useState } from "react";
import NotesList from "components/NotesList";
import { NoteType } from "components/Note";
//import "scss/App.scss";

function App() {
    const [notesList, setNotesList] = useState<NoteType[]>([]);

    const [noteTitle, setNoteTitle] = useState<string>("");
    const [noteDesc, setNoteDesc] = useState<string>("");

    useEffect(() => {
        const data = localStorage.getItem("notes");
        if (data) {
            setNotesList(JSON.parse(data));
        }
    }, []);

    useEffect(() => {
        localStorage.setItem("notes", JSON.stringify(notesList));
    }, [notesList])

    const addNote = (event: React.FormEvent<HTMLFormElement>) => {
        let note: NoteType = {
            title: noteTitle,
            desc: noteDesc,
        };
        setNotesList([...notesList, note]);
        event.preventDefault();
    };

    const changeTitle = (event: React.ChangeEvent<HTMLInputElement>) => {
        setNoteTitle(event.currentTarget.value);
    };

    const changeDesc = (event: React.ChangeEvent<HTMLTextAreaElement>) => {
        setNoteDesc(event.currentTarget.value);
    };

    return (
        <div className="container">
            <header>
                <h1>Notes App</h1>
            </header>
            <NotesList addNote={addNote} changeTitle={changeTitle} changeDesc={changeDesc} notes={notesList} />
        </div>
    );
}

export default App;

Пока проект ничего не делает, поэтому давайте добавим другие компоненты. Я создал три компонента в отдельных папках компонентов и заполнил их соответствующим образом.

NotesList.tsx:

import React from "react";
import AddNote from "components/AddNote";
import Note, { NoteType } from "components/Note";

type NotesListProps = {
    notes: NoteType[];
    addNote: (event: React.FormEvent<HTMLFormElement>) => void;
    changeTitle: (event: React.ChangeEvent<HTMLInputElement>) => void;
    changeDesc: (event: React.ChangeEvent<HTMLTextAreaElement>) => void;
};

function NotesList({ notes, addNote, changeTitle, changeDesc }: NotesListProps) {
    return (
        <main>
            {notes.map((note) => {
                return (
                    <Note
                        note={{
                            title: note.title,
                            desc: note.desc,
                        }}
                    />
                );
            })}
            <AddNote addNote={addNote} changeTitle={changeTitle} changeDesc={changeDesc} />
        </main>
    );
}

export default NotesList;

Note.tsx:

import React from "react";

export type NoteType = {
    title: string;
    desc: string;
}

interface NoteProps {
    note: NoteType;
}

function Note(props: NoteProps) {
    return (
        <div className="note">
            <h4>{props.note.title}</h4>
            <span>{props.note.desc}</span>
        </div>
    );
}

export default Note;

И AddNote.tsx:

import React from "react";

interface AddNoteProps {
    changeTitle: (event: React.ChangeEvent<HTMLInputElement>) => void;
    changeDesc: (event: React.ChangeEvent<HTMLTextAreaElement>) => void;
    addNote: (event: React.FormEvent<HTMLFormElement>) => void;
}

function AddNote(props: AddNoteProps) {
    return(
        <div className="note">
            <form onSubmit={props.addNote}>
                <input type="text" placeholder="Note Title" onChange={props.changeTitle} />
                <textarea placeholder="Note Body" onChange={props.changeDesc}></textarea>
                <input type="submit" value="Add Note" />
            </form>
        </div>
    );
}

export default AddNote;

Не самое сложное из того, что я делал, но определённо кажется более сложным, чем работа с jQuery или Angular, по крайней мере, мне. Я очень люблю React и считаю его любимым фреймворком, просто не знаю, что любить в нём, работая над подобными проектами. Если бы мне пришлось выбирать, то я бы сказать, что самый чистый из всех — это Angular, а JQuery кажется самым логичным (по крайней мере, для этого проекта). React — самый неуклюжий, с ним удобно работать, но он не кажется особо подходящим.

Vue


С этим фреймворком я работал один раз, и кому-то это может показаться оскорблением, но я действительно не видел смысла в возне с ним. Я могу использовать и Angular, и React. Мне кажется, что они покрывают почти все мои потребности (а оставшееся решают библиотеки), поэтому Vue никогда не казался мне полезным. Что ж, давайте создадим свой проект на Vue.

$ vue ui

По сути, я использовал всё по умолчанию, но с TypeScript и SCSS (в основном с dart sass, чтобы не ломать зависимости), потому что мне нравится применять их в своих проектах. Единственная реальная причина того, что я не использовал TypeScript в первом проекте, заключалась в том, что мне не хотелось возиться с обеспечением совместной работы jQuery и TS, но если вам интересно, то это возможно.

Как я подошёл к созданию приложения? Сначала я удалил почти всё, что было сгенерировано автоматически, и заменил код App вот на это:

<template>
  <div class="container">
    <header>
      <h1>Notes App</h1>
    </header>
    <main>
      <Note
        v-for="(note, index) in notes"
        :key="index"
        :title="note.title"
        :body="note.body"
      />
      <div class="note">
        <form @submit="submitForm()">
          <input type="text" placeholder="Note Title" v-model="title" />
          <textarea placeholder="Note Body" v-model="body"></textarea>
          <input type="submit" value="Add Note" />
        </form>
      </div>
    </main>
  </div>
</template>

<script lang="ts">
import { Component, Vue } from "vue-property-decorator";
import Note from "./components/Note.vue";

type NoteType = {
  title: string;
  body: string;
};

@Component({
  components: {
    Note,
  },
})
export default class App extends Vue {
  notes: Array<NoteType> = [];
  title!: string;
  body?: string;

  constructor() {
    super();
    const data = localStorage.getItem("notes");
    if (data) this.notes = JSON.parse(data);
  }

  submitForm(): void {
    let note: NoteType = {
      title: this.title,
      body: this.body || "",
    };
    this.notes.push(note);
    localStorage.setItem("notes", JSON.stringify(this.notes));
  }
}
</script>

<style lang="scss">
body {
  height: 100%;
  width: 100%;
  margin: 0;
}

.container {
  width: 100%;
  height: auto;
  margin: 0;
  display: flex;
  flex-direction: column;

  header {
    display: flex;
    align-items: center;

    width: 100%;
    height: 56px;
    background-color: #4e78b8;
    color: white;

    h1 {
      margin-left: 6px;
    }
  }

  main {
    margin: 10px;
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
    grid-gap: 1rem;
    align-items: center;

    .note {
      display: flex;
      flex-direction: column;

      padding: 10px;
      background-color: #a15fbb;
      border-radius: 5px;

      form {
        display: flex;
        flex-direction: column;

        textarea {
          resize: none;
        }
      }
    }
  }
}
</style>

А компонент Note выглядел вот так:

<template>
  <div class="note">
    <h4>{{ this.title }}</h4>
    <span>{{ this.body }}</span>
  </div>
</template>

<script lang="ts">
import { Component, Prop, Vue } from "vue-property-decorator";

@Component({
  components: {},
})
export default class App extends Vue {
  @Prop() title!: string;
  @Prop() body?: string;
}
</script>

И на этом всё.

Svelte


Я хотел изучить этот фреймворк, но и не думал касаться его, пока не решил написать эту статью. По сути, я начинал, не зная совершенно ничего, за исключением того, что Svelte очень любят веб-разработчики, но после этого опыта я, наверно, продолжу создавать проекты со Svelte. Вероятно, пока я в нём очень плох, но со временем ситуация может измениться.

Потратив десять минут на поиск несуществующего CLI для Svelte yarn create-*, я решил настроить проект с бойлерплейтом фреймворка. Я преобразовал проект в TypeScript, потому что я фанат языков со строгой типизацией, а потом приступил к работе. Занявшись стилями, я пошёл на принцип и отказался от SCSS. Под этим я подразумеваю, что не мог возиться с настройкой SCSS, какой бы лёгкой она ни была, поэтому просто скомпилировал его вручную. Вот с таким компонентом я начал работу:

<script lang="ts">
import Note from "./components/Note.svelte";

type NoteType = {
    title: string;
    body: string;
};

let notes: Array<NoteType> = [];

const data = localStorage.getItem("notes");
if (data) notes = JSON.parse(data);

let title: string = "";
let body: string = "";

function onSubmit() {
    let note: NoteType = {
        title: title,
        body: body
    };
    notes.push(note);
    localStorage.setItem("notes", JSON.stringify(notes));
}
</script>

<div class="container">
    <header>
        <h1>Notes App</h1>
    </header>
    <main>
        {#each notes as note}
            <Note title={note.title} body={note.body} />
        {/each}
        <div class="note">
            <form on:submit={onSubmit}>
                <input type="text" placeholder="Note Title" bind:value={title} />
                <textarea placeholder="Note Body" bind:value={body}></textarea>
                <input type="submit" value="Add Note" />
            </form>
        </div>
    </main>
</div>

<style>
body {
  height: 100%;
  width: 100%;
  margin: 0;
}

.container {
  width: 100%;
  height: auto;
  margin: 0;
  display: flex;
  flex-direction: column;
}
.container header {
  display: flex;
  align-items: center;
  width: 100%;
  height: 56px;
  background-color: #4e78b8;
  color: white;
}
.container header h1 {
  margin-left: 6px;
}
.container main {
  margin: 10px;
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
  grid-gap: 1rem;
  align-items: center;
}
.container main .note {
  display: flex;
  flex-direction: column;
  padding: 10px;
  background-color: #a15fbb;
  border-radius: 5px;
}
.container main .note form {
  display: flex;
  flex-direction: column;
}
.container main .note form textarea {
  resize: none;
}
</style>

А вот компонент Note:

<script lang="ts">
    export var title: string;
    export var body: string;
</script>

<div class="note">
    <h4>{title}</h4>
    <span>{body}</span>
</div>

Я обнаружил проблему, решения которой не знаю, и на данном этапе не хочу её решать: стили работают, только если вставить их в bundle.css, который затем сбрасывается при обновлении кода и ресурсов. Это не будет проблемой в полностью собранном приложении, но очень раздражает при тестировании. Не думаю, что буду решать эту проблему в ближайшее время, но, вероятно, со временем устраню её.

Заключение


Выше я говорил, что буду пробовать создавать при помощи Svelte и другие приложения, но не знаю, насколько решительно я готов выполнять это обещание. Хотя мне понравились многие аспекты Svelte, в нём слишком много препятствий, чтобы использовать его чаще. Учитывая проект, над которым я работал, React, по моему мнению, подвергся несправедливой критике. Angular по-прежнему кажется мне самым чистым, Vue — самым интересным, а jQuery — самым лучшим, что меня сильно удивило. Думаю, если бы мне пришлось выбирать фреймворк для будущих проектов, то это определённо бы зависело от проекта, но сам я вполне могу представить, что использую все пять, даже с учётом сложностей Svelte. Тем не менее, вероятно, основную свою работу я буду выполнять в Angular и React, а jQuery и Vue будут следующими по приоритету. Наверно, я дам Svelte ещё один шанс, но не думаю, что буду создавать в нём особо много проектов, вне зависимости от того, была ли справедлива критика в этом проекте. В любом случае, мне кажется, что любой из этих фреймворков станет отличным выбором для множества способов применения. Теперь я вижу, почему людям нравится Vue, но не могу сказать, что моё мнение очень сильно изменилось.

Код


Весь код выложен на github

— — — —
Дата-центр ITSOFT – размещение и аренда серверов и стоек в двух ЦОДах в Москве; colocation GPU-ферм и ASIC-майнеров, аренда GPU-серверов. Лицензии связи, SSL-сертификаты. Администрирование серверов и поддержка сайтов. UPTIME за последние годы составляет 100%.

Комментарии (25)


  1. noRoman
    31.08.2021 08:26
    +1

    jQuery лучший пока приложение небольшое, а потом, как в сказке «Золушка», после 12 часов карета … )))


    1. Layan
      31.08.2021 11:18
      +1

      Там такой пример, в котором вообще можно обойтись чистым JS почти без увеличения количества кода.


  1. i360u
    31.08.2021 08:34
    +7

    Какой смысл делать все это, не сравнив, в итоге, размер бандлов, скорость рендера или потребление памяти? Где ссылка на результат? Где ссылка на исходник в удобоваримом виде? Читатель должен все это скомпилировать и отрендерить сам у себя в голове? Пример с jQuery - особенно шикарен: тащим в проект зависимость, которая, по сути, не делает вообще ничего кроме дублирования ванилы... Ну и общий стиль: "я хотел использовать такой-то фреймворк, но не хотел. Я буду использовать то-то, но может и не буду...". Что автор сказать то хотел? Что на всех этих либах можно сделать туду-лист? А мы и не подозревали.


    1. YSpektor
      31.08.2021 09:23
      -3

      Преждевременная оптимизация - известный антипаттерн, а Дональд Кнут вообще назвал ее корнем всех зол. Если размер бандла, скорость рендеринга и потребление памяти удовлетворительные, т.е. не вызывает проблем у пользователя, то эти цифры не имеют значения. А я вас уверяю, в приведенном примере todo листа эти все показатели будут удовлетворительными. Чистота и количество кода здесь более интересный показатель, другое дело что опять таки, показанный пример совершенно недостаточен для того, чтобы сделать вывод, todo лист без проблем можно реализовать даже на jQuery, что автор и показал, но для более сложных случаев, jQuery превращает код в императивный ад.


      1. Ritan
        31.08.2021 09:35
        +6

        Если размер бандла, скорость рендеринга и потребление памяти удовлетворительные, т.е. не вызывает проблем у пользователя, то эти цифры не имеют значения.

        Да, особенно это хорошо видно, когда страница комментариев у хабра загружается минуту. Ведь у разработчиков такой проблемы не было, а значит её нет


        1. YSpektor
          31.08.2021 09:42
          -3

          Лично я с такой проблемой не сталкивался, но даже если страница загружается долго, уверены ли вы что это именно веб браузер долго не может отобразить вашу страницу? Или это ответ с сервера долго не приходит? Или еще в чем проблема? И да, повторюсь, если вы достоверно знаете, что, скажем, из-за размера бандла страдает user experience, то да, эта проблема, которую нужно решать, если нет - есть другие важные вещи, которые необходимо учитывать


          1. nin-jin
            31.08.2021 10:57
            +2

            Про тормоза хабра я тут писал: https://habhub.hyoo.ru/#!author=nin-jin/repo=HabHub/article=34


      1. JustDont
        31.08.2021 10:36
        +9

        Преждевременная оптимизация — известный антипаттерн

        Любители приводить этот тезис так же любят забывать, что речь идёт именно про преждевременную оптимизацию. И что "преждевременная" — это не одно и то же, что "пока не тормозит, но будет". Преждевременная — это когда вы вообще не знаете, где у вас bottleneck, и имеет ли он какое-то практическое значение. Когда вы заведомо знаете, что, где, и как именно у вас будет тормозить, и такие тормоза для вас неприемлемы — это уже не "преждевременная". Даже если вы этот код еще не написали и вам еще пока не прилетели письма счастья от ваших клиентов.


        И в вебе тормоза и риски очень неплохо просчитываются вперед.


        1. YSpektor
          31.08.2021 11:03
          -1

          С написанным в целом согласен, но лично я очень часто наблюдаю, как наоборот, в погоне именно за умозрительной оптимизацией при неустановленном узком месте (а зачастую вообще при отсутствии проблем в ближайшей перспективе) приносится в жертву качество кода.


      1. akuzmin
        31.08.2021 11:12
        +1

        Размер бандла - это крайне важно - с самого начала разработки, когда до реальных проблем еще далеко и все летает, и да самого конца. Веб-пользователи со всем их зоопарком устройств очень активно реагируют даже на легкие тормоза в UI. Когда наступают реальные проблемы, никакие антипаттерны и теоретические доводы вас не спасут, кем бы они ни были произнесены (и в каком контексте).

        Если Автор берется сравнивать фреймворки, то размер бандла для сравнения очень важно указывать, так как этот бандл - это render-blocking resources, то, что будет грузиться в первую очередь и блокировать рендеринг.


        1. VanKrock
          31.08.2021 23:20

          Размер бандла важен только если вы пишите B2C, если какое-нибудь B2B, которое пользователь один раз загрузил и работает весь день, то это уже совсем не важно. Например CRM, ERP, торговый терминал и тому подобное. Загрузил однажды, закэшировал и пользуйся. А вот удобство разработки сложной логики тут вылазит на приоритетные позиции


      1. i360u
        31.08.2021 15:01
        +1

        Преждевременная оптимизация - известный антипаттерн

        Кроме "преждевременной" есть еще "своевременная" и та, которая была необходима еще вчера. Выбор фреймворка - это далеко не то-же самое, что попытка экономии на циклах из трех элементов. Поменять стек "потом", когда гугл вас понизит в выдаче из за конского бандла, будет несравнимо дороже, чем в начале пути.


  1. ILaeeeee
    31.08.2021 08:50
    +1

    Я в js фреймворках особо не разбираюсь (на текущий момент), так, на jQuery и Vue формочки и прочее иногда леплю. Но почему то мне интуиция подсказывает, что человек с React переборщил. Или там действительно надо всё так детализировать?

    Максимально простой и читабельный же из этих примеров тут Svelte.


  1. anonymous
    00.00.0000 00:00



  1. Buzzzzer
    31.08.2021 11:14

    Можно еще TodoMVC посмотреть.



  1. Beginer_First
    31.08.2021 15:56

    Статья (врятли ее так можно назвать) перевод которого не следовало бы делать

    Заголовок и заключение , аля смотри как накалякать.


  1. Kirill_Amber
    31.08.2021 15:56

    Где тесты?


  1. derikn_mike
    01.09.2021 00:30

    согласитесь как ангуляр и реакт соснули у vue по чистоте понятности минимализму ?


  1. pavelsc
    01.09.2021 01:19

    А вот о чем такое сравнение сложно сказать. Типа "Смотри, мама, я cli такого-то фреймворка запустил"? Мне вот во Vue нравится плагин к хрому мониторить состояние, и то что стор это по сути просто большой объект, который к тому же легко завязать к локал стораджу плагином. Отсутствие этого в самой философии ангуляра не находит принятия во мне. Если делаешь что-то вроде виджетов чата, нужно во всех фреймворках велосипедить проброс ивентов между табами, из коробки такого не находил нигде. И стоит упомянуть вещь, которая будет стопить разработку, это интеграция с сервисами вроде рекапчи, Гугл мапс и чего-то менее популярного. Не все хорошо с этим даже у Vue, совсем бледно у svelte. Лучше всего экосистема в этом плане у Реакта. Хорошо если у вас продукт, и вам можно взять несколько спринтов для интеграции стороннего сервиса как фреймворк плагина. На аутсорсе такой роскоши нет и выбор фреймворка выбирается исходя из богатства экосистемы.

    Стоит ли говорить про такую вещь как нейтив которой нет в jQuery и svelte? Справедливости ради weex для Vue можно описать одним словом - боль. В Android Studio это даже не стартанет не выплюнув с десяток ошибок, от которых у не андроид разработчика волосы встают дыбом.

    Добавить сюда бэк с ворохом SQL и noSQL и окажется что фуллстек синоним слова ноулайфер :)



  1. hazg
    01.09.2021 10:46

    Svelte - все не так. Что не так? Все не так. Ну, хотя бы пример не работает и не должен.

    https://svelte.dev/repl/b84291af78cf49ba9aaa0a1e1774e482?version=3.42.4

    Этот вариант должен работать. Стили в вашем примере не могут работать, они в скоупе компонента и .container main .note form не будет работать из App.svelte для компонента Note

    Сабмит формы должен быть on:submit|preventDefault

    Для меня все выглядит многословно и... избыточно. Да, я переписал не на TS, но речь не про это. Свелте в переводе - тощий, стройный. Это так, если его не велосепедировать.


    В целом, подход людей, знакомых с другими фрейворками которые пробуют пользоваться свелте - удручает. Свелте не про JS. Он - компилятор, поэтому, человек, хорошо знакомый с JS\TS будет говорить - это не возможно в JS и сознательно построит велосипеды.

    Он модульный до тошноты. И да, на выхлопе это удобно и он заставляет делать все модульным. Хотя бы - стилями per module.

    Его реактивность и store выглядят как детский сад - и это прекрасно. Поставить $storyName.title, и забыть об обновлениях на странице.

    Просто пройдитесь по https://svelte.dev/examples#hello-world и посмотрите на то, как авторы видят подход к програмированию на этом фреймворке. Полчаса времени для знакомого с реактом, vue. Для тех, кто не любит перелопачивать сотни строк и не берет денег за кол-во строк - самое то.

    PS: Зачем парсить json? localStorage умеет объекты. (в своем переписанном примере использовал svelte/store, это svelte-way, гибко и ....в REPL не работает local storage из за iframe, как понимаю ). В проекте тоже использовал бы store, а к нему уже прикручивать - куда писать данные и от куда читать)


    1. nin-jin
      01.09.2021 11:11

       localStorage умеет объекты

      Он умеет исключительно строки.


      1. hazg
        01.09.2021 11:32

        моя неправда. спасибо.