一个vant组件是如何创建的

首先,从Vant组件的使用开始。

// js
import Vue from 'vue';
import {
    Button } from 'vant'; // 导入 Button

Vue.use(Button); // 注册 Button
// template
<van-button type="primary">主要按钮</van-button>

源码第一部分

// src/button/index.tsx 01 这里主要导入一些函数和类型
// 函数:useRoute createNamespace 
// 类型:PropType CSSProperties routeProps LoadingType (用来进行ts类型校验)
// 常量:BORDER_SURROUND 
// 其他组件:Icon Loading

import {
    PropType, CSSProperties } from 'vue';

// Utils
import {
    createNamespace } from '../utils';
import {
    BORDER_SURROUND } from '../utils/constant';
import {
    useRoute, routeProps } from '../composables/use-route';

// Components
import Icon from '../icon';
import Loading, {
    LoadingType } from '../loading';

const [createComponent, bem] = createNamespace('button');

这里,我们只看函数部分,通过 导入路径,我们找到了useRoute createNamespace 两个函数的实现。

useRoute

// src/composables/use-route.tsx
import {
   
  PropType,
  ExtractPropTypes,
  getCurrentInstance,
  ComponentPublicInstance,
} from 'vue';
import type {
    RouteLocationRaw } from 'vue-router';

export const routeProps = {
   
  to: [String, Object] as PropType<RouteLocationRaw>,
  url: String,
  replace: Boolean,
};

export type RouteProps = ExtractPropTypes<typeof routeProps>;

export function route(vm: ComponentPublicInstance<RouteProps>) {
   
	...
}

export function useRoute() {
   
	...
}

官方的注释是“Vue Router support”,我们抛开类型判断,来看它是如何实现的。这里,重要的是route和useRoute两个函数。

export function route(vm: ComponentPublicInstance<RouteProps>) {
    // 入参为一个vue对象vm
  const router = vm.$router;  
    // 获取 vm 的 router。
    // router:vue-router提供的api,可以调用其上的replace、push进行路由切换.注册时被挂载在vm上,通过vm.$router可以获取。注意和route做区分。
  const {
    to, url, replace } = vm; // 拿到vm上的路由信息

  if (to && router) {
    
    router[replace ? 'replace' : 'push'](to); // 调用 router 的方法进行路由切换
  } else if (url) {
   
    replace ? location.replace(url) : (location.href = url); 
      // 如果只有 url,可能是因为router不存在。使用系统提供的 location 进行路由切换。
  }
}

route 函数实际上就是对传入的 Vue实例 vm 进行了根据存储在 vm 上的路由信息一次路由切换。在切换时,会优先使用router,如果没有router,则会使用 location。

接下来是useRoute的代码:

export function useRoute() {
   
  const vm = getCurrentInstance()!.proxy as ComponentPublicInstance<RouteProps>;
  return () => {
   
    route(vm);
  };
}

很简单的步骤,获取当前 vue 实例,返回一个函数,函数里调用了一次route(vm)。这里是一个闭包结构,将vm了保存起来,这样,如果需要对当前vue实例进行一次路由切换时,就不需要再去获取了。

createNamespace

import {
    createBEM } from './bem';
import {
    createComponent } from './component';
import {
    createTranslate } from './translate';

export function createNamespace(name: string) {
   
  name = 'van-' + name;
  return [
    createComponent(name),
    createBEM(name),
    createTranslate(name),
  ] as const;
}

这个函数,将传入的 name 加上了van- 的前缀,然后,使用 name 调用了 三个函数 createComponent createBEM createTranslate,并将结果作为数组返回。

这里,我们看到这一阶段最后一个行代码

const [createComponent, bem] = createNamespace('button');

为了节省篇幅,我们就只看createComponent createBEM的代码。

createComponent
import {
    App, defineComponent, ComponentOptionsWithObjectProps } from 'vue';
import {
    camelize } from '../format/string';

export function createComponent(name: string) {
   
  return function (sfc: ComponentOptionsWithObjectProps) 
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值