关于DOM的基础操作

1.手写前端路由

手写路由两个核心
1)改变url地址,页面不刷新
2)如何检测url变化

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
/**
* hash 实现
* 1)hash改变页面不会刷新
* 2)通过hashchange监听hash变化
* history 实现
* 1)history提供了pushState、replaceState方法改变url的path不会引起页面刷新
* 2)popstate事件监听url路径变化
* 注意:浏览器前进、后退改变url的时候会触发popstate事件,
* javascript的history: go/back/forword 会触发该事件
* 但是通过pushState、replaceState以及a标签改变url的时候不会触发
*/
class HistoryRoute {
constructor() {
this.current = null
}
}
class VueRouter {
constructor(options) {
this.mode = options.mode || "hash"
this.routes = options.routes || [] //你传递的这个路由是一个数组表
this.routesMap = this.createMap(this.routes)
this.history = new HistoryRoute();
this.init()

}
init() {
if (this.mode === "hash") {
// 先判断用户打开时有没有hash值,没有的话跳转到#/
location.hash ? '' : location.hash = "/";
window.addEventListener("load", () => {
this.history.current = location.hash.slice(1)
})
window.addEventListener("hashchange", () => {
this.history.current = location.hash.slice(1)
})
} else {
location.pathname ? '' : location.pathname = "/";
window.addEventListener('load', () => {
this.history.current = location.pathname
})
window.addEventListener("popstate", () => {
this.history.current = location.pathname
})
}
}

createMap(routes) {
return routes.reduce((pre, current) => {
pre[current.path] = current.component
return pre;
}, {})
}
}

2、字符串格式化

实现下面的字符串格式化函数 format( String, Object),避免出现XSS :

1
2
3
4
5
6
7
document
.body
.innerHTML =
format('<div>I am {name}, my website is <a href="{website}">{website}</a></div>',{
name: 'James',
website: 'https://www.qq.com'
})
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
const str = '<div>I am { name }, my website is <a href="{website}">{website}</a></div>'
const data = {
name: 'James',
website: 'https://www.qq.com'
}
function format(str, data) {
return str
.replace(/&/g, '&amp')
.replace(/</g, '&lt;')
.replace(/>/g, '&gt;')
.replace(/ /g, '&nbsp;')
.replace(/\'/g, '&#39;')
.replace(/\"/g, '&quot;')
.replace(/\{(.*?)\}/g, (i, k) => data[k.trim()])
}
format(str, data)

3、数组渲染Dom

通过JS在下面的ul中插入10000条 li 节点,并在点击 li 时打印其下标

1
<ul id="list></ul>
1
2
3
4
5
6
7
8
9
10
11
12
13
const ul = document.querySelector('#ul')
const fragment = document.createDocumentFragment()
ul.innerHTML= ''
for (let i = 0; i < 10000; i++) {
const li = document.createElement('li')
li.innerText = i
li.setAttribute('data-index', i)
fragment.appendChild(li)
}
ul.appendChild(fragment)
ul.addEventListener('click', (e) => {
console.log(e.target.dataset.index)
})

4.网址判断

在输入框中如何判断输入的是一个正确的网址

1
2
3
4
5
6
7
8
9
var url = 'https://www.abc.com'
function checkUrl(url) {
try {
return new URL(url)
} catch(e) {
return false
}
}
checkUrl(url)

5、页面布局

请按照如下布局在pc端实现htm和css样式,要求:
a)A区域是 header部分,高度100像素,宽度根据屏幕自适应,居顶部展示
b)B区域固定宽度200像素,居左侧展示
c)C区域根据屏幕宽度自适应
d)D区域固定宽度200像素,居右侧展示
e)E区域高度80像素,宽度自适应,当整体内容不够满屏展示,E居屏幕底部展示
f)当整体内容超出屏幕高度,出现垂直滚动

demo:
https://www.epoos.com/demo/learn/layout1.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
<style>
.header {
background:#396;
position: fixed;
left: 0;
top: 0;
width: 100%;
height: 60px;
z-index: 2;
}
.header-none {
height: 60px;
}
.left {
background:#963;
position: absolute;
left: 0;
top: 60px;
width: 200px;
}
.content {
background:#693;
width: 100%;
min-height: 100%;
padding: 60px 200px 30px 200px;
margin-top: -60px;
box-sizing: border-box;
}
.right {
position: absolute;
right: 0;
top: 60px;
background:#369;
width: 200px;
}
.footer {
background:cornsilk;
float: left;
width: 100%;
height: 30px;
margin-top: -30px;
}
</style>

<body>
<div class="header">header</div>
<div class="header-none"></div>
<div class="left">left</div>
<div class="content" contenteditable="true"></div>
<div class="right">right</div>
<div class="footer">footer</div>
</body>