Kinh nghiệm css, javascript – frontend
Contents
- 1. CSS
- 2. Javascript
- 2.1 Javascript ES6
- 2.2 Tú chia sẻ javascript
- 2.3 Format date yyyy-mm-dd
- 2.4 Format date yyyy-mm-ddThh:mm cho thẻ input type datetime
- 2.5 Count down
- 2.6 set attribute css important
- 2.7 Check image exists by javascript
- 2.8 Upload File change image
- 2.9 Check phone number vietnam
- 2.10 Replace url not reload page
- 2.11 Convert 2 byte to 1 byte Japan
- 2.12 Check input file is image
- 2.13 Mask input javascript
- 2.14 Các khái niệm học thêm được
- 2.15 Tạo đối tượng mới
- 3. html
1. CSS
1.1 Kinh nghiệm chung
- transparent: thiết lập màu trong suốt
- transform: translate(10px,10px); dịch chuyển 2D
- transition: height 2s ease 3s; hiểu ứng chuyển đổi
[property] [duration] [timing-function] [delay] - flexbox: https://viblo.asia/p/huong-dan-su-dung
- gradient:
linear-gradient(direction, color-stop1, color-stop2, ...); từ một phía
radial-gradient(shape-size-at position, start-color... last-color); từ tâm
1.2 Các công cụ Tú chia sẻ
File dấu trang google chrome: mục yêu thích_18_11_2020. html
- Slider: Bxslider
+ Homepage: https://bxslider.com/
+ Tutorial: https://bxslider.com/install/
+ Goto Slide: tham khảo http://jsfiddle.net/dHxAJ/1/
+ Lưu ý: Khi có href ở item muốn working thì xử lý onclick
$(document).ready(function(){ var bxslider = $('.slider').bxSlider({ touchEnabled: false, oneToOneTouch: false }); JumpToSlide = function (slideNumber) { var slide = slideNumber - 1; bxslider.goToSlide(slide); }; }); //xu ly click href not working <a onclick="handleClick(this)" href="{{route("vn.searchJobCategoryFriendly", ["dich-thuat"]) }}"> function handleClick(obj) { let href = obj.getAttribute("href"); window.location.href = href; }
- Nav-mobile: Slick-nav
+ source code: https://github.com/ComputerWolf/SlickNav/tree/1.0.10
+ Blog: https://www.jqueryscript.net
+ Blog: https://wpbeaches.com/
+ Codepen: https://codepen.io/williamliao65
1.4 Library OwlCarousel and ScrollUp
- OwlCarousel: https://owlcarousel2.github.io/OwlCarousel2/
- Scroll up: https://markgoodyear.com/2013/01/scrollup-jquery-plugin/
1.5 Kinh nghiệm thực tập
1.5.1 Reset css
* { box-sizing: inherit; margin: 0; padding: 0; } html { font-size: 62.5%; line-height: 1.6rem; box-sizing: border-box; font-family: "Roboto", sans-serif; }
1.5.2 Center cả ngang và dọc
Tăng line-height và sử dụng text-align: center
.content-right__process-item-content { text-align: center; line-height: 4.7rem; font-size: 1.6rem; }
1.5.3 Cdn Fontawesome
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.1/css/all.min.css" />
Link font-awesome: https://fontawesome.com/
1.5.4 Xử lý mũi tên
Bạn làm mũi tên trỏ xuống từ thông báo, hoặc user để logout.
Hãy tạo thêm 1 lớp giả để ghi đè đường viền của box ngay tại điểm giao giữa mũi tên và box bên dưới.
1.5.4 box-shadow theo clip-path
<!-- html --> <div class="content-right__header-item-notify-triagle-wrap"> <div class="content-right__header-item-notify-triagle"> </div> </div>
/* css */ .content-right__header-item-notify-triagle-wrap { filter: drop-shadow( 0 0 5px rgba(50, 50, 0, 0.5)); position: absolute; right: 25px; top: 23px; display: none; } .content-right__header-item-notify-triagle { position: absolute; /* top: 14px; right: 3px; */ /* width: 2.2rem; height: 1.5rem; */ /* background-color: orange; box-shadow: 0 0px 9px #ccc; */ background-color: #6f64f8; color: #222; padding: 1rem 1rem 1rem 2rem; font: bold 32px system-ui; clip-path: polygon(50% 0%, 0% 100%, 100% 100%); }
1.5.5 Tạo hình ảnh trắng đen
img { -webkit-filter: grayscale(100%); /* Safari 6.0 - 9.0 */ filter: grayscale(100%); }
1.6 Thư viện crop image
Link demo and doc: https://fengyuanchen.github.io/cropperjs/
1.7 Các khái niệm học thêm được
- Specificity: Đánh giá độ ưu tiên của các selector
Biểu thức tính mức độ ưu tiên của selector
/*00110*/ #myDivId .myDivClass { font-size: 20px; } /*00030*/ .a .b .c { color: green; } /*00020*/ .a .b { color: red; }
Xem thêm bài viết: https://viblo.asia/p/css-specificity-Eb85ojpOl2G
2. css taking context:
+ Stacking Order: Mọi element trong một trong HTML có thể ở phía trước hay phía sau các element khác trong document. Đây được gọi là thứ tự xếp lớp (stacking order).
+ Một nhóm các element có chung một element cha sẽ cùng di chuyển chung với nhau trong stacking order, tạo nên khái niệm gọi là stacking context.
Xem thêm bài viết: https://viblo.asia/p/dieu-khong-ai-noi-cho-ban-ve-z-index-gDVK2jOeKLj
1.8 breakline cho \n
Để \n trình duyệt có thể hiển thị xuống dòng thì cần thêm css với thuộc tính sau:
white-space: break-spaces;
1.9 Không cho trình duyệt autofill
Thêm code sau vào input có type là password
autocomplete='new-password'
1.10 Word-break
Sử dụng
word-break: break-word;
Thay vì
word-break: break-all;
Thì sẽ tránh được case dấu . này
1・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・
2. Javascript
2.1 Javascript ES6
- Let vs Var vs Const
+ Let: biến cục bộ
+ Var: biến toàn cục
+ Const: hằng – không thay đổi giá trị - Objects
- The this Keyword
- Binding this
- Arrow Functions: ()=> {} cách viết ngắn gọn của function và không có binding
- Arrow Functions and this
- Array.map Method: Như foreach
- Object Destructuring: Lấy biến từ object dễ hơn
var person = { name: "Hao", age: 20, } let name = person.name; let age = person.age; //để ngắn gọn sử dụng Destructuring let { name, age } = person; //thay đổi tên biến let { name: ten, age } = person
- Spread Operator: dấu … => copy mảng, object
- Classes
- Inheritance : Kế thừa
- Modules : chia class thành các file khác nhau
- Named and Default Exports: xuất class thì file khác và import vào file sử dụng
Đây là video mình học ES6, dễ hiểu:
- Closures: Function lồng function, function con được sử dụng biến của function cha
2.2 Tú chia sẻ javascript
Link file word: Javascript
2.3 Format date yyyy-mm-dd
formatDate(date) { var d = new Date(date), month = '' + (d.getMonth() + 1), day = '' + d.getDate(), year = d.getFullYear(); if (month.length < 2) month = '0' + month; if (day.length < 2) day = '0' + day; return [year, month, day].join('-'); }
2.4 Format date yyyy-mm-ddThh:mm cho thẻ input type datetime
formatDate(dateInput) { let day = this.formatNumberAddZero( dateInput.getDate() ); let month = this.formatNumberAddZero( (dateInput.getMonth()+1) ); let date = dateInput.getFullYear() + '-' + month + '-' + day; let hours = this.formatNumberAddZero(dateInput.getHours()); let minutes = this.formatNumberAddZero(dateInput.getMinutes()); var time = hours + ":" + minutes; var dateTime = date+'T'+time; return dateTime; }, /** * format 1..9 =>01...09 */ formatNumberAddZero(number) { if (number >= 10) return number; else { switch (number) { case 1: return '01'; case 2: return '02'; case 3: return '03'; case 4: return '04'; case 5: return '05'; case 6: return '06'; case 7: return '07'; case 8: return '08'; case 9: return '09'; } } }
2.5 Count down
<script> function countdownTimer(strDate, index) { const difference = +new Date(strDate) - +new Date(); let remaining = "Time's up!"; if (difference > 0) { const parts = { hours: Math.floor((difference / (1000 * 60 * 60))), minutes: Math.floor((difference / 1000 / 60) % 60), seconds: Math.floor((difference / 1000) % 60), }; remaining = Object.keys(parts).map(part => { return `${parts[part]} ${part}`; }).join(" "); } console.log(remaining); let hour = ''; let minute = ''; let second = ''; let arraySplitHour = remaining.split(' hours '); hour = addZeroToNumber(arraySplitHour[0]); let arraySplitMinute = arraySplitHour[1].split(' minutes '); minute = addZeroToNumber(arraySplitMinute[0]); let arraySplitSecond = arraySplitMinute[1].split(' second'); second = addZeroToNumber(arraySplitSecond[0]); document.getElementById("hour-" + index).innerHTML = hour; document.getElementById("minute-" + index).innerHTML = minute; document.getElementById("second-" + index).innerHTML = second; } function addZeroToNumber( number ) { if ( number > 9 ) { return number } else { switch ( number ) { case '0': return '00'; case '1': return '01'; case '2': return '02'; case '3': return '03'; case '4': return '04'; case '5': return '05'; case '6': return '06'; case '7': return '07'; case '8': return '08'; case '9': return '09'; } } } $( document ).ready(function() { for(let i = 0; i < arrayTimeEventNotOver.length; i++) { countdownTimer(arrayTimeEventNotOver[i], i); } for(let i = 0; i < arrayTimeEventNotOver.length; i++) { setInterval(countdownTimer, 1000, arrayTimeEventNotOver[i], i); } }); </script>
Link bài viết: https://www.digitalocean.com/
2.6 set attribute css important
element.style.setProperty("padding-top", '10px', "important");
2.7 Check image exists by javascript
ImageExist(url) { url = window.location.origin + url; var http = new XMLHttpRequest(); http.open('HEAD', url, false); http.send(); return http.status!=404; }
2.8 Upload File change image
<p><input type="file" accept="image/*" name="image" id="file" onchange="loadFile(event)" style="display: none;"></p> <p><label for="file" style="cursor: pointer;">Upload Image</label></p> <p><img id="output" width="200" /></p> <script> var loadFile = function(event) { var image = document.getElementById('output'); image.src = URL.createObjectURL(event.target.files[0]); }; </script>
2.9 Check phone number vietnam
function phonenumber(inputtxt) { var phoneno = /(84|0[3|5|7|8|9])+([0-9]{8})\b/; if(inputtxt.match(phoneno)) { return true; } else { return false; } }
2.10 Replace url not reload page
window.history.pushState({ các biên cần lưu: giá trị }, '', url);
// bắt sự kiện ấn back trang về window.onpopstate = function(event) { location.replace(document.location); };
Tham khảo: https://developer.mozilla.org/en-US/docs/Web/API/History/pushState
https://developer.mozilla.org/en-US/docs/Web/API/Window/popstate_event
2.11 Convert 2 byte to 1 byte Japan
function toASCII(chars) { var ascii = ''; for(var i=0, l=chars.length; i<l; i++) { var c = chars[i].charCodeAt(0); // make sure we only convert half-full width char if (c >= 0xFF00 && c <= 0xFFEF) { c = 0xFF & (c + 0x20); } ascii += String.fromCharCode(c); } return ascii; } // example toASCII("ABC"); // returns 'ABC' 0x41
2.12 Check input file is image
<input type="file" name="background_image" id="background_image" accept="image/*" onchange="changeBackgroundImage(this)"> function changeBackgroundImage(inputFile) { var filePath = inputFile.value; // Allowing file type var allowedExtensions = /(\.jpg|\.jpeg|\.png|\.gif)$/i; if (!allowedExtensions.exec(filePath)) { alert('File is not an image. Please choose another file!'); inputFile.value = ''; } }
2.13 Mask input javascript
Download thư viện: https://github.com/beholdr/maska/archive/master.zip
1. Add library vào web
<script src="/dist/maska.js"></script>
2. Định nghĩa data-masked và thêm class masked
<input data-mask="##/##/####" class="masked">
3. Khởi tạo mask
$(document).ready(function () { Maska.create('.masked'); });
Xem thêm tại: https://www.cssscript.com/input-mask-maska/
2.14 Các khái niệm học thêm được
2.14.1 Closure
Closure: Sử dụng biến ngoài function, mặc dù biến đó đã return.
function numberGenerator() { // Local free variable that ends up within the closure var num = 1; function checkNumber() { console.log(num); } num++; return checkNumber; } var number = numberGenerator(); number(); // 2
2.14.2 Event loop
Event loop: Tự động đưa bất đồng bộ ở queue vào call stack khi call stack rỗng.
const foo = () => console.log("First"); const bar = () => setTimeout(() => console.log("Second"), 500); const baz = () => console.log("Third"); bar(); foo(); baz();
Xem thêm bài viết: https://viblo.asia/p/hieu-ve-co-che-xu-ly-su-kien-event-loop-trong-javascript-07LKXjX2lV4
2.14.3 Microtask và macrotask:
+ Microtask: Liên quan đến promise, … có độ ưu tiên cao hơn macrotask.
+ Macrotask: Liên quan setTimeout, setIntervel,… có độ ưu tiên thấp hơn microtask.
Cả hai cùng nằm trong queue,
function getUp() { console.log('I am waking up'); } function makeCoffee() { setTimeout(() => { console.log('Making coffee in 5 minutes'); }, 0); } function haveBreakfast() { Promise.resolve().then(() => { console.log('I have my breakfast'); }); } makeCoffee(); haveBreakfast(); getUp();
Xem thêm bài viết: https://viblo.asia/p/javascript-chay-bat-dong-bo-nhu-the-nao-gDVK2JW0KLj
2.14.4 Promise:
Tại mỗi thời điểm Promise sẽ có 1 trạng thái nhất đinh
pending
fulfilled
rejected
Static methods
Promise.resolve(value)
: Trả về một promise resolved (hoàn thành) với một giá trị cụ thể.Promise.reject(reason)
: Trả về một promise rejected (lỗi) với một lỗi cụ thể.Promise.all(iterable of multiple promises)
- Nhận vào một mảng các promise hoặc cũng có thể là non-promise (number, boolean, .etc).
- Trả về một promise mới.
- Chờ tất cả các promise trong mảng resolved, kết quả của promise mới này là một mảng chứa kết quả của các promise theo đúng thứ tự.
- 1 promise bất kì rejected, kết quả của promise mới này được trả về ngay lập tức lỗi của promise rejected đó, các promise khác vẫn tiếp tục thực thi nhưng kết quả bị bỏ qua.
- Thực thi promise dạng parallel.
Promise.race(iterable of multiple promises)
:- Nhận vào một mảng các promise hoặc cũng có thể là non-promise (number, boolean, .etc).
- Trả về một promise mới.
- Kết quả của promise mới là kết quả của promise bất kì đầu tiên resolved hoặc rejected.
Promise.allSetted(iterable of multiple promises)
:- Nhận vào một mảng các promise hoặc cũng có thể là non-promise (number, boolean, .etc).
- Trả về một promise mới.
- Chờ cho tất cả các promise được xử lý, kết quả trả về là mảng chứa các object chứa trạng thái và giá trị của promise kể cả resolved hay rejected.
Một vài trình duyệt với phiên bản mới gần đây đã hỗ trợ
Promise.any(iterable of multiple promises)
:experimental
Xem thêm bài viết: https://viblo.asia/p/nhung-dieu-can-biet-ve-promise-javascript-bJzKmJwEZ9N
2.14.5 Async/Await
Cách làm cho gọn code hơn. Tuy nhiên nó vẫn là Promise.
-
Async – khai báo một hàm bất đồng bộ (async function someName(){…}).
- Tự động biến đổi một hàm thông thường thành một Promise.
- Khi gọi tới hàm async nó sẽ xử lý mọi thứ và được trả về kết quả trong hàm của nó.
- Async cho phép sử dụng Await.
-
Await – tạm dừng việc thực hiện các hàm async. (Var result = await someAsyncCall ().
- Khi được đặt trước một Promise, nó sẽ đợi cho đến khi Promise kết thúc và trả về kết quả.
- Await chỉ làm việc với Promises, nó không hoạt động với callbacks.
- Await chỉ có thể được sử dụng bên trong các function async.
async function getJSONAsync() { // The await keyword saves us from having to write a .then() block. let json = await axios.get('https://tutorialzine.com/misc/files/example.json'); // The result of the GET request is available in the json variable. // We return it just like in a regular synchronous function. return json; } getJSONAsync().then( function(result) { // Do something with result. });
Thay vì
function getJSON() { // To make the function blocking we manually create a Promise. return new Promise( function(resolve) { axios.get('https://tutorialzine.com/misc/files/example.json') .then( function(json) { // The data from the request is available in a .then block // We return the result using resolve. resolve(json); }); }); } getJSONAsync().then( function(result) { // Do something with result. });
2.14.6 Generator javascript
Xen ngang quá trình xử lý.
Giống debug, có thể dừng chương trình ở 1 điểm break point nào đó.
Dùng biến đổi bất đồng bộ thành đồng bộ.
Điểm dừng sẽ là yield param
Xem thêm bài viết: https://viblo.asia/p/generator-trong-javasccript-WEMGBjjVGQK
2.14.7 Event Bubbling và Capturing
Bubbling xử lý sự kiện từ element đến element cha, ông, tổ tiên.
Capturing thì ngược lại từ tổ tiên, ông, cha, rồi mới tới element đó.
Vd: khi click vào thẻ td
//capturing window → document → table → tbody → tr → td // bubling td → tr→ tbody → table → document → window
Việc đăng ký capturing mặc định là false => tức là luôn áp dụng bubling.
Bạn có thể thay đổi bằng cách thêm tham số thứ ba
addEventListener("click", handler, true) /** * true => capturing * false => bubling (default) */
Không áp dụng cái nào chỉ thực hiện của element thôi thì sao?
=====> Sử dụng event.stopPropagation() nhé!
<body onclick="alert(`the bubbling doesn't reach here`)"> <button onclick="event.stopPropagation()">Click me</button> </body>
Khi chúng ta click và button Click me thì nó sẽ không bubbling đến event của <body>.
Xem thêm: https://viblo.asia/p/bubbling-va-capturing-event-trong-javascript-phan-1-m68Z0Nod5kG
https://viblo.asia/p/bubbling-va-capturing-event-trong-javascript-phan-2-bJzKmLnO59N
2.15 Tạo đối tượng mới
Với object và array muốn clone thành 1 object hoàn toàn mới, hãy luôn sử dụng cloneDeep. Vì sử dụng spread operator thì nó chỉ clone được 1 cấp thôi, những thằng con vẫn còn giữ tham chiếu cũ.
// sử dụng let formData = cloneDeep(state2.form); // thay vì let formData = {...state2.form};
3. html
- semantic tags: những thẻ có tên rõ ràng như header, footer, nav,..
- SEO cơ bản thẻ meta:
– Lúc trước google dựa vào thẻ meta title, description, keywork để sắp xếp thứ hạng, sau này đã bỏ không còn sử dụng.
– Các meta trên thì vẫn được TQ sử dụng.
Xem thêm: https://viblo.asia/p/ky-thuat-seo-co-ban-3wjAM7zLRmWe?fbclid=IwAR3vTmCEtoXxlTiZQ2NweZ1SyeTb2ILILnIKr09nNQ3StMv00Pr9OaQxrMo