一个属于自己的网页导航

1,383 阅读5分钟

先导

今天的内容并没有什么目录,主要是想创建一个属于自己的前端导航页面,把该项目的具体流程记录下来,供大家参考.
文章的附上了该项目的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可以留言评论.
记得持续学习,不断跟进!加油!