快速入門 Vue.js: 商品後台管理介面
MVVM 概念介紹
Vue.js 起手式
環境安裝 – Vue.js devtools
// HTML
<div id="app">
{{ counter }}
{{ text }}
</div>
// JS
Vue.createApp({
data() {
return {
counter: 5,
text: "這裡有一段文字",
};
},
}).mount("#app");
起手常見結構
// HTML
<div id="app">
{{ counter }}
<button type="button" v-on:click="clickMe">按我</button>
</div>
// JS
const app = {
// 資料 (函式)
data() {
return {
counter: 0,
};
},
// 生命週期 (函式)
created() {
this.counter = 10;
console.log(this);
},
// 方法 (物件)
methods: {
clickMe() {
// console.log(1);
this.counter = this.counter + 1;
},
},
};
Vue.createApp(app).mount("#app");
雙向綁定的技巧
// HTML
<div id="app">
<form>
{{ temp }}
<div class="mb-3">
<label for="productName" class="form-label">產品名稱</label>
<input
type="text"
id="productName"
class="form-control"
v-model="temp.name"
/>
</div>
<div class="mb-3">
<!-- HTML 屬性 -->
<img v-bind:src="temp.imageUrl" class="img-fluid" alt="" />
<label for="productImage" class="form-label">產品圖片</label>
<input
type="text"
id="productImage"
class="form-control"
v-model="temp.imageUrl"
/>
</div>
<button type="button" class="btn btn-secondary" v-on:click="confirmEdit">
更新
</button>
</form>
</div>
// JS
const App = {
data() {
return {
temp: {
name: "筆電",
imageUrl:
"https://images.unsplash.com/photo-1602526430780-782d6b1783fa?ixid=MXwxMjA3fDF8MHxwaG90by1wYWdlfHx8fGVufDB8fHw%3D&ixlib=rb-1.2.1&auto=format&fit=crop&w=1350&q=80",
},
};
},
methods: {
confirmEdit() {
console.log(this.temp);
},
},
};
Vue.createApp(App).mount("#app");
將資料加入於 Vue Data
// HTML
<div id="app">
<form>
<div class="mb-3">
<label for="productName" class="form-label">產品名稱</label>
<input
type="text"
id="productName"
class="form-control"
v-model="temp.name"
/>
</div>
<div class="mb-3">
<img :src="temp.imageUrl" class="img-fluid d-block" alt="" width="300" />
<label for="productImage" class="form-label">產品圖片</label>
<input
type="text"
id="productImage"
class="form-control"
v-model="temp.imageUrl"
/>
</div>
<button type="button" class="btn btn-secondary" v-on:click="confirmEdit">
更新
</button>
</form>
</div>
// JS
const products = [
{
id: "1",
imageUrl:
"https://images.unsplash.com/photo-1516906571665-49af58989c4e?ixlib=rb-1.2.1&ixid=MXwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHw%3D&auto=format&fit=crop&w=300&q=80",
name: "MacBook Pro",
onStock: false,
},
{
id: "2",
imageUrl:
"https://images.unsplash.com/photo-1512499617640-c74ae3a79d37?ixid=MXwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHw%3D&ixlib=rb-1.2.1&auto=format&fit=crop&w=300&q=80",
name: "iPhone",
onStock: false,
},
];
const App = {
data() {
return {
temp: {
name: "筆電",
imageUrl:
"https://images.unsplash.com/photo-1602526430780-782d6b1783fa?ixid=MXwxMjA3fDF8MHxwaG90by1wYWdlfHx8fGVufDB8fHw%3D&ixlib=rb-1.2.1&auto=format&fit=crop&w=1350&q=80",
},
products: [],
};
},
methods: {
confirmEdit() {
this.temp.id = new Date().getTime(); // unix timestamp
this.temp.onStock = false;
// console.log(this.temp);
this.products.push(this.temp); // 把 temp 加入到 products;
this.temp = {};
},
},
created() {
this.products = products;
},
};
Vue.createApp(App).mount("#app");
簡單語法呈現大量資料於畫面上
// HTML
<div id="app">
<table class="table">
<thead>
<tr>
<th>標題</th>
<th>圖片</th>
<th>銷售狀態</th>
<th>編輯</th>
</tr>
</thead>
<tbody>
<!-- :key 補上唯一值 -->
<tr
v-for="item in products"
key="item.id"
v-bind:class="{ 'table-success': item.onStock }"
>
<td>{{ item.name }}</td>
<td>
<img v-bind:src="item.imageUrl" width="300" alt="" />
</td>
<td>
<input type="checkbox" v-model="item.onStock" />
<!-- {{ item.onStock }} -->
</td>
<td>
<button type="button" class="btn btn-outline-primary">編輯</button>
</td>
</tr>
</tbody>
</table>
<form>
<div class="mb-3">
<label for="productName" class="form-label">產品名稱</label>
<input
type="text"
id="productName"
class="form-control"
v-model="temp.name"
/>
</div>
<div class="mb-3">
<img :src="temp.imageUrl" class="img-fluid d-block" alt="" width="300" />
<label for="productImage" class="form-label">產品圖片</label>
<input
type="text"
id="productImage"
class="form-control"
v-model="temp.imageUrl"
/>
</div>
<button type="button" class="btn btn-secondary" v-on:click="confirmEdit">
更新
</button>
</form>
</div>
// JS
const products = [
{
id: "1",
imageUrl:
"https://images.unsplash.com/photo-1516906571665-49af58989c4e?ixlib=rb-1.2.1&ixid=MXwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHw%3D&auto=format&fit=crop&w=300&q=80",
name: "MacBook Pro",
onStock: false,
},
{
id: "2",
imageUrl:
"https://images.unsplash.com/photo-1512499617640-c74ae3a79d37?ixid=MXwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHw%3D&ixlib=rb-1.2.1&auto=format&fit=crop&w=300&q=80",
name: "iPhone",
onStock: false,
},
];
const App = {
data() {
return {
products: [],
temp: {
name: "卡斯伯",
imageUrl:
"https://images.unsplash.com/photo-1602526430780-782d6b1783fa?ixid=MXwxMjA3fDF8MHxwaG90by1wYWdlfHx8fGVufDB8fHw%3D&ixlib=rb-1.2.1&auto=format&fit=crop&w=1350&q=80",
},
};
},
methods: {
confirmEdit() {
this.temp.id = new Date().getTime();
this.temp.onStock = false;
this.products.push(this.temp);
this.temp = {};
},
},
created() {
this.products = products;
},
};
Vue.createApp(App).mount("#app");
編輯你的資料狀態
// HTML
<div id="app">
<table class="table">
<thead>
<tr>
<th>標題</th>
<th>圖片</th>
<th>銷售狀態</th>
<th>編輯</th>
</tr>
</thead>
<tbody>
<tr
v-for="item in products"
:key="item.id"
:class="{'table-success': item.onStock}"
>
<td>{{ item.name }}</td>
<td>
<img :src="item.imageUrl" alt="" height="100" />
</td>
<td>
<input type="checkbox" v-model="item.onStock" />
</td>
<td>
<button
type="button"
class="btn btn-outline-primary"
v-on:click="editItem(item)"
>
修改
</button>
</td>
</tr>
</tbody>
</table>
<form>
<div class="mb-3">
<label for="productName" class="form-label">產品名稱</label>
<input
type="text"
id="productName"
class="form-control"
v-model="temp.name"
/>
</div>
<div class="mb-3">
<img :src="temp.imageUrl" class="img-fluid d-block" alt="" width="300" />
<label for="productImage" class="form-label">產品圖片</label>
<input
type="text"
id="productImage"
class="form-control"
v-model="temp.imageUrl"
/>
</div>
<button type="button" class="btn btn-secondary" v-on:click="confirmEdit">
更新
</button>
</form>
</div>
// JS
const products = [
{
id: "1",
imageUrl:
"https://images.unsplash.com/photo-1516906571665-49af58989c4e?ixlib=rb-1.2.1&ixid=MXwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHw%3D&auto=format&fit=crop&w=300&q=80",
name: "MacBook Pro",
onStock: false,
},
{
id: "2",
imageUrl:
"https://images.unsplash.com/photo-1512499617640-c74ae3a79d37?ixid=MXwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHw%3D&ixlib=rb-1.2.1&auto=format&fit=crop&w=300&q=80",
name: "iPhone",
onStock: false,
},
];
const App = {
data() {
return {
products: [],
temp: {
name: "筆電",
imageUrl:
"https://images.unsplash.com/photo-1602526430780-782d6b1783fa?ixid=MXwxMjA3fDF8MHxwaG90by1wYWdlfHx8fGVufDB8fHw%3D&ixlib=rb-1.2.1&auto=format&fit=crop&w=1350&q=80",
},
};
},
methods: {
confirmEdit() {
if (!this.temp.id) {
// 新增資料
this.temp.id = new Date().getTime();
this.temp.onStock = false;
this.products.push(this.temp);
this.temp = {};
} else {
this.products.forEach((item, i) => {
if (item.id === this.temp.id) {
this.products[i] = this.temp;
}
});
this.temp = {};
}
},
editItem(item1) {
// console.log("editItem", item1);
// 陷阱
// this.temp = item1;
// 淺層拷貝
this.temp = { ...item1 };
},
},
created() {
this.products = products;
},
};
Vue.createApp(App).mount("#app");
基礎章節作業: 完成新增、編輯商品項目
// HTML
<div id="app">
<div class="text-end">
<button class="btn btn-primary" type="button" v-on:click="addItem">
新增
</button>
</div>
<table class="table">
<thead>
<tr>
<th>標題</th>
<th>圖片</th>
<th>銷售狀態</th>
<th>編輯</th>
</tr>
</thead>
<tbody>
<tr
v-for="item in products"
:key="item.id"
:class="{'table-success': item.onStock}"
>
<td>{{ item.name }}</td>
<td>
<img :src="item.imageUrl" alt="" height="100" />
</td>
<td>
<input type="checkbox" v-model="item.onStock" />
</td>
<td>
<button
type="button"
class="btn btn-outline-primary"
v-on:click="editItem(item)"
>
修改
</button>
</td>
</tr>
</tbody>
</table>
<form v-if="isNew || temp.id">
<div class="mb-3">
<label for="productName" class="form-label">產品名稱</label>
<input
type="text"
id="productName"
class="form-control"
v-model="temp.name"
/>
</div>
<div class="mb-3">
<label for="productImage" class="form-label">產品圖片</label>
<input
type="text"
id="productImage"
class="form-control"
v-model="temp.imageUrl"
/>
</div>
<button type="button" class="btn btn-secondary" v-on:click="confirmEdit">
更新
</button>
</form>
</div>
// JS
const products = [
{
id: "1",
imageUrl:
"https://images.unsplash.com/photo-1516906571665-49af58989c4e?ixlib=rb-1.2.1&ixid=MXwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHw%3D&auto=format&fit=crop&w=300&q=80",
name: "MacBook Pro",
onStock: false,
},
{
id: "2",
imageUrl:
"https://images.unsplash.com/photo-1512499617640-c74ae3a79d37?ixid=MXwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHw%3D&ixlib=rb-1.2.1&auto=format&fit=crop&w=300&q=80",
name: "iPhone",
onStock: false,
},
];
const App = {
data() {
return {
products: [],
temp: {},
// 狀態,決定是否為新增產品
isNew: false,
};
},
methods: {
editItem(item) {
this.temp = { ...item };
},
confirmEdit() {
if (!this.temp.id) {
this.temp.id = new Date().getTime();
this.temp.onStock = false;
this.products.push(this.temp);
} else {
this.products.forEach((item, i) => {
if (item.id === this.temp.id) {
this.products[i] = this.temp;
}
});
}
this.temp = {};
this.isNew = false;
},
addItem() {
this.isNew = true;
this.temp = {};
},
},
created() {
this.products = products;
},
};
Vue.createApp(App).mount("#app");