Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Базы данных - лекция12 - веб-приложение React.js+Node.js

3a855e4e8dd144b8942da2463831a067?s=47 Anton
November 27, 2018

Базы данных - лекция12 - веб-приложение React.js+Node.js

3a855e4e8dd144b8942da2463831a067?s=128

Anton

November 27, 2018
Tweet

Transcript

  1. Веб-приложение на Node+React

  2. React.js: быстрый старт reactjs.org • reactjs.org/docs/add-react-to-a- website.html#add-react-in-one-minute • Одна страничка

    • Ничего не качаем • Скрипты не запускаем
  3. hello-react.html <!DOCTYPE html> <html> <head> <meta charset="UTF-8" /> <title>Hello React!</title>

    <!-- Для поддержки тегов script с параметром type="text/babel" --> <script src="https://unpkg.com/babel-core@5.8.38/browser.min.js"></script> <!-- Для ReactDOM.render --> <script src="https://unpkg.com/react@16/umd/react.development.js"></script> <script src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script> </head> <body> <div id="hello-react"></div> <script type="text/babel"> ReactDOM.render( <h1>Hello, world from React!</h1>, document.getElementById('hello-react') ); </script> <div> Работает на чистом <a href="https://facebook.github.io/react/docs/getting-started.html">React starter pack</a> </div> </body> </html>
  4. Вроде ничего особенного, но обратите внимание на незакавыченные теги внутри

    блока JavaScript <div id="hello-react"></div> <script type="text/babel"> ReactDOM.render( <h1>Hello, world from React!</h1>, document.getElementById('hello-react') ); </script>
  5. • Для поддержки тегов script с параметром type="text/babel": конвертирует синтаксис

    React в классический JavaScript в браузере на лету <script src="https://unpkg.com/babel-core@5.8.38/browser.min.js"></script> • Для ReactDOM.render <script src="https://unpkg.com/react@16/umd/react.development.js"></script> <script src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
  6. None
  7. Правильный подход: проект • reactjs.org/docs/create-a-new-react-app.html#create-react-app • Быстрый старт быстрый, но

    не эффективный, потом не удобный • Правильный подход — генерировать проект • Файлы React конвертируются в классический JavaScript до развертывания на сервере • Можно устанавливать сторонние библиотеки (например, с виджетами React) одной командой из репозитория NPM • Да, Node.js здесь используется для разработки клиентского кода на JavaScript (не путать здесь с кодом серверной части, она может быть любая — хоть Node.js, хоть PHP) • Скрипт-генератор проекта устанавливаем тоже из NPM
  8. create-react-app • Устанавливаем глобально ] sudo npm install -g create-react-app

    или локально ] npm install create-react-app • Создаем проект ] create-react-app webapp-client или • ] ./node_modules/.bin/create-react-app webapp-client
  9. Проект webapp-client/ webapp-client/package.json (правим время от времени) webapp-client/README.md webapp-client/public/ webapp-client/public/index.html

    (не правим) webapp-client/public/manifest.json webapp-client/src/ webapp-client/src/index.js (не правим) webapp-client/src/App.js (основная разработка здесь) webapp-client/build/
  10. webapp-client/src/index.js (не правим) import React from 'react'; import ReactDOM from

    'react-dom'; import './index.css'; import App from './App'; ReactDOM.render(<App />, document.getElementById('root'));
  11. webapp-client/src/App.js (основная разработка здесь) import React, { Component } from

    'react'; import logo from './logo.svg'; import './App.css'; class App extends Component { render() { return ( <div className="App"> <header className="App-header"> <img src={logo} className="App-logo" alt="logo" /> <p> Edit <code>src/App.js</code> and save to reload.</p> <a className="App-link" href="https://reactjs.org" target="_blank" rel="noopener noreferrer" >Learn React</a> </header> </div> ); } } export default App;
  12. Запустить: быстро • Быстро ] cd webapp-client ] npm start

    • Откроется браузер с адресом localhost:3000
  13. None
  14. Добавим виджеты • Пусть будут material-ui material-ui.com ] npm install

    material-ui --save • Поиск: «react components» «react component xxx»
  15. webapp-client/src/App.js import React from 'react'; import RaisedButton from 'material-ui/RaisedButton'; import

    logo from './logo.svg'; import './App.css'; class App extends React.Component { [...] } export default App;
  16. webapp-client/src/App.js [...] class App extends React.Component { constructor(props) { super(props);

    this.state = {clickCount: 0}; } click = () => { this.setState({clickCount: this.state.clickCount+1}); } [...] } [...]
  17. webapp-client/src/App.js [...] class App extends React.Component { [...] render() {

    return ( <div className="App"> <header className="App-header"> <img src={logo} className="App-logo" alt="logo" /> <h1 className="App-title">Welcome to React with Material-UI widgets</h1> </header> <p className="App-intro"> To get started, edit <code>src/App.js</code> and save to reload. </p> <RaisedButton primary={true} onClick={this.click} label="click me" /> <span style={{marginLeft: 20, fontWeight: 'bold'}}>{this.state.clickCount}</span> </div> ); } } [...]
  18. None
  19. Запустить: развернуть на сервер (deploy) • Развернуть (деплой) на сервер

    ] npm run build • Проект со всеми зависимостями появится в каталоге build/ • Его содержимое можно загрузить в корень с ресурсами и файлами html на сервер — там есть файл index.html • Это будет одностраничное приложение, только клиентский код • Файл build/index.html можно открыть и вручную, если добавить в package.json параметр { […] "homepage" : ".", […] }
  20. Добавим сервер, тоже на Node.js

  21. Проект • Веб-сервер для раздачи статического контента из отдельного каталога

    ] npm install serve-static • webapp-server/ • webapp-server/webapp-server.js • webapp-server/package.json сюда будем копировать содержимое webapp-client/build/ (или создать символьную ссылку) • webapp-server/client-build/
  22. webapp-server/webapp-server.js var http = require('http'); var serveStatic = require('serve-static'); var

    serve = serveStatic('client-build', {'index': ['index.html', 'index.htm']}) http.createServer(function (req, res) { console.log("request: " + req.url); switch(req.url) { [...] } }).listen(3000); console.log('Server running at http://localhost:3000/');
  23. webapp-server/webapp-server.js […] switch(req.url) { case "/call1": res.writeHead(200, {'Content-Type': 'text/plain'}); res.end("reply

    for /call1"); break; case "/call2": res.writeHead(200, {'Content-Type': 'text/plain'}); res.end("reply for /call2"); break; […] } [...]
  24. webapp-server/webapp-server.js […] switch(req.url) { […] default: serve(req, res, function(err) {

    // better use https://www.npmjs.com/package/finalhandler // in production instead if(!err) { res.writeHead(404, { 'Content-Type': 'text/html' }); res.write('<!DOCTYPE html>\n' + '<html>\n' + ' <head>\n' + ' <meta charset=\'utf-8\'>\n' + ' </head>\n' + ' <body>\n' ); res.write("404, NOT FOUND: " + req.url); res.end(' </body>\n' + '</html>\n'); } else { res.writeHead(500, { 'Content-Type': 'text/html' }); res.end(err.message); console.log(err); } }); } [...]
  25. Поправим клиента webapp-client/src/App.js

  26. webapp-client/src/App.js import React from 'react'; var styleBtn = { margin:

    10, padding: 5, borderStyle: 'solid', cursor: 'pointer' } class App extends React.Component { [...] } export default App;
  27. webapp-client/src/App.js class App extends React.Component { constructor(props) { super(props); this.state

    = {reply: " "}; } [...] }
  28. webapp-client/src/App.js class App extends React.Component { […] readServerString(url, callback) {

    var req = new XMLHttpRequest(); req.onreadystatechange = function() { if (req.readyState === 4) { // only if req is "loaded" if (req.status === 200) { // only if "OK" callback(undefined, req.responseText); } else { // error callback(new Error(req.status)); } } }; // can't use GET method here as it would quickly // exceede max length limitation req.open("POST", url, true); //Send the proper header information along with the request req.setRequestHeader("Content-type", "application/x-www-form-urlencoded"); req.send(); } […] }
  29. webapp-client/src/App.js class App extends React.Component { […] call1 = ()

    => { this.readServerString('/call1', function(err, res) { if(!err) { this.setState({reply: res}); } else { this.setState({reply: err.toString()}); } }.bind(this)); } call2 = () => { this.readServerString('/call2', function(err, res) { if(!err) { this.setState({reply: res}); } else { this.setState({reply: err.toString()}); } }.bind(this)); } [...] }
  30. webapp-client/src/App.js class App extends React.Component { […] render() { return

    ( <div style={{textAlign: 'center', marginTop: 30}}> <p> <span onClick={this.call1} style={styleBtn}>Прочитать с сервера значение 1</span> <span onClick={this.call2} style={styleBtn}>прочитать с сервера значение 2</span> </p> <p style={{marginTop: 40, fontSize: 24}}> Результат: <span style={{fontStyle: 'italic'}}>{this.state.reply}</span> </p> </div> ); } }
  31. Собираем клиента, запускаем сервер • Пересоберем клиента ] cd webapp-client

    ] npm run build • Копируем содержимое webapp-client/build в webapp- server/client-build/ (если есть символьная ссылка, то не нужно) • Запускаем сервер ] cd webapp-server ] node webapp-server.js • Открываем localhost:3000
  32. None
  33. None
  34. react-router reacttraining.com/react-router/ • Управление строкой URL в одностраничном приложении •

    TODO
  35. Лаба-8.0.1/8.0.2/8.0.3 • запустить демо-проекты React.js+Node.js Лаба-8.1 • перевести одну из

    лаб «динамический фильтр таблицы» на React плюс Material-UI • (или другая библиотека стандартных виджетов)