1. 程式人生 > >Express,mysql,ejs搭建簡單電影網站

Express,mysql,ejs搭建簡單電影網站

  1. npm init; npm install express moment mysql:我們使用nodejs的express框架,moment是一個日期處理類庫,mysql資料庫,ejs模板

  2. app.js 中例項化express,設定基本配置,如模板引擎,啟動埠號:

    var express = require('express');
    var path = require('path');
    
    var port = process.env.PORT || 3000; // 設定啟動埠
    var app = express();
    
    app.set('views', path.join(__dirname, 'views'
    )); // 設定模板引擎 app.set('views', './views'); app.set('view engine', 'ejs'); app.listen(port); console.log('start on port ' + port);
  3. app.js 設定路由,index.ejs設定dom模板,admin.ejs,list.ejs,detail.ejs

    <!DOCTYPE>
      <html>
        <head>
          <meta name="viewport" charset="UTF-8" content="width=device-width, initial-scale=1.0"
    >
    <title><%= title %></title> </head> <body> </body> </html>
    // index page
    app.get('/', function(req, res) {
      res.render('index', {
        title: '電影網首頁'
      });
    });
    // detail page
    app.get('/movie/:id', function(req, res) {
      res.render('detail', {
        title: '電影網詳情頁'
    }); }); // list page app.get('/admin/list', function(req, res) { res.render('list', { title: '電影網列表頁' }); }); // admin page app.get('/admin/movie', function(req, res) { res.render('admin', { title: '電影網錄入頁' }); });
  4. 當前目錄結構,includes是公共的部分footere.js,footer.ejs; options.js代表前端js邏輯
    (這裡寫圖片描述)

    課程中用了bower管理前端的包,但是我覺得沒有必要現在來增加學習成本,所以我選擇直接引入。安裝好jq和bootstrap後,找到node_modules中這兩個包的dist目錄,把靜態資源css和js複製到根目錄下的src中,需要在nodejs中,指定我們的靜態資源目錄 app.js app.use('/src', express.static(path.join(__dirname, 'src'))); // 指定靜態資源目錄 /src為虛擬的一個目錄,這樣就可以在ejs模板中使用了,<link rel="stylesheet" href="/src/css/bootstrap.css" >

  5. ejs模板基本語法

    • include 引入其他資料夾下的模板 <%- include('../includes/footer') %>
    • for迴圈<% for (var i = 0; i < moive.length; i++) { %><div><%= moive[i].title %></div><% } %>
    • 拼湊屬性<a href="/moive/<%= moive[i]._id %>">
  6. 資料庫 mysql (app.js)

    mysql的基本操作都是通過connect.query來實現的,官方文件

    • 連線資料庫,關於什麼時候連線關閉資料庫,我還要研究,文章後面已經新增

      var mysql = require('mysql');
      var connection = mysql.createConnection({
        host: 'localhost',
        user: 'root',
        password: '',
        database: 'moive'
      });
      connection.connect(); 
    • 查詢資料,修改app.get('/', function(req, res){})路由

      app.get('/', function(req, res) {
        // 查詢所有資料內容
        connection.query('SELECT * FROM moive_data', function(error, results, fields) {
          if (error) throw error;
          else {
            res.render('index', {
              title: '電影網首頁',
              moive: results
            });
          }
        });
      });

      最開始的時候results可以使用模擬資料

    • 新增一條資料

    // 新增一條資料 前端程式碼邏輯
    $('#addOption').on('click', function() {
      $.ajax({
        type: "POST",
        url: "/admin/add",
        data: {
          title: $("#inputTitle").val(),
          doctor: $("#inputDoctor").val(),
          country: $("#inputCountry").val(),
          year: $("#inputYear").val(),
          poster: $("#inputPoster").val(),
          language: $("#inputLanguage").val(),
          flash: $("#inputFlash").val(),
          summary: $("#inputSummary").val(),
        },
        success: function(res) {
          console.log("Data Saved: " + res);
        }
      });
    });
    • 刪除資料
    app.delete('/admin/list', function(req, res) {
      let id = req.body.id;
      console.log(id);
    
      connection.query(`delete from moive_data where _id = ${id}`, function(error, results, fields) {
        if (error) {
          console.log(error);
          connection.end();
        } else {
          console.log('delete: ', results)
        }
      });
    });
    
    // 刪除一條資料 前端邏輯程式碼
    $('.del').on('click', function() {
      let del_id = $(this).attr('data-id');
    
      $.ajax({
        type: "DELETE",
        url: "/admin/list",
        data: {
          id: del_id
        },
        success: function(res) {
          console.log("Data Saved: " + res);
        }
      });
    });
    • 更新修改一條資料

      1. 首先只是渲染一介面

        app.get('/admin/update/:id', function(req, res) {
          let id = req.params.id;
        
          connection.query(`select * from moive_data where _id = ${id}`, function(error, results, fields) {
            if (error) {
              console.log(error);
            } else {
              res.render('admin', {
                title: '電影網列表頁',
                moive: results
              });
            }
          });
        });
      2. 由於修改以及錄入我們使用的是同一個介面admin介面,所以我們也需要做一個判斷,判斷即將執行更新還是新增,更改options.js的前端程式碼

        $('#addOption').on('click', function() {
          let hiddenVal = $('#inputHidden').val(),
            itype = "PUT";
        
          if (!hiddenVal) {
            itype = "POST";
          }
          console.log(hiddenVal)
            // 隱藏域值為null,新增資料
          $.ajax({
            type: itype,
            url: "/admin/add",
            data: {
              id: hiddenVal,
              title: $("#inputTitle").val(),
              doctor: $("#inputDoctor").val(),
              country: $("#inputCountry").val(),
              year: $("#inputYear").val(),
              poster: $("#inputPoster").val(),
              language: $("#inputLanguage").val(),
              flash: $("#inputFlash").val(),
              summary: $("#inputSummary").val(),
            },
            success: function(res) {
              console.log("Data Saved: " + res);
            }
          });
        });
      3. 新增後端更新介面

        app.put('/admin/add', function(req, res) {
          let id = req.body.id;
          let [title, doctor, country, year, poster, language, flash, summary] = [req.body.title, req.body.doctor, req.body.country, req.body.year, req.body.poster, req.body.language, req.body.flash, req.body.summary];
        
          connection.query(`update moive_data set title=?,doctor=?,country=?,year=?,poster=?,language=?,flash=?,summary=? where _id = ${id}`, [title, doctor, country, year, poster, language, flash, summary], function(error, results, fields) {
            if (error) {
              console.log(error);
            } else {
              console.log('update: ' + results);
            }
          });
        });

      因為程式碼太多,只列出關鍵程式碼,詳細程式碼可以檢視github

重點

  1. 儲存資料庫資料的時候,text,var型別的欄位需要新增引號’${xx}’
  2. 關於ajax提交後的跳轉。我才明白,ajax做的是區域性重新整理就是為了不跳轉所以才使用ajax 如果你需要跳轉的那應該使用from表單提交。如果你實在不小心使用了ajax比如我,就應該在後端返回需要跳轉的url,在前端進行跳轉

     res.send({ status: 200, msg: "add success", url: "/" });
    
     //前端邏輯
      if (res.status === 200) {
         window.location.href = res.url;
      }

    但是我目前遇到的問題就是,跳轉時而成功時而失敗,失敗的時候出現:比如我當前的路由是/admin/add 跳轉的時候http請求頭卻會顯示referer屬性/admin/add?多了一個問號,操作完成後,瀏覽器不會跳轉到目標頁面而是重新整理當前頁面,瀏覽器會顯示/admin/add?,我目前沒有解決

  3. 連線池,mysql是自己支援了連線池,不同資料庫可能不一樣。

    • // 使用連線池連線資料庫
      var mysql = require("mysql");
      
      var pool = mysql.createPool({
        connectionLimit: 100,
        host: 'localhost',
        user: 'root',
        password: '',
        database: 'moive'
      });
      
      var query = function(sql, options, callback) {
        pool.getConnection(function(err, con) {
          if (err) {
            callback(err, null, null);
          } else {
            con.query(sql, options, function(err, results, fields) {
              callback(err, results, fields);
            });
          }
          con.release(); // 釋放資源
        });
      }
      
      module.exports = query;

      使用修改connection.query為query

        var query = require('./mysql-pool'); // 使用連線池連線資料庫
    
        app.get('/', function(req, res) {
      // 查詢所有資料內容
      query('select * from moive_data', [], function(error, results, fields) {
        if (error) {
          console.log(error);
        } else {
          res.render('index', {
            title: '電影網首頁',
            moive: results
          });
        }
      });
    });
  4. 新增錄入插入時間。在建立mysql的時候新增一個欄位 intime 如圖設定
    這裡寫圖片描述
    ,每次更新也回自動更新時間。獲取資料的事後根據時間排序只需要在sql語句中新增order by + 欄位 ,比如:select * from moive_data order by intime 就可以啦