--- tags: Vue 直播班 - 2022 冬季班 --- * [API 申請](https://vue3-course-api.hexschool.io/) * [API 文件](https://hexschool.github.io/vue3-courses-swaggerDoc/#/) # 第六週:Sweet Alert、Vue Loading * [Vite 模版](https://github.com/hexschool/vite-template) > 示範用 API:vue3-course-api.hexschool.io/v2/api/casper-hexschool/products/all ``` // .env VITE_APP_URL=https://vue3-course-api.hexschool.io/ VITE_APP_PATH=casper-hexschool ``` ::: spoiler 範例模版 ``` javascript <template> <h1>This is About page.</h1> <router-link to="/">Home</router-link> | <router-link to="/about">About</router-link> <div > <ul style="min-height:100px"> <li v-for="product in products" :key="product.id"> <h3>{{ product.title }}</h3> <img :src="product.imageUrl" width="200" alt=""> </li> </ul> </div> </template> <script> import axios from 'axios' const { VITE_APP_URL, VITE_APP_PATH } = import.meta.env export default { data () { return { products: [] } }, methods: { getProducts () { axios.get(`${VITE_APP_URL}/v2/api/${VITE_APP_PATH}/products/all`) .then((res) => { this.products = res.data.products }) } }, mounted () { this.getProducts() } } </script> <style scoped> </style> ``` ::: ## [Sweet Alert 2](https://sweetalert2.github.io/) * [安裝方法](https://sweetalert2.github.io/#download) * [Demo](https://sweetalert2.github.io/#examples) * [多顆按鈕](https://sweetalert2.github.io/#three-buttons) :::spoiler 輸入 input ```javascript Swal.fire({ title: '新增產品資訊', input: 'text', confirmButtonText: '儲存', inputPlaceholder: '請輸入產品資訊' }).then((result) => { console.log(result) /* Read more about isConfirmed, isDenied below */ if (result.isConfirmed) { Swal.fire('Saved!', '', 'success') } else if (result.isDenied) { Swal.fire('Changes are not saved', '', 'info') } }) ``` ::: :::spoiler 點擊取得所有產品資訊 ```javascript <template> <h1>This is About page.</h1> <router-link to="/">Home</router-link> | <router-link to="/about">About</router-link> <div> <input type="button" @click="getProducts" value="取得所有產品資料"> <ul> <li v-for="product in products" :key="product.id"> <h3>{{ product.title }}</h3> <img :src="product.imageUrl" width="200" alt=""> </li> </ul> </div> </template> <script> import Swal from 'sweetalert2' import axios from 'axios' const { VITE_APP_URL, VITE_APP_PATH } = import.meta.env export default { data () { return { products: [] } }, methods: { getProducts () { axios.get(`${VITE_APP_URL}/v2/api/${VITE_APP_PATH}/products/all`) .then((res) => { this.products = res.data.products Swal.fire('成功取得產品資訊') }) } } } </script> <style scoped> </style> ``` ::: ## [Vue Loading](https://github.com/ankurk91/vue-loading-overlay) ### component 元件載入 :::spoiler 範例程式碼 ```javascript <template> <h1>This is About page.</h1> <router-link to="/">Home</router-link> | <router-link to="/about">About</router-link> <div > <loading v-model:active="isLoading" :can-cancel="true" :color="color" :on-cancel="onCancel" :is-full-page="fullPage"/> <ul style="min-height:100px"> <li v-for="product in products" :key="product.id"> <h3>{{ product.title }}</h3> <img :src="product.imageUrl" width="200" alt=""> </li> </ul> </div> </template> <script> import Swal from 'sweetalert2' import Loading from 'vue-loading-overlay' import 'vue-loading-overlay/dist/css/index.css' import axios from 'axios' const { VITE_APP_URL, VITE_APP_PATH } = import.meta.env export default { data () { return { color: '#ff0000', products: [], isLoading: false, fullPage: true } }, components: { Loading }, methods: { getProducts () { axios.get(`${VITE_APP_URL}/v2/api/${VITE_APP_PATH}/products/all`) .then((res) => { this.products = res.data.products this.isLoading = false Swal.fire({ title: '載入成功!', icon: 'success', confirmButtonText: '確定' }) }) } }, mounted () { this.isLoading = true setTimeout(() => { this.getProducts() }, 5000) } } </script> <style scoped> </style> ``` ::: ### plugin 全域載入 :::spoiler main.js ```javascript import { createApp } from 'vue' import { LoadingPlugin } from 'vue-loading-overlay' import 'vue-loading-overlay/dist/css/index.css' import './style.css' import App from './App.vue' import router from './router' const app = createApp(App) app.use(LoadingPlugin, { color: '#FF0000' }) app.use(router) app.mount('#app') ``` ::: :::spoiler aboutView.vue ```javascript <template> <h1>This is About page.</h1> <router-link to="/">Home</router-link> | <router-link to="/about">About</router-link> <div > <ul style="min-height:100px" class="vl-parent" ref="formContainer"> <li v-for="product in products" :key="product.id"> <h3>{{ product.title }}</h3> <img :src="product.imageUrl" width="200" alt=""> </li> </ul> </div> </template> <script> import Swal from 'sweetalert2' import axios from 'axios' const { VITE_APP_URL, VITE_APP_PATH } = import.meta.env export default { data () { return { fullPage: false, products: [] } }, methods: { getProducts () { const loader = this.$loading.show({ // Optional parameters container: this.fullPage ? null : this.$refs.formContainer, canCancel: true, onCancel: this.onCancel }) setTimeout(() => { axios.get(`${VITE_APP_URL}/v2/api/${VITE_APP_PATH}/products/all`) .then((res) => { this.products = res.data.products loader.hide() Swal.fire({ title: '載入成功!', icon: 'success', confirmButtonText: '確定' }) }) }, 3000) } }, mounted () { this.getProducts() } } </script> <style scoped> </style> ``` ::: ### 客製化 * 不用 Vue Loading,僅小區塊用 loading 作法,[loading.io](https://loading.io/)、[BS5 元件](https://getbootstrap.com/docs/5.2/components/spinners/) :::spoiler 範例程式碼 ```javascript <template> <h1>This is About page.</h1> <router-link to="/">Home</router-link> | <router-link to="/about">About</router-link> <div><input type="button" value="手動取得購物車" @click="getMore()"> <img src="../assets/loading.gif" width="20" alt="loading" v-if="isLoading" > </div> <div > <ul style="min-height:100px" class="vl-parent" ref="formContainer"> <li v-for="product in products" :key="product.id"> <h3>{{ product.title }}</h3> <img :src="product.imageUrl" width="200" alt=""> </li> </ul> </div> </template> <script> import Swal from 'sweetalert2' import axios from 'axios' const { VITE_APP_URL, VITE_APP_PATH } = import.meta.env export default { data () { return { isLoading: false, products: [] } }, methods: { getMore () { this.isLoading = true setTimeout(() => { axios.get(`${VITE_APP_URL}/v2/api/${VITE_APP_PATH}/products/all`) .then((res) => { this.products = res.data.products this.isLoading = false Swal.fire({ title: '載入成功!', icon: 'success', confirmButtonText: '確定' }) }) }, 3000) } } } </script> <style scoped> </style> ``` :::