学习github的开源项目
项目介绍
特点
- 移动端支持
- DIY收藏网站
- 界面简洁友好
- 使用指南
技术栈
Figma
jQuery
(BootCdn)
SCSS
parcel
实时预览
@media
媒体查询
IconFont
( iconfont.cn)
SVG
Symbols
- JS 事件 阻止冒泡
LocalStorage
JSON
序列化
- 哈希表
webpack
配置
Git
& GitHub
- 短链处理
- 二维码链接
后续更新
- 实现
Bing + Google
搜索
- 实现搜索 关键词 弹幕效果
Bullet Screen
- vue版本
- react版本
思路
Figma
作图
- 实现手机端
- 写 HTML
- 写 SCSS
- 写 JS(事件监听、DOM 操作)
- 实现PC端
- 加 媒体查询 CSS
- 写 JS(单独处理PC端逻辑)
- 发布到
GitHub
Gitee
实现过程
使用Figma
作图
设计稿先导:https://dwz.cn/mnMSVtaC
- 不自己配色,通用背景配色
#EEEEEE
- 常用居中操作
- 分组操作
- Alt 平移复制
- Shift 保持比例 变形
- 使用 IconFont( iconfont.cn)的图标文字,下载 PNG 图片和生成链接插入网页
- 复制 CSS 代码
手机页面 PC页面 对比参考 谷歌 Chrome 和 微软 Edge 的导航
自动标注功能可以用 摹客网的
写HTML和SCSS
实时预览
查看大厂的 meta viewport
设置 进入chrome 开发者工具 > 移动端 > 点刷新 > 元素
index.html
style.scss
main.js
1
|
<meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no,viewport-fit=cover">
|
- 语义化标签
<header></header>
<main></main>
- 语义化样式类名
globalHeader
globalMain
site
siteList
lastLi
<form></form>
表单 搜索框
- 可以用a标签包裹div,实现点击链接
1
2
3
4
|
<form class="searchForm" method="get" action="https://www.baidu.com/s" target="_blank">
<input name="wd" type="text">
<button type="submit">搜索</button>
</form>
|
样式与布局
- reset CSS
flex
平均布局
justify-content
align-items
居中
- 谨慎加高度,内部最小的加,撑开外部的; 用
padding
使用 IconFont
- IconFont( iconfont.cn)
- 搜索关键词
plus
- 添加项目
- 查看在线链接
- 选择
Symbol
- 插入生成代码
<script src="//at.alicdn.com/t/font_1765894_oi0jnamflr.js"></script>
- 引入通用样式
1
2
3
4
5
6
7
8
9
|
<style type="text/css">
.icon {
width: 1em;
height: 1em;
vertical-align: -0.15em;
fill: currentColor;
overflow: hidden;
}
</style>
|
图片
1
|
img {max-width: 100%;max-height: 100%;}
|
手机端测试
- 查看 终端
ipconfig
- 获取 IP ,加上端口号
:1234
手机浏览器访问
jQuery
- 引入 jQuery CDN 加速 BootCDN
- 操作点击事件
- 用户输入 url 合法性判断
- 操作节点
1
2
3
4
5
6
7
8
9
10
|
const $li = $(`
<li>
<a href="${node.url}">
<div class="site">
<div class="logo">${node.logo[0]}</div>
<div class="link">${simplifyUrl(node.url)}</div>
</div>
</a>
</li>
`).insertBefore($lastLi)
|
哈希表(数组)的应用
main.js
1
2
3
4
5
6
7
8
9
10
11
12
13
|
const hashMap = [{
logo: 'A',
logType: 'text',
url: 'https://www.acfun.cn'
}, {
logo: './images/bilib.png',
logType: 'image',
url: 'https://www.bilibili.com'
}, {
logo: 'M',
logType: 'text',
url: 'https://developer.mozilla.org/zh-CN/'
}]// 注意用 parcel 时,默认在代码外加一层作用域 非全局变量 不用考虑全局污染
|
渲染函数
forEach
遍历生成节点添加,渲染
- 渲染 hashMap 之前必须先清空原来的
$siteList.find('li:not(.last)').remove()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
const render = () => {
$siteList.find('li:not(.last)').remove()
hashMap.forEach(node => {
const $li = $(`
<li>
<a href="${node.url}">
<div class="site">
<div class="logo">${node.logo[0]}</div>
<div class="link">${simplifyUrl(node.url)}</div>
</div>
</a>
</li>
`).insertBefore($lastLi)
})
}
|
- 将所有对节点的操作,变为操作 hashMap 的 push 操作,渲染页面
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
/* 事件处理 */
$('.addButton').on('click', () => {
let url = window.prompt("请输入网址")
/* 网址合法行判断 */
if (url.indexOf("http") !== 0) {
url = 'https://' + url
}
// console.log(url)
hashMap.push({
logo: url[0],
logoType: 'test',
url: url
})
render()
}
|
- 优化从第二个开始渲染
hashMap.slice(2)
LocalStorage 的应用
退出网站 用户关闭网站钱触发 存到 localStorage 里
- 监听事件
window.onbeforeunload()
1
2
3
4
5
6
7
8
9
10
|
// 退出网站 用户关闭网站钱触发 存到 localStorage 里
window.onbeforeunload = () => {
console.log('页面要关闭了') // 可以开启 Preserve log 查看
// 将 对象变为 字符串
const string = JSON.stringify(hashMap)
// console.log(hashMap)
// console.log(typeof hashMap)
// console.log(string)
// console.log(typeof string)
}
|
JSON
序列化
初始时
- 在 开发者选项 Application 选项卡中可以看到
- 从 LocalStorage 中读取
const x = localStorage.getItem('x')
- 注意读取的是字符串,需要转变为对象
- 将读取的字符串 变为 对象
const xObject = JSON.parse(x)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
const $siteList = $('.siteList')
const $lastLi = $siteList.find('li.last')
/* 初始时从 LocalStorage 中读取 */
const x = localStorage.getItem('x')
// 将读取的字符串 变为 对象
const xObject = JSON.parse(x)
// hashMap 初始化保底值
const hashMap = xObject || [{
logo: 'A',
logType: 'text',
url: 'https://www.acfun.cn'
}, {
logo: './images/bilib.png',
logType: 'image',
url: 'https://www.bilibili.com'
}, {
logo: 'M',
logType: 'text',
url: 'https://developer.mozilla.org/zh-CN/'
}]
|
退出页面时
- 退出页面时 保存 hashMap
- 将 hashMap 对象变为 字符串
const string = JSON.stringify(hashMap)
- 注意 localStorage 要保存的是字符串,需要将对象 hashMap 转变为字符串
- 保存到
localStorage.setItem('x', string)
1
2
3
4
5
6
7
8
9
10
11
|
// 退出网站 用户关闭网站钱触发 存到 localStorage 里
window.onbeforeunload = () => {
// console.log('页面要关闭了') // 可以开启 Preserve log 查看
// // 将 对象变为 字符串
const string = JSON.stringify(hashMap)
// console.log(typeof hashMap)
// console.log(hashMap)
// console.log(typeof string)
// console.log(string)
localStorage.setItem('x', string)
}
|
其他注意
- 清除 cookie 时 localstorage 就删除了
- 或存储硬盘满了,也可能会删除 localstorage
- 或使用无痕窗口
其他优化
- 缩短显示链接
- 处理 logo
- 简化 URL
- 删除功能
- PC 网页(媒体查询)
- PC 网页样式优化
- PC 样式影响了手机样式
- 键盘事件
缩短显示链接
1
2
3
|
const simplifyUrl = (url) => {
return url.replace('https://', '').replace('http://', '').replace('www.', '')
}
|
简化 URL
1
2
3
4
5
6
7
|
/* 显示链接 缩短 */
const simplifyUrl = (url) => {
return url.replace('https://', '')
.replace('http://', '')
.replace('www.', '')
}
/* <div class="link">${simplifyUrl(node.url)}</div> */
|
处理 logo
显示恰当的首字母
- 先去掉 logo 显示图片,直接显示字母
- 简化 去掉 logoType
- 删掉 localStorage 存储内容
- 调用
simplifyUrl(url)[0]
- 大写
simplifyUrl(url)[0].toUpperCase()
1
2
3
4
|
hashMap.push({
logo: simplifyUrl(url)[0].toUpperCase(),
url: url
})
|
- 大写也可以用 CSS 来控制
text-transform: uppercase;
显示 bug 输入长网址时 超出显示
再简化 URL
用正则表达式,表示以/
开头的字符
1
2
3
4
5
6
|
const simplifyUrl = (url) => {
return url.replace('https://', '')
.replace('http://', '')
.replace('www.', '')
.replace(/\/.*/,'') // 删除以 / 开头的内容 贪婪匹配
}
|
删除功能
- IconFont( iconfont.cn)
- 搜索关键词
close
选择一个图标
- 添加项目
- 更新在线链接
- 选择
Symbol
- 更新代码
<script src="//at.alicdn.com/t/font_1774301_yiq4rsp0i6q.js"></script>
- 样式
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
|
hashMap.forEach(node => {
const $li = $(`
<li>
<a href="${node.url}">
<div class="site">
<div class="logo">${node.logo}</div>
<div class="link">${simplifyUrl(node.url)}</div>
<div class="close">
<svg class="icon">
<use xlink:href="#icon-close"></use>
</svg>
</div>
</div>
</a>
</li>
`).insertBefore($lastLi)
})
/*
.close{
position: absolute;
right: 10px;
top: 5px;
}
*/
|
- 关闭图标在a标签里,点击穿透,需要阻止冒泡
- 监听对 close 图标的点击事件
1
2
3
4
|
$li.on('click','.close',(e)=>{
console.log('阻止冒泡')
e.stopPropagation()
})
|
点击close图标,还是跳转了
1
2
3
|
$li.on('click',()=>{
window.open(node.url, '_self')
})
|
webStorm 技巧 在变量后输入 .log
,按 Tab
健,变为console.log()
这个变量
- 在 hashMap 中找到表示点击当前网站的节点,然后删掉
- 需要索引 index
- forEach() 的第二个参数为 索引 index
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
|
hashMap.forEach((node, index) => {
const $li = $(`
<li>
<div class="site">
<div class="logo">${node.logo}</div>
<div class="link">${simplifyUrl(node.url)}</div>
<div class="close">
<svg class="icon">
<use xlink:href="#icon-close"></use>
</svg>
</div>
</div>
</li>
`).insertBefore($lastLi)
$li.on('click',()=>{
window.open(node.url,'_self')
})
$li.on('click','.close',(e)=>{
// console.log('阻止冒泡')
e.stopPropagation()
// console.log(hashMap);
// console.log(index);
hashMap.splice(index,1)
render() // 删除后 重新渲染
})
})
|
渲染函数
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
|
/* 操作 hashMap 渲染页面 */
const render = () => {
/* 再次渲染 hashMap 之前必须先 清空原来的 */
// 找到 的除了 lastLi 之外的所有 li
$siteList.find('li:not(.last)').remove()
hashMap.forEach((node, index) => {
const $li = $(`
<li>
<div class="site">
<div class="logo">${node.logo}</div>
<div class="link">${simplifyUrl(node.url)}</div>
<div class="close">
<svg class="icon">
<use xlink:href="#icon-close"></use>
</svg>
</div>
</div>
</li>
`).insertBefore($lastLi)
$li.on('click',()=>{
window.open(node.url,'_self')
})
$li.on('click','.close',(e)=>{
// console.log('阻止冒泡')
e.stopPropagation()
// console.log(hashMap);
// console.log(index);
hashMap.splice(index,1)
render()
})
})
}
|
- 大部分时间处理不恰当的操作:用JS操作代替 a 标签 点击跳转、阻止冒泡
- 剩下的时间才实现最终的逻辑
PC 网页(媒体查询)
- 业界常识:PC页面的宽度是固定的
- 优先用
max-width
- 当元素有最大/小宽度(固定)时,就可以用
margin:0 auto;
来居中,但会覆盖其他元素上下margin
- 用
margin-left:auto;
margin-right:auto;
- 平均布局用负 margin
PC 网页样式优化
- 通过改变
visibility
属性来显示/隐藏关闭按钮,再通过opacity
属性的改变达到渐变的动画效果
键盘事件
将Google嵌入iframe
发布到 GitHub
默认路径有问题
parcel build src/index.html --no-minify
换成 ./
parcel build src/index.html --no-minify --public-url ./
parcel build src/index.html src/search.html --no-minify --public-url ./
yarn build 一键发布
再次build的时,只需用yarn init -y
创建package.json
1
2
3
|
"scripts": {
"build":"rm -rf dist && parcel build src/index.html --no-minify --public-url ./"
},
|
再次 yarn build
原则和要点
原则
- 没有移动端设计稿,绝对不要做移动端页面
- 定一个小目标来实现(短链处理)
- 没完美,做到看不出Bug
要点
- 专业的前端工程师应该能快速的抄袭大厂网页里的
meta viewport
- 前端工程师可以 flex 布局一把梭,解决 80% 以上的需求
- 将对象变成一个字符串
JSON.stringify
- 将字符串变成一个对象
JSON.parse
- 一般来说
localStorage
里的数据用户清除浏览器数据的时候消失
优秀导航网页
参考文章
相关文章
- 作者: Joel
- 文章链接:
- 版权声明
- 非自由转载-非商用-非衍生-保持署名
- 河
掘
思
知
简