Ruofan Wei
    • Create new note
    • Create a note from template
      • Sharing URL Link copied
      • /edit
      • View mode
        • Edit mode
        • View mode
        • Book mode
        • Slide mode
        Edit mode View mode Book mode Slide mode
      • Customize slides
      • Note Permission
      • Read
        • Only me
        • Signed-in users
        • Everyone
        Only me Signed-in users Everyone
      • Write
        • Only me
        • Signed-in users
        • Everyone
        Only me Signed-in users Everyone
      • Engagement control Commenting, Suggest edit, Emoji Reply
    • Invite by email
      Invitee

      This note has no invitees

    • Publish Note

      Share your work with the world Congratulations! 🎉 Your note is out in the world Publish Note

      Your note will be visible on your profile and discoverable by anyone.
      Your note is now live.
      This note is visible on your profile and discoverable online.
      Everyone on the web can find and read all notes of this public team.
      See published notes
      Unpublish note
      Please check the box to agree to the Community Guidelines.
      View profile
    • Commenting
      Permission
      Disabled Forbidden Owners Signed-in users Everyone
    • Enable
    • Permission
      • Forbidden
      • Owners
      • Signed-in users
      • Everyone
    • Suggest edit
      Permission
      Disabled Forbidden Owners Signed-in users Everyone
    • Enable
    • Permission
      • Forbidden
      • Owners
      • Signed-in users
    • Emoji Reply
    • Enable
    • Versions and GitHub Sync
    • Note settings
    • Note Insights
    • Engagement control
    • Transfer ownership
    • Delete this note
    • Save as template
    • Insert from template
    • Import from
      • Dropbox
      • Google Drive
      • Gist
      • Clipboard
    • Export to
      • Dropbox
      • Google Drive
      • Gist
    • Download
      • Markdown
      • HTML
      • Raw HTML
Menu Note settings Versions and GitHub Sync Note Insights Sharing URL Create Help
Create Create new note Create a note from template
Menu
Options
Engagement control Transfer ownership Delete this note
Import from
Dropbox Google Drive Gist Clipboard
Export to
Dropbox Google Drive Gist
Download
Markdown HTML Raw HTML
Back
Sharing URL Link copied
/edit
View mode
  • Edit mode
  • View mode
  • Book mode
  • Slide mode
Edit mode View mode Book mode Slide mode
Customize slides
Note Permission
Read
Only me
  • Only me
  • Signed-in users
  • Everyone
Only me Signed-in users Everyone
Write
Only me
  • Only me
  • Signed-in users
  • Everyone
Only me Signed-in users Everyone
Engagement control Commenting, Suggest edit, Emoji Reply
  • Invite by email
    Invitee

    This note has no invitees

  • Publish Note

    Share your work with the world Congratulations! 🎉 Your note is out in the world Publish Note

    Your note will be visible on your profile and discoverable by anyone.
    Your note is now live.
    This note is visible on your profile and discoverable online.
    Everyone on the web can find and read all notes of this public team.
    See published notes
    Unpublish note
    Please check the box to agree to the Community Guidelines.
    View profile
    Engagement control
    Commenting
    Permission
    Disabled Forbidden Owners Signed-in users Everyone
    Enable
    Permission
    • Forbidden
    • Owners
    • Signed-in users
    • Everyone
    Suggest edit
    Permission
    Disabled Forbidden Owners Signed-in users Everyone
    Enable
    Permission
    • Forbidden
    • Owners
    • Signed-in users
    Emoji Reply
    Enable
    Import from Dropbox Google Drive Gist Clipboard
       owned this note    owned this note      
    Published Linked with GitHub
    Subscribed
    • Any changes
      Be notified of any changes
    • Mention me
      Be notified of mention me
    • Unsubscribe
    Subscribe
    # 前後端整合 - 學習 jQuery 與 Bootstrap ###### tags: `Tag(jQuery 與 Bootstrap)` ## 什麼是 SPA Single Page Application 想增進使用者體驗,而出現的一種==在前端利用 Ajax 達成不換頁的方法==。 ##### `優點` ```c * 後端只負責輸出資料,前端來負責抓資料跟渲染畫面。 * 後端變成了一個單純的 API,可以給不同的前端做調用。 * 把前後端完完全全的切開,就算後端壞掉,前端還是看得到畫面 * 前端壞掉,後端還是能安穩的輸出資料供其他服務使用。 ``` ##### `缺點` ```c * 檢視 SPA 頁面的原始碼,會發現沒有畫面上看到的內容的程式碼, 這是因為畫面的渲染是由 JavaScript 動態產生的,這樣會使網站的 SEO 表現很差 * 如果從伺服器抓取的資料比較多的話,第一次載入頁面的速度可能會比較慢。 ``` ## 怎麼樣用 PHP 自己寫出 API ##### `範例:作業` ###### `拿儲存到資料庫的todolist的 API` ```c <?php require_once('conn.php'); // 輸出jason資料 header('Content-type:application/json;charset=utf-8'); header('Access-Control-Allow-Origin: *'); // 錯誤處理 - 如果前端的資料是空的 if (empty($_GET['id'])) { $json = array( 'ok' => false, 'message' => 'Please provide a list ID' ); // 把資料變成jason的格式 $response = json_encode($json); echo $response; die(); } // 錯誤處理完之後可以拿資料 $id = intval($_GET['id']); //拿完資料後可以新增到資料庫裡面 $sql = "SELECT * FROM ruofan_todos WHERE id=?"; $stmt = $conn->prepare($sql); $stmt->bind_param('i', $id); $result = $stmt->execute(); //執行完之後可以根據內容來看有沒有成功 if(!$result) { $json = array( 'ok' => false, 'message' => $conn->error ); $response = json_encode($json); echo $response; die(); } // 判斷完錯誤處理後要把東西拿回來 $result = $stmt->get_result(); $row = $result->fetch_assoc(); // 如果成功有資料 產生一個陣列 $json = array( 'ok' => true, 'data' => array( 'id' => $row["id"], 'todo' => $row["todo"] ) ); // 把物件用json_encode這個function變成json的字串後輸出,這樣client就可以接收到 $response = json_encode($json); echo $response; ?> ``` ###### `把前端todolist的資料存到資料庫的 API` ```c <?php require_once('conn.php'); // 輸出jason資料 header('Content-type:application/json;charset=utf-8'); header('Access-Control-Allow-Origin: *'); // 錯誤處理 - 如果前端post的資料是空的 if (empty($_POST['todo'])){ $json = array( 'ok' => false, 'message' => 'no todos.' ); $response = json_encode($json); echo $response; die(); } // 錯誤處理完之後可以拿資料 $todo = $_POST['todo']; //拿完資料後可以新增到資料庫裡面 $sql = "INSERT INTO ruofan_todos(todo) VALUES (?)"; $stmt = $conn->prepare($sql); $stmt->bind_param('s', $todo); $result = $stmt->execute(); //執行完之後可以根據內容來看有沒有成功 - 如果沒有資料 if(!$result){ $json = array( 'ok' => false, 'message' => 'no todos.' ); // 把資料變成jason的格式 $response = json_encode($json); echo $response; die(); } // 如果成功有資料 產生一個陣列 $json = array( "ok" => true, "message" => "success", "id" => $conn->insert_id ); // 把物件用json_encode這個function變成json的字串後輸出,這樣client就可以接收到 $response = json_encode($json); echo $response; ?> ``` ## 如何在前端與自己開的 API 串接 ##### `範例:作業` ###### `把資料存到資料庫` ```javascript= // 儲存功能 $('.save').click(() => { // 先從UI拿到要存到資料庫的內容 let todos = []; $('.card').each((i, element) => { const check = $(element).find('.check-btn') const content = $(element).find('.content') // 把拿到的資料放到todos這個陣列裡 todos.push({ id: check.attr('id').replace('todo-', ''), content: content.text(), done: check.hasClass('checked') }) }) // 把陣列轉成JSON格式的字串 const data = JSON.stringify(todos) // 把todo的資料存到資料庫 $.ajax({ type: 'POST', url: `http://localhost:8080/ruofan_php/to-do-list/save_lists.php`, data: { todo: data }, success: function (res) { const resId = res.id window.location = 'http://localhost:8080/ruofan_php/to-do-list/todolist.html?id=' + resId alert('儲存成功') }, error: function () { alert('尚未成功') } }) }) ``` ###### `帶入id載入之前存在資料庫的資料` ```javascript= // 當輸入html標籤時,會印出標籤 function escapeHtml (todo) { return todo .replace(/&/g, "&amp;") .replace(/</g, "&lt;") .replace(/>/g, "&gt;") .replace(/"/g, "&quot;") .replace(/'/g, "&#039;"); } const template = ` <div class="card d-flex"> <div class="card-body"> <div class="add-todo"> <div class="check-btn {todoClass}" id="todo-{id}">⬜</div> <div for="todo-{id}" id="{id}" class="content">{content}</div> </div> <div class="edit-todo"> <i class="far fa-trash-alt delete"></i> <i class="fas fa-pencil-alt edit" data-toggle="modal" data-target="#edit-content"></i> </div> </div> </div> ` // 載入資料的功能 var searchParams = new URLSearchParams(window.location.search); const todoId = searchParams.get('id') // 載入 id對應的資料 if (todoId){ $.getJSON('http://localhost:8080/ruofan_php/to-do-list/get_lists.php?id=' + todoId, function(data){ const todos = JSON.parse(data.data.todo) restoreTodos(todos) }) } function restoreTodos(todos){ console.log(todos) // 可以印出todos 看一下資料長什麼樣子 for(let i=0; i<todos.length; i++){ const todo = todos[i] $('.comments').prepend( template .replace('{content}', escapeHtml(todo.content)) .replace(/{id}/g, todo.id) .replace('{todoClass}', todo.done ? 'checked' : '') ) if (todo.done) { $('#todo-' + todo.id).prop('checked', true) $('#todo-' + todo.id).html('✔️') $('#todo-' + todo.id).next().toggleClass('line-through') } } } ``` ## 在 server 與在 client render 的差別 >[React | 用實作了解 Server-Side Rendering 的運作原理](https://medium.com/starbugs/react-%E7%94%A8%E5%AF%A6%E4%BD%9C%E4%BA%86%E8%A7%A3-server-side-rendering-%E7%9A%84%E9%81%8B%E4%BD%9C%E5%8E%9F%E7%90%86-c6133d9fb30d) #### `client side render` 在執行期間「動態」去跟後端伺服器拿資料,當前端拿到資料以後,才用 JavaScript 動態的把那些內容填到網頁上面。 ```css= 前端透過 ajax 去跟後端的 API 互動,後端判斷資料是否正確,並把存到資料庫中, 並透過 API 把成功或失敗的 response 回傳給前端,而前端拿到的 response 後, 再由 JavaScript 來決定要渲染什麼畫面,所渲染的畫面是透過 JavaScript 操控 DOM 元素而動態產生的 ``` #### `server side render` Server 會用 URL 的 path 來決定要 Render 什麼畫面,然後顯示在前端頁面上 ###### `優點` ```css= * SEO SSR 在第一次載入時就會有內容在了,搜尋引擎表示非常滿意。 * 效能更好: 第一次 Render 的所有事情(包含 call API)都是 Server 做的, Client 端就比較沒有負擔。 ``` ###### `缺點` ```c - 所有內容都在伺服器端處理、組裝完成後才將完整的HTML/CSS/JavaScript 檔案 回傳給客戶端。也因為 HTML 檔(包含資料)是在伺服器上組裝完成才回傳給瀏覽器, 所以每次載入新資料的時候都需要換頁。 ``` ###### `範例` ```css= 當想要訪問文章列表這個頁面的時候,瀏覽器會送 request 到 server ,然後經過 controller 與 model,最後把資料帶給 view。 view 再回傳一份完整的 HTML 檔案(這個動作就叫做 render) ,而瀏覽器拿到之後,只要顯示出來就好。因為 render 在 server side ``` ## jQuery 是做什麼的 ? 與 vanilla js 的差別 ? >[淺談 JQuery](https://ithelp.ithome.com.tw/articles/10092592) >[jQuery 簡單介紹](https://jw310.github.io/2020/01/16/jQuery-base/#%E4%BD%BF%E7%94%A8-jQuery) 是一個 JavaScript 函式庫 (Javascipt Framework),加速網頁程式開發速度的工具,可以==解決跨瀏覽器的問題,也可以簡化語法== ###### `範例` `讀取網頁中的單選按鈕「radio Button」` ```cs 1 找出所有 input 元素 2 當元素是 radio button 且屬於某個 group 3 確認某個選項已經被勾選了 4 將勾選的值指派給 checkValue 變數 ``` ###### `JavaScript` ```javascript var checkValue; var elements = document.getElementsByTagName(‘input’); for (var n = 0; n < elements.length; n++){ if (elements[n].type == ‘radio’ && elements[n].name == ‘RadioGroup’ && elements[n].checked){ checkedValue = elements[n].value; } ``` ###### `jQuery` ```javascript= var checkValue = $('[name="radioGroup"]:checked').val(); ``` ##### `使用 jQuery` ```c // 選取元素 $("div") // 選取所有 <div> 元素 $("#menu") // 選取 id 為 menu 的元素 $(".content") // 選取 class 為 content 的元素 $("div#body") // 選取 id 為 body 的 <div> $('ul').children.eq(3).text(); // 取得第index個子節點: eq(index) 取得第三個子節點 ------------------------------------------------------------------- // 操作元素 // 讀取和修改一個元素的HTML內容: html() $("p").html(); // 讀取 <p> 元素的內容 $("p").html("Hello <b>world</b>!"); // 修改 <p> 元素的內容 // 讀取和修改一個元素的純文本內容: text() $("Element").text(); // 讀取 Element 的文本內容 $("Element").text("Hello <b>world</b>!"); // 修改 Element 的文本內容,Element 的 content 是 Hello <b>world</b>! 是文字格式,不是標籤元素 ------------------------------------------------------------------- // 讀取和修改一個表單元素的 value 值: val() // 若是多個元素,只能讀取第一個元素的內容。要使用 for 或 each 來讀取多個。 // 讀取每一個被 checked 的值 $('input:checkbox[name=size]:checked').each(function() { alert($(this).val()); }); $("Element").val(value); // 修改 ------------------------------------------------------------------- // 元素節點末端加入純文字或 HTML 語法(增加元素): append $("a[target]").append("(Opens in New Window)"); // 選取所有有 target 屬性的 `<a>`,並且在其節點下加入一段文字。 $(div).prepend("first"); // 元素節點前端加上純文字或 HTML 語法(增加元素): prepend() $("#test").addClass("aaa"); // class的新增: addClass() class的移除: removeClass() // $("#test").removeClass("aaa"); ------------------------------------------------------------------- // 事件 點選元素: click // //當 user 點選 id 為 open 的連結時,顯示 id 為 menu 的區塊,並回傳 false 避免瀏覽器真的換頁。 $("a#open").click(function() { $("#menu").show(); return false; }); ------------------------------------------------------------------- // 切換: toggle() // 按下 Hello 元素第一次會文字會是綠,第二次會是藍色 $('#mydiv').toggle( function(){ $(this).css({"color": "green"}); }, function(){ $(this).css({"color": "blue"}); }, ); ------------------------------------------------------------------- // ajax $.ajax({ type: "GET", //指定method url: 'ajax/test.html', success: function(data) { $('.result').html(data); alert('Load was performed.'); } }); // 取得 HTML: load() $("#htmDoc").load("test.html"); // 取得 JSON 格式的資料: getJSON() $.getJSON("test.json", function(data){ for (var idx in data) $("#menu").append("<li>" + data[idx] + "</li>"); }); // document ready 事件 // 網頁下載完成後立即執行 alert() $(document).ready(function() { alert('Hello'); }); ``` ## 什麼是 Bootstrap ? 原理及如何應用? >[Bootstrap 初學介紹 ](https://medium.com/@weilihmen/bootstrap-%E5%88%9D%E5%AD%B8%E4%BB%8B%E7%B4%B9-%E9%9D%9C%E6%85%8B%E7%AF%87-f20500235b33) >[Bootstrap](https://jw310.github.io/2019/12/14/bootstrap-base/) >[淺談Bootstrap](http://yenchic-blog.logdown.com/posts/257912-a-brief-talk-on-bootstrap) 前端框架,含HTML、CSS及JS等內容的框架,可以快速開發出一個網頁版型(包含響應式網頁)。 :::warning ![](https://i.imgur.com/ZG91ZYw.png) ::: ###### `navbar 範例` :::warning ![](https://i.imgur.com/6mS26mU.png) ::: ###### `alert 範例` :::warning ![](https://i.imgur.com/uXvwBOF.png) ::: ###### `調整alert的寬度` ```html <div class="row mt-4"> <!--這邊的mt-4 是margin-top:4px;的縮寫 --> <div class="col-12"> <!--這邊的col-12 是指直接讓alert滿格 --> <div class="alert alert-primary" role="alert"> 這是我的 todo 小作品! </div> </div> </div> ``` ###### `form 範例` :::warning ![](https://i.imgur.com/Cy5TU8w.png) ::: ###### `調整 form的寬度` ```html <div class="row"> <div class="col-12 col-md-8"> <div class="form-group"> <input type="text" placeholder="請輸入待辦事項" class="form-control" id="exampleInputPassword1"> </div> </div> <div class="col-12 col-md-4"> <button class="btn btn-primary btn-block">新增</button> <!--這邊的btn-block 讓button寬度可以滿格 --> </div> </div> ``` ###### `card 範例` :::warning ![](https://i.imgur.com/Rudhc4A.png) ::: ###### `調整 card的寬度` ```html <div class="card"> <!--原本的 style="width: 18rem; 刪掉,card的寬度就可以滿格 --> <div class="card-header"> Featured </div> <ul class="list-group list-group-flush"> <li class="list-group-item">Cras justo odio</li> <li class="list-group-item">Dapibus ac facilisis in</li> <li class="list-group-item">Vestibulum at eros</li> </ul> </div> ``` ###### `Badges 範例` :::warning ![](https://i.imgur.com/do56sty.png) ::: ###### `bootswatch - 提供不同主題顏色` :::warning ![](https://i.imgur.com/FBauPG5.png) ::: ###### `套用方式 - 在header加上連結` :::warning ![](https://i.imgur.com/vTDH6oB.png) :::

    Import from clipboard

    Paste your markdown or webpage here...

    Advanced permission required

    Your current role can only read. Ask the system administrator to acquire write and comment permission.

    This team is disabled

    Sorry, this team is disabled. You can't edit this note.

    This note is locked

    Sorry, only owner can edit this note.

    Reach the limit

    Sorry, you've reached the max length this note can be.
    Please reduce the content or divide it to more notes, thank you!

    Import from Gist

    Import from Snippet

    or

    Export to Snippet

    Are you sure?

    Do you really want to delete this note?
    All users will lose their connection.

    Create a note from template

    Create a note from template

    Oops...
    This template has been removed or transferred.
    Upgrade
    All
    • All
    • Team
    No template.

    Create a template

    Upgrade

    Delete template

    Do you really want to delete this template?
    Turn this template into a regular note and keep its content, versions, and comments.

    This page need refresh

    You have an incompatible client version.
    Refresh to update.
    New version available!
    See releases notes here
    Refresh to enjoy new features.
    Your user state has changed.
    Refresh to load new user state.

    Sign in

    Forgot password

    or

    By clicking below, you agree to our terms of service.

    Sign in via Facebook Sign in via Twitter Sign in via GitHub Sign in via Dropbox Sign in with Wallet
    Wallet ( )
    Connect another wallet

    New to HackMD? Sign up

    Help

    • English
    • 中文
    • Français
    • Deutsch
    • 日本語
    • Español
    • Català
    • Ελληνικά
    • Português
    • italiano
    • Türkçe
    • Русский
    • Nederlands
    • hrvatski jezik
    • język polski
    • Українська
    • हिन्दी
    • svenska
    • Esperanto
    • dansk

    Documents

    Help & Tutorial

    How to use Book mode

    Slide Example

    API Docs

    Edit in VSCode

    Install browser extension

    Contacts

    Feedback

    Discord

    Send us email

    Resources

    Releases

    Pricing

    Blog

    Policy

    Terms

    Privacy

    Cheatsheet

    Syntax Example Reference
    # Header Header 基本排版
    - Unordered List
    • Unordered List
    1. Ordered List
    1. Ordered List
    - [ ] Todo List
    • Todo List
    > Blockquote
    Blockquote
    **Bold font** Bold font
    *Italics font* Italics font
    ~~Strikethrough~~ Strikethrough
    19^th^ 19th
    H~2~O H2O
    ++Inserted text++ Inserted text
    ==Marked text== Marked text
    [link text](https:// "title") Link
    ![image alt](https:// "title") Image
    `Code` Code 在筆記中貼入程式碼
    ```javascript
    var i = 0;
    ```
    var i = 0;
    :smile: :smile: Emoji list
    {%youtube youtube_id %} Externals
    $L^aT_eX$ LaTeX
    :::info
    This is a alert area.
    :::

    This is a alert area.

    Versions and GitHub Sync
    Get Full History Access

    • Edit version name
    • Delete

    revision author avatar     named on  

    More Less

    Note content is identical to the latest version.
    Compare
      Choose a version
      No search result
      Version not found
    Sign in to link this note to GitHub
    Learn more
    This note is not linked with GitHub
     

    Feedback

    Submission failed, please try again

    Thanks for your support.

    On a scale of 0-10, how likely is it that you would recommend HackMD to your friends, family or business associates?

    Please give us some advice and help us improve HackMD.

     

    Thanks for your feedback

    Remove version name

    Do you want to remove this version name and description?

    Transfer ownership

    Transfer to
      Warning: is a public team. If you transfer note to this team, everyone on the web can find and read this note.

        Link with GitHub

        Please authorize HackMD on GitHub
        • Please sign in to GitHub and install the HackMD app on your GitHub repo.
        • HackMD links with GitHub through a GitHub App. You can choose which repo to install our App.
        Learn more  Sign in to GitHub

        Push the note to GitHub Push to GitHub Pull a file from GitHub

          Authorize again
         

        Choose which file to push to

        Select repo
        Refresh Authorize more repos
        Select branch
        Select file
        Select branch
        Choose version(s) to push
        • Save a new version and push
        • Choose from existing versions
        Include title and tags
        Available push count

        Pull from GitHub

         
        File from GitHub
        File from HackMD

        GitHub Link Settings

        File linked

        Linked by
        File path
        Last synced branch
        Available push count

        Danger Zone

        Unlink
        You will no longer receive notification when GitHub file changes after unlink.

        Syncing

        Push failed

        Push successfully