Translate

Поиск по этому блогу

Показаны сообщения с ярлыком Babel. Показать все сообщения
Показаны сообщения с ярлыком Babel. Показать все сообщения

вторник, 26 февраля 2019 г.

React + Webpack 4 + Babel 7 Руководство по установке.

Это руководство для тех, кто ищет свои способы настройки среды React, Webpack и Babel.





Это руководство относится к последним версиям React 16, Webpack 4 и Babel 7.

Facebook создал и поддерживает готовое приложение - creat-react-app, которое уже включает все необходимые настройки и отлично подходит для начинающих разработчиков.

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

Создание структуры.

Убедитесь, что у вас установлены Node.js и NPM.

node -v npm -v


Результат:



Если не установлены, то установите с официального сайта.

Я работаю под Windows -8 и в редакторе VS-Code.

Перейдите в нужную вам директорию и создайте основную папку для вашего проекта. У меня это будет папка react-min-setup

mkdir react-min-setup
cd react-min-setup


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

npm init -y


Вы можете извлечь файл package.json после инициализации вашего проекта как проекта npm. Он должен быть заполнен вашими значениями по умолчанию. Если вы хотите изменить настройки по умолчанию, вы можете просмотреть и изменить их с помощью следующих команд в командной строке:

npm config list

npm set init.author.name ""
npm set init.author.email "you@example.com"
npm set init.author.url "example.com"
npm set init.license "MIT"


После настройки вашего проекта npm, вы можете установить пакеты узлов (библиотеки) в свой проект с помощью самого npm. После установки нового пакета узла, он должен появиться в вашем файле package.json .

Я это сделаю из терминала редактора.



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

index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>React + Webpack 4 + Babel 7 </title>
</head>
<body>
    <div id="app"></div>
    <script src="./bundle.js"></script>
</body>
</html>



В файле ничего особенного. Есть корневой див, в котором будет размещаться весь React - проект и подключен файл bundle.js из этой же папки dist, в который и будут собираться все файлы нашего проекта, с помощью webpack.

Два важных факта о содержании:

файл bundle.js будет сгенерирован Webpack
Атрибут id = "app" поможет нашему корневому компоненту React найти точку входа

Поэтому наши следующие возможные шаги:
  1. настроить Webpack для объединения наших исходных файлов в один файл как bundle.js
  2. построить наш первый корневой компонент React, который использует точку входа id = "app"

На этом этапе все файлы проекта доступны в гит-репо react-min-setup-abc ci -m "Initiall commit layout project"

Настройка Webpack

Вы будете использовать Webpack в качестве модуля сборки и инструмента построения приложения. Более того, вы будете использовать webpack-dev-server для обслуживания вашего приложения в локальной среде. В противном случае вы не сможете увидеть его в браузере для его разработки. И последнее, но не менее важное: вам понадобится пакет узла webpack-cli, чтобы позже настроить конфигурацию Webpack в файле конфигурации. Давайте установим все три пакета узлов, используя npm.

Из корневой папки:

npm install --save-dev webpack webpack-dev-server webpack-cli


Теперь у вас должна быть папка node_modules, где вы можете найти сторонние зависимости. Зависимости также будут перечислены в файле package.json , так как вы использовали флаг –save-dev . Ваша структура папок должна выглядеть следующим образом:

Структура папки:

 - dist
 - - index.html
 - node_modules
 - package.json


В файле package.json вы можете добавить стартовый скрипт (выделил красным) дополнительно к заданным по умолчанию скриптам для запуска webpack-dev-server.

package.json

 "scripts": {
    "start": "webpack-dev-server --config ./webpack.config.js --mode development",
    "test": "echo \"Error: no test specified\" && exit 1"
  },



В файле появились установленные зависимости:



Сценарий определяет, что вы хотите использовать webpack-dev-server с файлом конфигурации с именем webpack.config.js . --mode development это Флаг, который просто добавляет WebPack по умолчанию конфигурации , которые пришли с Webpack 4. Вам не нужен флаг для Webpack 3.

Давайте создадим необходимый файл webpack.config.js .

module.exports = {
    entry: './src/index.js',
    output: {
      path: __dirname + '/dist',
      publicPath: '/',
      filename: 'bundle.js'
    },
    devServer: {
      contentBase: './dist'
    }
  };



Грубо говоря, в конфигурационном файле сказано, что:
  1. мы хотим использовать файл src / index.js в качестве точки входа для объединения всех импортированных файлов.
  2. Связанные файлы приведут к файлу bundle.js, который
  3. будет сгенерирован в нашей уже настроенной папке / dist . Эта папка будет использоваться для обслуживания нашего приложения.


В нашем проекте отсутствует папка и файл src / index.js . Создадим их. В файл index.js добавим, какой - нибудь вывод в консоль. Например:


   console.log('My Minimal React Webpack Babel Setup');



Структура проекта:

 - dist
  - - index.html
 - node_modules
 - src
  - - index.js
 - package.json
 - webpack.config.js


Теперь вы сможете запустить свой webpack-dev-server.

npm start


По умолчанию, проект запустится на порту 8080. И если посмотрим в консоль, то увидим наше сообщение.



Сейчас, вы подаете свое приложение через Webpack прямо в браузер. Вы связываете файл точки входа src / index.js как bundle.js , используете его в dist / index.html и можете увидеть его console.log()в консоли разработчика.

Пока это только файл src / index.js . Но позже вы импортируете больше файлов JS в этот файл, который автоматически будет упакован Webpack в файл bundle.js, который и будет создан.

На этом этапе все файлы проекта доступны в гит-репо react-min-setup-abc
ci -m "Webpack installation and setup"

Настройка Babel

Babel позволяет вам писать свой код с помощью JavaScript, который еще не поддерживается в большинстве браузеров. Например: JavaScript ES6 (ES2015) и более поздних версиях . С помощью Babel код возвращается обратно в стандартный JavaScript, так что каждый браузер, не имеющий всех реализованных функций JavaScript ES6 и не только, может его интерпретировать. Чтобы заставить Babel работать, вам нужно установить две его основные зависимости.

Из корневой папки:

npm install --save-dev @babel/core @babel/preset-env


Кроме того, чтобы подключить его к Webpack, вам необходимо установить так называемый загрузчик ("лодырь" - 😉 ):

npm install --save-dev babel-loader


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

Из корневой папки:

npm install --save-dev @babel/preset-react


Теперь, когда все пакеты узлов установлены, вам нужно настроить файлы package.json и webpack.config.js так, чтобы они соответствовали изменениям Babel.

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

package.json


{
  "name": "react-min-setup",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "start": "webpack-dev-server --config ./webpack.config.js --mode development",
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "Yaroslav",
  "license": "ISC",
  "babel": {
    "presets": [
      "@babel/preset-env",
      "@babel/preset-react"
    ]
  },
  "devDependencies": {
    "@babel/core": "^7.3.3",
    "@babel/preset-env": "^7.3.1",
    "@babel/preset-react": "^7.0.0",
    "babel-loader": "^8.0.5",
    "webpack": "^4.29.5",
    "webpack-cli": "^3.2.3",
    "webpack-dev-server": "^3.2.0"
  }
}



webpack.config.js


module.exports = {
    entry: './src/index.js',
    module: {
      rules: [
        {
          test: /\.(js|jsx)$/,
          exclude: /node_modules/,
          use: ['babel-loader']
        }
      ]
    },
    resolve: {
      extensions: ['*', '.js', '.jsx']
    },
    output: {
      path: __dirname + '/dist',
      publicPath: '/',
      filename: 'bundle.js'
    },
    devServer: {
      contentBase: './dist'
    }
  };



Вы можете снова запустить приложение. Ничего не должно было измениться, за исключением того, что теперь вы можете использовать будущие функциональные возможности ECMAScript для JavaScript.

Я просто допишу в файл src/index.js, что-то такое, например:


   console.log('My Minimal React Webpack Babel Setup');

   const obj={name:'Yaroslav', age: 48, id:1};
   let {name} = obj;
   console.log(name);


Запускаем проект:

npm start


Идем на 8080 порт и в консоли видим:



Необязательный шаг - извлечь конфигурацию Babel в отдельный файл конфигурации .babelrc


Создаем файл .babelrc в корне проекта.

Теперь вы можете добавить конфигурацию для Babel, которую вы ранее добавили в свой package.json (в коде файла выше это красным выделил) , в файл .babelrc . Не забудьте удалить конфигурацию из package.json позже.
Это должно быть настроено только в одном месте!
.babelrc


{
  "presets": [
    "@babel/preset-env",
    "@babel/preset-react"
  ]
}



Babel позволяет вам использовать будущий JavaScript в вашем браузере, потому что он превращает его в ванильный JavaScript. Теперь вы настроены на создание своего первого компонента React.

На этом этапе все файлы проекта доступны в гит-репо react-min-setup-abc
ci -m "Babel installation and setup"

Настраиваем React

Чтобы использовать React, вам нужно еще два пакета узлов. Пакеты установим через npm.

Из корневой папки:

npm install --save react react-dom


В вашем src / index.js вы можете реализовать свою первую запись в мире React.

src / index.js

import React from 'react';
import ReactDOM from 'react-dom';

const title = 'My Minimal React Webpack Babel Setup';

ReactDOM.render(
  <div>{title}</div>,
  document.getElementById('app')
);



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

ReactDOM.render нужны два параметра. Первый параметр - это ваш JSX. У него должен быть всегда один корневой узел.

Второй параметр - это узел, к которому должен быть добавлен ваш вывод. Помните , когда мы использовали <div id="app"></div> в / index.html файл? Этот же идентификатор - ваша точка входа в React.



На этом этапе все файлы проекта доступны в гит-репо react-min-setup-abc
ci -m "React installation and setup"

Hot Module Replacement

Очень полезный пакет, который позволит вам значительно упростит разработку и сократит время. Когда вы что-то меняете в исходном коде, эти изменения будут применяться в вашем приложении, запущенном в браузере, без перезагрузки всей страницы . Более подробно, на странице приложения - react-hot-loader

Из корневой папки:

npm install --save-dev react-hot-loader


Вы должны добавить еще несколько настроек в ваш файл конфигурации Webpack.

webpack.config.js

const webpack = require('webpack');
module.exports = {
    entry: './src/index.js',
    module: {
      rules: [
        {
          test: /\.(js|jsx)$/,
          exclude: /node_modules/,
          use: ['babel-loader']
        }
      ]
    },
    resolve: {
      extensions: ['*', '.js', '.jsx']
    },
    output: {
      path: __dirname + '/dist',
      publicPath: '/',
      filename: 'bundle.js'
    },
    plugins: [
      new webpack.HotModuleReplacementPlugin()
    ],
    devServer: {
      contentBase: './dist',
      hot: true
    }
  };



Кроме того, в файле src / index.js вы должны указать , что горячая перезагрузка доступна и должна использоваться.

SRC / index.js

import React from 'react';
import ReactDOM from 'react-dom';

const title = 'My Minimal React-16 Webpack- 4  Babel Setup';

ReactDOM.render(
  
{title}
, document.getElementById('app') ); module.hot.accept();


Теперь вы можете запустить свое приложение снова.

Из корневой папки:

npm start


Когда вы меняете свой title в компоненте React в файле src / index.js , вы должны увидеть обновленный вывод в браузере без перезагрузки браузера. Если вы удалите module.hot.accept();строку в консоли, то браузер выполнил перезагрузку. То есть, если что-то изменилось в коде, изменения применились!

На этом этапе все файлы проекта доступны в гит-репо react-min-setup-abc ci -m "Installation and setup Hot Module Replacement"

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

Успехов и хорошего кодинга!



                                                                                                                                                             

Телеграм канал - Full Stack JavaScript Developer

пятница, 21 декабря 2018 г.

Бэкенд на Node+Express+MongoDB

Сегодня мы создадим бэкенд-часть приложения на стэке NodeJS+ExpressJS+MongoDB



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

Я уже рассказывал о подобных приложениях своих постах - Блог на NodeJS Express MongoDB

Главное отличие этого поста будет в использовании собственной, локально установленной базы MongoDB и я постараюсь не повторяться.

Нам потребуется установленная платформа Node.js и менеджер пакетов NPM. О том как их скачать, установить и настроить я рассказывал в своих постах ранее - Простые Советы - JAVASCRIPT.

Для того чтобы убедиться что у вас все установлено и настроено правильно выполним последовательно в КС (терминал - командная строка) следующие команды:

node -v
npm -v
mongod --version


Увидим что-то подобное.



У вас будут свои версии.

Если MongoDB не установлена, то последняя команда выдаст ошибку. В этом случае вам нужно перейти на официальный сайт MongoDB и установить нужную версию локально. Это просто и я на этом останавливаться не буду.

Для того, чтобы запустить сервер базы данных, нам нужно ввести в КС следующую команду:

mongod


Вы увидите, что то похожее:



Нам интересно последняя строчка выделенная красным. Она говорит о том. что база готова к работе и запущена на порте - 27017

Не закрывая это окно команд. Откроем еще одно - ⊞ Win + R Введем - cmd и нажмем Enter.

В этом окне введем последовательно команды:

mongo
show dbs




Получим список всех существующих баз данных.

Для того, чтобы остановить работу сервера нам нужно нажать сочетание клавиш Ctrl + C. Для остановки локального сервера (на будущее) требуется ввести еще и подтверждение - y. Затем- нажать Enter.

Перейдем к разработке серверной части приложения.

Мы будем использовать фреймворк Express

Вначале создадим папку нашего проекта и перейдем в нее:

mkdir server-side
cd server-side


Если вы используете Git для разработки, то я рекомендую сразу создать файл .gitignore, куда сразу добавить папку с модулями ноды - node_modules.

echo node_modules/ >> .gitignore




Если вы работаете в VS-code, то введите:

code .


Или иным способом откройте папку в вашем любимом редакторе кода.

В дальнейшем я буду использовать терминал VS-code, но вы можете легко использовать и КС.

Инициализация приложения

На этом этапе мы создадим папку package.json - со всеми зависимостями.

npm init


Или с флагом -y.

Об этом я очень подробно рассказывал в посте Блог на NodeJS Express MongoDB ( I ).

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



Устанавливаем Express

Для этого в КС (терминале), находясь в рабочей папке проекта:

npm install express --save


Установится фреймворк и добавится в зависимости нашего проекта - package.json



Файл index.js - точка входа.

Так как, мы когда инициализировали наш проект (создавали файл package.json), оставили по умолчанию точку входа - "main": "index.js", то нам нужно создать файл index.js в корне нашего проекта.

В нем мы сразу подключим фреймворк Express методом require. Здесь же создадим константу app, которая будет выполнять серверную часть нашего приложения.


 const express = require('express');
 const app = express();



Добавим метод get, которым будем выводить все посты на страницу по запросу на адрес:
http://localhost:3000/posts
И поставим прослушивание порта нашим сервером:


app.get('/posts', function(req, res) {
     return res.send(posts);
 });

app.listen(3000, ()=> console.log('Server running on 3000 port'));



Все вместе index.js:


 const express = require('express');
 const app = express();
 
  app.get('/posts', function(req, res) {
     return res.send(posts);
 });
 
  app.listen(3000, ()=> console.log('Server running on 3000 port'));



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

Создание тестовых записей

В файл index.js, сразу после инициализации сервера ( константа app), добавим константу posts с тестовыми записями наших постов.


  const posts = [
     {
         title:  "lorem ipsum1",
         text: "Lorem ipsum dolor sit amet Lorem ipsum dolor sit amet consectetur adipisicing elitconsectetur adipisicing elit. Pariatur fugit fuga ut voluptas nostrum ullam eum accusantium consequuntur necessitatibus dolores. Pariatur hic officiis numquam ipsam perspiciatis officia maxime iusto vitae."
     },
     {
         title:  "lorem ipsum2",
         text: "Lorem ipsum dolor sit amet  Pariatur fugit fuga ut voluptas nostrum ullam eum accusantium consequuntur necessitatibus dolores. Pariatur hic officiis numquam ipsam perspiciatis officia maxime iusto vitae."
     },
     {
         title:  "lorem ipsum3",
         text: "Lorem ipsum dolor sit amet consectetur adipisicing elit. Pariatur fugit fuga ut voluptas nostrum ullam eum accusantium consequuntur necessitatibus dolores. Pariatur hic officiis numquam ipsam perspiciatis officia maxime iusto vitae."
     },
     {
         title:  "lorem ipsum4",
         text: "Lorem ipsum dolor sitLorem ipsum dolor sit amet consectetur adipisicing elit amet consectetur adipisicing elit. Pariatur fugit fuga ut voluptas nostrum ullam eum accusantium consequuntur necessitatibus dolores. Pariatur hic officiis numquam ipsam perspiciatis officia maxime iusto vitae."
     }    
 ];



Запускаем сервер:

node index.js


Переходим по адресу: http://localhost:3000/posts



Видим все посты на странице.

У меня в браузере добавлено расширение для более красивого показа формата JSON - JSONView. У вас это может выглядеть просто строками, которые содержит переменная posts.

На этом этапе я инициализировал git и добавил все изменения в репозиторий на сайте gitHub.com - server-side-abcinblog ci -m (здесь и далее - коммит) "output all tests posts"

Теперь можно сделать вывод единственного поста на страницу по id

Для этого мы добавим метод get с двумя параметрами. Первый - путь, где через /:id мы указываем изменчивый параметр и получаем его значение из строки запроса const id = req.params.id;


app.get('/posts/:id', function(req, res) {
    const id = req.params.id;
    res.send(posts[id]);
});



Запускаем сервер, переходим по адресу http://localhost:3000/posts/1 и видим:



Если изменить в адресной строке id поста (цифра отмечена красным), то мы увидим соответствующий пост. Нумерация постов начинается по id с нуля, а мы поставили первым постом не ноль, а "пост номер один", поэтому будет выглядеть так. Мне кажется. что так понятнее и более наглядно.

Теперь разберемся с созданием новой записи. Для этого нам потребуется еще одна библиотека - body-pareser, которая поможет нам получать данные из тела запроса.

Более подробно узнать о работе с этой библиотекой можно узнать из официальной документации на gitHub и здесь.

Подключаем ее обычным способом и используем ее для написания метода post

const bodyParser = require('body-parser');
// после инициализации const app
 app.use(bodyParser.urlencoded({ extended: true}));
 app.use(bodyParser.json());
// в методах:
 app.post('/posts', function(req, res) {
    // получаем данные из тела запроса и сохраняем в конст.
    const data = req.body;
    // посмотрим что у нас там? 
    console.log(data);
    // добавляем полученные данные к постам
    posts.push(data);
    // чтобы не было бесконечного цикла - вернем все посты на страницу
    return res.send(posts);
});



После внесения изменений в файлы проекта не забывайте перезапускать сервер.
Ctrl + C и снова

node index.js


Для проверки будем использовать утилиту Postman. Я уже много раз рассказывал вам о работе с ней в моих постах. Это легко, просто и удобно. Если забыли, то посмотрите в поиске по ярлыкам.

Итак. Идем в Postman делаем GET для всех постов. Посмотрели и убедились, что все работает:



Теперь выберем запрос POSTи во вкладке body введем данные для нашего поста в формате - JSON.



Нажимаем Send и получаем ниже список со всеми постами, включая новый.



А в терминале наш console.log(data) выведет эти данные так:



Подключение к базе данных MongoDB и добавление первой тестовой записи.

Для работы с MongoDB мы будем использовать стороннюю библиотеку - mongoose, помощью который мы будем производить все манипуляции с базой данных. Для установки библиотеке в терминале (КС), в папке нашего проекта напишем команду:

npm install mongoose


Перед тем как добавить первую теcтовую запись, запустим сервер MongoDB:

mongod


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

В новом окне терминала:

mongo
show dbs


Итак, вы получите список всех созданных локально баз данных.

Удалить локальную базу данных MongoDB

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

use test1


Поле этого ввести команду:

db.dropDatabase()


Всё! База данных удалена. Для того, чтобы убедиться в этом, выведем еще раз список всех доступных баз данных:

show dbs


Все действия вы можете увидеть на скрине ниже.



Создание новой базы данных MongoDB

Здесь ве еще проще, чем можно подумать. Для создания новой базы данных я взял полностью готовый код на сайте mongoose и добавил его в наш файл index.js, предварительно я все там закомментировал.


const mongoose = require('mongoose');
mongoose.connect('mongodb://localhost/'server-side');

const Cat = mongoose.model('Cat', { name: String });

const kitty = new Cat({ name: 'Zildjian' });
kitty.save().then(() => console.log('meow'));



Красным, отмечено название создаваемой базы данных. Его можно изменить на ваше усмотрение. Если коротко разобрать то, что делает наш код, то:
  1. На первой строке - мы подключаем саму библиотеку.
  2. Ниже мы подключаемся к серверу и указываем конкретную базу данных.
  3. Третьей строкой создаем модель - таблицу, указывая к ней конкретную схему.
  4. После этого мы создаем экземпляр с названием данных.
  5. Сохраняем эти данные и после их успешного сохранения, отображаем пользователю конкретную информацию.
Если сейчас запустить сервер:

node index.js


В терминале (КС) мы увидим meow, как на фото ниже:



Давайте проверим, наличие баз данных (в другом окне):

show dbs


то мы увидим вновь созданную базу:



Установка Babel

Babel - про эту библиотеку я уже много раз рассказывал в других постах, но стоит напомнить, что она нужна для того, чтобы мы могли писать код в новом стандарте не задумываясь над его совместимостью в различных браузерах. Короче говоря, он переводит код из ES6 в ES6. Для того, чтобы установить Babel, нам нужно установить четыре библиотеки. Сам Babel и различные пресеты.

npm install babel-cli babel-core babel-preset-env babel-preset-stage-0 --save-dev


  1. babel-core
  2. babel-cli
  3. babel-preset-stage-0
  4. babel-preset-env
На этом этапе все изменения вы можете посмотреть в репо - server-side-abcinblog ci -m"reate DB - local and test"

Для проверки работы установленных пакетов, мы можем удалить, или закомментировать весь код в файле index.js и добавить код написанный на ES6 для проверки:


const arr = [1, 2, 3, 4, 5, 6];
const result = arr.map(el => el * 3);
console.log(result);



Для работы наших пакетов нам нужно создать файл конфигурации - .babelrc в корне проекта


{
    "presets": ["env","stage-0"]
}



В скрипты, файла package.json добавлю скипт, который будет запускать Babel и переводить наши файлы из файла index.js в ES5 и складывать готовые файлы в папку (которую он сам и создаст) - dist


 "scripts": {
    "build": "babel  index.js -d dist",
    "test": "echo \"Error: no test specified\" && exit 1"
  },



Теперь, для запуска нам нужно набрать команду:

npm run build


После запуска, у нас появится новая папка dist



Для конкатенации массивов таким способом - [...arr1, ...arr2], мы установим Babel-plugin: babel-plugin-transform-object-rest-spread

npm install --save-dev babel-plugin-transform-object-rest-spread


Для того, чтобы не писать несколько команд сразу в терминале, мы внесем изменения в скрипты в файле package.json


  "scripts": {
    "build": "babel  index.js -d dist",
    "start":"node dist/index.js", 
    "build-start": "npm run build && npm run start"
  },



  1. Первая команда, ранее нами добавленная, конвертирует код.
  2. Вторая команда запускает конвертированный файл из папки dist.
  3. Третья команда выполняется предыдущие две сразу, вместе.
Запусти наш код:

npm run build-start


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



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

На этом этапе все изменения вы можете посмотреть в репо - server-side-abcinblog ci -m"Babel"

Для того, чтобы наш проект имел более правильную структуру, я в корне проекта создал папку src и перенес в нее файл index.js из корня. В файле package.json я изменил сроку build в scripts следующим образом:


  "scripts": {
    "build": "babel  src -d dist",
    "start":"node dist/index.js", 
    "build-start": "npm run build && npm run start"
  },



Можно еще раз запустить:

npm run build-start


чтобы убедиться, что все работает правильно.

Создание модели

В папке src создадим папку для наших моделей - models и в ней файл - Post.js. Это модель, которая будет работать с таблицами наших статей. Нам нужно импортировать сам mongoose и Schema из библиотеки mongoose. Описываем схему для нашего поста. Нам требуется заголовок, собственно текст и дата создания записи. С помощью свойства timestamps будут добавляться эти даты.


import mongoose, { Schema } from 'mongoose';

const PostSchema = new Schema(
    {
        title: String,
        text: String,
    },
    {
        timestamps: true
    }
);
const Post = mongoose.model('Post', PostSchema);

export default Post;



В конце мы экспортируем модель Post по умолчанию. Теперь нам нужно подключиться к базе данных и создать первую запись. В файле src/index.js я все удалю и добавлю


import mongoose from 'mongoose';

import PostModel from './models/Post';

mongoose.connect('mongodb://localhost/server-side');

const post = new PostModel({
    title: "Первая запись",
    text: "Привет Мир"
});

post.save().then(() => console.log('OK'));



Здесь мне кажется. все понятно. Импортировали mongoose и саму модель PostModel. Создали экземпляр модели и указали тестовые данные. Чтобы сохранить саму запись, мы обращаемся к методу save(), который возвращает Promise.

Перед тем. как запустить код, стоит проверить, что у нас отсутствует база данных.

Так как, я уже создавал такую базу, то я выполнил ее удаление.



Запускаем код:

npm run build-start


В консоли вы увидите:



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



Теперь выполним команды последовательно:
  1. use server-side
  2. show collections
  3. db.posts.find()




На этом этапе я сделал коммит и все изменения здесь - server-side-abcinblog ci -m"Connection with MongoDB and first tests record"

Запросы на добавление записи

В файле src/index.js подключим express и body-parser для обработки тела запроса.

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

Подключаем body-parser для нашего express- приложения.

ВАЖНО - подключение к базе данных располагать сразу после создания сервера - выше остального кода.

Создаем обработчик для приема и обработки POST запросов.

Теперь вместо тестовой записи, мы будем принимать реальные данные от клиента, которые мы сохранили в переменно data

Вместо ответа в консоли мы вернет ответ в виде JSON.

Последней строкой, ставим приложение на прослушивание по определенному порту. В моем случае - 3000.


import mongoose from 'mongoose';
import express from 'express';
import bodyParser from 'body-parser';
import PostModel from './models/Post';

const app = express();

mongoose.connect('mongodb://localhost/server-side');

app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json());

app.post('/posts', (req, res) => {
    const data = req.body;
    // console.log(req.body);
    const post = new PostModel({
        title: data.title,
        text: data.text
    });

    post.save().then(() => {
        res.send({ status: "OK"});
    });
});

app.listen(3000, () => console.log("Server running on 3000 port"));



Запускаем приложение.

npm run build-start


Для тестовых запросов мы продолжим использовать утилиту Postman

Делаем POST с тестовой записью и получаем статус- OK



Теперь убедимся, что запись появилась в базе данных. В консоли (mongo) сделаем еще один запрос:

db.posts.find()


И если все у вас прошло успешно то вы увидите - новую запись.



На этом этапе я сделал коммит и все изменения здесь - server-side-abcinblog ci -m"POST with Postman"

CRUD

GET - Обработчик для получения записей.

Выполнив метод Post.find() без параметров, мы получим все записи. И выполняем проверку ошибок в запросе. Это важно и нужно сделать везде.

//вверху файла к импортам добавим 
import Post from './models/Post';
// после post - запроса сразу
 app.get('/posts', (req, res) => {
     Post.find().then((err, posts) => {
         if(err){
             res.send(err);
         }
         res.json(posts);
     });
 });



Идем в постмен и делаем обычный GET - запос.



Теперь мы можем проверить и добавление записи, выведя потом все записи снова.

POST -запрос.



GET -запрос.



На этом этапе я сделал коммит и все изменения здесь - server-side-abcinblog ci -m"GET all posts"

DELETE - обработчик для удаления записей.

Здесь все просто. Мы будем использовать параметр id. Для удаления записи мы используем метод remove(), котоый принимает объект с параметрами. Проверяем, чтобы после выполнения запроса, запись была возвращена. Это будет говорить о том. что запись была успешно удалена из базы данных. Иначе - возвращаем ошибку.


 app.delete('/posts/:id', (req, res) => {
     PostModel.remove({
         _id: req.params.id
     }).then(post => {
         if(post) {
             res.json({ status: "deleted"});
         } else {
             res.json({ status: "error"});
         }
     })
 })



Теперь с помощью утилиты Postman отправим за сервер DELETE - запрос с id той записи, которую мы хотим удалить.

Сохраняем и перезапускаем сервер. Идем в Postman.

Я решил удалить вторую запись, поэтому скопировал ее id и подставил в адрес, сразу после слэша.



Нажал и получил:



Если сейчас выполнить GET всех постов, то получим:



Второго поста нет - он успешно удален.

На этом этапе я сделал коммит и все изменения здесь - server-side-abcinblog ci -m"DELETE post"

UPDATE - обработчик обновления записи.

Здесь мы будем использовать метод PUT, который принимает в параметрах id записи.

С помощью метода .findByIdAndUpdate() мы будем обновлять конкретную запись.

Первым параметром - id, вторым - объект со свойством set, которое хранит новые данные.

Не забываем про обработчик ошибок.


 app.put('/posts/:id', (req, res) => {
     PostModel.findByIdAndUpdate(req.params.id, {$set: req.body}, (err) => {
         if(err) {
             res.send(err);
         }
         res.json({ status: "update"});
     });
 });



Запускаем сервер и идем в Postman.

Здесь мы попытаемся обновить запись. Используем id.



Получили статус - status: "update"

Теперь, если мы опять выведем все посты методом GET, то мы увидим на месте второго поста - обновленные данные.



На этом этапе я сделал коммит и все изменения здесь - server-side-abcinblog ci -m"UPDATE post"

Контроллер.

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

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

Для начала в папке src мы создадим папку - controllers и уже в ней создадим файл - PostController.js.

Этот класс контроллера будет содержать пять методов, каждый из которых будет выполнять свою задачу. Так как, слушатель принимает вторым параметром функцию, о мы просто скопируем их из файлов (index.js. Пример:


    update(req, res)  {
        PostModel.findByIdAndUpdate(req.params.id, {$set: req.body}, (err) => {
            if(err) {
                res.send(err);
            }
            res.json({ status: "update"});
        });
    }




Красным выделил то, что скопировали, но удалили стрелочную функцию. Дополнительно мы создадим метод read(), который будет возвращать конкретную статью по ее id.


import PostModel from '../models/Post';
import Post from '../models/Post';
class PostController {
    index(req, res) {
        Post.find().then((err, posts) => {
            if(err){
                res.send(err);
            }
            res.json(posts);
        });
    }
    create(req, res) {
        const data = req.body;
        // console.log(req.body);
        const post = new PostModel({
            title: data.title,
            text: data.text
        });

         post.save().then(() => {
            res.send({ status: "OK"});
        });
    }
    read(req, res) {
        PostModel.findOne({ _id: req.params.id}).then(post => {
            if(!post) {
                res.send({ error:"nor found"});
            } else {
                res.json(post);
            }
        })
    }
    update(req, res)  {
        PostModel.findByIdAndUpdate(req.params.id, {$set: req.body}, (err) => {
            if(err) {
                res.send(err);
            }
            res.json({ status: "update"});
        });
    }
    delete(req, res)  {
        PostModel.remove({
            _id: req.params.id
        }).then(post => {
            if(post) {
                res.json({ status: "deleted"});
            } else {
                res.json({ status: "error"});
            }
        });
    }
};

 export default PostController;



Теперь подключим его в основной файл:

import mongoose from 'mongoose';
import express from 'express';
import bodyParser from 'body-parser';
import PostController from './controllers/PostController';
const Post = new PostController();
// import PostModel from './models/Post'; перенесли в контроллер.
// import Post from './models/Post'; перенесли в контроллер.
const app = express();

mongoose.connect('mongodb://localhost/server-side');

app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json());

app.get('/posts', Post.index);
app.get('/posts/:id', Post.read);
app.post('/posts', Post.create);
app.delete('/posts/:id', Post.delete);
app.put('/posts/:id', Post.update);

app.listen(3000, () => console.log("Server running on 3000 port"));



Функции запросов мы поменяли на методы из контроллера.

Напрямую обращаться к методам нельзя поэтому вверху файла мы создали экземпляр класса в отдельной переменной:

const Post = new PostController();

Теперь запускаем сервер и проверим все методы, через Postman, как мы это делали ранее.

Проверим создание поста, вывод всех постов, обновление и удаление.

На этом этапе я сделал коммит и все изменения здесь - server-side-abcinblog ci -m"Creating a controller"

Таким образом мы написали вся серверную часть нашего приложения.










                                                                                                                                                             

среда, 19 сентября 2018 г.

ES6: Классы (IX).

Классы в ES6

Классы являются основой объектно-ориентированное программирование но не в JavaScript.



Все материалы по ES6


В объектно-ориентированное программирование наследование основано на прототипах объектов, а не на классах.

Если вы когда-нибудь писали код на Java Script имитируя классы, ты уверен согласитесь синтаксис не самый элегантный и простой.

С появлением es6 JavaScript наконец-то добавлена поддержка классов. Новый синтаксис не вводит новую объектно-ориентированная модель наследования, внутри используется всё те же прототипы.

Синтаксис классов это так называемый syntactic Sugar или синтаксический сахар, который призван немного подсластить, то есть упростить работу с классами и наследованием в JavaScript.

Сегодня мы рассмотрим новый синтаксис классов, а в следующем посте - наследование.

Первое, что мы сделаем, это запустим скрипт Babel, который будет следить за файлами и при их изменении создавать свежие версии.

Откроем папку проекта в командной строке (КС). Вводим команду:

npm run watch


И нажать Enter

В папке src создадим файл classes.js и сразу укажу его в файле index.html

<script src="src/classes.js"></script>

HTML последние версии браузеров поддерживает класс без транспиляции, и мой браузер входит в их число, но тем не менее в конце, мы посмотрим на транспилированный код.

Начнем сначала а именно создание классов.

Создание классов

Класс это формы или шаблон по которому создаются объекты. Классы в JavaScript определяют свойства, то есть какой будет объект и методы - что этот объект будет делать. При создание классов используется ключевое слово class, после которого указывается имя класса. В качестве примера я создам класс названием Task - или задача. Тело класса находится в фигурных скобках и в нём будут находиться члены класса, методы и свойства. А в консоли мы посмотрим на класс используя оператор typeof.


class Task {

};

console.log( typeof Task );





В консоли мы видим function. Это означает, что классы это функции, которые создают объекты. Теперь перейдем к созданию объектов.

Объекты

Объект - это экземпляр или представитель класса.

То есть объект созданный по шаблону с определёнными свойствами и методами указанными в классе. Для создания объектов мы используем ключевое слово new.

После класса мы объявим переменную task с маленькой буквы и в качестве значения укажу new Task То есть мы вызываем функцию Task передний ней ключевое слово - new.

Теперь, давайте в консоли посмотрим на тип переменной task и также проверим является ли task, представителем класса Task -с большой буквы.

Мы можем это проверить используя оператор instanceof.


class Task {

};

let task = new Task();

console.log( typeof task );
console.log( task instanceof Task );





Мы видим, что переменная тоски является объектом или точнее, содержит ссылку на объект, и этот объект является представителем класса.

Конструктор.

Конструктор - это особый метод, который вызывается в момент создания объекта.

То есть когда мы используем ключевое слово new Он создаёт свойства и инициализирует. То есть подготавливает объект к использованию.

В классе может быть только один конструктор!

Если мы укажем несколько, то получим ошибку.

Если же мне укажем конструктор вообще-то JavaScript создаст пустой конструктор.

Для того чтобы объявить конструктор в теле класса пишем constructor() {} Внутри конструктора я выведу сообщение о том что происходит создание задачи.


class Task {
 constructor() {
  console.log('Происходит создание задачи');
 }
};

let task = new Task();

console.log( typeof task );
console.log( task instanceof Task );



Давайте посмотрим на результат браузере.



и мы увидим сообщение о создании задачи

тем самым мы увидели, что конструктор сработал.

Свойства

Свойства - это характеристики объекта.

Они описывают какой объект или что у него имеется.

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

Для того чтобы создать свойства у объекта, в конструкторе используется ключевое слово this, которое указывает на объект, который мы создаем.

Например у класса Task будет свойства title или заголовок, который будет содержать заголовок задачи.

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

"Выучить JavaScript"


class Task {
 constructor() {
  this.title = "Выучить JavaScript";
  console.log('Происходит создание задачи');
 }
};

let task = new Task();

console.log( typeof task );
console.log( task.title );



и в консоли давайте выведем значение title.



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

let task = new Task("Выучить JavaScript");

Далее, в конструкторе нам необходимо указать параметр title.

И давайте присвоим ему значение по умолчанию пустую строку.

И свойству при присвоении - значение параметра title.


class Task {
 constructor( title = '' ) {
  this.title = title;
  console.log('Происходит создание задачи');
 }
};

let task = new Task("Выучить JavaScript");

console.log( typeof task );
console.log( task.title );



И в консоли мы видим тот же самый результат.

Теперь мы можем создать вторую задачу и в качестве заголовка указать что-нибудь другое - номер "выучить ES6".


class Task {
 constructor( title = '' ) {
  this.title = title;
  console.log('Происходит создание задачи');
 }
};

let task = new Task("Выучить JavaScript");
let task2 = new Task("Выучить ES6");

console.log( typeof task );
console.log( task.title );
console.log( task2.title );





Давайте добавим классу Task ещё одно свойство которое будет называться done, в котором будет указываться выполнена задача или нет.

По умолчанию мы поставим false. То есть задачи по умолчанию будет не выполнена.

При создании объекта принимать аргумент done мы не будем.

Одно маленькое замечание - свойства указывается только в конструкторе! Если у вас есть опыт работы с другими языками и такими как Java, C++ или C# в которых свойство указывает отдельно от конструктора, а в конструкторе инициализируется, то в джаваскрипт свойство указываются исключительно в конструкторе!




Так как на фото выше мы сделать не можем!

Или убрать слово let и var или const всё это не будет работать!

Насколько я знаю это исправят в следующей версии JvaScript.

Далее мы рассмотрим создание методов методы.

Методы.

Методы это то что объект умеет делать, то есть его возможности.

По сути это функции, которые в классе называются методами.

Давайте добавим классу Task метод complete(){}, с помощью которого мы укажем что задача выполнена.

Чтобы указать метод мы пишем названия метода, после чего пара круглых скобок за ними пару фигурных скобок. В теле метода мы напишем this.done = true;

Заметьте что между методами в классах не ставится, если я поставлю то мы получим ошибку


И для того чтобы видеть результат - console.log(`Задача "${this.title}" выполнена!`);


class Task {
 constructor( title = '' ) {
  this.title = title;
                this.done = false;
  console.log('Происходит создание задачи');
 }
  complete() {
  this.done = true;
  console.log(`Задача "${this.title}" выполнена!`);
 }
};

let task = new Task("Выучить JavaScript");
let task2 = new Task("Выучить ES6");

console.log( typeof task );
console.log( task.title );
console.log( task2.title );

task2.complete();





В самом сообщении воспользуюсь шаблоны строкой.

Далее, придём к статическим свойствам и методам

Статические свойства и методы



Статические свойства.



Статические свойства - это свойства которые принадлежат самому классу, а не объектам, созданным на его основе.

Статические свойства часто используются для хранения вспомогательной информации и в отличие от многих других языков, например Java, C++ или C#, мы не можем Объявлять статические свойства используют ключевое слово static.

Если мы попробую написать будет ошибка.



Так что же делать если статическая переменная мы не можем объявить о самом классе?

В самом деле это делается очень просто.

После объявления класса, мы пишем название класса и далее, так как функции в JavaScript являются такими же объектами, как и всё остальное, мы можем просто присвоить свойство.

И сразу укажем значение.

И в конструкторе при создании задачи мы давали Task.count += 1;

И после того как мы создали задачу...

class Task {
 constructor( title = '' ) {
  this.title = title;
  this.done = false;
  Task.count += 1;
  console.log('Происходит создание задачи');
 }
  complete() {
  this.done = true;
  console.log(`Задача "${this.title}" выполнена!`);
 }
};

Task.count = 0; 

let task = new Task("Выучить JavaScript");
let task2 = new Task("Выучить ES6");


console.log( task.title );
console.log( task2.title );

console.log( Task.count );
task2.complete();



Давайте вывезем значение в консоль. Оно должно равняться двум.



И действительно, мы видим 2.

Статические методы.

Статические методы это методы которые принадлежат самому классу, а не объектам созданным на его основе.

Статические методы часто используются для создания вспомогательных функций.

Давайте добавим Task статический метод.

Для того чтобы создать статический метод убежим ключевое слово static и дальше название метода.

Статический метод getDefaultTitle() с помощью которого мы сможем получить значение заголовка по умолчанию если тот не был передан. Поэтому в теле метода мы просто вернем слово "Задача".


 static getDefaultTitle() {
   return "Задача";
 }



теперь в конструкторе мы можем указать ->


class Task {
 constructor( title = Task.getDefaultTitle() ) {
  this.title = title;
  this.done = false;
  Task.count += 1;
  console.log('Происходит создание задачи');
 }
 get done() {
  return this.done === true ? 'Выполнено' : 'Не выполнено';
 }
 complete() {
  this.done = true;
  console.log(`Задача "${this.title}" выполнена!`);
 }
 static getDefaultTitle() {
   return "Задача";
 }
};

Task.count = 0; 

let task = new Task("Выучить JavaScript");
let task2 = new Task("Выучить ES6");
let task3 = new Task();

console.log( task.title );
console.log( task2.title );
console.log( task3.title );

console.log( Task.count );
task2.complete();



Давайте создадим задачу 3 без аргументов посмотрим на результат.



И мы видим что заголовок задачи 3 просто задача.

Если мы попытаемся вызвать метод .getDefaultTitle() у образца объекта которые мы сохранили в переменной task или task2 - не важно, то мы получим ошибку!

Давайте попробуем так - task.getDefaultTitle();

Мы получим ошибку Uncaught TypeError: task.getDefaultTitle is not a function.То есть у объектов task этого метода нет!

Единственный способ получить к нему доступ - использовать название самого класса!

У классов, помимо свойство методов можно добавить особые свойства get и set.

Особые свойства get и set.

Особые свойства get и set еще называются геттер и сеттер которые внутри класса выглядит ведут себя как методы а снаружи выглядит и ведут себя как свойства.

эти свойства - методы позволяют получить доступ и присвоить значение "настоящим свойствам объекта". То есть выступать в роли фильтра.

Давайте добавим свойства get и set классу - Task.

Для начала я немного почищу код. Удалю все созданные объекты и их выводы, кроме одного - task.

Итак начнем.

Get или гетер.
Если вывести в консоль значения console.log(task.done); то мы увидим false.



И если задача была бы выполнена тогда true.

Эти значения не совсем понятны простым пользователям. Было бы неплохо если бы при обращении к свойствам появлялось понятное сообщение.

Эту проблему можем решить используя свойство Get.

Давайте добавим классу Task это свойство.

Для этого в классе после конструктора я напишу слова get далее - название done, пару кругу скобок и пару фигуры скобок. Очень похоже на метод.

Но на самом деле это и есть метод.

Свойство get связывает свойства объекта с функцией, которая будет вызываться при обращении к этому свойству или методу.

В теле метода мы вернём строку в соответствии со значением свойства done.

Если done будет равняться true, то мы вернем одно значение если false то другое.

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



Которая говорит нам о том что не удалось указать свойство get .

Дело в том что название свойств Get и Set не должны совпадать с названием основных свойств объекта!

В нашем примере объявляя свойство get done() мы перезаписываемый значение done которое изначально указанно в конструкторе.

Есть несколько способов решить эту проблему и все они сводятся к переименование названий.

В других языках, например C#, названия личных свойств, там они называются полями, пишется с маленькой буквы, а публичных свойств с большой.

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

Также JavaScript свойства и методы в классах не делятся на личные и публичные.

Они всегда публичные!

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

Давайте перед свойством done поставить нижнее подчеркивание.

this._done = false;

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


class Task {
 constructor( title = Task.getDefaultTitle() ) {
  this.title = title;
  this._done = false;
  Task.count += 1;
  console.log('Происходит создание задачи');
 }
 get done() {
  return this._done === true ? 'Выполнено' : 'Не выполнено';
 }
  complete() {
  this.done = true;
  console.log(`Задача "${this.title}" выполнена!`);
 }
  static getDefaultTitle() {
   return "Задача";
 }
};

Task.count = 0; 

let task = new Task("Выучить JavaScript");
console.log(task.done, task._done);





Давайте попробуем выполнить задачу


task.complete();
console.log(task.done, task._done);



И ещё раз посмотрим.

И мы получили ошибку!



Это произошло потому что мы объявили свойство get но в методе .complete() мы присваиваем this.done значение true, но при этом свойства set мы не указали.


  complete() {
  this.done = true;
  console.log(`Задача "${this.title}" выполнена!`);
 }



Давайте добавим классу Task свойство set.

Свойство set
. Для этого после get я напишу set дальше название свойства.

Отличие set от get заключается в том что set принимает параметр ,который мы можем присвоить свойству, предварительно проверив этот параметр.

Вы можете назвать его как угодно но чаще всего его называют value.

И в теле метода мы проверим наличие значения value и Является ли это значение типом boolean. Если мы прошли проверку это свойство мы присвоим this._done.

Если же мы проверку не прошли то в консоли мы выдадим ошибку.


class Task {
 constructor( title = Task.getDefaultTitle() ) {
  this.title = title;
  this._done = false;
  Task.count += 1;
  console.log('Происходит создание задачи');
 }
 get done() {
  return this._done === true ? 'Выполнено' : 'Не выполнено';
 }
 set done(value) {
  if(value!== undefined && typeof value === 'boolean') {
   this._done = value;
  } else {
   console.error("Ошибка! Укажите значение true или false.");
  }
 }
  complete() {
  this.done = true;
  console.log(`Задача "${this.title}" выполнена!`);
 }
  static getDefaultTitle() {
   return "Задача";
 }
};

Task.count = 0; 

let task = new Task("Выучить JavaScript");
console.log(task.done, task._done);
task.complete();
console.log(task.done, task._done);



Давайте посмотрим на результат и мы видим что задача успешно выполнена!



Давайте попробуем присвоить, допустим Один.


  complete() {
  this.done = 1;
  console.log(`Задача "${this.title}" выполнена!`);
 }



И мы видим сообщение об ошибке.

О том что мы указали неверные значения.



Свойств можем указать сколько угодно.

В нашем примере мы можем переделать свойств title для того чтобы она использовала get и set. нам даже не обязательно иметь внутреннее свойство для того чтобы воспользоваться get и set.

Тем самым мы получим так называемая псевдо-свойства.

У классов, также как у объектов в ES6, название свойств методов может быть вычислено динамически, используя новый синтаксис - квадратные скобки.

У нас в конце-концов получился вполне себе полноценный класс.

И напоследок Давайте взглянем на то что сгенерировал Babel.


'use strict';

var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();

function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

var Task = function () {
 function Task() {
  var title = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : Task.getDefaultTitle();

  _classCallCheck(this, Task);

  this.title = title;
  this._done = false;
  Task.count += 1;
  console.log('Происходит создание задачи');
 }

 _createClass(Task, [{
  key: 'complete',
  value: function complete() {
   this.done = 1;
   console.log('\u0417\u0430\u0434\u0430\u0447\u0430 "' + this.title + '" \u0432\u044B\u043F\u043E\u043B\u043D\u0435\u043D\u0430!');
  }
 }, {
  key: 'done',
  get: function get() {
   return this._done === true ? 'Выполнено' : 'Не выполнено';
  },
  set: function set(value) {
   if (value !== undefined && typeof value === 'boolean') {
    this._done = value;
   } else {
    console.error("Ошибка! Укажите значение true или false.");
   }
  }
 }], [{
  key: 'getDefaultTitle',
  value: function getDefaultTitle() {
   return "Задача";
  }
 }]);

 return Task;
}();

;

Task.count = 0;

var task = new Task("Выучить JavaScript");
console.log(task.done, task._done);
task.complete();
console.log(task.done, task._done);



Здесь очень много сгенерированного кода но в целом, в принципе, можно различить название класса Task свойства и пр.

Если выписали объектно-ориентированный JavaScript используя ES5, то вы писали, скорее всего, что-то похожее на то что сгенерировал Babel. Не совсем конечно, но близко.

Лично я очень рад что в JavaScript наконец-то появились классы.

Но многие программисты могут со мной не согласится, так как JavaScriptэто больше функциональный язык нежели чем классический.

А прелесть JavaScript заключается в том, что если выходите пользоваться классами, то можете пользоваться классами если хотите писать функциональной код Можете писать функциональный код. Здесь каждый найдёт что-то по душе!

Далее рассмотрим наследование.



                                                                                                                                                             


Хотите освоить самые современные методы написания React приложений? Надоели простые проекты? Нужны курсы, книги, руководства, индивидуальные занятия по React и не только? Хотите стать разработчиком полного цикла, освоить стек MERN, или вы только начинаете свой путь в программировании, и не знаете с чего начать, то пишите через форму связи, подписывайтесь на мой канал в Телеге, вступайте в группу на Facebook.Пишите мне - kolesnikovy70 почта gmail.com