此阶段多练习 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');
},
},
});
<<: [2020铁人赛] Day26 - 用DocX汇出Word档案
昨天我们让 Line Bot 可以成功回应使用者验证码了,但是这样只要任何人加入 Line Bot ...
写在前面 刚开始学程序语言的时候总会有一些看起来很简单但很容易跳进去的坑,基础运算子还有逻辑运算在我...
线性的资料储存方式一般有两种 array (阵列) list node (链结) 这两种差别到底在那...
前言 HIYO!又是阿峻我啦~ 不知从何时开始,Deep Learning 跟 AI 这两个名词好像...
_Layout布局(版面配置)页 预设当我们新建好.net5 mvc专案後 比方今天新增一个空的Ra...