学习github的开源项目
- 预览链接:http://dwz.win/95z
- 代码链接:http://dwz.win/952
Figma设计稿:https://dwz.cn/mnMSVtaC
项目介绍
特点
- 移动端支持
- DIY收藏网站
- 界面简洁友好
- 使用指南
技术栈
FigmajQuery(BootCdn)SCSSparcel实时预览@media媒体查询IconFont( iconfont.cn)SVGSymbols- JS 事件 阻止冒泡
LocalStorageJSON序列化- 哈希表
webpack配置Git&GitHub- 短链处理
- 二维码链接
后续更新
- 实现
Bing + Google搜索 - 实现搜索 关键词 弹幕效果
Bullet Screen - vue版本
- react版本
思路
Figma作图- 实现手机端
- 写 HTML
- 写 SCSS
- 写 JS(事件监听、DOM 操作)
- 实现PC端
- 加 媒体查询 CSS
- 写 JS(单独处理PC端逻辑)
- 发布到
GitHubGitee
实现过程
使用Figma作图
设计稿先导:https://dwz.cn/mnMSVtaC
- 不自己配色,通用背景配色
#EEEEEE - 常用居中操作
- 分组操作
- Alt 平移复制
- Shift 保持比例 变形
- 使用 IconFont( iconfont.cn)的图标文字,下载 PNG 图片和生成链接插入网页
- 复制 CSS 代码
手机页面 PC页面 对比参考 谷歌 Chrome 和 微软 Edge 的导航
自动标注功能可以用 摹客网的
写HTML和SCSS
实时预览
parcel src/index.html
meta viewport
查看大厂的
meta viewport设置 进入chrome 开发者工具 > 移动端 > 点刷新 > 元素
index.htmlstyle.scssmain.js1<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>语义化样式类名
globalHeaderglobalMainsitesiteListlastLi<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-contentalign-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>
图片
|
|
手机端测试
- 查看 终端
ipconfig - 获取 IP ,加上端口号
:1234手机浏览器访问
jQuery
- 引入 jQuery CDN 加速 BootCDN
- 操作点击事件
- 用户输入 url 合法性判断
操作节点
1 2 3 4 5 6 7 8 9 10const $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
|
|
渲染函数
forEach遍历生成节点添加,渲染渲染 hashMap 之前必须先清空原来的
$siteList.find('li:not(.last)').remove()1 2 3 4 5 6 7 8 9 10 11 12 13 14 15const 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 20const $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 样式影响了手机样式
- 键盘事件
缩短显示链接
|
|
简化 URL
|
|
处理 logo
显示恰当的首字母
- 先去掉 logo 显示图片,直接显示字母
- 简化 去掉 logoType
- 删掉 localStorage 存储内容
- 调用
simplifyUrl(url)[0] 大写
simplifyUrl(url)[0].toUpperCase()1 2 3 4hashMap.push({ logo: simplifyUrl(url)[0].toUpperCase(), url: url })大写也可以用 CSS 来控制
text-transform: uppercase;
显示 bug 输入长网址时 超出显示
再简化 URL
用正则表达式,表示以
/开头的字符
- 正则表达式30分钟入门教程
-
1 2 3 4 5 6const 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 25hashMap.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图标,还是跳转了
去掉 a 标签, 用 JS 监听点击 li 标签
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 26hashMap.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属性的改变达到渐变的动画效果
键盘事件
- 在 document 上绑定键盘事件
将Google嵌入iframe
- 得到 chrome 插件
Double Shot Search和 jQuery 插件 purl的启发 - 搜索
iframe src google.com - HTML - 如何在iframe中显示google.com?
发布到 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
在
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里的数据用户清除浏览器数据的时候消失
优秀导航网页
参考文章
- 2020版前端体系课【方方】之【项目】前端导航站点(上)
- 2020版前端体系课【方方】之【项目】前端导航站点(下)
- 优秀导航网页
- 完善的输入框监听方案:兼容、高效和组合输入友好
- js监听input输入框值的实时变化
相关文章
- 无