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
      • Invitee
    • 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
    • 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 Sharing URL Create Help
Create Create new note Create a note from template
Menu
Options
Versions and GitHub Sync 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
Invitee
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