此階段多練習 Vue.js 的各項語法及指令,目標先以完成一頁式的產品新增、刪除、修改的頁面(先不串接 API)。
課程練習連結
<div id="app" class="container mt-3">
<div>
<div class="text-right mt-4">
<button class="btn btn-primary" @click="openModal('new')">
建立新的產品
</button>
</div>
<table class="table mt-4">
<thead>
<tr>
<th width="15%">分類</th>
<th>產品名稱</th>
<th>產品圖像</th>
<th width="10%">原價</th>
<th width="10%">售價</th>
<th width="10%">是否啟用</th>
<th width="15%">編輯</th>
</tr>
</thead>
<tbody>
<tr v-for="(item) in products" :key="item.id">
<td>{{ item.category }}</td>
<td>{{ item.title }}</td>
<td><template>
<img class="thumb-img" :src="item.imageUrl" alt="">
</template></td>
<td>{{ item.origin_price }}</td>
<td>{{ item.price }}</td>
<td>
<span v-if="item.is_enabled" class="text-success">啟用</span>
<span v-else>未啟用</span>
</td>
<td>
<div class="btn-group">
<button class="btn btn-outline-primary btn-sm mr-2"
@click="openModal('edit' , item)">編輯</button>
<button class="btn btn-outline-danger btn-sm"
@click="openModal('delete' , item)">刪除</button>
</div>
</td>
</tr>
</tbody>
</table>
<!-- Modal -->
<div id="productModal" class="modal fade" tabindex="-1" role="dialog"
aria-labelledby="exampleModalLabel"
aria-hidden="true">
<div class="modal-dialog modal-xl" role="document">
<div class="modal-content border-0">
<div class="modal-header bg-dark text-white">
<h5 id="exampleModalLabel" class="modal-title">
<span>新增產品</span>
</h5>
<!-- 關閉按鈕-->
<button type="button" class="close"
data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<!--modal-header END -->
<div class="modal-body">
<div class="row">
<div class="col-sm-4">
<div class="form-group">
<label for="imageUrl">輸入圖片網址</label>
<input id="imageUrl"
v-model="tempProduct.imageUrl" type="text"
class="form-control" placeholder="請輸入圖片連結">
</div>
<img :src="tempProduct.imageUrl" alt="" class="img-fluid">
</div>
<!--col-sm-4 END -->
<div class="col-sm-8">
<div class="form-group">
<label for="title">標題</label>
<input id="title"
v-model="tempProduct.title" type="text"
class="form-control" placeholder="請輸入標題">
</div>
<div class="form-row">
<div class="form-group col-md-6">
<label for="category">分類</label>
<input id="category"
v-model="tempProduct.category" type="text"
class="form-control" placeholder="請輸入分類">
</div>
<div class="form-group col-md-6">
<label for="unit">單位</label>
<input id="unit"
v-model="tempProduct.unit" type="text"
class="form-control" placeholder="請輸入單位">
</div>
</div>
<div class="form-row">
<div class="form-group col-md-6">
<label for="origin_price">原價</label>
<input id="origin_price"
v-model="tempProduct.origin_price" type="text"
class="form-control" placeholder="請輸入原價">
</div>
<div class="form-group col-md-6">
<label for="price">售價</label>
<input id="price"
v-model="tempProduct.price" type="text"
class="form-control" placeholder="請輸入售價">
</div>
</div>
<div class="form-group">
<label for="description">產品描述</label>
<input id="description"
v-model="tempProduct.description" type="text"
class="form-control" placeholder="請輸入產品描述">
</div>
<div class="form-group">
<label for="content">說明內容</label>
<input id="content"
v-model="tempProduct.content" type="text"
class="form-control" placeholder="請輸入說明內容">
</div>
<div class="form-group">
<div class="form-check">
<input type="checkbox" id="is_enabled"
v-model="tempProduct.is_enabled"
class="form-check-input" :true-value="1"
:flase-value="0">
<label for="is_enabled" class="form-check-label">
是否啟用</label>
</div>
</div>
</div>
<!--col-sm-8 END-->
</div>
<!--row END -->
</div>
<!--modal-bady END -->
<div class="modal-footer">
<button class="btn btn-outline-secondary" type="button"
data-dismiss="modal">取消</button>
<button class="btn btn-primary" type="button" @click="saveProduct">
確認</button>
</div>
<!--modal-footer END -->
</div>
</div>
</div>
<!--productModal END -->
<div id="delProductModal" class="modal fade" tabindex="-1" role="dialog"
aria-labelledby="exampleModalLabel"
aria-hidden="true">
<div class="modal-dialog" role="document">
<div class="modal-content border-0">
<div class="modal-header bg-danger text-white">
<h5 id="exampleModalLabel" class="modal-title">
<span>刪除產品</span>
</h5>
<!-- 關閉按鈕-->
<button type="button" class="close"
data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<!--modal-header END -->
<div class="modal-body">
是否刪除 <strong class="text-danger">{{ tempProduct.title }}</strong>
商品(刪除後將無法恢復)。
</div>
<!--modal-bady END -->
<div class="modal-footer">
<button class="btn btn-outline-secondary"
type="button" data-dismiss="modal">取消</button>
<button class="btn btn-danger" type="button" @click="delProduct">
確認刪除</button>
</div>
<!--modal-footer END -->
</div>
</div>
</div>
<!--delProductModal END -->
</div>
</div>
new Vue({
//指定
el: '#app',
//資料
data: {
products: [
{
id: 20200805001,
unit: '隻',
category: '運動手錶',
title: 'SUUNTO 7',
origin_price: 15900,
price: 12900,
description: '結合豐富的【戶外運動】與【智慧生活】功能於一體的 GPS 腕錶',
content: '一般智慧型手錶',
is_enabled: 1,
imageUrl: 'https://img.empyrean.tw/40F72F99-F4A3-4AF0-8680-A40F01307BC9.png',
},
{
id: 20200805002,
unit: '隻',
category: '運動手錶',
title: 'SUUNTO 5',
origin_price: 12900,
price: 9450,
description: '堅固輕巧質精,擁有絕佳的電池續航力,支援四星定位的 GPS 運動腕錶',
content: '中強運動可使用',
is_enabled: 0,
imageUrl: 'https://img.empyrean.tw/DEE3E9B7-86BF-4FFC-9BE3-3EF207F9B9F8.png',
},
{
id: 20200805003,
unit: '隻',
category: '運動手錶',
title: 'SUUNTO 9 BARO',
origin_price: 27800,
price: 24800,
description: '堅固強勁,超長電池續航力及氣壓式高度的多項目運動GPS腕錶',
content: '旗艦級三鐵錶',
is_enabled: 1,
imageUrl: 'https://img.empyrean.tw/4E23BD85-544B-42F9-AFF7-3E39787AB593.png',
},
],
tempProduct: {}, //暫存區
},
//方法
methods: {
//把暫存資料存回原本物件或新建資料
saveProduct() {
let vm = this;
if (vm.tempProduct.id) { //覆蓋原有資料
const id = vm.tempProduct.id;
vm.products.forEach((item, i) => {
if (item.id === id) {
vm.products[i] = vm.tempProduct;
}
});
} else { //新建資料
const id = new Date().getTime();
vm.tempProduct.id = id;
vm.products.push(vm.tempProduct);
}
vm.tempProduct = {};
$('#productModal').modal('hide');
},
//開啟視窗
openModal(product, item) {
let vm = this;
switch (product) {
//新增
case 'new':
vm.tempProduct = {};
$('#productModal').modal('show');
break;
//編輯
case 'edit':
vm.tempProduct = Object.assign({}, item);
// 物件淺拷貝,把資料做拷貝到空物件,不要動到原本的
$('#productModal').modal('show');
break;
//刪除
case 'delete':
vm.tempProduct = Object.assign({}, item);
$('#delProductModal').modal('show');
break;
default:
break;
}
},
//刪除資料
delProduct() {
let vm = this;
if (vm.tempProduct.id) {
const id = vm.tempProduct.id;
vm.products.forEach((item, i) => {
if (item.id === id) {
vm.products.splice(i, 1);
vm.tempProduct = {};
}
});
}
$('#delProductModal').modal('hide');
},
},
});