先导
今天的内容并没有什么目录,主要是想创建一个属于自己的前端导航页面,把该项目的具体流程记录下来,供大家参考.
文章的附上了该项目的GitHub源码,感兴趣的可以给个star,谢谢
GitHub
布局
这个项目主要用到了flex的布局形式,同时兼备移动端和pc端两个页面布局的形式,首先我们讲解在移动端的布局,首先展示一下html的布局
这个布局还是比较简单,其实就是包含了一个搜索框,以及一个大的导航框,在搜索框中运用了form来进行请求,然后搜索跳转,在method中是发送get请求,然后action是请求的地址.
在input中name用于对提交到服务器后的表单数据进行标识.然后将button的类型设置为submit(虽然是自动设置为submit,但是为了保险起见 自己再设置一遍)
在这里采用了语义化标签,header,main.这里的布局应该还是比较清晰易懂的.
分成了上下两个部分,搜索栏,和导航栏,导航栏在这里仅将新增网站按钮写死,其他的按钮将会通过script动态写入.
在这里我们给main,header设置了class类,主要是因为一个项目开发可能由多人开发,若其他人也更改了header的样式,将会和我们的冲突掉,所以为了养成习惯,在此也加入了class.
在这里的css样式其实还是比较简单的,主要是用的flex布局,在此给各位读者演示一下该项目中比较常用的几种css样式,以及一些css的技巧
简单的讲解一下flex的居中设置的方法,要给父元素设置弹性盒模型
display: flex; //设置弹性盒模型
justify-content: center; //设置主轴居中
align-items: center; //设置次轴居中
这种居中的方式是不是感觉不敢相信,就简单的三行代码即可实现居中
通过设置cursor改变鼠标指针放在一个元素边界范围内时所用的光标形状
cursor: default; //默认光标(通常是一个箭头)
cursor: pointer //光标呈现为指示链接的指针(一只手)
该项目中用到的css样式比较基础,只要大家经常使用应该能想到怎么去写样式,下面展示一下修改好样式的界面
开启js
本项目主要采用的是jQuery的库,在html文件内首先引入,切记要引入在自己的js之前
<script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.5.1/jquery.js"></script>
我们运用了jQuery的库来获取,和监听事件
$('.addButton').on('click', () => {
let url = prompt('请问你要添加的网址');
// 判断http是不是开头 若不是则自动添加
if(url.indexOf('https') !== 0) {
url = 'https://' + url
}
})
当点击新增网站后,若用户输入的网址不是以https开头,我们会自动为用户拼接上https,以防止有些网站必须加上才可以正常的访问,通过indexOf判断https出现的位置是不是在最开始的位置 我们获取siteList,last两个节点
const $siteList = $('.siteList')
const $last = $('.last')
在未考虑到localStorage时,我们可以通过动态拼接,然后通过jQuery链式调用的方式,将生成的li添加到siteList内
const $li = $(`<li>
<a href="${url}">
<div class="site">
<div class="logo">
${url[8]}
</div>
<div class="link">${url}</div>
</div>
</a>
</li>
`).insertBefore($last)
以上即可完成动态插入 但是若想运用localStorage的方式,需要创建一个hash数组的形式存储,通过forEach遍历,然后动态的插入数组中的内容
const hashMap = [{logo: 'A', logoType: 'text', url: 'https://www.acfun.cn'},
{logo: './images/blibli.png', logoType: 'image', url: 'https://www.bilibibli.com'}]
hashMap.forEach((node, index) => {
const $li = $(`<li>
<a href="${node.url}" target="_blank">
<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($last)
创建后再开始时就要运行此代码,然后自动创建li,但是这样创建两遍,就会重复数据的产生,所以当点击添加事件时,我们还需将之前的所有li都移除掉
$siteList.find('li:not(.last)').remove()
这样选择 除了新增按钮 其他全部都移除掉
我们将重复的函数抽成render函数
const render = () => {
// 找到除了最后一个的li然后每个都移除掉
$siteList.find('li:not(.last)').remove()
// 遍历数组,将每一项插入到新增网站之前
hashMap.forEach((node, index) => {
const $li = $(`<li>
<a href="${node.url}" target="_blank">
<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($last)
$li.on('click', '.close', e => {
e.preventDefault();
if(confirm('确认删除?')) {
hashMap.splice(index, 1)
render()
}
})
})
}
同时在这里我们还添加了一个删除的按钮,通过监听close事件,然后确认是否删除当前索引所在的对象,在删除以后重新做渲染更新.
在这里,基本的一个前端导航是可以实现了,但是还有很多的细节未去矫正,例如网站关闭后存储的导航链接就不复存在,这也不是我们的本意,接下来我们对该项目再做一些完善,保存至localStorage
完善
首先localStorage是HTML5的新技术,主要是用于长久保存整个网站的数据,保存的数据没有过期时间,直到手动去删除,但是localStorage在IE8以上的才支持,所以本导航仅支持IE8以上的浏览器.
若想保存,首先要监听离开事件
window.onbeforeunload = () => {
}
由于要存储到localStorage内只能存储字符串,我们要将hashMap存进去,但它为数组,我们需要通过JSON.stringify()转换成字符串,然后再通过localStorage.setItem()存入localStorage中
window.onbeforeunload = () => {
let string = JSON.stringify(hashMap) //JSON.stringify这是JSON提供的一种方法,序列化
localStorage.setItem('x',string)
}
这样既可在离开网站的时候,将我们添加的数组存入到localStorage中.
我们在开始时需要判断,用户浏览器中是否存在localStorage,判断前需要将localStorage内的数据转成对象,然后再进行判断
let xObject = JSON.parse(x) // JSON.parse这是JSON提供的一种方法,反序列化
当转换后,我们需要获取到用户的localStorage,然后进行判断,若没有则写入固定的,若有则取用
let x = localStorage.getItem('x');
const hashMap = xObject || [{logo: 'A', logoType: 'text', url: 'https://www.acfun.cn'},
{logo: './images/blibli.png', logoType: 'image', url: 'https://www.bilibibli.com'}]
到此就完成了localStorage的配置,以及新增链接的实现,但此仅为移动端,还有bug未处理 若用户输入的url很长想要简化url有以下两种方法. 方法一.可以使用replace替换即可,但是有局限性(该方法只能把超出的变成省略号,并不能完整显示路径) 方法二.要通过正则表达式进行匹配 /后的所有内容
const simplifyUrl = (url) => {
let newUrl = url.replace('https://', '').replace('http://', '').replace('www.', '');
newUrl = newUrl.length>12?newUrl.substring(0,12) + '...':newUrl
return newUrl
} // 方法一
const simplifyUrl = (url) => {
let newUrl = url.replace('https://', '').replace('http://', '').replace('www.', '').replace(/\/.*/, '')
return newUrl
} // 方法二
在该项目中我们运用到了媒体查询,以下简单举出项目的一个例子供大家学习,若想知道项目中所有的媒体查询可下载源码查询.
@media screen and (min-width: 500px) {
.globalHeader {
margin-top: 200px;
margin-bottom: 150px;
}
}
这里设置的是当屏幕最小宽度大于500时,globalHeader类会增加上以下的两种样式,若改为max-width: 500px,则适配的是当屏幕最大宽度为500以下的屏幕 这里还对按键触发做了相应的设置,大家可以看一下代码,在很多时候都需要取消默认事件,在这里通过for循环遍历,然后用window.open(链接)打开相应的链接即可
$(document).on('keypress', e => {
const { key } = e;
for(let i=0;i< hashMap.length;i++) {
if(hashMap[i].logo.toLowerCase() === key) {
window.open(hashMap[i].url)
}
}
})
以下为下载后需要操作的代码.
开发
yarn global add parcel-bundler
parcel src/index.html
build命令
yarn build
总结
该项目的实现还是比较容易,但是运用了一些新的技术,比如localStorage,媒体查询,同时还运用了JSON的序列化和反序列化,在该项目中,还是有不足的地方,若有读者下载了发现bug可以留言评论.
记得持续学习,不断跟进!加油!