如何在NPM上发布自己的React组件(包)

发布于:2025-08-01 ⋅ 阅读:(17) ⋅ 点赞:(0)

我们在项目中都写过一些可以公用的功能,今天小编教会大家,如何将这些公共的功能或组件进行封装、打包并发布在npm上去,使之成为一个可以供更多开发者使用的npm包。

第一步:创建项目

mkdir rc-checkbox-virtual-list 
创建一个文件夹,我的叫做rc-checkbox-virtual-list,你可以根据你自己来

cd rc-checkbox-virtual-list 
进入创建好的rc-checkbox-virtual-list文件夹中

npm init或npm init -y
这里主要是初始化一些基本信息
使用npm init -y是默认生成相关信息
使用npm init 需要你手动输入相关信息

最后生成一个package.json文件,大致如下:

{
  "name": "rc-checkbox-virtual-list",
  "version": "1.0.0",
  "description": "a react component",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
  },
  "keywords": [
    "react",
    "checkbox",
    "list"
  ],
  "author": "luanjialin",
  "license": "ISC"
}

第二步:创建相关目录结构

在项目根目录下手动创建 src、lib、test文件夹
src: 用来存放源代码
lib: 用来存放编译后的代码,这个目录只读
test:用来存放测试代码目录

第三步:编写组件

在新建src目录中,我自己创建了一个RcCheckBoxList文件夹
里面写了一个RcCheckBoxList.js文件和RcCheckBoxList.css文件
同时在src下,我创建了一个index.js文件,用来引用并导出RcCheckBoxList.js


你可以根据自己的组件实际情况来编写
下面是我的代码


src/RcCheckBoxList/RcCheckBoxList.js文件
import React ,{ useState ,useEffect} from 'react';
import {Checkbox} from 'antd';
import './RcCheckBoxList.css';
import 'antd/dist/antd.css';

function RcCheckBoxList(props)  {
  const [isCheckAll, setisCheckAll] = useState(false)
  const [addmanList,setaddmanList]=useState([]);
  const [xingmingList,setxingmingList]=useState([...props.dataSource]);

  useEffect(()=>{
    // 这里判断翻页新传递的数据和选中的数据是否存在...
    console.log('addmanList',addmanList);
    setisCheckAll(false);
    let data=[...props.dataSource];
    let num=0;
    let addmanlist=addmanList;
    data.forEach(item => {
      let matched = addmanlist.find(obj => obj.id === item.id);
      if (matched){
        item.checked=true;
        num+=1;
      }        
    });
    if(num==data.length){
      setisCheckAll(true);
    }
    setxingmingList([...data]);
  },[props.dataSource])

  function onCheckChange(e,item){
    let ischecked=e.target.checked;
    let selectId=item.id;
    let num=0;
    let xingminglist=xingmingList;
    xingminglist.map((item,index)=>{
      if(item.id==selectId){
        item.checked=ischecked;
        if(item.checked==true){
          setaddmanList(prev=>[...prev,item]);
          props.check([...addmanList,item]);
        }else{
          let array=addmanList.filter(i=>i.id!==selectId);
          setaddmanList([...array]);
          props.check([...array]);
        }
      }
    })
    setxingmingList([...xingminglist]);
    xingminglist.map((item,index)=>{
      if(item.checked==true){
        num+=1;
      }
    })
    if(num==xingminglist.length){
      setisCheckAll(true);
    }else{
      setisCheckAll(false);
    }    
  };

  function onCheckAllChange(e){
    let ischecked=e.target.checked;
    setisCheckAll(ischecked);
    let addmanlist=addmanList;
    let xingminglist=xingmingList;
    xingminglist.map((item,index)=>{
      item.checked=ischecked;
    })
    if(ischecked==true){
      let array = [...new Set([...xingminglist,...addmanlist].map(item => JSON.stringify(item)))].map(item => JSON.parse(item));
      setaddmanList(array);
      props.allcheck(array);
    }else{
      let array = addmanlist.filter(itemA => !xingminglist.some(itemB => itemA.id === itemB.id));
      setaddmanList(array);
      props.allcheck(array);
    }

  };

  return (

      <div className="alarmNotice2_draw_top_body">
        <div className="alarmNotice2_draw_top_body_header">
          <div className="alarmNotice2_draw_top_body_header_left"><Checkbox onChange={onCheckAllChange} checked={isCheckAll}></Checkbox><div className="alarmNotice2_draw_top_body_header_left_name">人员姓名</div></div>
          <div className="alarmNotice2_draw_top_body_header_right">部门</div>
        </div>
        <div  className="alarmNotice2_draw_top_body_list">
          { 
              xingmingList.map((item,index)=>{
                return (
                  <div className="alarmNotice2_draw_top_body_list_item" key={item.id}>
                    <div className="alarmNotice2_draw_top_body_list_item_left">
                      <Checkbox  onChange={(e)=>onCheckChange(e,item)} checked={item.checked}></Checkbox>
                      <div className="alarmNotice2_draw_top_body_list_item_left_name">{item.name}</div>
                    </div>
                    <div className="alarmNotice2_draw_top_body_list_item_right">{item.department}</div>
                  </div>
                )
              })
          }
        </div>
      </div>
    
  )
}

export default RcCheckBoxList;



src/RcCheckBoxList/RcCheckBoxList.css文件
.alarmNotice2_draw_top_body{
  width: 100%;
  height: calc(100% - 100px);
  display: flex;
  flex-direction: column;
  justify-content: flex-start;
  align-items: flex-start;
  overflow: auto;
}
.alarmNotice2_draw_top_body_header{
  width: 100%;
  display: flex;
  flex-direction: row;
  justify-content: center;
  align-items: center;
  height: 50px;
  border-bottom: 1px solid #eee;
}
.alarmNotice2_draw_top_body_header_left{
  width: 49%;
  display: flex;
  flex-direction: row;
  justify-content: flex-start;
  align-items: center;
}
.alarmNotice2_draw_top_body_header_left_name{
  margin-left: 10px;
  font-weight: 500;
  font-size: 14px;
  color: rgba(0, 0, 0, .85);
}
.alarmNotice2_draw_top_body_header_right{
  width: 49%;
  display: flex;
  flex-direction: row;
  justify-content: flex-start;
  align-items: center;
  font-size: 14px;
  font-weight: 500;
  color: rgba(0, 0, 0, .85);
}
.alarmNotice2_draw_top_body_list{
  width: 100%;
  display: flex;
  flex-direction: column;
  justify-content: flex-start;
  align-items:center;
}
.alarmNotice2_draw_top_body_list_item{
  width: 100%;
  display: flex;
  flex-direction: row;
  justify-content: center;
  align-items: center;
  height: 50px;
  border-bottom: 1px solid #efefef;
}
.alarmNotice2_draw_top_body_list_item_left{
  width: 49%;
  display: flex;
  flex-direction: row;
  justify-content: flex-start;
  align-items: center;
}
.alarmNotice2_draw_top_body_list_item_left_name{
  margin-left: 10px;
  font-size: 14px;
  color: rgba(0, 0, 0, .85);
}
.alarmNotice2_draw_top_body_list_item_right{
  width: 49%;
  display: flex;
  flex-direction: row;
  justify-content: flex-start;
  align-items: center;
  font-size: 14px;
  color: rgba(0, 0, 0, .85);
}
.alarmNotice2_draw_bottom{
  width: 100%;
  height: 50px;
  display: flex;
  flex-direction: row;
  justify-content: flex-start;
  align-items:center;
}
.alarmNotice_draw_bottom_btn{
  margin-right: 10px;
  border-radius: 5px;
}




src/index.js文件
import RcCheckBoxList from './RcCheckBoxList/RcCheckBoxList.js';
export {RcCheckBoxList};

对应目录结构:

第四步:babel转码 将es6变成浏览器可以读取的es5

npm install --save-dev 
babel-cli 
babel-core 
babel-loader 
babel-plugin-istanbul 
babel-preset-es2015 
babel-preset-react 
babel-preset-stage-0 
react 
react-dom
antd@4.x.x

安装好后package.json如下:

"devDependencies": {
    "antd": "^4.24.16",
    "babel-cli": "^6.26.0",
    "babel-core": "^6.26.3",
    "babel-loader": "^10.0.0",
    "babel-plugin-istanbul": "^7.0.0",
    "babel-preset-es2015": "^6.24.1",
    "babel-preset-react": "^6.24.1",
    "babel-preset-stage-0": "^6.24.1",
    "react": "^19.1.1",
    "react-dom": "^19.1.1"
  }

第五步:修改我们的入口文件,并且修改scripts文件

"main": "./lib/index.js",
"scripts": {
    "clean": "rm -rf lib && mkdir lib",
    "lib": "npm run clean && babel src --out-dir lib --copy-files"
},

修改后和上图一致

第六步:项目根目录中添加.babelrc文件

{"presets": ["es2015","stage-0","react"],"plugins": ["transform-react-jsx"]}

第七步:打包

项目根目录中运行:
npm run lib

第八步:发布至NPM

npm login
输入相关账号密码或者验证码
npm publish 
推送包到npm


网站公告

今日签到

点亮在社区的每一天
去签到