суббота, 26 декабря 2020 г.

A programmer: JavaScript #28. Routing in React

Некоторое время назад делал я тестовое задание по стеку MERN (MongoDB, ExpressJS, React, NodeJS). Сделать вовремя не сумел, но добрые люди согласились мне помочь доделать его - для себя, просто чтобы разобраться. Важный комментарий был мне дан по поводу того, что при маршрутизации моя программа перезагружает страницу, чего не должно быть, поскольку в этом случае теряется вся логика Single Page Application, для чего, собственно, и разработан React. Логика, напомню, состоит в том, что вместо загрузки необходимых страниц с сервера по каждому запросу, должно загружаться всё и сразу (кроме баз данных), и в зависимости от запроса - отрисовываться на клиенте то, что нужно, но без перезагрузки страницы. И понял я, что с маршрутизацией в React'e мне, оказывается, ещё нужно разобраться получше.

Итак, для маршрутизации в React'e существует модуль react-router-dom, который предоставляет несколько ключевых инструментов:

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

Router - в сущности, аналог href - в нем прописывается путь, в зависимости от которого должно быть отрисовано нужное содержание.

Если кроме непосредственных ссылок надо обработать отсутствующую страницу, то Route'ы надо обернуть в Switch.

Кроме того, можно использовать Redirect, Link и NavLink (который отличается от Link тем, что в нем можно ещё и ссылаться не описание стилей для линков).

Так вот, в моем случае надо было использовать Link вместо Route - в этом случае страница не перезагружается, и маршрутизация осуществляется на клиенте, в противном случае идет запрос на сервер:

<Link to="/"><button type="button">Home</button></Link>

Информация взята отсюда, отсюда и отсюда.

пятница, 18 декабря 2020 г.

A programmer: JavaScript #27. Hooks in React

Поскольку, грубо говоря, в JavaScript всё есть объект, то и компоненты React тоже вполне логично интерпретируются как объекты. А у объектов, как известно, есть состояние (state) и есть поведение. Состояние хранится в самом объекте, и его можно в нем же менять через this.setState. Но в последнее время разработчики React стараются отходить от такой практики и использовать компоненты как "функциональные компоненты", или просто функции. А функции не имеют состояния (stateless). Но состояние - вещь необходимая, и возникшую проблему надо решать - для этого и придумали хуки (hooks). Хук - это функция, которая меняет состояние, которое хранится в локальной переменной.

Классический пример - использование хука useState для счетчика (сначала его надо импортировать и библиотеки 'react'):

const [count, setCount] = useState(0);

Здесь происходит "деструктуризация массива" - объявляются и переменная состояния (count), и собственно хук (setCount). То есть запись эквивалентна следующей:

var countStateVariable = useState(0);

var count = countStateVariable[0]; // Объявление переменной состояния

count = 0; // Присваивание начального значения

var setCount = сountStateVariable[1]; // Объявление хука

Теперь к ним можно обращаться в рендере:

button onClick={() => setCount(count + 1)}

Другой классический пример – хук useEffect. Он определяет действия, которые должны быть выполнены после каждого рендера – то есть заменяет собой встроенные методы, которые связанны с жизненным циклом компонента (componentDidMount, componentDidUpdate и др.). Поскольку перерисовка компонента обычно связана с изменением состояния (за которое обычно отвечает useState), то часто оба эти хука используются вместе:

const [count, setCount] = useState(0);

useEffect(() => { document.title = `Вы нажали ${count} раз` });

В данном случае document.title будет перерисовываться при каждом изменении состояния.

Существуют и другие хуки, а также можно написать собственные.

Информация взята отсюда, отсюда, отсюда.

среда, 16 декабря 2020 г.

A programmer: JavaScript #26. A conditional statement in React

Некоторое время назад мучился с небольшой проблемой: вроде бы программа работала правильно, но в консоли браузера откуда-то выскакивало сообщение "GET http://localhost:3000/undefined". Расследование показало, что это связано с тем, что я добавляю в базу данных объект без картинки, при этом у меня должен отрисовываться элемент, который имеет свойство

backgroundImage: `url(${this.state.picture})`

То есть, когда картинки нет, он выбрасывает undefined, что логично. Мне посоветовали написать так:

this.state.picture && { backgroundImage: `url(${this.state.picture})` }

"Странная запись" - подумал я, имея в виду оператор "И", и пошел разбираться. Оказалось, что всё логично: React читает эту строчку последовательно слева направо. Если картинка в state есть, то он И отрисовывает её, а если её нет, то на операторе "И" прекращает читать строку, потому что вне зависимости от того, что дальше, значение будет false, и до запроса на вывод картинки дело не доходит.

вторник, 15 декабря 2020 г.

A programmer: JavaScript #25. Widdleware in ExpressJS

Тема, которая почему-то вообще не попадалась мне на глаза раньше, но оказалась полезной и достаточно несложной. Напомню, что ExpressJS - это фреймворк для более простой работы с вебсервером. Грубо говоря, если в "ванильном" варианте надо было работать с XMLHttpRequest-объектом (XHR) NodeJS'a, то в ExpressJS создается свой объект app, через каторый и идет взаимодействие с сервером. Так вот, маршрутизация предполагает, что серверная часть имеет эндпойнты (например, "/api"), при обращении к которым выполняются некоторые действия. Например:

app.get("/api", (req, res) => {

    // code

})

Так вот, существует возможность указать некоторые функции, которые должны быть выполнены ПЕРЕД выполнением данного года. Для этого определяется некоторая функция, кроме req и res она принимает параметр next, который вызывается в конце этой функции, чтобы передать выполнение следующему middleware или собственно основному коду (если надо выдать ошибку, она передается как параметр внутри next(error), никакой другой параметр там передаваться не может). Например:

const middleware = (req, res, next) => {

    // code

    next();

}

Чтобы подключить middleware, надо указать:

app.use("/api", middleware);

Если указать без указания на рут, middleware будет "подключено" глобально, то есть будет выполняться в любом руте:

app.use(middleware);

Ну и, разумеется middleware, как и любой кусок кода можно импортировать извне, а внутри только подключать.

Информация взята отсюда, отсюда и отсюда.

вторник, 24 ноября 2020 г.

A programmer: JavaScript #24. AJAX, XMLHttpRequest, fetch(), async/await

Когда я первый раз узнал об AJAX-запросах, это было связано с необходимостью получать данные с сервера, не перезагружая страницу. И выглядело это приблизительно так:

Что означало: при нажатии кнопки на клавиатуре в поле "login", взять данные и передать их методом POST в обработчик ajax.php (название файла, разумеется, может быть любым - скрин с php-проекта), и в случае успешной отработки обработчика, вывести результат на страницу в элемент с названием "#login_warning".

И, собственно, вся асинхронность у меня стала после этого ассоциироваться с тем, что оказалось всего-лишь частью библиотеки jQuery. Но принципиально - это только частный случай Asynchronous JavaScript And XML (AJAX). О чем идет речь?

Ранее я говорил, что promise - это способ справиться с асинхронностью - сделать так, чтобы команды выполнялись последовательно, поскольку часто бывает так, что для выполнения следующей функции нужен результат предыдущей, а в JavaScript это не гарантировано. Чаще всего это нужно при отправке http-запросов, когда данные должны быть выведены после получения ответа от сервера.

Без promise'ов это коротко выглядит так: создается специальный объект XMLHttpRequest, не нем открывается соединение и посылается запрос. Заранее определяется, что должно выполниться при том или ином ответе сервера:


fetch() - это интерфейс получения запросов - то есть способ сделать то же самое. "Под капотом" он создает объект request'a, посылает его, но возвращает promise с обработкой response'а:

 

На самом деле там вставляются ещё проверки, формат вывода данных, а в случае POST-запроса ещё и дополнительные параметры, но принцип таков.

Ну и async/await - это приблизительно то же самое. async перед функцией указвает на то, что функция возвращает promise, соответственно, внутри функция будет ждать результата от promise'a (в этом месте пишется await). Ну и поскольку promise может завершиться с ошибкой, то всё это оборачивается в try-catch:


Информация - отсюда, отсюда, отсюда, отсюда, отсюда. На самом деле ещё много откуда, но это самые последние по времени использования ресурсы.

UPD: 

1. Нашел ещё один очень удобный ресурс - вот он. Здесь показаны разные варианты работы с асинхронными запросами в одном видео.

2. Про популярный нынче axios ничего не писал, но там логика приблизительно такая же.

четверг, 19 ноября 2020 г.

A programmer: JavaScript #23. Prototype inheritance (Прототипное наследование)

Если коротко, наследование - это способ получения полей и методов без того, чтобы явно декларировать их в самом объекте. Осуществляется это указанием, что данный объект является "наследником" какого-то другого объекта, а значит, он по умолчанию имеет те же поля и методы, что и "родитель", плюс обычно добавляет какие-то собственные или переопределяет родительские. Это удобно.

В JavaScript используется "прототипное наследование". Что это значит и в чем отличие от "классического" наследования. Под классическим наследованием я здесь буду понимать то, которое используется в Java. В классическом наследовании наследуются не объекты, а классы. А объект имеет те поля и методы, которые должны иметь объекты его класса (включая наследуемые от классов-родителей). Это создает структуру наследования, что имеет свои преимущества и недостатки.

Прототипное наследование отличается тем, что наследуются именно объекты и именно от объектов. То есть некоторый объект может объявить другой объект своим прототипом:

var object = Object.create(prototypeObject);

Здесь object объявляет себя наследником объекта prototypeObject, слеовательно, он имеет такие же, как у него поля и методы.

Собственно, можно наследовать не только объект от объекта, но и класс от класса - через конструкторы:

ClassA.prototype = Object.create(ClassB.prototype);

Только в этом случае сам конструктор тоже наследуется - и у ClassA будет конструктор от ClassB. Чтобы этого не происходило нужно отдельно его прописать (как бы "вернуть" себе обратно):

ClassA.prototype.constructor = ClassA;

Технически это выглядит так, что любой объект имеет скрытое свойство [[Prototype]], которое можно явно задать (иначе оно равно null):

let object.__proto__ = prototypeObject;

 Здесь __proto__ - геттер/сеттер для [[Prototype]],в более поздних версиях языка он заменяется функциями Object.getPrototypeOf и , хотя __proto__ тоже поддерживается.

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

Важно отметить, что this всегда указывает на сам объект, но не на его протоип. То есть прототип выступает для наследника как хранилище объектов. Поясняю:

Пусть в прототипе есть метод:

setState() {

    this.state = true;

}

Если его вызвать на экземпляре наследника (object.setState()), то state = true будет присвоен наследнику, а не прототипу.

Информация взята отсюда, отсюда и отсюда.

A programmer: JavaScript #22. Closures (Замыкания)

Короткая и простая тема. Думал я поначалу. Есть, как минимум, два объяснения, что это такое.

Во-первых, замыкания - это, грубо говоря, способ создать приватное свойство. То есть есть свойство объявляется внутри функции, а сама функция его возвращает с помощию внутренней функции. Это означает, что свойство остается неизменным, кто бы ни вызывал функцию, потому что область его видимости остается внутри. Например, функция:

function private() {

    let a = 0;

    return function() {

        return a;

    };

};

В ней никто не имеет доступа к переменной а извне, и потому не может её изменить.

Во-вторых, замыкания - это функция внутри функции. Основная польза от этого в том, что её можно присвоить какой-то переменной, а вызвать потом через эту переменную. Например, результатом присвоения let variable = private(); будет variable, которая при вызове variable() будет возвращать а. Одним из самых распространенных применеий замыканий является счетчик: 

function private() {

    let a = 0;

    return function() {

        return a++;

    }

}

let counter = private(); 

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

Вот тут-то мне и стало непонятно: если функция отработала, то она должна была бы уничтожиться? Тогда в следующий раз заново бы создавалась и инициализировалась новая let a = 0;? Тогда о каком счетчике может быть речь?

Ответ пришлось поискать, и вот он: объект существует пока существует ссылка на него. И здесь мы имеем, что да, функция private() отработала, но внутренняя по отношению к ней функция продолжает существовать, поскольку в момент вызова private() её присвоили другому объекту (где она может ожидать своего вызова). А значит, и private() не уничтожена, а переменная изменила своё значение (в данном случае а = а+1)!

Если детализировать, то:

1. При вызове функции создается лексическое окружение (этой функции) - LexicalEnvironment, в котором, например, будут искаться переменные, если они не были найдены локально внутри. Грубо говоря, это внешняя область видимости по отношению к данной функции.

2. Также создании любая функции получает скрытое свойство [[Environment]], которое ссылается на её окружение (и тем самым как бы "запоминает" его). Для внутренней функции окружением будет внешняя функция с теми значениями переменных, которые на данный момент в ней есть.

То есть в момент вызова counter() значение переменной а будет находится во внешней по отношению к ней private(), и равняться это значение будет тому, которое существует на момент очередного вызова counter(). Другими словами, каждый новый counter() будет находить новую переменную а в своем окружении (имеющую то значение, которое осталось в результате предыдущего вызова counter()). Вот вам и счетчик.

Подробнее - здесь.

четверг, 12 ноября 2020 г.

A programmer: JavaScript #21. Event loop + Promises

JavaScript - однопоточный язык, то есть у него один стек, следовательно, только одна комманда может быть выполнена в единицу времени. Но если у тебя только один поток, как у JavaScript, это может привести к серьёзным задержкам. Проблема с однопоточностью решается "асинхронностью". То есть JavaScript использует дополнительные ресурсы браузера или NodeJS или какого-либо другого окружения, кроме собственно основного движка, для того, чтобы иметь возможность что-то делегировать этим ресурсам и не ждать окончания одной операции, чтобы приступить к следующей.

Это реализуется через "цикл событий" ("event loop"):

  1. Когда функция вызывается, она загружается в стек.
  2. Но потом она начинает выполняться в "дополнительных ресурсах" пока не выполнится до конца.
  3. Пока она выполняется "в стороне", другие функции из стека могут быть в него загружены.
  4. Когда функция выполнена, она возвращается сначала в "очередь на возвращение" ("task queue") и обратно в стек.

Event loop - потому что JavaScript циклом мечется между стеком, и "очередью", проверяя, 1) пустой ли стек, и если стек пустой, то 2) есть ли в очереди то, что нужно возвращать. И если ещё нету, бежит дальше по кругу, если есть - помещает это (то, что первое в очереди) в стек.

И здесь есть большая проблема: часто мы не можем знать, в какой очередности будут выполняться функции. То есть что выполнится первым - то, что идет следующим в коде или то, что вернется из очереди?

Так вот, чтобы избежать синхронности придумали колбеки ("callback"). Колбек - это функция, которая передается в качестве параметра в другую функцию, если нужно, чтобы она была выполнена после той, в которую передана (или в нужном месте внутри). Например:

function callback() {

    console.log('I am callback!');

};

let a = 'I am a parameter of anotherFunction!';

function anotherFunction(a, callback) {

    console.log(a);

    callback();

}

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

Чтобы его избежать, придумали (например) промисы ("promises").

Промис - это объект, который "обещает" выполнить то, что внутри. Он принимает функцию, которая имеет параметры resolve и reject, которые, соответственно, вызываются в случае успешного или неуспешного выполнения (вызываются с необходимыми параметрами). То есть, промис не только имеет возвращаемое значение той функции, которая выполнялась внутри него, но и состояние, успешно или нет прошло выполнение. И это состояние можно использовать - в случае неуспешного выполнения - ловить ошибку, добавив к промису через точку catch(...), а в случае успешного - вызывать следующую функцию, добавив к промису через точку then(...). Ну и соответственно, можно промисы цеплять в цепочку один за одним, если принципиально последовательное выполнение определенных функций.

И поскольку я вчера тупил, и не смог написать промис на собеседовании, то вот пример:

let promise = new Promise(function(resolve, request) {

    let data = 5 + 3;

    resolve(data);

}).then(function(data) {

     console log(data + 125);

});

Как-то так.

понедельник, 9 ноября 2020 г.

A programmer: JavaScript #20. Pattern "Observer"

В общих чертах петтерн "observer" (обозреватель, наблюдатель) предполагает, что есть некий объект, который меняет своё состояние и оповещает об этом тех, кто подписан на уведомления (subscribers). Применительно к React'у это более, чем актуально, поскольку при изменении состояния (данных), компоненты должны перерисовываться, а значит, должны следить за изменениями сообветствующих данных.

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

А вот как: 

С одной стороны, файл, где происходит отрисовка компонентов (допустим, index.js) вызывает rerender() и передает туда state, который предварительно импортирует:

rerender(state);

То есть index.js зависит от state'а, как и положено.

Но index.js также вызывает метод subscribe и передает туда вызов свой rerender():

subscribe(rerender);

Теперь rerender() может быть вызван прямо в state, при этом state от него не зависит, а только использует реализацию.

С другой стороны, при изменении state вызывает callSubscriber(), но его реализацию он получает в распоряжение из метода subscribe():

// некоторые изменения данных

callSubscriber();

В самом state он описывается приблизительно так:

export const subscribe = (observer) => {
     rerender = observer;
}

То есть теперь callSubscriber(), вызываемый в state, - это тот самый rerender(), который реализован в index.js.

Следовательно, теперь при любом изменениии state, он вызывает метод перерисовки, который он получил через subscribе. Это означает, что state по-преженему не зависит от UI, потому что ему всё равно, как реализована перерисовка - он её только вызывает, но не импортирует.

P.S.: Обычно паттерн "observer" объясняют на примере Java. В некотором смысле оно понятнее, потому что там есть интерфейсы как отдельные сущности. Но вот мне помогло объяснение в исполнении Димыча.

воскресенье, 8 ноября 2020 г.

A programmer: JavaScript #19 The logic of React. Part 1

Снова про React. На этот раз вдохновился довольно объёмным курсом от Димыча (IT-KAMASUTRA, "Курс "React JS - путь самурая 1.0", уроки, практика") - он объясняет всё очень подробно и понятно, действительно большой молодец, рекомендую.

React – библиотека для фронтенда, то есть для удобной отрисовки страницы, которая должна быть видна в браузере. Собственно, пишу только об основных принципах и ключевых особенностях.

1. React используется для Single Page Application. «Классический вариант» работы с сайтом предполагает, что когда нужно показать что-то с данного сайта, браузер посылает запрос на сервер, и сервер присылает новую страницу. В свою очередь логика Single Page Application предполагает, что практически всё необходимое загружается в браузер сразу, и при запросах на новый контент уже сам браузер отрисовывает его, не обращаясь к серверу.

2. Для этого используется модульность и виртуальный DOM. Если DOM (Document Object Model) – это модель документа, то виртуальный DOM – это копия этой модели в памяти Reactа. В соответствии с виртуальным DOM’ом React «собирает» страницу из компонентов. Если нужно что-то перерисовать, он вносит необходимые изменения а нужный компонент, реагирует на изменения – поэтому и «React». В каждом компоненте есть метод render(), который, собственно, и отрисовывает его. Поэтому не затрагиваются все остальные элементы страницы, что обеспечивает быструю работу.

3. Сложность состоит в том, что слои отображения (User Interface (UI) – то, чем и являются компоненты) и бизнес-логика должны быть разделены. Изменения view предполагают операции с данными, но данные не должны храниться в самих компонентах – компоненты должны использовать только те данные, которые пришли из слоя бизнес-логики. Следовательно, их надо как-то передавать из уровня бизнес-логики в UI и обратно.

4. Из уровня бизнес-логики в UI данные передаются через props’ы – атрибуты компонентов. Они могут передаваться от родительских компонентов в наследников, в которых они становятся элементами state – состояния данного компонента.

5. Нюанс состоит в том, что если нужно передать props’ы на несколько уровней, то и прописывать их нужно на каждом уровне, что неудобно. Чтобы этого не делать, используют Context – некоторое хранилище данных. Компонент, в котором он создаётся, помещается в обёртку Context.Provider, который и передаёт необходимые props’ы, а остальные помещаются в обёртку Context.Consumer. Что означает, что они имеют доступ ко всем props’ам, которые предоставляет Context.Provider.

6. Для того, чтобы передать некоторые данные из UI на уровень бизнес-логики, в тех же props’ах компонентам передаются и необходимые методы. Сами методы прописаны на уровне бизнес-логики, но передаётся возможность их вызова.

7. На уровне бизнес-логики создают store – хранилище данных (состояний компонентов). С помощью переданных им методов компоненты передают туда данные. С помощью переданных компонентам props’ов компоненты перерисовывают себя – это постоянно работающий цикл. Такое «архитектурное решение» называется Flux. Для его реализации существуют «системы управления состоянием» («state management system»), наиболее известная из них – Redux.

8. В React возможет функциональный и объектно-ориентированный (ООП) подходы. В первом случае оперируют функциями, во втором – классами. Классы могут содержать и собственный state – состояние, и собственные функции. Если объект вызывает собственный метод, используется this. Но если мы передаем метод куда-либо, то контекст выполнения меняется, тогда this будет указывать на другой объект. Чтобы не происходило путаницы, метод привязывают к его контексту с помощью метода bind().

9. В Store кроме данных содержатся методы для работы с данными. Обычно их выносят в общий метод, называемый dispatch(), и передают ему (кроме необходимых данных) объект action, который имеет определенный тип. В зависимости от типа dispatch() выполняет нужный функционал. Это сокращает запись в компонентах (вместо того, чтобы прописывать разные отдельные методы).

 Продолжение следует.

пятница, 21 августа 2020 г.

A programmer: PHP #2 Странный WordPress

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




Но в админке WordPress'а категории товаров указаны нормальными человеческими словами, а тут, как мы видим, ID. Возникает вопрос, как соотнести названия категорий и их ID?

Ответ оказался весьма интересным:

"Как посмотреть ID категории?- Зайдите в Консоль-> Записи Рубрики, кликните на заданную рубрику и в адрресной строке после ID= будет номер категории"

Огромное спасибо автору, а полный текст статьи здесь.



понедельник, 3 августа 2020 г.

A programmer: JavaScript #18 Heroku

Пару слов об опыте решения проблемы, которая, в общем, оказалась проблемой невнимательности (как часто бывает). Дело в том, что запушенное мной на Heroku приложение, написанное на React'e, не запускалось. Смотрел логи, гуглил ошибки и прочее - непонятно. В итоге оказалось, что не подумал о двух вещах. Во-первых, для запуска вебприложения нужен вебсервер! Вот ведь новость какая :) Написал, добавил в проект. Во-вторых (и это было неочевидно), его нужно было явно прописать в Procfile'e. Значит, надо его создать в нем написать (в моем случае):

web: node server.js

Где web - тип контейнера, server.js - название файла с сервером. И еще: чтобы не заморачиваться с отдельным гитом для Heroku, можно подключить собственный гитха, с которого он будет брать код, а потом либо вручную либо автоматически деплоить его. В документации это всё есть.


четверг, 9 июля 2020 г.

A programmer: JavaScript #17 React + Heroku

Хочется похвастаться. Я искал бесплатный или недорогой сервер, на котором можно было бы запускать Node.js и на нем всё остальное. Давно слышал про Heroku, но только сегодня руки дошли разобраться - создал один тестовый проект прямо там и второй просто туда задеплоил, оба на React'е. Собственно, пересказывать, как это делать, смысла не вижу, поскольку есть очень понятный мануал: https://devcenter.heroku.com/articles/getting-started-with-nodejs. А ещё - отличное видео:



вторник, 7 июля 2020 г.

A programmer: JavaScript #16 React (vs. Angular)

Продолжаю метаться между JavaScript'ом и Data Science. В первом случае интересны работающие программы, во втором - извлечение информации. Имея в виду лучшые возможности найти работу, JavaScript побеждает. Поэтому решил разобраться с React'ом Angular'ом. Сегодня про React.


Итак, React - это фреймворк для web development'а. Ключевая особенность - модульность. То есть ты создаешь компоненты (куски твоего сайта) и вставляешь из в один общий элемент. Всё это с помощью JavaScript, разумеется:

 

Здесь функция render получает параметры 1) что вставлять и 2) куда вставлять. Сами вставляемые компонеты структурно состоят из двух файлов, один из которых отрисовывает кусок страницы, а второй - стили к нему:


То же самое можно делать не через функции, а через классы. При отрисовке компонента на странице можно передавать специфические для него данные (props), которые передаются в конструктор как параметры. Значения внутри компонента (класса) называются state. По сути, это локальная пересенная (объект), для доступа к которому извне, соответственно, нужны сеттеры и геттеры. Ну и плюс особенности маршрутизации (свой js-пакет) и синтаксиса (jsx). В общем, мне понравилось - ничего сложного.

В Angular, в свою очередь, тоже модульность, тоже особенности синтаксиса и маршрутизации, но:
 - очень большой фреймворк - занимает много места;
 - его надо отдельно запускать (кроме веб-сервера на node.js, например);
 - долго запускается;
 - очень зависит от настроек - и своих, и браузера (в этом месте у меня случился затык, поэтому дальше я пока не пошел).

Пока что так.

вторник, 2 июня 2020 г.

Data Science mini-courses - Done

Во время карантина прошел 6 миникурсов по Data Science на http://www.datacamp.com/:









воскресенье, 31 мая 2020 г.

Facebook sharing problem solved

Вчера столкнулся с проблемой: при расшаривании вебстраницы в Фейсбуке превьюшка отражала неправильную информацию. Мне посоветовали A Guide to Sharing for Webmasters. И за это спасибо, потому что там есть информация о том, как сделать правильно. Если коротко, но надо прописать нужные property в meta в head сайта, что я и сделал. Но! Ничего не менялось!

Потому что фейсбуковский краулер, который индексирует страницы, посещает их раз в 30 дней. Но есть выход! На странице Sharing Debugger вы не только можете посмотреть, какую информацию проиндексировал краулер, и как давно, но и нажать кнопочку "Scrape again" - и он проиндексирует вашу страницу прямо сейчас. Solved.

понедельник, 20 апреля 2020 г.

Карантин и интроверты

Вообще-то карантин для меня обернулся, скорее, благом, чем злом по разным причинам (по крайней мере, пока). Среди прочего, потому, что я интроверт, и мне обычно не надо много общения - в большинстве случаев социальных сетей и мессенджеров мне вполне хватает. Плюс моя работа - это работа за компьютером, в основном. Но, как известно, работа дома оказывается сложной потому, что сложно переключаться в рабочее состояние. Так вот, на прошлой неделе я натолкнулся на интересное - один товарищ стримил свой рабочий процесс из дома. Не то, что именно он делал, а сам процесс сидения за компьютером, чего-то делания, слушания фоном музыки, периодических отлучек из-за стола и т.д. То есть того, что ты мог бы наблюдать, работая в офисе. Имея к тому же возможность этот виртуальный офис выключить в любой момент, такой стрим - идеальный способ войти в рабочее состояние: "Вот он что-то делает, а я-то что тунеядствую?!" Жаль, что зрителей было мало, и товарищ прекратил эту практику. Так кто же этот таинственный незнакомец? Рекомендую - youtube-канал АйТиБорода. Там периодически встречаются интересные интервью. Мне вот, например, понравилось:


среда, 25 марта 2020 г.

Снова про git


Когда-то я писал про основы git: https://myownselfdevelopment.blogspot.com/2018/09/a-programmer-javascript-8.html. Есть необходимость кое-что добавить.

Например, мне пришлось переключаться с githab'a на gitlab. Это оказалось несколько нетривиальной задачей почему-то. В итоге оказалось, что надо просто переназначить url:

git remote set-url origin https://gitlab.com/oleksiy76/phpwebapp.git

А посмотреть, куда ты подключен можно так:

git remote -v

UPD: Ещё один неплохой курс про git:


How to work from home

На самом деле это просто перепост видео:



Эти советы очень часто повторяются, но к ним Стив Павлина, например, добавляет ещё один. Я сейчас быстро не нашел ссылку, где именно об этом говорит - можете поискать здесь: https://www.stevepavlina.com/. Совет такой: натренируйте себе "bad eye" - строгий взгляд, которым вы будете отпугивать домашних, когда они будут приходить отвлекать вас (а они будут).


суббота, 29 февраля 2020 г.

A programmer: PHP #1

Проблема с тем, что бесплатный хостинг доступен почти исключительно на Apahe и заточен под PHP и MySQL, решилась тем, что пришлось разбираться с этим стеком.

Во-первых, учил PHP, точнее, переписывал свой сайт, где это было необходимо. Всё, на самом деле, довольно просто - прописываешь кусок кода прямо внутри вёрстки, что удобно, подключаешь куда надо другие файлы. Единственное, с чем бился долго - это проверка длины имени при вводе в форму, но только потому, что долго не мог правильно сформулировать запрос. Дело в том, что у меня уже было это реализовано на JavaScript'e - жалко было отказываться, но никуда не денешься. Плюс хотелось, чтобы всё это проверялось без перезагрузки страницы. JavaScript'овые варианты выходили как-то криво, плюс они ведь работают только на клиенте, а мне нужно было, чтобы была связь с сервером. Оказалось, нужны AJAX-запросы - разобрался с ними.

Во-вторых, устанавливал локально всё - Apahe, PHP, MySQL и phpMyAdmin. С MySQL долго бился, потому что имя моего компьютера содержало кириллические буквы. А с phpMyAdmin - потому что настройки шифрования клиента (phpMyAdmin ) и сервера не совпадали (MySQL). Но в итоге всё получилось, и я доволен собой в конце концов.