作者:我不吃饼干呀 原文:https://juejin.im/post/5c9edb066fb9a05e267026dc
前端面试中常见的手写代码题合集
CSS 部分 两栏布局
要求:垂直两栏,左边固定右边自适应。
查看代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 <!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 ; } .outer2 { display : flex; } .outer2 .left { flex-grow : 0 ; flex-shrink : 0 ; flex-basis : 200px ; } .outer2 .right { flex : auto; } .outer3 { position : relative; } .outer3 .left { position : absolute; width : 200px ; } .outer3 .right { margin-left : 200px ; } .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 >
三栏布局
要求:垂直三栏布局,左右两栏宽度固定,中间自适应
查看代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 <!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 : skyblue; } .right { background : gold; } .outer1 { padding : 0200px 0100px; } .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 : 0200px 0100px; } .outer2 .left { width : 100px ; float : left; margin-left : -100% ; } .outer2 .right { width : 200px ; float : left; margin-left : -200px ; } </style > </head > <body > <div class ="outer outer1" > <div class ="middle" > 圣杯-middle </div > <div class ="left" > 圣杯-left </div > <div class ="right" > 圣杯-right </div > </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 >
圣杯布局 和 双飞翼布局
和三栏布局要求相同,不过中间列要写在前面保证优先渲染。
查看代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 <!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 : 0200px 0100px; } .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 : 0200px 0100px; } .outer2 .left { width : 100px ; float : left; margin-left : -100% ; } .outer2 .right { width : 200px ; float : left; margin-left : -200px ; } </style > </head > <body > <div class ="outer outer1" > <div class ="middle" > 圣杯-middle </div > <div class ="left" > 圣杯-left </div > <div class ="right" > 圣杯-right </div > </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 >
三角形
实现一个三角形
常见题目,通过 border
实现 查看代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 <!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 90px80px70px; 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 实现一个宽高自适应的正方形
查看代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 <!DOCTYPE html > <html > <head > <meta charset ="utf-8" /> <title > </title > <style > .square1 { width : 10% ; height : 10vw ; background : red; } .square2 { width : 20% ; height : 0 ; padding-top : 20% ; background : orange; } .square3 { width : 30% ; overflow : hidden; background : yellow; } .square3 ::after { content : '' ; display : block; margin-top : 100% ; } </style > </head > <body > <div class ="square1" > </div > <div class ="square2" > </div > <div class ="square3" > </div > </body > </html >
扇形
实现一个 1/4 圆、任意弧度的扇形
有多种实现方法,这里选几种简单方法(我看得懂的)实现。 查看代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 <!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 > .sector1 { height : 0 ; width : 0 ; border : 100px solid; border-radius : 50% ; border-color : turquoise tomato tan thistle; } .sector2 { height : 100px ; width : 200px ; border-radius : 100px 100px00; overflow : hidden; } .sector2 ::after { content : '' ; display : block; height : 0 ; width : 0 ; border-style : solid; border-width : 100px 58px0; border-color : tomato transparent; transform : translate (42px , 0 ); } .sector3 { height : 100px ; width : 100px ; border-top-right-radius : 100px ; overflow : hidden; } .sector3 ::after { content : '' ; display : block; height : 100px ; width : 100px ; background : tomato; transform : rotateZ (-30deg ); transform-origin : left bottom; } .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; } .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 >
水平垂直居中
实现子元素的水平垂直居中
查看代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 <!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; } .inner1 { position : absolute; top : 50% ; left : 50% ; margin-top : -50px ; margin-left : -50px ; } .inner2 { position : absolute; top : 0 ; right : 0 ; bottom : 0 ; left : 0 ; margin : auto; } .outer3 { display : flex; justify-content : center; align-items : center; } .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 实现 查看代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 <!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; } .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 写一个弹出框效果
查看代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 <!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 : 02px 12px0rgba (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
,并可以横向滚动。
查看代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 <!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 ; } .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 无敌。
JavaScript 部分 手写 bind、call 和 apply 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 Function .prototype .bind = function (context, ...bindArgs ) { context = context || window ; if (typeof func !== 'function' ) { thrownewTypeError ('Bind must be called on a function' ); } let args = bindArgs.concat (callArgs); if (thisinstanceof func) { } return func.call (context, ...args); } } context = context || window ; context.func = this ; if (typeof context.func !== 'function' ) { thrownewTypeError ('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' ) { thrownewTypeError ('apply must be called on a function' ); } let res = context.func (...args); delete context.func ; return res; }
实现一个继承 1 2 3 4 5 6 } Base .call (this ); }
实现一个 new 1 2 3 4 5 6 7 8 9 10 11 12 if (typeof fun !== 'function' ) { returnnewError ('参数必须是一个函数' ); } 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; }
实现一个 instanceof 1 2 3 4 5 6 7 8 while (a) { if (a.__proto__ === b.prototype ) return true ; a = a.__proto__ ; } returnfalse; }
手写 jsonp 的实现 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 console .log ('通过jsonp获取后台数据:' , data); document .getElementById ('data' ).innerHTML = data; } (functionjsonp () { let head = document .getElementsByTagName ('head' )[0 ]; js.src = 'http://domain:port/testJSONP?a=1&b=2&callback=foo' ; head.appendChild (js); })(); return `${callback} (${a + b} )` ; }
ajax 的实现 感觉这个有点无聊了…… 查看代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 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 ( ) { 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); } ajax ({ method : 'GET' , url : '...' , success : function (res ) { console .log ('success' , res); }, async : true , params : { p : 'test' , t : 666 }, headers : { 'Content-Type' : 'application/json' } })
reduce 的实现 1 2 3 4 5 6 7 8 9 functionreduce (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; }
实现 generator 的自动执行器 要求是 yield
后面只能是 Promise
或 Thunk
函数,详见 es6.ruanyifeng.com/#docs/gener…
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 functionrun (gen) { let g = gen (); functionnext (data) { let result = g.next (data); if (result.done ) return result.value ; if (result.value instanceofPromise) { result.value .then (data => next (data)); } else { result.value (next); } } return next (); } console .log (data); cb (); } function *gen ( ) { let a = yieldPromise.resolve (1 ); console .log (a); let b = yieldPromise.resolve (2 ); console .log (b); yield func.bind (null , a + b); } run (gen);
节流 老生常谈了,感觉没必要写太复杂
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 functionthrottle (func, wait) { let timer = null ; returnfunction (...args ) { if (!timer) { func (...args); timer = setTimeout (() => { timer = null ; }, wait); } } }
防抖 1 2 3 4 5 6 7 8 9 10 11 12 13 14 functiondebounce (func, wait) { let timer = null ; returnfunction (...args ) { if (timer) clearTimeout (timer); timer = setTimeout (() => { func (...args); }, wait); } }
手写 Promise 简单实现,基本功能都有了。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 const PENDING = 1 ;const FULFILLED = 2 ;const REJECTED = 3 ;functionMyPromise (executor) { let self = this ; this .resolveQueue = []; this .rejectQueue = []; this .state = PENDING ; this .val = undefined ; functionresolve (val) { if (self.state === PENDING ) { setTimeout (() => { self.state = FULFILLED ; self.val = val; self.resolveQueue .forEach (cb => cb (val)); }); } } functionreject (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 ) { returnnew 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 ) { returnnew 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 ) { returnnew 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 ) { returnthis.then (null , onReject); } MyPromise .all = function (promises ) { returnnew 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 ) { returnnew MyPromise (function (resolve, reject ) { for (let i = 0 ; i < promises.length ; i++) { promises[i].then (resolve, reject); } }); } MyPromise .resolve = function (val ) { returnnew MyPromise (function (resolve, reject ) { resolve (val); }); } MyPromise .reject = function (err ) { returnnew MyPromise (function (resolve, reject ) { reject (err); }) }
实现一个路由 - Hash 实现原理就是监听 url 的哈希值变化了
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 <!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 >
路由实现 - history 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 <!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 > functionchangeRoute (route) { let path = route.dataset .path ; changePage (path); history.pushState ({ content : path }, null , path); } let content = e.state && e.state .content ; changePage (content); }); functionchangePage (pageContent) { let content = document .getElementById ('content' ); content.innerText = pageContent; } </script > </body > </html >
还有一些稍复杂的可以写,有时间再补。