稀土掘金 稀土掘金

【源码学习】第22期 | 看了vant4源码才知道原来loading组件还可以这样实现!

背景

    Vant 是一个轻量、可靠的移动端组件库,而 Vant 4.x 版本适用于 Vue 3 开发,今天就来学习一下Loading 加载组件的实现!

收获清单

  • vue-devtools打开所在文件
  • 如何用vue3+ts开发一个loading组件
  • 一些实用的工具函数

环境准备

    开始阅读源码前先看 README.md,这里基本会教你怎么用它,接着看贡献文档 CONTRIBUTING.md,下图为贡献文档的环境跟运行项目说明:

图片.png

下载源码

git clone https://github.com/youzan/vant.git
cd vant
// 安装依赖及运行项目
pnpm i 
pnpm dev

vue-devtools打开所在文件

图片.png     选择DemoBlock打开文件后发现,呀,这不是咱们很熟悉的组件么?主要有card跟title属性,并根据card属性显示插槽,但是也不是咱们要找的loading啊,那么到底是怎么实现的呢?

图片.png

    带着这个问题,先看看app.vue的代码

<template>

  <demo-nav />

  <router-view v-slot="{ Component }">

    <keep-alive>

      <demo-section>

        <component :is="Component" />

      </demo-section>

    </keep-alive>

  </router-view>

</template>

    这里主要用内置组件插槽来实现路由页面显示,主要涉及了vue的 内置特殊元素相关知识,日常开发技能+1

图片.png

    接着我们可以给vant\packages\vant-cli\site\mobile\router.js打断点调试,继而找到loading所在文件

图片.png

图片.png

源码分析

    找到loading所在文件后,我们接着来分析一下关键源码

入口文件

    文件所在路径vant\packages\vant\src\loading\index.ts,主要是通过withInstall注册loading组件,并把loading相关的类型暴露出去

import { withInstall } from '../utils';

import _Loading from './Loading';

export const Loading = withInstall(_Loading);

export default Loading;

export { loadingProps } from './Loading';

export type { LoadingType, LoadingProps } from './Loading';

export type { LoadingThemeVars } from './types';

declare module 'vue' {

  export interface GlobalComponents {

    VanLoading: typeof Loading;

  }

}

withInstall

export function withInstall<T extends Component>(options: T) {

  (options as Record<string, unknown>).install = (app: App) => {

    const { name } = options;

    if (name) {

      app.component(name, options);

      app.component(camelize(`-${name}`), options);

    }

  };

  return options as WithInstall<T>;

}
  • withInstall入参为泛型类型的options
  • 主要作用是给入参options添加install属性
    • 若传入组件名称,则通过app.component同时注册名为vant-loadingVantLoading的全局组件

主文件 loading\Loading.tsx

    在源码setup处打断点可以看到loading组件的props值分别有那些,以及loading组件主要是通过renderIconrenderText来分别渲染图标和文字,接着从应用的工具函数细看一下具体实现:

图片.png

createNamespace 函数

export function createNamespace(name: string) {
  const prefixedName = `van-${name}`;
  return [
    prefixedName,
    createBEM(prefixedName),
    createTranslate(prefixedName),
  ] as const;
}

    createNamespace主要根据传入name值返回van-${name}、createBEM函数和createTranslate函数,其中createBEM函数的作用看调试截图会更清晰点:

图片.png

extend 函数

export const extend = Object.assign;

    其实就是Object.assign的别名,Object.assign() 方法用于将所有可枚举属性的值从一个或多个源对象复制到目标对象,它将返回目标对象。

const target = {name:'yuexia'}
const source = {hobby:'meditation'}
const result = Object.assign(target,source)
console.log(result,target==result) 
//{ name: 'yuexia', hobby: 'meditation' } true

getSizeStyle 函数

export function getSizeStyle(

  originSize?: Numeric | Numeric[]

): CSSProperties | undefined {

  if (isDef(originSize)) {

    if (Array.isArray(originSize)) {

      return {

        width: addUnit(originSize[0]),

        height: addUnit(originSize[1]),

      };

    }

    const size = addUnit(originSize);

    return {

      width: size,

      height: size,

    };

  }

}

    getSizeStyle函数返回组件的尺寸(带单位宽高的值),大概意思是:

  1. 判断入参是否非undefined和null
  2. 用Array.isArray判断入参是否为数组,若是则分别取值,否则直接返回addUnit函数处理后的值作为宽高

addUnit添加单位

export function addUnit(value?: Numeric): string | undefined {

  if (isDef(value)) {

    return isNumeric(value) ? `${value}px` : String(value);

  }

  return undefined;

}

    addUnit函数的作用是给入参添加单位,其中isDef函数判断入参是否非undefined和null

总结

    本文调试学习了vant4源码中loading组件的实现,学习了其关联的工具函数,虽然loading组件只是文字跟图标的渲染,但其实现方式还是很值得我们在日常开发(尤其是ts的项目)参考应用的~

哆哆女性网耳东兔子都城快餐灰姑娘的读后感50字七画起名吉利的字河池网站设计公司孤独的夜伤感散文netflix最新剧集做不锈钢加工起名大全宁波网站优化服务义乌seo外贸seo调优推广给旅游公司起名大全有特色的公司起名梦幻飞仙破解版二维码电子签名王起名字男孩2020网站优化培训班男孩宝宝起名字打分免费网站推广优化价格qq音速家族系统为树木起名服装公司名字起名大全晚上梦见掉牙齿周公解梦用成语送男孩起名字周公解梦梦见做鞋子网站建设外包家居行业事件营销推广策划傲慢与偏见2005免费完整版在线秦起名女孩姓名seo的优化流程淀粉肠小王子日销售额涨超10倍罗斯否认插足凯特王妃婚姻不负春光新的一天从800个哈欠开始有个姐真把千机伞做出来了国产伟哥去年销售近13亿充个话费竟沦为间接洗钱工具重庆警方辟谣“男子杀人焚尸”男子给前妻转账 现任妻子起诉要回春分繁花正当时呼北高速交通事故已致14人死亡杨洋拄拐现身医院月嫂回应掌掴婴儿是在赶虫子男孩疑遭霸凌 家长讨说法被踢出群因自嘲式简历走红的教授更新简介网友建议重庆地铁不准乘客携带菜筐清明节放假3天调休1天郑州一火锅店爆改成麻辣烫店19岁小伙救下5人后溺亡 多方发声两大学生合买彩票中奖一人不认账张家界的山上“长”满了韩国人?单亲妈妈陷入热恋 14岁儿子报警#春分立蛋大挑战#青海通报栏杆断裂小学生跌落住进ICU代拍被何赛飞拿着魔杖追着打315晚会后胖东来又人满为患了当地回应沈阳致3死车祸车主疑毒驾武汉大学樱花即将进入盛花期张立群任西安交通大学校长为江西彩礼“减负”的“试婚人”网友洛杉矶偶遇贾玲倪萍分享减重40斤方法男孩8年未见母亲被告知被遗忘小米汽车超级工厂正式揭幕周杰伦一审败诉网易特朗普谈“凯特王妃P图照”考生莫言也上北大硕士复试名单了妈妈回应孩子在校撞护栏坠楼恒大被罚41.75亿到底怎么缴男子持台球杆殴打2名女店员被抓校方回应护栏损坏小学生课间坠楼外国人感慨凌晨的中国很安全火箭最近9战8胜1负王树国3次鞠躬告别西交大师生房客欠租失踪 房东直发愁萧美琴窜访捷克 外交部回应山西省委原副书记商黎光被逮捕阿根廷将发行1万与2万面值的纸币英国王室又一合照被质疑P图男子被猫抓伤后确诊“猫抓病”

哆哆女性网 XML地图 TXT地图 虚拟主机 SEO 网站制作 网站优化