页面的完善


大纲链接 §

[toc]


封装hooks 对 组件 或 功能 的逻辑复用

https://juejin.cn/post/6989778275526508574 | vue3 可复用&组合 - 掘金 https://www.jb51.net/article/220201.htm | Vue3 composition API实现逻辑复用的方法_vue.js_脚本之家 https://juejin.cn/post/7031929132057362446 | vue3 基础(一):可复用 & 组合 - 掘金 https://www.jianshu.com/p/e8cce33cfea9 | Vue3 composition API如何实现逻辑复用 - 简书 https://jishuin.proginn.com/p/763bfbd29a5f | vue3.0新型状态管理和逻辑复用方式-技术圈 http://xunmengren.work/2020/09/20/react-hook%E5%92%8Cvue3%E6%96%B0%E7%89%B9%E6%80%A7%E7%9A%84%E6%80%9D%E8%80%83/ | react-hook和vue3新特性的思考 | 寻梦人的个人博客 https://www.cnblogs.com/dingshaohua/p/15694553.html | vue可复用性 & 组合 - 华少丁 - 博客园 https://imbf.cc/a/01fe0c21 | 记录几个vue3 demo项目开发的问题-之间的个人博客 https://www.1024sou.com/article/418701.html | 浅析Vue CompositionAPI和React Hooks对比:hook的意义、两者差别(原理-链表/Proxy、代码执行-每次渲染都执行/组件创建时运行、声明响应式状态、如何跟踪依赖、生命周期、自定义hook、Ref获取元素、计算属性附加函数、Context和provide/inject、在渲染上下文中暴露值) - 1024搜-程序员专属的搜索引擎 https://www.zhihu.com/question/458362474 | vue3 组合式API(setup)的新特性是否会使得业务逻辑集中在一起而臃肿难以维护? - 知乎


实现头部banner向不同方向滚动时隐藏显示和尾部信息固定

  • 子组件内 BlogBody.tsx
    • 声明 props 外部数据 BlogBodyProps: {isSHow: Boolean}
    • emits 发布自定义事件 ['showHeaderFooter']
    • const main = ref(); 获取节点
    • const oldScrollTop = ref(0); 记录初始位置
    • scrollingCB 判断滚动方向 向上滚显示 向下滚隐藏
      • 获取 document.documentElement.scrollTop
      • 判断滚动方向 scrollTop - oldScrollTop.value 触发自定义事件 并传值
        • 为正 ctx.emit('showHeaderFooter', true)
        • 为负 ctx.emit('showHeaderFooter', false)
      • 更新滚动位置 oldScrollTop.value = scrollTop;
    • 挂载 滚动监听window.document.addEventListener('scroll', scrollingCB);
    • 卸载 滚动监听window.document.removeEventListener('scroll', scrollingCB);

BlogBody.tsx

 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
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
import {defineComponent, onMounted, onUnmounted,} from 'vue';

// props
const BlogBodyProps = {
  isSHow: Boolean
};

export default defineComponent({
  props: BlogBodyProps,
  emits: ['showHeaderFooter'],
  setup(props, ctx) {
    const main = ref();

    const oldScrollTop = ref(0);

    // 判断滚动方向 显示/隐藏 回调
    const scrollingCB = () => {
      // 滚动条距文档顶部的距离(做兼容处理)
      // 注意是对象 document.documentElement 的属性 scrollTop
      // 监听 window.document 的元素 documentElement.scrollTop 属性值变化
      const scrollTop = document.documentElement.scrollTop || document.body.scrollTop;
      // 滚动条滚动的距离
      const scrollStep = scrollTop - oldScrollTop.value;
      // 更新——滚动前,滚动条距文档顶部的距离
      oldScrollTop.value = scrollTop;
      // 关键 scrollStep 为正 向下 隐藏导航栏;
      // 为负 向上 显示导航栏
      scrollStep < 0
        ? (ctx.emit('showHeaderFooter', true))
        : (ctx.emit('showHeaderFooter', false));
    };

    onMounted(() => {
      window.document.addEventListener('scroll', scrollingCB);
    });

    onUnmounted(() => {
      window.document.removeEventListener('scroll', scrollingCB);
    });

    return {
      main,
    };
  },
  render() {
    return (
      <main ref={(el) => this.main = el}>
        <router-view/>
      </main>
    );
  }

});


实现 分页页面切换,自动平滑滚动至顶部

src/utils/scrollToTop.ts

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
/*
* window.requestAnimationFrame() 告诉浏览器希望执行一个动画,
* 并且要求浏览器在下次重绘之前调用指定的回调函数更新动画。
* 该方法需要传入一个回调函数作为参数,该回调函数会在浏览器下一次重绘之前执行
* requestAnimationFrame:优势:由系统决定回调函数的执行时机
* 60Hz的刷新频率,那么每次刷新的间隔中会执行一次回调函数,不会引起丢帧,不会卡顿
* */
export const scrollToTop = () => {
  const c = document.documentElement.scrollTop || document.body.scrollTop;
  if (c > 0) {
    window.requestAnimationFrame(scrollToTop);
    window.scrollTo(0, c - c / 8);
  }
}

实现时间显示美化

封装为方法 ``

 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
33
34
35
36
37
38
39
import dayjs from 'dayjs';

export const friendlyDate = (dataStr: string | Date): string => {
  let dateObj = (typeof dataStr === 'object') ? dataStr : new Date(dataStr);
  let time = dateObj.getTime();
  let now = Date.now();
  let space = now - time;
  /*
  let str = '';
    switch (true) {
      case space < 60000:
        str = '刚刚';
        break;
      case space < 1000 * 3600:
        str = Math.floor(space / 60000) + '分钟前';
        break;
      case space < 1000 * 3600 * 24:
        str = Math.floor(space / (1000 * 3600)) + '小时前';
        break;
      default:
        str = Math.floor(space / (1000 * 3600 * 24)) + '天前';
    }
    return str;*/

  const dateMark = {
    [`${space >= 1000 * 3600 * 24 * 30}`]: () => `${dayjs(dataStr).format('YYYY-MM-DD')}`,
    [`${space < 1000 * 3600 * 24 * 30}`]: () => `${Math.floor(space / (1000 * 3600 * 24))}天前`,
    [`${space < 1000 * 3600 * 24}`]: () => `${Math.floor(space / (1000 * 3600))}小时前`,
    [`${space < 1000 * 3600}`]: () => `${Math.floor(space / 60000)}分钟前`,
    [`${space < 60000}`]: () => '刚刚',
  };

  if (typeof dataStr === 'object') {
    return dataStr.toISOString();
  }

  return dateMark['true']();
};

在组件中的使用 BlogIndex

1
2
3
4
5
6
createdAt.value = beautifyDate(blogCreatedAt);

//...
<span class={blogIndex.date}>
  {`${beautifyDate(createdAt)}`} {/* 美化时间显示 */}
</span>

https://zh.javascript.info/switch | “switch” 语句 https://wangdoc.com/javascript/features/style.html#switchcase-%E7%BB%93%E6%9E%84 | 编程风格 - JavaScript 教程 - 网道 https://developer.mozilla.org/zh-CN/docs/Web/SVG/Element/switch | switch - SVG | MDN https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Statements/switch | switch - JavaScript | MDN

https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Statements/switch#%E4%BD%BF%E7%94%A8%E5%A4%9A%E5%87%86%E5%88%99_case_%E7%9A%84%E6%96%B9%E6%B3%95 | switch - JavaScript | MDN https://juejin.cn/post/6952484438789849125 | js中if 和 switch 判断语句的区别 - 掘金 https://juejin.cn/post/6854573209598033928 | Switch…case语句加范围判断 - 掘金 https://juejin.cn/post/6844903997476700174 | 精讲 JavaScript 的 “switch” 语句 - 掘金 https://juejin.cn/post/6844903758401372174 | 其实我们可以少写点if else和switch - 掘金 https://juejin.cn/post/6844904037922373639 | 你可能不知道的 TypeScript 高级技巧 - 掘金 https://its401.com/article/qq_44746132/104939982 | TypeScript:Enum枚举和泛型_一树梨花的博客-程序员ITS401_typescript 枚举 泛型 - 程序员ITS401 https://developer.51cto.com/article/639287.html | Typescript代码整洁之道-51CTO.COM https://segmentfault.com/a/1190000040817957 | 聊聊TypeScript中枚举对象(Enum) - SegmentFault 思否 https://juejin.cn/post/7071106037968797703#refetch | 万一 Github不让用了,Gitee同步指南请收好 - 掘金 https://www.imooc.com/wenda/detail/534429 | js中switch语句中case值可不可以表示一个范围_慕课猿问 https://www.zhihu.com/question/442136109 | (32 封私信 / 64 条消息) typescript中如何约束取值范围? - 知乎 https://zhuanlan.zhihu.com/p/357167292 | TypeScript 条件语句 - 知乎 https://www.it1352.com/1094905.html | 在Typescript中对子进行范围限定的问题 - IT屋-程序员软件开发技术分享社区 https://www.cnblogs.com/gaoshang212/p/15604274.html | 【Typescirpt】定义数字范围类型 - E不小心 - 博客园 https://blog.csdn.net/zhengshengnan123/article/details/90641081 | (11条消息) TypeScript中的if判断及等于的写法_shengnan_only的博客-CSDN博客_typescript 判断字符串相等 https://segmentfault.com/q/1010000013897575 | typescript 限定索引范围 - SegmentFault 思否 https://www.136.la/shida/show-385351.html | 如何在Typescript中把字母数字值转换为数值范围?_136.la https://cloud.tencent.com/developer/ask/sof/410024 | 如何限制typescript中的枚举字符串值 - 问答 - 云+社区 - 腾讯云 https://www.zhangshengrong.com/p/281oqjxbNw/ | TypeScript 中如何限制对象键名的取值范围 / 张生荣 https://segmentfault.com/a/1190000019935975 | TypeScript中高级应用与最佳实践 - SegmentFault 思否 https://www.zhihu.com/question/60168510/answer/733352978 | (32 封私信 / 62 条消息) TypeScript 的 enum 是一种错误吗? - 知乎


骨架屏

参考文章


一键换肤 (待实现)



参考文章

相关文章


  • 作者: Joel
  • 文章链接:
  • 版权声明
  • 非自由转载-非商用-非衍生-保持署名