从零实现一套属于自己的UI框架-发布到npm

2023-11-04

汤小梦

https://juejin.im/post/5e200ee86fb9a02fdd38986d

不知不觉马上就要放假了,写一篇文章祝愿 2020 越来越好!

如今前端工程师的要求越来越高了,需要掌握的技术点越来越多了,会一些基本的前端技能完全适应不了快速变化的前端领域了。接下来我将从零实现一个自己的UI组件库并发布到npm上,提供给需要的朋友参考也总结下自己对封装组件的理解方便以后复习。本项目以button按钮为例,详细的记录一下封装一个Button UI组件每一个步骤以及需要注意的地方:

效果

需要技能

  1. 需要掌握 Vue 的基本语法

  2. 组件之间的通信

  3. 插槽的用法

  4. vue-cli3 创建项目、打包

  5. npm & git 的用法

创建项目

检查 node 环境配置

先本地全局安装node环境,vue的运行是依赖于nodenpm的管理工具来实现的,node下载地址。下载好node之后,打开cmd管理工具,输入node -v,回车,查看node版本号,出现版本号则说明安装成功,注意:node 的版本要在 8.9  或更高版本 (推荐 8.11.0+)

    node -v  npm -v

Vue 版本

  • 关于旧版本

如果你已经全局安装了旧版本的 vue-cli (1.x 或 2.x),你需要先通过 npm uninstall vue-cli -g 或 yarn global remove vue-cli 卸载它, Vue CLI 的包名称由 vue-cli 改成了 @vue/cli。

  • 安装新版本

    npm install -g @vue/cli
    # OR
    yarn global add @vue/cli
  • 查看版本

    vue --version | vue -V

创建项目

    vue create mc-ui
    OR
    vue ui 也可以使用UI图形化界面创建项目

注意:由于我们是开发一个第三方依赖库,我们选择 Manually select features。

  1. 选择那些特性需要安装在项目中

     (*) Babel
     ( ) TypeScript
     ( ) Progressive Web App (PWA) Support
     ( ) Router
     ( ) Vuex
     (*) CSS Pre-processors
     (*) Linter / Formatter
     ( ) Unit Testing
     ( ) E2E Testing

系统默认的包含了基本的 Babel + ESLint 设置的 preset,我们只需要选择CSS配置。移动键盘上下键选择需要的特性,按下键盘空格键即可选中

  1. 安装哪一种 CSS 预处理语言

      Sass/SCSS (with dart-sass)
      Sass/SCSS (with node-sass)
      Less
      Stylus

由于Element UI中的样式采用Sass,所以我们选择第一项即可 为什么不选择第二项呢?因为dart-sass比node-sass更好下载

  1. 选择代码风格

      ESLint with error prevention only
      ESLint + Airbnb config
      ESLint + Standard config
      ESLint + Prettier

因个人喜好选择即可,我比较喜欢第三种

  1. 那种方式进行代码格式检测

     (*) Lint on save
     ( ) Lint and fix on commit

选择Ctrl+S保存时检测代码格式即可

  1. 配置文件生成方式

      In dedicated config files
      In package.json

因个人喜好,我比较喜欢选择第二种

  1. 是否保存预配置

    Save this as a preset for future projects? (y/N)

看项目需要,我这里选择 N。回车后,系统会自动帮我们把选择的配置集成到模板中,然后生成一个完整的项目。

核心逻辑

我们大致按照Element UI的 源码 目录进行我们自己的UI库项目开发。所以删除系统自动为我们创建的src、assets等目录,在根目录中创建一个packages目录用来存放我们要开发的UI组件;在根目录创建一个test目录用于测试我们自己开发的UI组件。由于我们更改了原项目的目录结构,使得系统本地运行以及打包找不到对应的目录,我们需要在项目的根目录中创建一个vue.config.js文件夹手动的去修改webpack配置,使得系统本地运行和打包正常。

    // vue.config.js
    const path = require('path');
    module.exports = {
        pages: {
            index: {
                entry: 'test/main.js',
                template: 'public/index.html',
                filename: 'index.html'
            }
        },
        chainWebpack: config => {
            config.module
            .rule('js')
            .include.add(path.resolve(__dirname, 'packages')).end()
            .use('babel')
            .loader('babel-loader')
            .tap(options => {
                return options;
            })
        }
    }

基础样式

  • 基础<mc-botton class="mc-bottom"></mc-botton>的实现

  1. <template>

    <template>
      <button class="mc-button">
        <span>
    	  <slot></slot> // slot表示插槽
    	</span>
      </button>
    </template>

注意:为什么要在slot插槽外面加个span标签呢?为了美观,每个自定义button组件间相互有点间距????

  1. <script>

    export default {
      name: 'McButton'
    }

注意:组件中填写name属性,是为了封装组件提供install方法时,动态获取每个组件名进行组件注册

  1. <style>

    .mc-button {
      box-sizing: border-box;
      outline: none;
      margin: 0;
      transition: 0.1s;
      font-weight: 500;
      -moz-user-select: none;
      -webkit-user-select: none;
      -ms-user-select: none;
      ....
    }

注意:user-select属于CSS3的属性,值为none表示禁止用户选中文字

  1. 效果

basic_button

常见类型

  • 基础<mc-botton type="xxx" class="mc-bottom"></mc-botton>的实现

常见的类型有:primary / success / warning / danger / info / text

  1. <template>

    <button 
        class="mc-button" 
        :class="[
          `mc-button--${type}`
        ]">
        ...
    </button>

注意:为什么绑定class时采用数组形式,而不用对象形式,因为会有多个动态绑定的属性,且使用对象的形式,这样就只有数组里可以放多个动态属性,且属性可以为对象

  1. <script>

    props: {
        type: {
          type: String,
          default: 'default'
        }
    }

注意:这里接收属性为什么不用数组的形式?因为我们是封装组件给别人用的,所以要限制一些条件,不能让用户随意的输入

  1. <style>

该功能时,样式没有改动

  1. 效果

type_button

朴素按钮

  • 基础<mc-botton plain class="mc-bottom"></mc-botton>的实现

  1. <template>

    <button 
        class="mc-button" 
        :class="[
          `mc-button--${type}`,
          {
        		'is-plain': plain
           }
        ]">
        ...
    </button>

注意:为什么绑定class时采用数组形式,而不用对象形式,因为会有多个动态绑定的属性,且使用对象的形式,这样就只有数组里可以放多个动态属性,且属性可以为对象

  1. <script>

    plain: {
      type: Boolean,
      default: false
    }
  1. <style>

    &.is-plain:hover,
      &.is-plain:focus {
        background: #fff;
        border-color: #409eff;
        color: #409eff;
    }
  1. 效果

plain_button

添加圆角

  • 基础<mc-botton round class="mc-bottom"></mc-botton>的实现

  1. <template>

    <button 
        class="mc-button" 
        :class="[
          `mc-button--${type}`,
          {
                ...
                'is-round': round
           }
        ]">
        ...
    </button>
  1. <script>

    round: {
          type: Boolean,
          default: false
    }
  1. <style>

    &.is-round {
        border-radius: 20px;
        padding: 12px 23px;
     }
  1. 效果

round_button

添加圆形

  • 基础<mc-botton class="mc-bottom is-circle"></mc-botton>的实现

  1. <template>

    <button 
        class="mc-button" 
        :class="[
          `mc-button--${type}`,
          {
                ...
                'is-circle': circle
           }
        ]">
        ...
    </button>
  1. <script>

    circle: {
          type: Boolean,
          default: false
    }
  1. <style>

    &.is-circle {
        border-radius: 50%;
        padding: 12px;
    }
  1. 效果

circle_button

是否禁用

  • 基础<mc-botton class="mc-bottom" disabled></mc-botton>的实现

  1. <template>

    <button 
        ...
        :disabled="disabled"
        :class="[
          `mc-button--${type}`,
          {
                ...
                'is-disabled': disabled
           }
        ]">
        ...
    </button>
  1. <script>

    disabled: {
          type: Boolean,
          default: false
    }

注意:添加是否被禁用时有两个作用:第一、让用户不能点击;第二、改变按钮样式 3. 效果

添加图标

  • 基础<mc-botton icon="el-icon-check" class="mc-bottom"></mc-botton>的实现

  1. <template>

    <button
        ...
        >
        <i :class="icon" v-if="icon"></i>
        <!-- 如果没有传入插槽的时候才显示 -->
        <span v-if="$slots.default"><slot></slot></span>
    </button>
  1. <script>

    icon: {
        type: String,
        default: ''
    }
  1. <style>

    .mc-button [class*=mc-icon-]+span {
      margin-left: 5px;
    }

i标签上加v-if的目的:让用户即可以上传图标也可以上传文字或者上传文字和图标

注意:既传图标也传文字的话,图标和文字隔的很近,我们需要特殊处理下; 但是如果特性处理的话,单独的图标会不居中显示;所以我们要使用$slots获取包含有插槽的才让其显示处理

  1. 效果

icon_button

点击事件

  • 基础<mc-botton class="mc-bottom" @click="handleClick"></mc-botton>的实现

  1. <template>

    <button
        ...
        @click="handleClick"
        >
        ...
    </button>
  1. <script>

    methods: {
        handleClick (e) {
            this.$emit('click', e) // 向父组件派发一个click事件,e表示携带的参数
        }
    }
  1. 效果

click_button

打包

在Vue-cli3的 官方文档 中有个构建目标有明确的说明怎么打包成一个应用或者一个库!此时,我们需要在package.json中添加一条打包命令

    vue-cli-service build --target lib 指定打包的文件

然后控制台执行yarn lib即可将我们的组件库包括字体图标一起打包生成一个dist文件夹

上传github & 发布 npm

将代码上传到github

首先登录github 官网 创建一个新的仓库,然后复制新仓库的git地址。然后在我们本地创建的项目根目录执行git init,初始化git,然后再终端执行以下命令:

    git remote add origin
    git add .
    git commit -am ":rocket: project init"
    git push -u origin master

大家有没有发现我提交的commit不一样,其实就是用到了gitmoji这个依赖而已,简单说下他的用法:

  1. 全局安装这个依赖  npm install -g gitmoji-cli

  2. commit 提交代码时,加上表情符号就好。例如:":bug: xxxx", 这样你提交的代码注释前面就会加一个emoji图标,很炫酷的哦,小伙伴们可以试一下????

  3. 常见的emoji有::art: 、 :ambulance: 、:lipstick:等等

将代码发布到npm

由于我们开发的组件库是给别人用的,我们没有必要把所有的代码都发布到npm上。所以我们需要在项目的根目录创建一个.npmignore的文件,忽略那些文件上传

    // .npmignore
    # 忽略目录test/
    packages/
    public/
     
    # 忽略指定文件
    vue.config.js
    babel.config.js
    *.map
    .editorconfig.js

注意:由于我们要上传到npm上,所以我们本地npm的源要使用npm的源,不能使用淘宝源或其他的。查看一下本地电脑所有的源:

一切准备工作做好后,打开终端,执行npm login进行登录

  • 登录

执行npm login命令,系统会提示输入账户和密码。如果没有npm账户,请注册 → npm官网

  • 发布

若账户登录成功后,就可以再次执行 npm publish 进行发布

  • 注意

  1. 一定要在package.json的scripts中添加main方便其他人下载时找到对应打包的文件

  2. 上传到npm上时,要将package.json中的private属性值改为false

  3. 修改源码后发布到npm时一定要更改项目的版本号

总结

相信只要从头看到尾的小伙伴就会发现,封装一个组件很容易,主要的工作在于CSS样式上。只要自己有时间,然后根据像Element、iView、Antd等优秀的第三方UI库的源码,也可以实现一套属于自己的UI库。不管是面试还是自己公司内部需要搭建自己的UI库,只要小伙伴们掌握了封装组件的原理,其他的都问题不大。希望有需要的小伙伴手动敲一遍,加深对封装组件的过程。????加油

如果你觉得这篇内容对你挺有启发,我想邀请你帮我三个小忙:

  • 点个【在看】,或者分享转发,让更多的人也能看到这篇内容

  • 关注公众号【全栈前端精选】,不定期分享原创&精品技术文章。

  • 公众号内回复:【 1 】。加入全栈前端精选公众号交流群。

欢迎评论区留下你的精彩评论~

觉得文章不错可以分享到朋友圈让更多的小伙伴看到哦~

客官!在看一下呗

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

从零实现一套属于自己的UI框架-发布到npm 的相关文章

  • Acesrc and Hunting【模拟 贪心】

    HDU 6660 题目链接 这道题主要就是讲我们从任意点出发 每次走的都是没走过并且 曼哈顿距离大于1小于3的点 然后问能不能覆盖完整幅图 这里就想到一个很经典的问题 4399小游戏除草游戏 以前玩过的一个小游戏倒是让我对这道题的解法有了方
  • 动手学数据分析 Task4

    动手学数据分析 Task4 一 可视化展示泰坦尼克号数据集中男女中生存人与死亡人数的比例图 二 可视化展示泰坦尼克号数据集中不同票价的人生存和死亡人数分布情况 三 可视化展示泰坦尼克号数据集中不同年龄的人生存与死亡人数分布情况 一 可视化展
  • Maven的基础知识

    Maven介绍 Maven 是一个项目管理和 综合工具 Maven 提供了开发人员构建一个完整的生命周期框架 开发团队可以自动完成项目的基础工具建设 Maven 使用标准的目录结构 和 默认构建生命周期 Maven是什么 它是一个 Apac
  • 各种绕过(MD5

    文章目录 MD5 0e开头的数组 MD5弱比较 MD5数组绕过 MD5 SQL注入 SHA1 SHA1弱比较 和 MD5弱类型比较同理 SHA1碰撞 MD5 0e开头的数组 MD5弱比较 QNKCDZO 240610708 byGcY so
  • 表设计为什么主键尽量无意义_奉上数据库表设计的十三条建议

    前言 本文总结了数据库表设计的十三条建议 这十三条建议只作为大家的参考 具体需要根据自己的项目来设计 来自 梦尘啊 链接 https juejin cn post 6902236691348586510 1 原始单据与实体之间的关系 表的设
  • Go:go mod vendor 使用

    Go go mod vendor 使用 1 背景 我们基于 go mod 机制来管理我们项目的依赖库版本 其中 go mod 记录了依赖库版本信息 一般第三方依赖库 包括公司内网gitlab上的依赖库 其源码都不被包含在我们的项目内部 而是
  • 5.自动装配:autowire=“byName“ or “byType“ + 使用注解【@Autowired 、@Qualifier、 @Resource】

    文章目录 自动装配说明 本博客环境搭建 自动装配 autowire byName 按名称自动装配 autowire byType 按类型自动装配 使用注解 1 Autowired 按类型自动转配的 不支持id匹配 2 Qualifier 不
  • hypertable管理当前rangserver和历史rangserver

    purge old log files void OperationRecoveryBlocker execute HT INFOF Entering RecoveryBlocker lld threadid d Lld header id
  • Docker安装

    镜像 Docker 镜像 Image 就是一个只读的模板 镜像可以用来创建 Docker 容器 一个镜像可以创建很多容器 它也相当于是一个root文件系统 比如官方镜像 centos 7 就包含了完整的一套 centos 7 最小系统的 r
  • ns2编程小技巧(转)

    1 tcl脚本传入一个int变量给c 代码在command解析里 int nodenum atoi argv 2 printf d nodenum 2 在nam中输出结果 Tcl instance evalf ns trace annota
  • Ubuntu下配置VScode及LeetCode,开始撸代码

    Ubuntu20 04下配置VScode及LeetCode 开始撸代码 一 配置VScode环境 1 软件下载 2 软件安装及启动 3 C 基础插件的安装 4 配置软件内部Debug 5 配置内部Debug工具时的异常 正常请跳过此步 6
  • JS获取本地图片和网络图片的宽高尺寸和存储大小

    最新更新时间 2020年07月08日09 13 28 猛戳 查看我的博客地图 总有你意想不到的惊喜 本文内容 图片作为一种记录信息的载体 比文本更加生动 比视频更加精简 在日常生活中的用处很大 作为前端开发人员 操作图片的场景非常多 本文记
  • 跨域产生原因和跨域解决方案

    一 为什么会出现跨域问题 出于浏览器的同源策略限制 同源策略是一种约定 它是浏览器最核心也就是最基本的安全功能 如果缺少了同源策略 浏览器的正常功能会受到影响 可以说WEB是构建在同源策略基础之上的 浏览器只是针对同源策略的一种实现 同源策
  • 有限元方法的核心思想是什么?

    有限元方法的核心思想是什么 有限元方法似乎是在不断地简化着什么 请问有限元方法的核心思想是什么 在哪些层面对方程做了简化 每一次简化的依据和思路是什么 2 条评论 按投票排序 按时间排序 31 个回答 菲兹 睡眠厌倦患者 138 人赞同 有
  • vue3+ts+setup获取全局变量getCurrentInstance

    前言 vue3的 setup中是获取不到this的 为此官方提供了特殊的方法 让我们可以使用this 达到我们获取全局变量的目的 但是在使用typescript的时候 就会有一些新的问题产生 这里来做一个整理 vue3官方提供的方法 1 引
  • ChatGPT、New Bing、文心一言、通义千问等 AI 工具到底哪个更AI? - 第二期

    文章目录 前言 选手介绍 ChatGPT New Bing 文心一言 钉钉的文档AI 通义千问 Stable Diffusion 文心一格 前言 本次是上次文章的后续 经历了这么久的时间 我也是在几个月前拿到了通义千问的测试资格 本次参加的
  • 密码爆破漏洞详解——黑客必修入门操作( 建议收藏 )

    隔壁老张 狗剩啊 隔壁xx村的王姐家的女娃好漂亮 我想盗她qq啊 你帮我个忙呗 狗剩 我不会呀 村里大妈 那个狗剩啊 连盗个qq号都不会 他妈还好意思说他是学网络安全当黑客的 密码爆破介绍 密码爆破又叫 暴力猜解 简单来说就是将密码逐个尝试
  • 第四章:进击,拿到Web最高权限

    1 根据前关已经得到了cookie 现在需要修改cookie达到登录系统的目的 2 打开网站 以谷歌浏览器为例 F12打开控制台 找到Application 对图中3 4的值进行修改 修改的内容为你获取到的cookie的内容 3 4分别对应
  • Unity XCode 拨号和一键加群

    拨号 void CallPhone const char iphone NSString nsIphone NSString stringWithFormat tel s iphone NSLog nsIphone NSURL url NS
  • centos如何查看linux内核,版本号

    root localhost uname a Linux localhost localdomain 3 10 0 957 el7 x86 64 1 SMP Thu Nov 8 23 39 32 UTC 2018 x86 64 x86 64

随机推荐

  • CSDN博客的RSS订阅---使用foxmail订阅

    CSDN博客有RSS订阅 使用foxmail订阅 好处是可以第一时间邮件通知 订阅自己的博客可以作为备份 foxmail订阅方法 CSDN博客有RSS订阅 使用foxmail订阅 好处是可以第一时间邮件通知 订阅自己的博客 可以作为备份 f
  • Python爬虫教程:包图网免费付费素材爬取【附源码】

    包图网大家都知道吧 集齐海量设计素材 十分好用 可惜太贵了 今天就带大家使用Python 爬虫爬取这些素材并且保存到本地 抓取一个网站的内容 我们需要从以下几方面入手 1 如何抓取网站的下一页链接 2 目标资源是静态还是动态 视频 图片等
  • LeetCode - 回文类问题总结

    子串与子序列 1 字符子串 指的是字符串中连续的n个字符 如abcdefg中 ab cde fg等都属于它的字串 2 字符子序列 指的是字符串中不一定连续但先后顺序一致的n个字符 即可以去掉字符串中的部分字符 但不可改变其前后顺序 如abc
  • moudo网络库剖析

    muduo简介 muduo是陈硕大神在Linux平台下基于C C 开发的高性能网络库 在此基础上可以很方便的扩展 进行二次开发编写如http服务器 muduo网络库的核心框架 one thread per thread Reactor模式
  • Font Awesome 的使用

    之前一直使用的是 iconfont 阿里巴巴出品的一个字体图标库 但是最近 iconfont 不再支持 CDN 引入 只能本地下载 这样一来修改图标就非常的麻烦 于是 就找了一个类似的图标库 现在使用的比较多的一个国外字体图标库 使用方式和
  • 基于红外感应的远距离智能跟随小车,自动跟随小车

    跟随原理 下面介绍红外感应的跟随小车的自动跟随部分 基本原理 在小车上安装一个红外接收器 能测量红外入射角的感应器 人手持一个红外发射模块 根据不同的入射角 调整小车前进方向 若入射角在右边 就控制小车右转 若入射角在左边 就控制小车左转
  • QListWidget使用体验

    主窗口继承QWidget class CustomListWidgetDemo public QWidget 自定义CustomListWidget继承QListWidget class CustomListWidget public QL
  • linux sys pread64,pread()函数

    pread是一个函数 用于带偏移量地原子的从文件中读取数据 带偏移量地原子的从文件中读取数据 函数原型 ssize t pread intfd void buf size tcount off toffset 用法 返回值 成功 返回成功读
  • 新手 Java 编程思想应该如何提高?

    简化一下就是从理解抽象开始 最先要理解的就是 类 接口通常被理解为 全抽象 在Java中也有重要地位和作用 其次就是抽象类介于接口和类之间的概念 另外理解面向对象编程过程 逐渐掌握封装 继承 多态的应用从而形成一个完整的面相对象编程思想 理
  • script 脚本标签中 defer 和 async (延缓 和 异步)

    原文章 https segmentfault com q 1010000000640869 本文章讲解几个点
  • 运营新人也可以做的副业平台丨闲鱼运营(下)

    文章上半部分给大家深度分享了关于闲鱼的赚钱方法和店铺权重建设该如何提升 如果没有看上半部分内容 直接翻阅主页就可以查阅到 接下来我们分享关于闲鱼运营的下半部分 店铺运营 闲鱼何运营总共分为三个部分 第一个部分是闲鱼养号 第二部分是内容编辑
  • K8s二进制部署-flanneld报(Couldn‘t fetch network config)

    1 报错提示 将网络配置信息写入了ETCD中 启动flanneld测试时一直报错 具体报错如下 root master1 tail 100f var log messages Dec 15 23 39 22 localhost flanne
  • 多文件编辑作业(2023.1.10)

    第一题 main c include head h int main int argc const char argv char str hello my student int start 0 int end strlen str 1 M
  • 提供一个用于计算两个point之间的距离方法_汇总

    作者 Tom Hardy Date 2020 02 18 来源 汇总 基于3D点云的深度学习方法 前言 三维数据通常可以用不同的格式表示 包括深度图像 点云 网格和体积网格 点云表示作为一种常用的表示格式 在三维空间中保留了原始的几何信息
  • 已解决报错UnboundLocalError: local variable ‘title‘ referenced before assignment

    1 今天抓取某网站的数据时 显示报错UnboundLocalError local variable title referenced before assignment Traceback most recent call last Fi
  • 无法启动64位idea,无法启动idea64.exe的一种原因(意外删除破解文件导致无法打开idea)

    前言 突然有一天 我的IDEA出现了问题 点击桌面快捷方式的idea毫无反应 无奈之下重装了IDEA 但还是有相同的问题 无法打开64位的idea 网上找了一堆博客 花了两个多小时终于解决了 写篇博客记录下这个问题 1 首先打开idea b
  • 初识网络安全(黑客技术)

    目录 前言 一 安全事件案例 二 网络安全行业公司 三 网络安全岗位 四 网络安全网站 五 src漏洞平台 总结 前言 网络安全是指保护计算机网络和网络上的数据免受未经授权的访问 使用 泄露 破坏和干扰的一系列措施和技术 在当今数字化时代
  • JAVA web 获取系统时间

  • ROS---保存地图

    建立save map sh文件夹 bin bash rosrun map server map saver f catkin ws src hypharos minicar launch map mymap 保存地图时我们进入此文件所在文件
  • 从零实现一套属于自己的UI框架-发布到npm

    汤小梦 https juejin im post 5e200ee86fb9a02fdd38986d 不知不觉马上就要放假了 写一篇文章祝愿 2020 越来越好 如今前端工程师的要求越来越高了 需要掌握的技术点越来越多了 会一些基本的前端技能