六角學院_Vue直播班_主線任務
1.將原本刪除 modal 的 html,變成 x-template,元件標籤(delete-product-modal)
問題 | 成因 | 行動 |
---|---|---|
預設匯出失敗 | 不知道怎麼寫 | 偷看助教寫的,改用 x-template 比較簡單 |
1.1 將 bootstap 實體化移到 delete-product-modal 的 mounted 裡面
問題 | 成因 | 行動 |
---|---|---|
沒辦法把 modal 關掉 | 把關掉的 function ( hideModal ) 放到 methods 外面所以叫不到 | 塞回 methods |
2.註冊 delete-product-modal
問題 | 成因 | 行動 |
---|---|---|
註冊失敗 | 忘記區域註冊方法 | 偷看助教的,改成全域註冊 |
3.使用 delete-product-modal
問題 | 成因 | 行動 |
---|---|---|
一直跳錯 | x-template 的 script 標籤要放在 div.app 外面 | 放到外面 |
4.將選擇的產品(tempProduct) 傳入 delete-product-modal
5.點選確認刪除會刪掉商品,跳出提示後,關閉 modal
問題 | 成因 | 行動 |
---|---|---|
按下確認刪除之後列表上的資料不會更新 | 刪除完後沒辦法呼叫外面的 this.getProducts() | 內層用 emit 傳一個 update 事件呼叫外層的 getProducts() |
1 改成全域註冊的原件
1.1 將原本新增編輯 modal 的 html,變成 x-template
<script type="text/x-template" id="delProductModal"></script>
1.2 進行全域註冊
app.component('update-product-modal', {
template: '#productModal',
data() {
return {
apiUrl: 'https://vue3-course-api.hexschool.io/v2',
path: 'jasonchen',
};
},
});
1.3 將 bootstrap 實體化移到 update-product-modal 的 mounted
mounted() {
// 創建 bootstrap 實體
// 新增和編輯的 modal
productModal = new bootstrap.Modal(
document.getElementById('productModal'),
{
// esc 沒辦法關掉 modal
keyboard: false,
// 點選旁邊沒辦法關掉 modal
backdrop: 'static',
}
);
}
2 將元件要用的資料傳入( update-product-modal )
2.1 在 html 使用 update-product-modal
<update-product-modal></update-product-modal>
2.2 將選擇的產品( tempProduct )傳入 update-product-modal
<update-product-modal
:temp-product="tempProduct"
></update-product-modal>
2.3 將傳入的 tempProduct 用 props 接住
app.component('update-product-modal', {
template: '#productModal',
props: ['tempProduct'],
});
2.4 將是否是編輯功能( isEdit )傳入,來決定 modal 是新增 modal 還是編輯 modal
<update-product-modal
:temp-product="tempProduct"
:is-edit="isEdit"
></update-product-modal>
2.5 將傳入的 isEdit 用 props 接住
app.component('update-product-modal', {
template: '#productModal',
props: ['tempProduct', 'isEdit'],
});
3 將原本在外面的 methods 搬到元件裡面
3.1 點選新增 modal 的確認會呼叫 addProduct() 、editProduct(),當成功時會
3.1.1 呼叫 hideModal(),關閉 modal
3.1.1 向外傳出 update 事件
methods: {
addProduct() {
const url = `${this.apiUrl}/api/${this.path}/admin/product`;
const addData = { data: this.tempProduct };
axios
.post(url, addData)
.then((res) => {
alert(res.data.message);
this.hideModal();
this.$emit('update');
})
.catch((err) => {
alert(err.data.message);
});
},
editProduct() {
const url = `${this.apiUrl}/api/${this.path}/admin/product/${this.tempProduct.id}`;
const editData = { data: this.tempProduct };
axios
.put(url, editData)
.then((res) => {
alert(res.data.message);
this.hideModal();
this.$emit('update');
})
.catch((err) => {
alert(err.data.message);
});
},
// 把關閉 modal 拉出來做成 function,將功能拆分清楚
hideModal() {
productModal.hide();
},
},
3.2 外層接收 update 事件,呼叫 getProducts()
<update-product-modal
:temp-product="tempProduct"
:is-edit="isEdit"
@update="getProducts"
></update-product-modal>
methods: {
getProducts() {
// 清空 tempProduct
this.tempProduct = { imagesUrl: [] };
const url = `${this.apiUrl}/api/${this.path}/admin/products`;
axios
.get(url)
.then((res) => {
this.products = res.data.products;
})
.catch((err) => {
alert(err.data.message);
});
},
}
1 放入分頁結構
<!-- 分頁 -->
<nav aria-label="Page navigation ">
<ul class="pagination">
<!-- 上一頁符號 -->
<li class="page-item">
<a class="page-link" href="#" aria-label="Previous">
<span aria-hidden="true">«</span>
</a>
</li>
<!-- 頁碼 -->
<li class="page-item"><a class="page-link" href="#">1</a></li>
<li class="page-item"><a class="page-link" href="#">2</a></li>
<li class="page-item"><a class="page-link" href="#">3</a></li>
<!-- 下一頁符號 -->
<li class="page-item">
<a class="page-link" href="#" aria-label="Next">
<span aria-hidden="true">»</span>
</a>
</li>
</ul>
</nav>
2 data 部分新增 pagination ,在 getProducts() 拿到要做出分頁的資訊
const app = createApp({
data() {
pagination: {},
};
},
methods: {
getProducts() {
// 清空 tempProduct
this.tempProduct = { imagesUrl: [] };
const url = `${this.apiUrl}/api/${this.path}/admin/products`;
axios
.get(url)
.then((res) => {
this.products = res.data.products;
this.pagination = res.data.pagination;
})
.catch((err) => {
alert(err.data.message);
});
}
}
});
3 v-for 出幾個分頁
<li class="page-item" v-for="num in pagination.total_pages" :key="num">
<a class="page-link" href="#">{{num}}</a>
</li>
4 是否有前一頁和後一頁
<!-- 上一頁符號 -->
<li class="page-item" :class="{disabled : !pagination.has_pre}">
<a class="page-link" href="#" aria-label="Previous">
<span aria-hidden="true">«</span>
</a>
</li>
<!-- 下一頁符號 -->
<li class="page-item" :class="{disabled : !pagination.has_next}">
<a class="page-link" href="#" aria-label="Next">
<span aria-hidden="true">»</span>
</a>
</li>
5 在 data 新增現在的頁數( nowPage ),增加這個是為了在每次執行 getProducts() 時,不會跳回到第一頁
const app = createApp({
data() {
nowPage: 1,
};
},
methods: {
getProducts() {
// 清空 tempProduct
this.tempProduct = { imagesUrl: [] };
const url = `${this.apiUrl}/api/${this.path}/admin/products?page=${this.nowPage}`;
axios
.get(url)
.then((res) => {
this.products = res.data.products;
this.pagination = res.data.pagination;
this.nowPage = res.data.pagination.current_page;
})
.catch((err) => {
alert(err.data.message);
});
}
});
6 使用 nowPage 決定頁碼的 style
<li class="page-item" v-for="num in pagination.total_pages" :key="num" :class="{active : num === nowPage}">
<a class="page-link" href="#">{{num}}</a>
</li>
7 點擊分頁頁碼會去取得該頁的資訊
<li class="page-item" v-for="num in pagination.total_pages" :key="num" :class="{active : num === nowPage}">
<a class="page-link" href="#" @click="changePage(num)">{{num}}</a>
</li>
const app = createApp({
methods: {
changePage(page) {
this.nowPage = page;
this.getProducts();
}
});
1 改成全域註冊的原件
1.1 將原本分頁 的 html,變成 x-template
<script type="text/x-template" id="productsPagination"></script>
1.2 進行全域註冊
app.component('products-pagination', {
template: '#productsPagination'
});
2 將元件要用的資料傳入( update-product-modal )
2.1 在 html 使用 update-product-modal
<products-pagination></products-pagination>
2.2 將選頁碼資訊( pagination ),傳入 update-product-modal
<products-pagination
:pagination="pagination"
></products-pagination>
2.3 將傳入的 tempProduct 用 props 接住
app.component('products-pagination', {
template: '#productsPagination',
props: ['pagination'],
});
3 內元件( products-pagination )向外元件傳送資訊
3.1 點選頁碼時會向外面傳出 update 事件和現在點選的頁碼數字
<li class="page-item" v-for="num in pagination.total_pages" :key="num" :class="{active : num === pagination.current_page}">
<a class="page-link" href="#" @click.prevent="$emit('update',num)">{{num}}</a>
</li>
3.2 外層接收 update 事件和點選數字,呼叫 changePage()
<products-pagination
:pagination="pagination"
@update="changePage"
></products-pagination>
const app = createApp({
methods: {
changePage(page) {
this.nowPage = page;
this.getProducts();
}
});
4 點選上下一頁可以換頁
4.1 點選上下一頁會向外面傳出 update 事件和加或減現在點選的頁碼數字( nowPage加或減 1 )
<!-- 上一頁符號 -->
<li class="page-item" :class="{disabled : !pagination.has_pre}">
<a class="page-link" href="#" aria-label="Previous" @click.prevent="$emit('update',pagination.current_page-1)">
<span aria-hidden="true">«</span>
</a>
</li>
<!-- 下一頁符號 -->
<li class="page-item" :class="{disabled : !pagination.has_next}">
<a class="page-link" href="#" aria-label="Next" @click.prevent="$emit('update',pagination.current_page+1)">
<span aria-hidden="true">»</span>
</a>
</li>
4.2 要避免第一頁和最後一頁爆掉問題
changePage(page) {
// 第一頁不能往前
if (page <= 1) {
page = 1;
}
// 最後一頁不能往後
if (page >= this.pagination.total_pages) {
page = this.pagination.total_pages;
}
this.nowPage = page;
this.getProducts();
}
1.每次 getProducts(),就清空 tempProduct ,原本是寫在按各個 modal 確認按鈕時會執行,現在每次按確認都會傳出一個 update 事件執行 getProducts() ,所以寫在getProducts() 裡面一次就好
getProducts() {
// 清空 tempProduct
this.tempProduct = { imagesUrl: [] };
const url = `${this.apiUrl}/api/${this.path}/admin/products`;
axios
.get(url)
.then((res) => {
this.products = res.data.products;
})
.catch((err) => {
alert(err.data.message);
});
},
2.另外在打開新增 modal 時,也要清空一次 tempProduct,保險起見
openModal(type, product) {
// 使用深層拷貝避免改動 modal 的值時,改到外面清單的值
this.tempProduct = JSON.parse(JSON.stringify(product));
if (type === 'delete') {
delProductModal.show();
} else if (type === 'add') {
// 清空 tempProduct
this.tempProduct = { imagesUrl: [] };
this.isEdit = false;
productModal.show();
} else if (type === 'edit') {
this.isEdit = true;
productModal.show();
}
}
問題 | 成因 | 行動 |
---|---|---|
cookie 寫不進去 | 忘記怎麼把回傳的 cookie 寫進去 | 偷看之前寫的 |