Intro
Nếu các bạn xài mạng xã hội thì cũng hay gặp trường hợp mạng bị mất và xuất hiện dòng chữ thông báo về tình trạng mạng của mình ,Mục đích bài viết này chúng ta sẽ cùng nhau xem làm thử bảng thông báo như nào nhé
Lưu ý :
- Để tránh trường hợp báo window not define đối với dự án SSR thì bạn nên thêm thẻ
<ClientOnly>
bọc lại nhé nhé
- Kiểm tra trình duyệt hỗ trợ trước khi integrate vào dự án nhé
Lý thuyết
Ở đây chúng ta sẽ sử dụng thuộc tính navigator của window , nó cho phép chúng ta biết được chi tiết về network của client ví dụ như tình trạng mạng, loại mạng sử dụng (2g,3g,4g..) , tốc độ tải . Các bạn có thể đọc thêm tại navigator **ở đây **
Code
Mình sẽ sử dụng Nuxt 3 để code cho phần này
Chúng ta tiến hành dựng sườn cho phần toast thông báo
// components/toasNetwork.vue <div class="toast"> <div class="content"> <div class="icon"> <i class="uil uil-wifi"/> </div> <div class="details" > <span>You're online now</span> <p>Hurray! Internet is connected.</p> </div> </div> </div>
Phần Style: Code style cho component , cũng như thêm hiệu ứng
@import url('https://fonts.googleapis.com/css2?family=Poppins:wght@200;300;400;500;600;700&display=swap');
@import url('https://unicons.iconscout.com/release/v3.0.6/css/line.css'); * { margin: 0; padding: 0; box-sizing: border-box; font-family: 'Poppins', sans-serif;
} body { overflow: hidden; background: #f2f2f2;
} .page { position: relative; min-height: 100vh; min-width: 100vw; background-image: url(https://i.ibb.co/4fMB4tr/background-demo.png); background-size: 100% auto; background-repeat: no-repeat; background-position: center -3px;
} .wrapper { position: absolute; top: 20px; left: 20px;
} @keyframes show_toast { 0% { transform: translateX(-100%); } 40% { transform: translateX(10%); } 80%, 100% { transform: translateX(20px); }
} .wrapper.hide { animation: hide_toast 1s ease forwards;
} .wrapper.show { animation: show_toast 1s ease forwards;
} @keyframes hide_toast { 0% { transform: translateX(20px); } 40% { transform: translateX(10%); } 80%, 100% { opacity: 0; pointer-events: none; transform: translateX(-100%); }
} .wrapper .toast { background: #fff; padding: 20px 15px 20px 20px; border-radius: 10px; border-left: 5px solid #2ecc71; box-shadow: 1px 7px 14px -5px rgba(0, 0, 0, 0.15); width: 430px; display: flex; align-items: center; justify-content: space-between;
} .wrapper .toast.offline { border-color: #ccc;
} .toast .content { display: flex; align-items: center;
} .content .icon { font-size: 25px; color: #fff; height: 50px; width: 50px; text-align: center; line-height: 50px; border-radius: 50%; background: #2ecc71;
} .toast.offline .content .icon { background: #ccc;
} .content .details { margin-left: 15px;
} .details span { font-size: 20px; font-weight: 500;
} .details p { color: #878787;
} .toast .close-icon { color: #878787; font-size: 23px; cursor: pointer; height: 40px; width: 40px; text-align: center; line-height: 40px; border-radius: 50%; background: #f2f2f2; transition: all 0.3s ease;
} .close-icon:hover { background: #efefef;
}
Composable : Ở đây mình sẽ tách phần logic qua Composable là useNetWork.ts
để sau này có thể tái sử dụng , đây là 1 chức năng hay của Nuxt 3 mình rất thích
// Composables for Network
// composables/useNetWork.ts export default function useNetwork(timeDuration = 2000) { const navigator = window.navigator; const isOnline = ref(navigator.onLine); const isShow = ref(false); //Tiến hành xe window.addEventListener('online', () => { isOnline.value = true; }); window.addEventListener('offline', () => { isOnline.value = false; }); const hideToast = (time = 2000) => { setTimeout(() => { isShow.value = false; }, time); }; // Khi chúng ta bắt được sự kiện thay đổi mạng (isOnline) ở phía trên chúng ta sẽ tiến hành hiện popup và tắt popup theo thời gian mong muốn với timeDuration watch(isOnline, () => { //Chỗ này mình mong muốn là sẽ phải tắt thuộc tính show trước khi mở lại toast tránh trường hợp người dùng đang được mở popup sẽ ko có animation isShow.value = false; nextTick(() => { isShow.value = true; hideToast(timeDuration); }); }); // Ở đây mình sử dụng readonly để tránh trường hợp edit được 2 trạng thái này bên ngoài , chỗ này các bạn có thể bỏ không nếu muốn return { isOnline: readonly(isOnline), isShow: readonly(isShow) };
}
Sau khi thêm phần logic xong thì quay lại phần template để gắn phần logic vào thôi
// components/toasNetwork.vue
<template> <div class="page"> <div :class="['wrapper', isShow ? 'show' : 'hide']"> <ClientOnly> <div :class="[{ offline: !isOnline }, 'toast']"> <div class="content"> <div class="icon"> <i :class="['uil', isOnline ? 'uil-wifi' : ' uil-wifi-slash']" ></i> </div> <div class="details" v-if="isOnline"> <span>You're online now</span> <p>Hurray! Internet is connected.</p> </div> <div class="details" v-else> <span>You're offline now</span> <p>Opps! Internet is disconnected.</p> </div> </div> </div> </ClientOnly> </div> </div>
</template> <script lang="ts" setup>
const { isOnline, isShow } = useNetwork(3000);
</script>
Vậy là xong rồi tận hưởng thành quả thôi .
Hẹn gặp lại vào các bài viết tiếp theo see ya !!
Nguồn :
Learnvue : https://www.youtube.com/watch?v=4M6D9_ALczY&t=209s&ab_channel=LearnVue