CRUD x Vue.js x PHP x MYSQL PDO

更新於 發佈於 閱讀時間約 30 分鐘

S1.建立資料庫 user

 -
-- 資料表結構 `users`
--

CREATE TABLE `users` (
`name` varchar(20) NOT NULL,
`email` text NOT NULL,
`password` text NOT NULL,
`id` int(11) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

S2.建立 index.htm

a.載入 vue.js、jquery、bootstrap

b.版面建立


S3.vue.js程式

新增、查看列表、互動視窗、修改、刪除

S4.PHP程式 x CRUD
增刪查改(CRUD)
Create - 建立
Read -讀取、查詢
Update - 更新
Delete - 刪除

vue.js 生命週期

vue.js 生命週期


index.htm

<!-- 
20201031 by JokerWu
20220527 新修-步驟拆解 & 加註版
_1=建立資料
_2=建立列表
_3=互動視窗
_4=完整
-->
<!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>Vue.js PHP MYSQL</title>
</head>

<!--
程式中 變數、函式命名有
駝峰式命名法
每一個單字的首字母都採用大寫字母
例如:FirstName、LastName、CamelCase
也被稱為Pascal命名法
-->

<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script src="http://code.jquery.com/jquery-3.6.0.min.js"></script>

<!--
jquery 可以改成 axios套件來處理AJAX
Axios是很輕量的套件,只有約13kb
jQuery比較笨重 主要是用來處理AJAX
所以axios 在vue.js 來說是較好的選擇
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
-->

<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@3.3.7/dist/css/bootstrap.min.css">
<script src="https://cdn.jsdelivr.net/npm/bootstrap@3.3.7/dist/js/bootstrap.min.js"></script>

<style>
table, th, td {
border: 1px solid black;
border-collapse: collapse;
}
th, td {
padding: 25px;
}
</style>

<body>
<!-- 版面 -->
<div id="myApp"> <!-- 此處的 id 跟 vue.js //el: 互動 -->
<div class="container"><!-- .container 是BS5的預設類別, 是一個RWD 固定寬度的內容容器 -->
<h1 class="text-center">建立資料</h1>

<div class="row">
<div class="col-md-6">
<form method="POST" action="create.php" v-on:submit.prevent="doCreate">
<!--
v-on:submit.prevent
submit ->表單送出
.prevent->不換頁刷新頁面
doCreate->vue.js 自訂義函式 用來將表單資料 以JSON格式 送出至create.php

v-on:submit.prevent可簡寫為
@:submit.prevent
-->
<div class="form-group">
<label>姓名</label>
<input type="text" name="name" class="form-control" />
</div>

<div class="form-group">
<label>Email</label>
<input type="email" name="email" class="form-control" />
</div>

<div class="form-group">
<label>密碼</label>
<input type="password" name="password" class="form-control" />
</div>

<input type="submit" value="建立" class="btn btn-primary" />
</form>
</div>
</div>
<!-- 版面 列表頁 -->
<h1 class="text-center">列表</h1>

<table class="table">
<tr>
<th>排序ID</th>
<th>姓名</th>
<th>Email</th>
<th>管理</th>
</tr>
<!--
以下為使用 vue.js for迴圈

參考範例 v04.html & v05.html
只要把 v-for 放在一個 <li> 上就有 for 的效果
item 是參數(你也可為它取別的名字)用來表示陣列元素
list 指的是自定義的陣列名稱(陣列元素為數個物件)
in 也可以寫成 of,因為這樣更接近原生 JavaScript 疊代器的語法

v-for 還支援第二個參數 — — 索引值(index)
帶入索引值參數的方法是在原本 item 的位置改寫成 (item, index) 即可

此處 v-for 放在一個<tr>內使用
陣列元素 以 user 命名 ->代表 資料表內的欄位名稱
索引值 以 index 命名 ->表示第幾筆資料
而 users 為 從 vue.js 收到JSON資料 解出後 的資料集名稱
-->
<tr v-for="(user, index) in users">
<td v-text="user.id"></td>
<td v-text="user.name"></td>
<td v-text="user.email"></td>
<td>
<button type="button" v-bind:data-id="user.id" v-on:click="showEditUserModal" class="btn btn-primary">編輯</button>
<!--
v-bind
v03.html範例
雙花括號 填資料的方法,不適用 HTML 屬性 因此應該把 v-bind: 加在 HTML 屬性前面,且在屬性對應的值中放置參數,在 Model 中定義要傳入的值。v-bind 的縮寫是去掉 v-bind、只留下一個冒號 :
v-bind 是將狀態綁定到 HTML 元素上
因此
v-bind:data-id="user.id"
此處可改為
:data-id="user.id"


v-bind:data-id 此處的data-id 是為了帶值到彈出視窗(互動視窗 或叫 Modal)內的 user.id 欄位
.getAttribute(''):取得屬性->DOM語法
選取元素時用元素的屬性去選 e.target.getAttribute('data-value')

btn-primary ->BS5 預設按鈕樣式

v-on:click 可參照 v06.html & v06_01.html
v-on: 事件 = "方法名稱()"
v-on: 的縮寫是 @
-->

<form method="POST" action="delete.php" v-on:submit.prevent="doDelete" style="display: contents;">
<!--
display: contents
此處使用暴力法 直接用 Style 處理
display->改變元素對外所參與的佈局環境 或 對內佈局環境,提供後面元素佈局的規則
也就是 這個form層 不套用CSS格式 但子層套用
詳細範例可參照 1.htm
-->
<input type="hidden" name="id" v-bind:value="user.id" />
<input type="submit" name="submit" class="btn btn-danger" value="刪除" />
</form>
</td>
</tr>
<!-- vue.js for迴圈 End -->
</table>
</div>
<!-- 列表 END -->


<!-- Modal 互動視窗-->
<div class="modal fade" id="editUserModal">
<div class="modal-dialog" role="document">
<!--
Bootstrap 一次只支援一個互動視窗。
role屬性的目的是識別解析軟件元素及其子元素

modal用法
modal.show() //顯示 modal
modal.hide() //隱藏 modal
modal.destroy() //移除 Modal 產生的 dom 元素與 event listeners

以下為 BS5 modal 結構
「data-backdrop="static"」 鎖定背景,點擊背景時不自動關閉視窗
「fade」 淡入、淡出的轉場效果
「modal-lg」視窗大小,如modal-lg、modal-md、modal-sm
「data-dismiss="modal"」 關閉視窗
「data-keyboard="true"」 是否用ESC鍵關閉,預設為true

-------
<div id="OOXX" class="modal fade" tabindex="-1" role="dialog" aria-hidden="true" data-backdrop="static" data-keyboard="true">
<div class="modal-dialog modal-lg" >
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal">
<span>&times;</span>
-------
aria-label = alt (讀螢幕的軟體可以用 無障礙空間 就像 html 的 role屬性
<a href="#" title="設置"><img src="gear.png"></a> => title="設置" 不會唸出
<a href="#" aria-label="設置"><img src="gear.png"></a> => aria-label="設置" 可唸出
詳細 可參照 WAI-ARIA W3C編撰的規格

&times; => X 符號
-->
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">修改資料</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
</div>

<div class="modal-body">
<form method="POST" action="update.php" v-on:submit.prevent="doUpdate" id="form-edit-user" v-if="user != null">
<!--
v-if 請參照 v10.htm
-->
<input type="hidden" name="id" v-bind:value="user.id" />

<div class="form-group">
<label>姓名</label>
<input type="text" name="name" v-bind:value="user.name" class="form-control" />
</div>
<!--
class="form-control" =>BS5 form表單控制
可以使用 .form-control-lg 和 .form-control-sm 設置高度
不然就不要填 用預設
-->
<div class="form-group">
<label>Email</label>
<input type="email" name="email" v-bind:value="user.email" class="form-control" />
</div>
</form>
</div>

<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-dismiss="modal">關閉</button>
<button type="submit" name="submit" class="btn btn-primary" form="form-edit-user">確定修改</button>
</div>
</div>
</div>
<!-- Modal 互動視窗 END -->


<!-- 下方是 頭myApp 跟 內容container 的 div-->
</div>
</div>
<!--
直譯式程式
即時互動 如 BS.js 、 jQuery、Vue.js
一般都放後面
-->
<script src="VueControl.js"></script>

VueControl.js

	const myApp = new Vue({
el: "#myApp", //el: HTML '元素 id'
data: { //資料結構 版面要用的那些資料 從這來的
users: [],//JSON讀取來的資料 或 view版面過來的 初始宣告 為空的 users
user: null //初始宣告變數 user 主要是給互動視窗用
},
methods: {
//建立資料函式
doCreate: function () {
const self = this; //this 關鍵字使用 此處使用 this可方便使用且資料比較不會錯亂
const form = event.target; //事件DOM元件 此處使用 可控制表單那些欄位

const ajax = new XMLHttpRequest(); //AJAX 通訊初始
ajax.open("POST", form.getAttribute("action"), true);
//使用AJAX 將 form 表單 的元素 action 建立
//意思就是 以AJAX即時不刷新 POST的通訊方式
//將form表單資料傳輸至 action="create.php"

ajax.onreadystatechange = function () {
/*
ajax.onreadystatechange
當資料有變化時
觸發事件AJAX
XMLHttpRequest.readyState
客戶端物件目前的狀態
0 UNSENT 客戶端已被建立,但 open() 方法尚未被呼叫。
1 OPENED open() 方法已被呼叫。
2 HEADERS_RECEIVED send() 方法已被呼叫,而且可取得 header 與狀態。
3 LOADING 回應資料下載中,此時 responseText 會擁有部分資料。
4 DONE 完成下載操作。

xmlhttp.status的值及解釋:可查表 較常遇到
200——成功
202——接受和處理、但處理未完成
400——錯誤請求,如語法錯誤
401——請求授權失敗
404——沒有發現檔案、查詢或URl
*/
if (this.readyState == 4) {
if (this.status == 200) {
// console.log(this.responseText);

const user = JSON.parse(this.responseText);
//JSON.parse() 方法把會把一個JSON字串轉換成JavaScript的數值或是物件。

//資料處理
self.users.unshift(user);
/*
陣列資料 原型:Array.prototype.unshift()
將資料加到第一個
例如:
array.unshift('老媽');
console.log(array); // ["老媽", "小明", "杰倫", "漂亮阿姨", "小美"]
與 push() 雷同
*/
}
}
};
//建立form表單資料傳輸 使用 AJAX 即時刷新
const formData = new FormData(form);
ajax.send(formData);
},
//-------建立資料函式 END

//取得所有資料 建立列表頁
getData: function () {
const self = this;

const ajax = new XMLHttpRequest();
ajax.open("POST", "read.php", true);

ajax.onreadystatechange = function () {
if (this.readyState == 4) {
if (this.status == 200) {
// console.log(this.responseText);
const users = JSON.parse(this.responseText);
self.users = users; //將取得的資料 帶進users 給vue.js data用
}
}
};

const formData = new FormData();
ajax.send(formData);
},
//-------
//建立 互動視窗函式
showEditUserModal: function () {
const id = event.target.getAttribute("data-id");
//使用AJAX 將 列表頁的 v-bind:data-id="user.id"
//傳送接收過來

//比對 users 陣列內 有沒有 傳送過來的 user.id 值
//有的話 給互動視窗用的變數 user 改成這一個
for (var a = 0; a < this.users.length; a++) {
if (this.users[a].id == id) {
this.user = this.users[a];
break;
}
}

$("#editUserModal").modal("show"); //將互動視窗顯示
/*
modal用法
modal.show() //顯示 modal
modal.hide() //隱藏 modal
modal.destroy() //移除 Modal 產生的 dom 元素與 event listeners
*/
},
//-------建立 互動視窗函式 END
//更新函式
doUpdate: function () {
const self = this;
const form = event.target;

const ajax = new XMLHttpRequest();
ajax.open("POST", form.getAttribute("action"), true);
//此處AJAX 取得來自互動視窗的 form表單
//action="update.php" 從這一頁 產生的 JSON 資料

//---資料改變 START --
ajax.onreadystatechange = function () {
if (this.readyState == 4) {
if (this.status == 200) {
// console.log(this.responseText);

const user = JSON.parse(this.responseText);
// console.log(user);

//接下來要進行 原本資料排序的資料處理
//因為資料更改後 原users陣列資料會與更新的不同
//因此先找出來該筆資料 原理與line bot 範例同
var index = -1; //為避免麻煩 直接使用本程式不可能出現的數字 如7秒魚範例手法
for (var a = 0; a < self.users.length; a++) {
if (self.users[a].id == user.id) {
index = a;
break;
}
}

// 建立暫存陣列 準備進行陣列重整
//宣告的暫存資料 等於 JSON來的 更新過陣列資料
const tempUsers = self.users;

//將取得有變化的陣列索引 改變成 互動視窗用的 user 變數
tempUsers[index] = user;

// update the local array by removing all old elements and inserting the updated users
//清掉 users 成為空陣列
//在將 users 變成 暫存的陣列 也就是新的資料
self.users = [];
self.users = tempUsers;
}
}
};
//---資料改變 END --

//表單資料 用AJAX 不跳轉頁面傳送
const formData = new FormData(form);
ajax.send(formData);

//隱藏互動視窗
$("#editUserModal").modal("hide");
},
//更新函式 END

//刪除函式
doDelete: function () {
const self = this;
const form = event.target;

const ajax = new XMLHttpRequest();
ajax.open("POST", form.getAttribute("action"), true);

ajax.onreadystatechange = function () {
if (this.readyState == 4) {
if (this.status == 200) {
// console.log(this.responseText);

//移除 users 陣列的資料
for (var a = 0; a < self.users.length; a++) {
if (self.users[a].id == form.id.value) {
self.users.splice(a, 1);
/*
使用arr.splice(要插入或刪除的索引位置, 要刪除的元素數量, 要插入的元素內容)
此處我們使用 a = 位置 索引值
然後再用第二個參數 刪除的元素數量=1
一次只刪一個
*/
break;
}
}
}
}
};

const formData = new FormData(form);
ajax.send(formData);
},
//刪除函式 END
//-----
},//方法結束
//使用AJAX 進行監聽讀取資料 詳細請參照 vue.js 生命週期(lifecycle)圖 mounted
mounted: function () {
this.getData();
}
});

原碼:https://reurl.cc/e3k8yL

給有需要的朋友~

謝謝~宅見~

留言
avatar-img
留言分享你的想法!
avatar-img
吳佳鑫的沙龍
41會員
136內容數
獨立遊戲開發紀錄
吳佳鑫的沙龍的其他內容
2025/04/12
🗓 Steam 上市日期:2025/4/28 | 🖤 加入願望清單:https://store.steampowered.com/app/3634400/Elara/ 「他們說我太敏感,說我不合群。 但我只是——不想學會沉默。」 —Elara Quinn 你是否曾經在工作時,感
Thumbnail
2025/04/12
🗓 Steam 上市日期:2025/4/28 | 🖤 加入願望清單:https://store.steampowered.com/app/3634400/Elara/ 「他們說我太敏感,說我不合群。 但我只是——不想學會沉默。」 —Elara Quinn 你是否曾經在工作時,感
Thumbnail
2025/03/05
在靈異頻發的醫院夜班,小護士林筱筱意外發現她的冷酷上司——蘇醫生,竟然早已死亡五年,從此她與這位神秘的「鬼醫生」攜手處理靈異事件,並在驚魂不斷的夜班中逐漸建立起一段超越生死的羈絆。
Thumbnail
2025/03/05
在靈異頻發的醫院夜班,小護士林筱筱意外發現她的冷酷上司——蘇醫生,竟然早已死亡五年,從此她與這位神秘的「鬼醫生」攜手處理靈異事件,並在驚魂不斷的夜班中逐漸建立起一段超越生死的羈絆。
Thumbnail
2025/02/24
這是一篇懸疑驚悚小說,描述女主角江語珊調查一起離奇命案的故事。死者林曦是一位心理學教授,死於自家公寓,現場佈滿鏡子,死者嘴角帶著詭異的微笑。語珊在調查過程中發現,此案與一種名為「鏡像侵蝕」的心理現象有關,並逐漸被捲入其中。
Thumbnail
2025/02/24
這是一篇懸疑驚悚小說,描述女主角江語珊調查一起離奇命案的故事。死者林曦是一位心理學教授,死於自家公寓,現場佈滿鏡子,死者嘴角帶著詭異的微笑。語珊在調查過程中發現,此案與一種名為「鏡像侵蝕」的心理現象有關,並逐漸被捲入其中。
Thumbnail
看更多
你可能也想看
Thumbnail
大家好,我是一名眼科醫師,也是一位孩子的媽 身為眼科醫師的我,我知道視力發展對孩子來說有多關鍵。 每到開學季時,診間便充斥著許多憂心忡忡的家屬。近年來看診中,兒童提早近視、眼睛疲勞的案例明顯增加,除了3C使用過度,最常被忽略的,就是照明品質。 然而作為一位媽媽,孩子能在安全、舒適的環境
Thumbnail
大家好,我是一名眼科醫師,也是一位孩子的媽 身為眼科醫師的我,我知道視力發展對孩子來說有多關鍵。 每到開學季時,診間便充斥著許多憂心忡忡的家屬。近年來看診中,兒童提早近視、眼睛疲勞的案例明顯增加,除了3C使用過度,最常被忽略的,就是照明品質。 然而作為一位媽媽,孩子能在安全、舒適的環境
Thumbnail
我的「媽」呀! 母親節即將到來,vocus 邀請你寫下屬於你的「媽」故事——不管是紀錄爆笑的日常,或是一直想對她表達的感謝,又或者,是你這輩子最想聽她說出的一句話。 也歡迎你曬出合照,分享照片背後的點點滴滴 ♥️ 透過創作,將這份情感表達出來吧!🥹
Thumbnail
我的「媽」呀! 母親節即將到來,vocus 邀請你寫下屬於你的「媽」故事——不管是紀錄爆笑的日常,或是一直想對她表達的感謝,又或者,是你這輩子最想聽她說出的一句話。 也歡迎你曬出合照,分享照片背後的點點滴滴 ♥️ 透過創作,將這份情感表達出來吧!🥹
Thumbnail
Vue3 學習筆記,專案建立與基礎響應式篇
Thumbnail
Vue3 學習筆記,專案建立與基礎響應式篇
Thumbnail
本篇純粹紀錄實作流程,以方便未來可以照此版繼續優化改進作法,這篇會使用Laravel 9版本並搭配Boostrap 5來做開發。 發現將每一次的實作作筆記,回頭再看的時候,就可以發現實作差異並進行改正,沒搞懂的底層操作也能在覆盤的時候理解,建議大家都要筆記自己的實作流程。
Thumbnail
本篇純粹紀錄實作流程,以方便未來可以照此版繼續優化改進作法,這篇會使用Laravel 9版本並搭配Boostrap 5來做開發。 發現將每一次的實作作筆記,回頭再看的時候,就可以發現實作差異並進行改正,沒搞懂的底層操作也能在覆盤的時候理解,建議大家都要筆記自己的實作流程。
Thumbnail
1. 安裝node.js 2. 建立專案: 接著會詢問一些初始化設定的東西,按照需求選擇即可: 3. 執行 打開http://localhost:3000/ 即可看到畫面。 pages Nuxt.js會自動配置pages中每一個.vue檔案的route。 假設在pages資料夾下新增一個如下內容的a
Thumbnail
1. 安裝node.js 2. 建立專案: 接著會詢問一些初始化設定的東西,按照需求選擇即可: 3. 執行 打開http://localhost:3000/ 即可看到畫面。 pages Nuxt.js會自動配置pages中每一個.vue檔案的route。 假設在pages資料夾下新增一個如下內容的a
Thumbnail
在寫頁面之前,先來介紹 Vue 頁面結構。 首先先在 src/components 底下建立一個 home.vue 跟寫一個 html 頁面很像,一樣是分成 寫網頁內容、script、style,三個部分,只是 html 標籤換成了 template。 template 就是相當於原生 html 檔
Thumbnail
在寫頁面之前,先來介紹 Vue 頁面結構。 首先先在 src/components 底下建立一個 home.vue 跟寫一個 html 頁面很像,一樣是分成 寫網頁內容、script、style,三個部分,只是 html 標籤換成了 template。 template 就是相當於原生 html 檔
Thumbnail
專案建好了,那先來講 Vue 的專案架構 詳細內容很多,所以我挑重點講 public index.html public/index.html 是 Vue 頁面的 entry point,進入一個 Vue 頁面會先進 public/index.html,再套用 App.vue,最後才是進入你寫的 .
Thumbnail
專案建好了,那先來講 Vue 的專案架構 詳細內容很多,所以我挑重點講 public index.html public/index.html 是 Vue 頁面的 entry point,進入一個 Vue 頁面會先進 public/index.html,再套用 App.vue,最後才是進入你寫的 .
Thumbnail
前言 Vue 在過去的一兩年內快速發展,寫法也一直改變,我在過去一年多也更改了兩次寫法,在這個系列中我將以最新的 composition api + typescript 寫法進行教學。 javascript 有兩大痛點,一個是異步問題,另一個是弱型別。要渲染畫面一定要多線程同時異步處理,不然真的一
Thumbnail
前言 Vue 在過去的一兩年內快速發展,寫法也一直改變,我在過去一年多也更改了兩次寫法,在這個系列中我將以最新的 composition api + typescript 寫法進行教學。 javascript 有兩大痛點,一個是異步問題,另一個是弱型別。要渲染畫面一定要多線程同時異步處理,不然真的一
Thumbnail
data() method 續上篇,這邊修改一下HomeView.vue的code。 Before: After: 在頁面最下方顯示 name: Vic,data method直接回傳name變數,在<template>中可以直接用{{ name }}將變數顯示出來。 結果如下: v-model
Thumbnail
data() method 續上篇,這邊修改一下HomeView.vue的code。 Before: After: 在頁面最下方顯示 name: Vic,data method直接回傳name變數,在<template>中可以直接用{{ name }}將變數顯示出來。 結果如下: v-model
Thumbnail
假設資料如下: local DB裡面的test Collection SELECT SELECT可以這樣寫: 由於config/database.php中設定的default DB_CONNECTION是mysql,所以這邊特別指定使用mongodb connection。 回傳結果如下: 軟刪除
Thumbnail
假設資料如下: local DB裡面的test Collection SELECT SELECT可以這樣寫: 由於config/database.php中設定的default DB_CONNECTION是mysql,所以這邊特別指定使用mongodb connection。 回傳結果如下: 軟刪除
Thumbnail
S1.建立資料庫 user S2.建立 index.htm a.載入 vue.js、jquery、bootstrap b.版面建立 S3.vue.js程式 新增、查看列表、互動視窗、修改、刪除 index.htm VueControl.js 原碼:https://reurl.cc/e3k8yL
Thumbnail
S1.建立資料庫 user S2.建立 index.htm a.載入 vue.js、jquery、bootstrap b.版面建立 S3.vue.js程式 新增、查看列表、互動視窗、修改、刪除 index.htm VueControl.js 原碼:https://reurl.cc/e3k8yL
追蹤感興趣的內容從 Google News 追蹤更多 vocus 的最新精選內容追蹤 Google News