若是您發現錯誤,請必定要告訴我,拯救一個辣雞(但很帥)的少年就靠您了!javascript
要求:垂直兩欄,左邊固定右邊自適應。css
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<style> .outer { height: 100px; margin-bottom: 10px; } .left { background: tomato; height: 100px; } .right { background: gold; height: 100px; } /* 浮動 */ .outer1 .left { width: 200px; float: left; } .outer1 .right { width: auto; margin-left: 200px; } /* flex */ .outer2 { display: flex; } .outer2 .left { flex-grow: 0; flex-shrink: 0; flex-basis: 200px; } .outer2 .right { flex: auto; /* 1 1 auto */ } /* position */ .outer3 { position: relative; } .outer3 .left { position: absolute; width: 200px; } .outer3 .right { margin-left: 200px; } /* position again */ .outer4 { position: relative; } .outer4 .left { width: 200px; } .outer4 .right { position: absolute; top: 0; left: 200px; right: 0; } </style>
</head>
<!-- 左右兩欄,左邊固定,右邊自適應 -->
<body>
<div class="outer outer1">
<div class="left">1-left</div>
<div class="right">1-right</div>
</div>
<div class="outer outer2">
<div class="left">2-left</div>
<div class="right">2-right</div>
</div>
<div class="outer outer3">
<div class="left">3-left</div>
<div class="right">3-right</div>
</div>
<div class="outer outer4">
<div class="left">4-left</div>
<div class="right">4-right</div>
</div>
</body>
</html>
複製代碼
要求:垂直三欄佈局,左右兩欄寬度固定,中間自適應html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<style> .outer, .left, .middle, .right { height: 100px; margin-bottom: 5px; } .left { background: tomato; } .middle { background: lightgreen; } .right { background: gold; } /* 左右分別設置絕對定位 中間設置外邊距 */ .outer1 { position: relative; } .outer1 .left { position: absolute; width: 100px; } .outer1 .middle { margin: 0 200px 0 100px; } .outer1 .right { position: absolute; width: 200px; top: 0; right: 0; } /* flex 佈局 */ .outer2 { display: flex; } .outer2 .left { flex: 0 0 100px; } .outer2 .middle { flex: auto; } .outer2 .right { flex: 0 0 200px; } /* 浮動佈局 可是 html 中 middle要放到最後 */ .outer3 .left { float: left; width: 100px; } .outer3 .right { float: right; width: 200px; } .outer3 .middle { margin: 0 200px 0 100px; } </style>
</head>
<!-- 三欄佈局 左右固定 中間自適應 -->
<body>
<div class="outer outer1">
<div class="left">1-left</div>
<div class="middle">1-middle</div>
<div class="right">1-right</div>
</div>
<div class="outer outer2">
<div class="left">2-left</div>
<div class="middle">2-middle</div>
<div class="right">2-right</div>
</div>
<div class="outer outer3">
<div class="left">3-left</div>
<div class="right">3-right</div>
<div class="middle">3-middle</div>
</div>
</body>
</html>
複製代碼
和三欄佈局要求相同,不過中間列要寫在前面保證優先渲染。前端
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<style> .outer, .left, .middle, .right { height: 100px; margin-bottom: 5px; } .left { background: tomato; } .middle { background: lightgreen; } .right { background: gold; } /* 聖盃佈局 經過浮動和負邊距實現 */ .outer1 { padding: 0 200px 0 100px; } .outer1 .middle { width: 100%; float: left; } .outer1 .left { width: 100px; float: left; margin-left: -100%; position: relative; left: -100px; } .outer1 .right { width: 200px; float: left; margin-left: -200px; position: relative; left: 200px; } /* 雙飛翼佈局 */ .outer2 .middle-wrapper { width: 100%; float: left; } .outer2 .middle { margin: 0 200px 0 100px; } .outer2 .left { width: 100px; float: left; margin-left: -100%; } .outer2 .right { width: 200px; float: left; margin-left: -200px; } </style>
</head>
<!-- 三欄佈局 左右固定 中間自適應 -->
<body>
<!-- 聖盃佈局 middle 最早 -->
<div class="outer outer1">
<div class="middle">聖盃-middle</div>
<div class="left">聖盃-left</div>
<div class="right">聖盃-right</div>
</div>
<!-- 雙飛翼佈局 middle 最早 多一層 div -->
<div class="outer outer2">
<div class="middle-wrapper">
<div class="middle">雙飛翼佈局-middle</div>
</div>
<div class="left">雙飛翼佈局-left</div>
<div class="right">雙飛翼佈局-right</div>
</div>
</body>
</html>
複製代碼
實現一個三角形java
常見題目,經過 border
實現es6
<!DOCTYPE html>
<html>
<head>
<title>三角形</title>
<style type="text/css"> .box1, .box2, .box3, .box4 { height: 0px; width: 0px; float: left; border-style: solid; margin: 10px; } .box1 { /* 等腰直角 */ border-width: 100px; border-color: tomato transparent transparent transparent; } .box2 { /* 等邊 */ border-width: 100px 173px; border-color: transparent tomato transparent transparent; } .box3 { /* 等腰 */ border-width: 100px 80px; border-color: transparent transparent tomato transparent; } .box4 { /* 其餘 */ border-width: 100px 90px 80px 70px; border-color: transparent transparent transparent tomato; } </style>
</head>
<body>
<div class="box1"></div>
<div class="box2"></div>
<div class="box3"></div>
<div class="box4"></div>
</body>
</html>
複製代碼
使用 css 實現一個寬高自適應的正方形web
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<style> /* 都是像對於屏幕寬度的比例 */ .square1 { width: 10%; height: 10vw; background: red; } /* margin/padding 百分比是相對父元素 width 的 */ .square2 { width: 20%; height: 0; padding-top: 20%; background: orange; } /* 經過子元素 margin */ .square3 { width: 30%; overflow: hidden; /* 觸發 BFC */ background: yellow; } .square3::after { content: ''; display: block; margin-top: 100%; /* 高度相對於 square3 的 width */ } </style>
</head>
<!-- 畫一個正方形 -->
<body>
<div class="square1"></div>
<div class="square2"></div>
<div class="square3"></div>
</body>
</html>
複製代碼
實現一個 1/4 圓、任意弧度的扇形ajax
有多種實現方法,這裏選幾種簡單方法(我看得懂的)實現。json
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<style> /* 經過 border 和 border-radius 實現 1/4 圓 */ .sector1 { height: 0; width: 0; border: 100px solid; border-radius: 50%; border-color: turquoise tomato tan thistle; } /* 相似三角形的作法加上父元素 overflow: hidden; 也能夠實現任意弧度圓 */ .sector2 { height: 100px; width: 200px; border-radius: 100px 100px 0 0; overflow: hidden; } .sector2::after { content: ''; display: block; height: 0; width: 0; border-style: solid; border-width: 100px 58px 0; border-color: tomato transparent; transform: translate(42px,0); } /* 經過子元素 rotateZ 和父元素 overflow: hidden 實現任意弧度扇形(此處是60°) */ .sector3 { height: 100px; width: 100px; border-top-right-radius: 100px; overflow: hidden; /* background: gold; */ } .sector3::after { content: ''; display: block; height: 100px; width: 100px; background: tomato; transform: rotateZ(-30deg); transform-origin: left bottom; } /* 經過 skewY 實現一個60°的扇形 */ .sector4 { height: 100px; width: 100px; border-top-right-radius: 100px; overflow: hidden; } .sector4::after { content: ''; display: block; height: 100px; width: 100px; background: tomato; transform: skewY(-30deg); transform-origin: left bottom; } /* 經過漸變設置60°扇形 */ .sector5 { height: 200px; width: 200px; background: tomato; border-radius: 50%; background-image: linear-gradient(150deg, transparent 50%, #fff 50%), linear-gradient(90deg, #fff 50%, transparent 50%); } </style>
</head>
<body>
<div style="display: flex; justify-content: space-around;">
<div class="sector1"></div>
<div class="sector2"></div>
<div class="sector3"></div>
<div class="sector4"></div>
<div class="sector5"></div>
</div>
</body>
</html>
複製代碼
實現子元素的水平垂直居中跨域
<!DOCTYPE html>
<html>
<head>
<title>水平垂直居中</title>
<style type="text/css"> .outer { height: 200px; width: 200px; background: tomato; margin: 10px; float: left; position: relative; } .inner { height: 100px; width: 100px; background: black; } /* * 經過 position 和 margin 居中 * 缺點:須要知道 inner 的長寬 */ .inner1 { position: absolute; top: 50%; left: 50%; margin-top: -50px; margin-left: -50px; } /* * 經過 position 和 margin 居中 (2 */ .inner2 { position: absolute; top: 0; right: 0; bottom: 0; left: 0; margin: auto; } /* * 經過 flex 進行居中 */ .outer3 { display: flex; justify-content: center; align-items: center; } /** * 經過 position 和 transform 居中 */ .inner4 { top: 50%; left: 50%; transform: translate(-50%,-50%); position: absolute; } </style>
</head>
<body>
<div class="outer outer1">
<div class="inner inner1"></div>
</div>
<div class="outer outer2">
<div class="inner inner2"></div>
</div>
<div class="outer outer3">
<div class="inner inner3"></div>
</div>
<div class="outer outer4">
<div class="inner inner4"></div>
</div>
</body>
</html>
複製代碼
要求:清除浮動
能夠經過 clear:both
或 BFC 實現
<!DOCTYPE html>
<html>
<head>
<title>清除浮動</title>
<style type="text/css"> .outer { width: 200px; background: tomato; margin: 10px; position: relative; } .inner { height: 100px; width: 100px; background: pink; margin: 10px; float: left; } /* 僞元素 */ .outer1::after { content: ''; display: block; clear: both; } /* 建立 BFC */ .outer2 { overflow: hidden; } </style>
</head>
<body>
<div class="outer outer1">
<div class="inner"></div>
</div>
<div class="outer outer2">
<div class="inner"></div>
</div>
</body>
</html>
複製代碼
使用 CSS 寫一個彈出框效果
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<style> .bg { height: 666px; width: 100%; font-size: 60px; text-align: center; } .dialog { z-index: 999; position: fixed; top: 0; right: 0; bottom: 0; left: 0; background: rgba(0, 0, 0, 0.5); } .dialog .content { min-height: 300px; width: 600px; background: #fff; border-radius: 5px; border: 1px solid #ebeef5; box-shadow: 0 2px 12px 0 rgba(0,0,0,.1); position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); } </style>
</head>
<body>
<div class="bg">
頁面內容
</div>
<div class="dialog">
<div class="content">
彈出框
</div>
</div>
</body>
</html>
複製代碼
要求:一個
div
內部放不少水平div
,並能夠橫向滾動。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=div, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<style> body,html { margin: 0; padding: 0; } /* flex 實現 */ /* .nav { display: flex; height: 30px; border: 1px solid #000; padding: 3px; overflow-x: auto; } .nav::-webkit-scrollbar { display: none; } .item { flex: 0 0 200px; height: 30px; margin-right: 5px; background: gray; } */ /* inline-block 和 white-space: nowrap; 實現 */ .nav { height: 30px; padding: 3px; border: 1px solid #000; overflow-x: auto; white-space: nowrap; } .nav::-webkit-scrollbar { display: none; } .item { display: inline-block; width: 200px; height: 30px; margin-right: 5px; background: gray; } </style>
</head>
<!-- 水平滾動導航欄 -->
<body>
<div class="nav">
<div class="item">item1</div>
<div class="item">item2</div>
<div class="item">item3</div>
<div class="item">item4</div>
<div class="item">item5</div>
<div class="item">item6</div>
<div class="item">item7</div>
<div class="item">item8</div>
<div class="item">item9</div>
</div>
</body>
</html>
複製代碼
CSS 部分完,總結,Flex 無敵。
Function.prototype.bind = function(context, ...bindArgs) {
// func 爲調用 bind 的原函數
const func = this;
context = context || window;
if (typeof func !== 'function') {
throw new TypeError('Bind must be called on a function');
}
// bind 返回一個綁定 this 的函數
return function(...callArgs) {
let args = bindArgs.concat(callArgs);
if (this instanceof func) {
// 意味着是經過 new 調用的 而 new 的優先級高於 bind
return new func(...args);
}
return func.call(context, ...args);
}
}
// 經過隱式綁定實現
Function.prototype.call = function(context, ...args) {
context = context || window;
context.func = this;
if (typeof context.func !== 'function') {
throw new TypeError('call must be called on a function');
}
let res = context.func(...args);
delete context.func;
return res;
}
Function.prototype.apply = function(context, args) {
context = context || window;
context.func = this;
if (typeof context.func !== 'function') {
throw new TypeError('apply must be called on a function');
}
let res = context.func(...args);
delete context.func;
return res;
}
複製代碼
// 參考 You Dont Know JavaScript 上卷
// 基類
function Base() {
}
// 派生類
function Derived() {
Base.call(this);
}
// 將派生類的原型的原型鏈掛在基類的原型上
Object.setPrototypeOf(Derived.prototype, Base.prototype);
複製代碼
// 手動實現一個 new 關鍵字的功能的函數 _new(fun, args) --> new fun(args)
function _new(fun, ...args) {
if (typeof fun !== 'function') {
return new Error('參數必須是一個函數');
}
let obj = Object.create(fun.prototype);
let res = fun.call(obj, ...args);
if (res !== null && (typeof res === 'object' || typeof res === 'function')) {
return res;
}
return obj;
}
複製代碼
// a instanceof b
function _instanceof(a, b) {
while (a) {
if (a.__proto__ === b.prototype) return true;
a = a.__proto__;
}
return false;
}
複製代碼
// foo 函數將會被調用 傳入後臺返回的數據
function foo(data) {
console.log('經過jsonp獲取後臺數據:', data);
document.getElementById('data').innerHTML = data;
}
/** * 經過手動建立一個 script 標籤發送一個 get 請求 * 並利用瀏覽器對 <script> 不進行跨域限制的特性繞過跨域問題 */
(function jsonp() {
let head = document.getElementsByTagName('head')[0]; // 獲取head元素 把js放裏面
let js = document.createElement('script');
js.src = 'http://domain:port/testJSONP?a=1&b=2&callback=foo'; // 設置請求地址
head.appendChild(js); // 這一步會發送請求
})();
// 後臺代碼
// 由於是經過 script 標籤調用的 後臺返回的至關於一個 js 文件
// 根據前端傳入的 callback 的函數名直接調用該函數
// 返回的是 'foo(3)'
function testJSONP(callback, a, b) {
return `${callback}(${a + b})`;
}
複製代碼
感受這個有點無聊了……
// Asynchronous Javascript And XML
function ajax(options) {
// 選項
var method = options.method || 'GET',
params = options.params,
data = options.data,
url = options.url + (params ? '?' + Object.keys(params).map(key => key + '=' + params[key]).join('&') : ''),
async = options.async === false ? false : true,
success = options.success,
headers = options.headers;
var request;
if (window.XMLHttpRequest) {
request = new XMLHttpRequest();
} else {
request = new ActiveXObject('Microsoft.XMLHTTP');
}
request.onreadystatechange = function() {
/** readyState: 0: 請求未初始化 1: 服務器鏈接已創建 2: 請求已接收 3: 請求處理中 4: 請求已完成,且響應已就緒 status: HTTP 狀態碼 **/
if (request.readyState === 4 && request.status === 200) {
success && success(request.responseText);
}
}
request.open(method, url, async);
if (headers) {
Object.keys(headers).forEach(key => request.setRequestHeader(key, headers[key]));
}
method === 'GET' ? request.send() : request.send(data);
}
// e.g.
ajax({
method: 'GET',
url: '...',
success: function(res) {
console.log('success', res);
},
async: true,
params: {
p: 'test',
t: 666
},
headers: {
'Content-Type': 'application/json'
}
})
複製代碼
function reduce(arr, callback, initial) {
let i = 0;
let acc = initial === undefined ? arr[i++] : initial;
for (; i < arr.length; i++) {
acc = callback(acc, arr[i], i, arr);
}
return acc;
}
複製代碼
要求是 yield
後面只能是 Promise
或 Thunk
函數,詳見 es6.ruanyifeng.com/#docs/gener…
function run(gen) {
let g = gen();
function next(data) {
let result = g.next(data);
if (result.done) return result.value;
if (result.value instanceof Promise) {
result.value.then(data => next(data));
} else {
result.value(next);
}
}
return next();
}
// ======== e.g. ==========
function func(data, cb) {
console.log(data);
cb();
}
function *gen() {
let a = yield Promise.resolve(1);
console.log(a);
let b = yield Promise.resolve(2);
console.log(b);
yield func.bind(null, a + b);
}
run(gen);
/** output: 1 2 3 **/
複製代碼
老生常談了,感受不必寫太複雜
/** * 節流函數 限制函數在指定時間段只能被調用一次 * 用法 好比防止用戶連續執行一個耗時操做 對操做按鈕點擊函數進行節流處理 */
function throttle(func, wait) {
let timer = null;
return function(...args) {
if (!timer) {
func(...args);
timer = setTimeout(() => {
timer = null;
}, wait);
}
}
}
複製代碼
/** * 函數調用後不會被當即執行 以後連續 wait 時間段沒有調用纔會執行 * 用法 如處理用戶輸入 */
function debounce(func, wait) {
let timer = null;
return function(...args) {
if (timer) clearTimeout(timer); // 若是在定時器未執行期間又被調用 該定時器將被清除 並從新等待 wait 秒
timer = setTimeout(() => {
func(...args);
}, wait);
}
}
複製代碼
簡單實現,基本功能都有了。
const PENDING = 1;
const FULFILLED = 2;
const REJECTED = 3;
function MyPromise(executor) {
let self = this;
this.resolveQueue = [];
this.rejectQueue = [];
this.state = PENDING;
this.val = undefined;
function resolve(val) {
if (self.state === PENDING) {
setTimeout(() => {
self.state = FULFILLED;
self.val = val;
self.resolveQueue.forEach(cb => cb(val));
});
}
}
function reject(err) {
if (self.state === PENDING) {
setTimeout(() => {
self.state = REJECTED;
self.val = err;
self.rejectQueue.forEach(cb => cb(err));
});
}
}
try {
// 回調是異步執行 函數是同步執行
executor(resolve, reject);
} catch(err) {
reject(err);
}
}
MyPromise.prototype.then = function(onResolve, onReject) {
let self = this;
// 不傳值的話默認是一個返回原值的函數
onResolve = typeof onResolve === 'function' ? onResolve : (v => v);
onReject = typeof onReject === 'function' ? onReject : (e => { throw e });
if (self.state === FULFILLED) {
return new MyPromise(function(resolve, reject) {
setTimeout(() => {
try {
let x = onResolve(self.val);
if (x instanceof MyPromise) {
x.then(resolve);
} else {
resolve(x);
}
} catch(e) {
reject(e);
}
});
});
}
if (self.state === REJECTED) {
return new MyPromise(function(resolve, reject) {
setTimeout(() => {
try {
let x = onReject(self.val);
if (x instanceof MyPromise) {
x.then(resolve);
} else {
resolve(x);
}
} catch(e) {
reject(e);
}
});
});
}
if (self.state === PENDING) {
return new MyPromise(function(resolve, reject) {
self.resolveQueue.push((val) => {
try {
let x = onResolve(val);
if (x instanceof MyPromise) {
x.then(resolve);
} else {
resolve(x);
}
} catch(e) {
reject(e);
}
});
self.rejectQueue.push((val) => {
try {
let x = onReject(val);
if (x instanceof MyPromise) {
x.then(resolve);
} else {
resolve(x);
}
} catch(e) {
reject(e);
}
});
});
}
}
MyPromise.prototype.catch = function(onReject) {
return this.then(null, onReject);
}
MyPromise.all = function(promises) {
return new MyPromise(function(resolve, reject) {
let cnt = 0;
let result = [];
for (let i = 0; i < promises.length; i++) {
promises[i].then(res => {
result[i] = res;
if (++cnt === promises.length) resolve(result);
}, err => {
reject(err);
})
}
});
}
MyPromise.race = function(promises) {
return new MyPromise(function(resolve, reject) {
for (let i = 0; i < promises.length; i++) {
promises[i].then(resolve, reject);
}
});
}
MyPromise.resolve = function(val) {
return new MyPromise(function(resolve, reject) {
resolve(val);
});
}
MyPromise.reject = function(err) {
return new MyPromise(function(resolve, reject) {
reject(err);
})
}
複製代碼
實現原理就是監聽 url 的哈希值變化了
<!DOCTYPE html>
<html>
<head>
<title>hash 路由</title>
</head>
<body>
<header>
<a href="#home">首頁</a>
<a href="#center">我的中心頁</a>
<a href="#help">幫助頁</a>
</header>
<section id="content"></section>
<script> window.addEventListener('hashchange', (e) => { let content = document.getElementById('content'); content.innerText = location.hash; }) </script>
</body>
</html>
複製代碼
<!DOCTYPE html>
<html>
<head>
<title>history 路由</title>
</head>
<body>
<header>
<a onclick="changeRoute(this)" data-path="home">首頁</a>
<a onclick="changeRoute(this)" data-path="center">我的中心頁</a>
<a onclick="changeRoute(this)" data-path="help">幫助頁</a>
</header>
<section id="content"></section>
<script> function changeRoute(route) { let path = route.dataset.path; /** * window.history.pushState(state, title, url) * state:一個與添加的記錄相關聯的狀態對象,主要用於popstate事件。該事件觸發時,該對象會傳入回調函數。 * 也就是說,瀏覽器會將這個對象序列化之後保留在本地,從新載入這個頁面的時候,能夠拿到這個對象。 * 若是不須要這個對象,此處能夠填 null。 * title:新頁面的標題。可是,如今全部瀏覽器都忽視這個參數,因此這裏能夠填空字符串。 * url:新的網址,必須與當前頁面處在同一個域。瀏覽器的地址欄將顯示這個網址。 */ changePage(path); history.pushState({ content: path }, null, path); } /** * 調用 history.pushState() 或者 history.replaceState() 不會觸發 popstate 事件。 * 點擊後退、前進按鈕、或者在 js 中調用 history.back()、history.forward()、history.go() 方法會觸發 */ window.addEventListener('popstate', (e) => { let content = e.state && e.state.content; changePage(content); }); function changePage(pageContent) { let content = document.getElementById('content'); content.innerText = pageContent; } </script>
</body>
</html>
複製代碼
還有一些稍複雜的能夠寫,有時間再補。