教练,我想从零做一个自己的ui组件库

微信扫一扫,分享到朋友圈

教练,我想从零做一个自己的ui组件库

很多时候面对日常的工作业务需求,或者面对新项目时往往都是 npm i element-ui -S 安装element或者Ant的组件库,但如果自己想要面对特殊的需求需要定制组件往往需要不断修改,改完又往往忘记了整理,最后就是不断的重复。

你所写的每一个 vue 文件都可以视为一个组件,随着业务的不断深入,页面写多了想将组件集合起来封装成一个组件库的想法也不断加剧。仅在此写下组件库的构建思路和历程,供自己记忆学习,也希望能帮助到你。

目录构建

  • 推荐使用@vue/cli 进行项目的构建 npm install -g @vue/cli

  • 命令行中输入 vue reate orange_collect 快速初始化一个项目。


  • 将src的目录文件改为examples,用来写组件相关文档和事例。

  • 再新建一个src目录,里面只放一个main.js用来作为打包入口

  • 在根目录下新建一个 packages 文件夹,用来进行组件的编写。

  • 在根目录下新建一个vue.config.js文件,配置如下

    const NODE_ENV = 'development' // 开发环境 打包doc
    // const NODE_ENV = 'lib' // 组件库 上传npm
    const components = require('./build/compontents.json');
    const path = require('path')
    const baseConfig = {
    chainWebpack: config => {
    config.resolve.alias
    .set('@', path.resolve('examples'))
    .set('~', path.resolve('packages'))
    config.module
    .rule('js')
    .include
    .add('/packages')
    .end()
    .use('babel')
    .loader('babel-loader')
    .tap(options => {
    // 修改它的选项...
    return options
    })
    },
    //如有scss配置需求
    // css: {
    //   extract: false,
    //   loaderOptions: {
    //     // 给 sass-loader 传递选项
    //     sass: {
    //       data: `@import "public/css/ui.scss";`
    //     }
    //   },
    // }
    }
    const devConfig = {
    pages: {
    index: {
    entry: 'examples/main.js',
    template: 'public/index.html',
    filename: 'index.html',
    }
    },
    publicPath: './',
    outputDir: 'docs',
    ...baseConfig
    }
    const buildConfig = {
    configureWebpack: {
    entry: components,
    output: {
    filename: '[name].js',
    libraryTarget: 'commonjs2',
    },
    },
    outputDir: 'lib',
    productionSourceMap: false,
    ...baseConfig
    }
    module.exports = NODE_ENV === 'development' ? devConfig : buildConfig;
    复制代码

这里通过判断NODE_ENV来判断项目的打包方式,在development下把examples 加入编译,将 examples/main.js 设置为文件入口。设置 examplespackages 的别名。

此时运行 npm run serve 已可以正常启动项目。将HelloWorld页面稍作修改,添加样式和布局。

  • router 中添加页面路由
    import Vue from 'vue'
    import Router from 'vue-router'
    import Home from '../components/HelloWorld.vue'
    //组件
    import component from './component'
    Vue.use(Router)
    export default new Router({
    routes: [
    {
    path: '/',
    name: 'home',
    component: Home,
    redirect: '/component/installation',
    children: [
    //组件
    ...component,
    ]
    },
    ]
    })
    复制代码

    相关界面如上,需要样式和布局代码可以去我的 github 上查看,再次不在赘述。

组件编写

常规组件编写

  • 我们组件的编写都在packages文件夹中进行,举个:chestnut:(例子),现编写一个测试的button组件。
    ├─packages
    │  └─orange_btn                      #组件模块名称文件夹
    │     ├─src
    │     |  ├─orange_btn.vue
    │     └─index
    ├─index.js
    复制代码
  • 新建一个如上的目录结构,接下来我们就需要在 orange_btn.vue 中编写相关的业务代码。通过props来定义组件的相关组件和状态扩展。
    export default {
    props: {
    type: {
    type: String,
    default: "default"
    },
    size: String,
    icon: {
    type: String,
    default: ""
    }
    },
    name: "orange-button",
    data() {
    return {};
    },
    复制代码
  • 值得注意的是在orange_btn.vue中 name 属性尤为重要它是必须要写的,是判断是否唯一组件的标识,所以你写的应该是不重名的。之后 name 将用来判定组件,如这里的 nameorange-button 在之后完 成组件的注册并且最终使用的时候则是 <orange-button></orange-button>

组件图标的引入和使用

  • 建议使用 iconfont矢量图库 将ui的图标上传,或在图标库中寻找合适的图标后,下载至本地。
  • 将图中的字体文件夹引入项目

  • 在packages文件夹的 index.js 和examples的 main.js 中对字体文件进行引入 import './assets/font/iconfont.css'
  • 使用 iconfont +类名 <i/>

组件暴露

  • 每一个组件都需要如此步骤,先建立组件同名的文件夹,然后在 orange_btn 文件夹下的 index·js 下编写暴露代码,用于安装单个组件

    import BlackBtn from './src/orange_btn.vue'
    // 为组件提供 install 安装方法,供按需引入
    BlackBtn.install = function (Vue) {
    Vue.component(BlackBtn.name, BlackBtn)
    }
    // 默认导出组件
    export default BlackBtn
    复制代码
  • 在packages文件夹下新建一个 index.js 用来管理,可以避免我们的组件越来越多,需要重复引入,循环安装所有组件。

    import orange_btn from './orange_btn'
    // 存储组件列表
    const components = [
    orange_btn
    ]
    // 定义 install 方法,接收 Vue 作为参数。如果使用 use 注册插件,则所有的组件都将被注册
    const install = function (Vue) {
    // 判断是否安装
    if (install.installed) return
    // 遍历注册全局组件
    components.map(component => Vue.component(component.name, component))
    }
    // 判断是否是直接引入文件
    if (typeof window !== 'undefined' && window.Vue) {
    install(window.Vue)
    }
    export default {
    // 导出的对象必须具有 install,才能被 Vue.use() 方法安装
    install,
    // 以下是具体的组件列表
    orange_btn
    }
    复制代码

组件引入

  • 在examples用来写组件相关文档和事例。在examples的 main.js 中引入


  • 使用 <orange-button></orange-button> 已可以在页面中使用,由此可以编写相关的文档说明。


打包配置

  • 在项目组件编写过后,就可以将组件打包:package:上传至npm使用
  • vue.config.js 下的NODE_ENV改为lib模式
  • 新建build文件夹,写一个方法
    const fs = require('fs-extra');
    const path = require('path');
    function isDir(dir) {
    return fs.lstatSync(dir).isDirectory();
    }
    function transformStr3(str) {
    var re = /-(w)/g;
    return str.replace(re, function ($0, $1) {
    return $1.toUpperCase();
    });
    }
    // function firstUpperCase(str) {
    //     return str.toLowerCase().replace(/( |^)[a-z]/g, (L) => L.toUpperCase());
    // }
    const json = {};
    const dir = path.join(__dirname, '../packages');
    const files = fs.readdirSync(dir);
    files.forEach(file => {
    const absolutePath = path.join(dir, file);
    if (isDir(absolutePath)) {
    let fileKey = transformStr3(file.replace('orange_', ''))
    // console.log(fileKey)
    json[fileKey] = `/Users/chenzhikun/project/GitHub/orange_ui/packages/${file}/index.js`; //mac
    // json[fileKey] = `D:/projects/orange_ui/packages/${file}/index.js`;  //windows
    }
    });
    复制代码
  • 通过运行方法,获得组件的路径之后在 vue.config.js 中引入 const components = require('./build/compontents.json')
  • 运行 npm run build 可以得到一个lib文件,这个文件就是我们最终要上传到npm的文件。此时文件目录如下。

微信扫一扫,分享到朋友圈

教练,我想从零做一个自己的ui组件库

前端工程化 - 聊聊 Webpack v3 到 Webpack v5 的核心架构变迁

上一篇

一个简单示例-刷新你对Vue2响应式原理的认知

下一篇

你也可能喜欢

教练,我想从零做一个自己的ui组件库

长按储存图像,分享给朋友