【Rollup】自定义组件 - 文章渲染组件

前言

利用 Rollup 构建一个文章展示抽屉SDK,用来记录前端自定义SDK的过程

工程实践

初始化

  • 创建项目
mkdir packageName 
npm init -y
  • Typescript功能初始化
npm install typescript -D
npx tsc -init
  • 创建 rollup.config.js
import typescript from 'rollup-plugin-typescript2';
import less from 'rollup-plugin-less';
import clear from 'rollup-plugin-clear';
export default {
  input: ['./src/index.ts'],
  output: [
    {
      file: './lib/umd/index.js',
      name: 'DumboUI',
      format: 'umd',
      sourcemap: true,
    },
    {
      file: './lib/esm/index.js',
      format: 'es',
      sourcemap: true,
    },
  ],
  plugins: [
    typescript(), // 会自动读取 文件tsconfig.json配置
    less({ output: './lib/index.less' }),
    clear({
      targets: ['lib'],
    }),
  ],
  external: ['react', 'react-dom'],
};

添加插件依赖包

npm install rollup-plugin-typescript2 rollup-plugin-less rollup-plugin-clear -D

package.json 添加dev脚本

 "scripts": {
    "dev": "rollup -c rollup.config.js -w"
 }

image-20211212224607431

业务开发

  • 安装 React 必需依赖包
npm install react react-dom
npm install @types/react @types/react-dom  -D
  • 编写组件代码

参考文章最后业务代码

  • 本地开发调试

    sdk项目包执行

sudo npm link

​ 业务项目执行

npm link @levenx/grouper
  • 效果图
    在这里插入图片描述
    视频地址
    https://cdn.jsdelivr.net/gh/levenx/picture@master/material/docs.mov

构建打包

  • package.json
{
  "name": "@levenx/grouper",
  "version": "0.0.2",
  "description": "",
  "main": "./lib/umd/index.js",
  "module": "./lib/esm/index.js",
  "types": "./lib/esm/index.d.ts",
  "publishConfig": {
    "access": "public"
  },
  "scripts": {
    "dev": "rollup -c rollup.config.js -w",
    "build":"rollup -c rollup.config.js"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "@types/marked": "^4.0.1",
    "@types/react": "^17.0.37",
    "@types/react-dom": "^17.0.11",
    "rollup": "^2.61.1",
    "rollup-plugin-clear": "^2.0.7",
    "rollup-plugin-less": "^1.1.3",
    "rollup-plugin-typescript2": "^0.31.1",
    "typescript": "^4.5.3"
  },
  "peerDependencies": {
    "react": "^17.0.2",
    "react-dom": "^17.0.2"
  },
  "dependencies": {
    "classnames": "^2.3.1",
    "marked": "^4.0.7"
  }
}

执行打包命令

npm run build

发布npm包

  • Npm登陆
npm login

设置好username, password,email

  • Npm发布
npm publish

SDK使用步骤

  1. 引入 sdk 依赖

    这个包已经成功上传,感兴趣的可以尝试使用下

npm install @levenx/grouper
  1. sdk使用
import Grouper from '@dumbo/grouper';

const docs = new Grouper();
// 展示
docs.render({title:'title',content:'content'})

业务代码

入口 index.tsx

import React from 'react';
import ReactDOM from 'react-dom';
import Preview from '@/components/preview';

export interface GrouperDocConfig {
    root?: HTMLElement;
    title?: string;
    content?: string;
}

export default class GrouperDoc {

    config;

    root;

    constructor(config: GrouperDocConfig) {
        this.config = config;
    }

    destory() {
        ReactDOM.unmountComponentAtNode(this.root);
    }

    render(config: GrouperDocConfig) {
        const { title, content, root } = config;
        let div = root;
        if (!root) {
            div = document.createElement('div');
            document.body.appendChild(div);
        }
        this.root = div;
        const App = <Preview onClose={this.destory.bind(this)} title={title} content={content} />;
        ReactDOM.render(App, div)
    }

}

// components/preview/index.tsx

import React, { useState, useEffect, useMemo } from 'react';
import classnames from 'classnames';
import { marked } from 'marked';
import './index.less';

interface PreviewProps {
    onClose: () => void;
    title: string;
    content: string;
}

export default function Preview(props: PreviewProps) {
    const { onClose, title, content } = props;
    const [visible, setVisible] = useState(false);

    useEffect(() => {
        setTimeout(() => {
            setVisible(true);
        }, 0);
    }, [])

    const article = useMemo(() => {
        return marked(content)
    }, [content]);

    return (
        <div className={classnames("grouper-preview", { "grouper-preview--visible": visible })}>
            <div className="grouper-preview__title">
                <span className="title">{title}</span>
                <span className="close" onClick={() => {
                    setVisible(false);
                    setTimeout(() => {
                        onClose()
                    }, 300);
                }}>x</span>
            </div>
            <div className="grouper-preview__content" dangerouslySetInnerHTML={{ __html: article }} />
        </div>
    )
}

// components/preview/index.less

.grouper-preview {
  width: 400px;
  height: 800px;
  position: fixed;
  right: 10px;
  bottom: 10px;
  background: #ffffff;
  border-radius: 4px;
  box-shadow: 0 0 5px 1px rgba(0, 0, 0, 0.1);
  display: flex;
  flex-direction: column;
  transform: translateX(100%);
  transition: all 0.3s ease-in-out;
}

.grouper-preview--visible {
  transform: translateX(0);
}

.grouper-preview__title {
  padding: 10px;
  font-weight: 600;
  font-size: 18px;
  border-bottom: 1px solid #f1f1f1;
  display: flex;
  gap: 20px;
  align-items: center;
  justify-content: space-between;

  .title {
    flex: 1;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }

  .close {
    cursor: pointer;
  }
}

.grouper-preview__content {
  padding: 10px;
  overflow-y: scroll;

  img{
      max-width: 100%;
  }
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

乐闻x

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值