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

news/2024/7/15 18:25:36 标签: typescript, react.js, javascript, rollup, 工程构建

前言

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

工程实践

初始化

  • 创建项目
mkdir packageName 
npm init -y
  • Typescript功能初始化
npm install typescript -D
npx tsc -init
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%;
  }
}


http://www.niftyadmin.cn/n/1143001.html

相关文章

gson 不忽略空_儿童房都用高低床?它不一定适合你娃!

现在很多九零后、八零后的爸爸妈妈都开始有了二胎计划&#xff0c;对于儿童房的装修可以说是用尽了心思&#xff0c;很多人都会选择高低床&#xff0c;来解决空间有限的问题。不过对于高低床每个人都有着自己的观点——有的人觉得非常实用&#xff0c;有的人则觉得不太安全&…

tcp转websocket_WebSocket与普通Socket的差异

1.背景1.1.WebSocket与普通Socket的差异Socket简单理解&#xff1a;Socket IP地址 端口 协议。具体来说&#xff0c;Socket是一套标准&#xff0c;它完成了对TCP/IP的高度封装&#xff0c;屏蔽网络细节以方便开发者更好地进行网络编程。Socket有自己的原语。WebSocketWebSoc…

实现一个Switch开关组件只需要一个div?详细记录Switch组件开发过程

最终效果图 实现逻辑 一、switch容器 // html<div className"dumbo-switch"></div>// css.dumbo-switch {height: 22px;width: 44px;border: 1px solid;border-radius: 100px;border: 1px solid #cccccc;cursor: pointer;}二、switch inner // html// c…

介绍数据库中的wal技术_SQLite中的WAL机制详细介绍

一、什么是WAL&#xff1f;WAL的全称是Write Ahead Logging&#xff0c;它是很多数据库中用于实现原子事务的一种机制&#xff0c;SQLite在3.7.0版本引入了该特性。二、WAL如何工作&#xff1f;在引入WAL机制之前&#xff0c;SQLite使用rollback journal机制实现原子事务。roll…

python图形界面数据库开发_图形用户界面数据库

我在self.view_records()处收到一个错误。我创建了这个函数来查询数据库。然后我尝试在类中调用该函数来检索数据库并将其显示给GUI。在Error: self.view_records(self) AttributeError: products object has no attribute view_recordsfrom tkinter import* from tkinter impo…

python返回列表数据类型_python 数据类型之列表(list)

一、表达方式1、英文[]表示2、列表内部可以存储任意类型的数据3、可变的有序序列二、常用函数1、type()&#xff1a;查询变量的类型&#xff0c;如type(["name", "sex", "age"]) list2、len()&#xff1a;查询列表的长度&#xff0c;如len([&qu…

在线图片视频资源转存

背景 怎么将网上心仪的图片、视频保存到自己的资源空间(图床)&#xff1f;给你一个资源链接&#xff0c;你需要几步将这个资源转存到git上&#xff1f;一般人的做法可能就是先将资源下载到本地&#xff0c;然后再本地上传到对应的资源空间&#xff1f;如果操作一个资源转存&am…

python操作json_python如何操作json文件

Python对Json文件的操作主要用到的model是&#xff1a;json&#xff0c; 所以首先我们要把json加载进来:import json 然后我们用到的是json下的 json.load / json.dumps 函数&#xff0c;结合IO的基本文件操作函数 open/write/close实现对json文件的操作。 1. 首先我们需要新建…