Я разделяю свой код на 3 логические категории: представление, независимая библиотека и общий код приложения.

Представление — это любой модуль, который выводит визуальный элемент, будь то SVG, 3D или DOM, независимая библиотека подходит для кода, не привязанного к приложению (например, определение браузера), а общий код приложения — это модули, которые логически связаны с приложением. (например: маршрутизатор и модели).

Мои представления следуют одному и тому же интерфейсу, все они имеют метод render , intro и outro, preload и dispose также являются опцией, когда это необходимо, ниже приведен базовый шаблон:

class View {
    constructor() {
    }
    render() {
    }
    intro() {
    }
    outro() {
    }
    preload() {
    }
    dispose() {
    }
}
export default View;

render не требует пояснений, он отображает визуальный элемент на экране.

Вот пример загрузки шаблона и добавления его в DOM:

import tmpl from "templates/view.html"
class View {
    constructor() {
        this.el = undefined;
    
    }
    render(parent) {
        this.el = parseHTML(tmpl);
        parent.appendChild(this.el)
    }
}

А здесь с использованием ThreeJS:

class View {
    constructor(camera, renderer, scene) {
        this.camera = camera;
        this.renderer = renderer;
        this.scene = scene;
        this.material = undefined;
        this.geometry = undefined;
        this.mesh = undefined;
    }
    render() {
        this.geometry = new THREE.BoxGeometry( 1, 1, 1 );
        this.material = new THREE.MeshBasicMaterial();
        this.mesh = new THREE.Mesh( geometry, material );
        this.scene.add( this.mesh );
    }
}

intro — это место, где я вызываю метод render и пишу анимацию перехода, обычно в конце анимации есть обратный вызов (о котором я расскажу в статье Router). Иногда я вызываю метод preload перед рендерингом элементов.

outro — это место, где я пишу переход и вызываю dispose в конце (при необходимости).

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

В dispose я очищаю все переменные (устанавливая их значения в undefined ), удаляю все события и сами элементы, это очень важно для предотвращения утечки памяти.

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

Повторное использование кода

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

С помощью JavaScript довольно легко написать повторно используемый код в виде композиции:

function basicComp(comp) {
    comp.preload = function() {
        // reusable code here
   
    }
}
export default basicComp;

Чтобы повторно использовать этот код внутри другого компонента:

import basicComp from "scripts/shared/comp/basicComp"
class Component {
    constructor() {
        basicComp(this)
    }
}
export default Component;

Просмотр страницы и компонент

Обычно в моих проектах есть 2 типа просмотра: компонентный и постраничный.

Компоненты — это независимые визуальные библиотеки, которые можно повторно использовать в приложении, в то время как просмотры страниц — это отдельные экземпляры, привязанные к маршрутизатору, и именно здесь я инициализирую все компоненты, используемые на конкретной странице:

import Component from "scripts/shared/comp/component"
class PageView {
    constructor() {
        this.component = undefined;
    }
    render() {
        this.component = new Component();
        this.component.render(document.body)
    }
}
export default new PageView;

Компонент также может инициализировать другие компоненты внутри, следуя той же структуре, что и выше.

Заключение

Что мне нравится в этом подходе, так это то, что каждый визуальный модуль имеет один и тот же интерфейс, все представляет собой модуль ES6 с render, intro и outro, нет необходимости усложнять создание различных подписей на основе логических функций, как это делают некоторые фреймворки.

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

В следующем разделе я расскажу о маршрутизаторах и о том, как с ними связаны просмотры страниц, следите за обновлениями!

Не хотите начать сначала? Перейдите в указатель.