从零开始的博客开发(三)

功能与问题

  • 为每篇文章添加一个目录,可以抓取二号标题
  • 返回顶部

实现

目录

  • 前几篇好像忘记说了,目前的md解析实现方法都有些问题,我把要提取出来的数据都放在了组件的data里边,因为每个组件是唯一的,所以data就没有用函数的形式,而是直接赋值,虽然可以实现需要的功能,但是不符合规定的使用规范,以后进行改进。
  • 目录的实现是通过正则匹配每篇文章中的<h2>标签,把其中的内容设置为id属性,在展示文章的时候,通过id获得每个<h2>标签的高度,监听目录的点击,滚动页面到制定高度即可
  • 代码:
    //h2标签的匹配
    function setDoc(html) {
    var reg = /<h2>([\s\S]*?)<\/h2>/g
    var sidebar = []
    html = html.replace(reg, (str, content) => {
      sidebar.push("'"+content+"'")
      return `<h2 id='${content}'>
        <a href="#${content}"/>
        ${content}
        </h2>`
    })
      return {html:html, sidebar: sidebar}
    }
    
    //滚动
    //anchor是一个由当前文章h2标签高度组成的数组
    goto(index) {
        let timer = null,
            _that = this,
            flag = true,
            target = this.anchor[index]+250,
            max = document.body.scrollHeight - document.documentElement.clientHeight;
        flag = document.documentElement.scrollTop<target;
        console.log(this.anchor)
        timer = 
        requestAnimationFrame(function fn() {
          if (flag&&document.documentElement.scrollTop < target) {
            if(document.documentElement.scrollTop+50 >= max||document.documentElement.scrollTop+50 >= target){
              document.documentElement.scrollTop=Math.min(target, max);
              cancelAnimationFrame(timer);
            }else{
              document.documentElement.scrollTop += Math.max((target-document.documentElement.scrollTop)/30,50);
              document.body.scrollTop = document.documentElement.scrollTop;
              timer = requestAnimationFrame(fn);
            }
          } else if(!flag&&document.documentElement.scrollTop > target){
              if(document.documentElement.scrollTop-50 < target){
                document.documentElement.scrollTop=target;
                cancelAnimationFrame(timer);
              }else{
                document.documentElement.scrollTop -= Math.max((document.documentElement.scrollTop-target)/30,50);
                document.body.scrollTop = document.documentElement.scrollTop ;    
                timer = requestAnimationFrame(fn);
              }
          } else {
            cancelAnimationFrame(timer);
          }
        });
      }
    
  • 为了让滚动更加丝滑,使用了一个requestAnimationFrame()函数,语法:window.requestAnimationFrame(callback);会自动向callback函数传入一个参数,表示开始去执行回调函数的时刻。返回一个整数,可以作为参数传入window.cancelAnimationFrame()来取消调用。简单说就是会以最佳的频率调用函数,只需要在回调函数中编写动画操作就行了。
  • 遇到的一些小问题:
      • 当滚动到最底部时,会因为文档的总高度小于h2标签的高度+浏览器窗口的高度,导致滚动不到指定位置,因而一直停在最底部,滚不回去了。
      • 解决的办法就是加个最底部的判断,当超出最大高度时,就停在最底部。
      • 当切换页面之后,目录的跳转位置没有变化,也就是anchor数组没有更新。
      • 目录组件是单独的,通过向它传入目录的数据实现相关的功能,一开始把读取anchor数组的代码写在了created钩子里,导致路由变化以后没有更新。改到updated里边就好了。

返回顶部

  • 因为滚动原理差不多,就一起做了。代码如下:
  • 
    
    mounted(){
      window.addEventListener("scroll",this.show,true);
    },
    methods: {
      //滚动
      back() {
        let backTop = null,
        _that = this;
        backTop = requestAnimationFrame(function fn() {
                if(document.documentElement.scrollTop > 0){
                  document.documentElement.scrollTop -= Math.max((document.documentElement.scrollTop)/10,50);
                  document.body.scrollTop = document.documentElement.scrollTop ;    
                  backTop = requestAnimationFrame(fn);
                } else {
                  cancelAnimationFrame(back);
                }
              });
      },
      //是否显示
      show(){
        this.isShow = document.documentElement.scrollTop > this.showHeight
      }
    },
    computed: {
    },
    destroyed(){
      window.removeEventListener("scroll",this.show);
    }
    
  • 悬浮就是动态添加class设置position: fixed;

总结

  • 对Vue的生命周期的理解加深了一点,一些数据更新方面的问题,多半是出在了生命周期函数的选择上。根据何时要更新数据,写在正确的钩子函数里边。
  • 注意拼写,因为拼写错误找了好久的错误,真的是蠢死了,最后发现是变量名字拼错了真的是想砸键盘
  • 源码地址https://github.com/DouMJun/myBlog-Vue欢迎提问和联系我

参考:

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值