移动端插件化之uniapp+vue3+vite+ts项目搭建并开发一个自己的移动端ui库,支持h5、app等

仓库地址

先把仓库地址贴上:dxx-mobile-ui
上周遗留的问题已解决,现已支持在Vue SFC中引入外部类型定义。

创建项目

第一次搭建项目看再多文档都不如参考官方文档:项目搭建

简单来说就以下三个步骤:

  1. 全局安装 vue-cli
    pnpm install -g @vue/cli

  2. 创建以 typescript 开发的工程
    npx degit dcloudio/uni-preset-vue#vite-ts my-vue3-project

  3. 更新到最新正式版
    npx @dcloudio/uvm@latest

项目就创建好了

插件化准备

接下来的步骤在 HBuilderX 里操作比较保险,万一以后它文件目录又变了呢,是吧。

为什么叫插件化准备,因为我们要开发一个公用的组件库,让大家通过npm install xxx就可以使用,那我们就要发布到npm上面去,那么在uniapp上我们就要开发插件来实现,最后把插件上传到npm。插件化开发官方文档参考:https://uniapp.dcloud.net.cn/plugin/uni_modules.html#%E5%BC%80%E5%8F%91-uni-modules-%E6%8F%92%E4%BB%B6

1.打开 HBuilderX ,导入刚才创建的项目

在这里插入图片描述

2.右键根目录,选择 新建uni_modules目录(X),新建后就会在 src 下生成一个 uni_modules文件

在这里插入图片描述

3.右键 uni_modules ,选择 新建uni_modules插件(H),会弹出一个弹窗。

在这里插入图片描述

4.填写插件 ID,就相当于我们组件库的名字,我这儿就取名dxx-mobile-ui(插件 ID 最好唯一,如果你要发布到插件市场的话),点击创建。

在这里插入图片描述

5.创建后,会在 uni_modules下自动生成一个文件,文件下的目录就是这样子。

![在这里插入图片描述](https://img-blog.csdnimg.cn/direct/64c8ca244a804419900c5d5fc420a1de.png

6.接下来我们就可以在components下开发自己的组件了。先把compenents下自动生成的组件改造一下,组件名字请不要乱取,建议规范一下,后面使用的时候好设置easycom

在这里插入图片描述

代码如下:

<template>
  <view class="content">{{ title }}, 我是d-test组件 </view>
</template>
<script lang="ts">
export default {
  name: "d-test", // 重要!引用组件的名字,必须导出
};
</script>
<script setup lang="ts">
import { ref } from "vue";
const title = ref("Hello");
</script>

<style>
.content {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  font-size: 36rpx;
  color: #8f8f94;
}
</style>

此时你已经可以在 src/pages/index/index.vue 里调试此组件了(不管你是在vscode终端输入pnpm run dev:h5,还是直接从HBuilderX里点击运行到浏览器,都可以调试,运行到其他端也可以),只需要在里面写上如下代码即可,无需手动引入。

<template>
  <d-test></d-test>
</template>

<script setup lang="ts">
</script>

<style>
</style>

7.但是我们是要发布到npm上,那就需要一个统一的入口,所以我们在src/uni_modules/dxx-mobile-ui下新建一个index.ts文件,代码如下:

const install = (App: any) => {
  Object.values(
    import.meta.glob("./components/*/index.ts", { eager: true })  // 动态引入components下的index.ts文件
  ).forEach((item: any) => {
    App.component(item.name, item);
  });
};

export default {
  install,
};

2.要在src/uni_modules/dxx-mobile-ui/components/d-test文件下新增一个入口文件index.ts,以后就按这种规范来开发组件了,代码如下:

import { ref } from "vue";
import type DTest from "./d-test.vue";

const getDTestRef = () => ref<InstanceType<typeof DTest> | null>(null);

export { getDTestRef };

export default { name: "DTest", title: "测试组件" };

到这里我们的准备工作已经做完了,接下来我们就可以在components下开发我们的组件了。我又在下面添加了一个组件,等会看看是否两个组件都能使用正常。
在这里插入图片描述

发布到npm

发布到npm需要切换镜像,有时候会遇到ETIMEDOUT 443错误,这需要我们翻墙才行,我的建议是单独开一个终端来代理,终端代理,是单独的,不会影响到其他地方。如果你还没有代理服务器,恐怕需要你自行查阅了,我的有时候会抽风,不知道什么原因。

1.完善 src/uni_modules/dxx-mobile-ui下的 package.json,新增这两行:

  • name必须唯一
  • private必须是false
  • 以后每次发布的时候版本号都需要修改
"name": "dxx-mobile-ui",
"private": false,

如果想了解其他字段什么意思,请查看该文:package.json配置

2.打开文件src/uni_modules/dxx-mobile-ui,在这个文件下开一个cmd终端,我们要把这个插件上传到npm
在这里插入图片描述

3.切换镜像

npm config set registry https://registry.npmjs.org

4.输入代理服务器,登录npm,接下来会叫你输入npm用户名、npm密码、邮箱,稍后会发一个验证码到你的邮箱,输入验证码就登录成功。(没有npm账号的去注册一个)

set https_proxy=http://127.0.0.1:7890
set http_proxy=http://127.0.0.1:7890
pnpm login

在这里插入图片描述

5.发布,接着执行:

pnpm publish

发布成功

在这里插入图片描述

然后你就可以去npm搜到你发的这个包了。接下来就是如何使用的问题了。

在这里插入图片描述

使用

另起一个项目,方法一样,安装

pnpm add dxx-mobile-ui

在入口文件src/main.ts引入

import { createSSRApp } from 'vue'
import App from './App.vue'
import DxxMobileUI from 'dxx-mobile-ui'

export function createApp() {
  const app = createSSRApp(App)
  app.use(DxxMobileUI)
  return {
    app,
  }
}

在src/pages.json中添加配置,这样就可以不用每次使用都导入了。

"easycom": {
		"autoscan": true,
		"custom": {
			"^d-(.*)": "dxx-mobile-ui/components/d-$1/d-$1"
		}
	}

然后在页面中直接使用即可

 <d-button></d-button>
  <d-test></d-test>

效果如下

在这里插入图片描述

好了,到这里就基本结束了,但是开发过程中,我们难免会使用 typescript ,有意思的是,vue并不支持什么复杂类型从外部引入,意思就是你这样写会报错:
在这里插入图片描述

你只能在内部写类型,不能从外部引入

const emits = defineEmits<{...}>();

既然有这个问题,就让我们来解决一下吧。

支持在Vue SFC中引入外部类型定义

  • 安装,记得先切换回淘宝镜像 npm config set registry https://registry.npmmirror.com
pnpm add prettier decomment -D
  • 修改 vite.config.ts 文件
import { defineConfig } from "vite";
import uni from "@dcloudio/vite-plugin-uni";
import fs from "fs";
import path from "path";
import prettier from "prettier";
import decomment from "decomment";
import type { Plugin } from "vite";

// 支持在Vue SFC中引入外部类型定义
const vueSfcImportType = (): Plugin => {
  return {
    name: "vue-sfc-import-type",
    enforce: "pre",
    async transform(code, id) {
      // 不是vue文件 返回
      if (!/\.(vue)$/.test(id)) return;
      const typePath = path.resolve(id, "../type.sfc.ts");
      // 不存在type.sfc.ts文件 返回
      if (!fs.existsSync(typePath)) return;
      // 文件内容
      let typeFileContent = decomment(fs.readFileSync(typePath).toString());
      typeFileContent = await prettier.format(typeFileContent, {
        semi: true,
        parser: "typescript",
      });
      // 将文件内容去掉换行符 变成一行
      typeFileContent = typeFileContent.replace(/[\r\n]/g, "");
      // 替换的正则表达式
      const regex = /import .* from "\.\/type\.sfc"/g;
      // 将导入type.sfc的那一行进行替换
      const res = code.replace(regex, typeFileContent);
      return res;
    },
  };
};

// https://vitejs.dev/config/
export default defineConfig(async ({ command, mode }) => {
  return {
    plugins: [uni(), vueSfcImportType()],
  };
});

此时就不报错了,原理就是将导出的内容变成一行代码,然后与vue文件中import...type.sfc的那一行进行替换。

总结

移动端插件化与web端不同,且网上不易搜索,明白了原理你就会发现,其实就是在uni_modules下写插件而已,最后把这个插件发布就行了。

  • 39
    点赞
  • 40
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值