JS 开发工具库 前言 一、开发环境准备 二、工具函数的封装 1、Ajax 的封装 2、datePicker 3、文件导出功能的实现 3-1 导出 Word 三、项目打包 1、打包前准备 1.1 初始化项目 1.2 下载依赖 1.3 配置 Webpack 1.4 配置打包命令 1.5 项目打包 1.6 测试 2、暴露工具函数 2.1 在工具函数中使用 export 导出 2.2 在入口函数引入 2.3 测试使用 四、项目发布 1、注册 npm 账号 2、修改 package.json 配置 3、切换 npm 源 4、登录与发布 5、强制删除已发布的库 项目源码
前言
日常开发中我们总会需要封装各种各样的函数,有的函数在项目中用到多次,有的甚至在很多项目中都要用到 这就需要我们将封装的函数打包成库,方便下次使用 本文将是使用 JavaScript 开发函数,并上传到 npm
一、开发环境准备
1、安装 Node
2、创建项目
在自己平常放置项目代码的文件夹下创建一个项目文件夹(建议别使用中文名称) 然后在新创建的项目文件夹下分别创建两个文件,一个用于测试的 html,一个用于开发的 js(就是正常开发项目时的样子) 然后就可以正常开发了
二、工具函数的封装
1、Ajax 的封装
function ajax ( { method, url, params, data } ) { method = method. toUpperCase ( ) return new Promise ( ( resolve, reject) = > { let xhr = nullif ( window. XMLHttpRequest) { xhr = new XMLHttpRequest ( ) ; } else { xhr = new ActiveObject ( "Microsoft.XMLHTTP" ) ; } let str = "" for ( let k in params) { str += `${ k} = ${ params[ k] } & `} str = str. slice ( 0 , - 1 ) xhr. open ( method, url + '?' + str) if ( method == = 'POST' || method == = 'PUT' || method == = 'DELETE' || method == = 'PATCH' ) { xhr. setRequestHeader ( 'Content-type' , 'application/json' ) xhr. send ( JSON. stringify ( data) ) } else { xhr. send ( ) } xhr. responseType = 'json' xhr. onreadystatechange = function ( ) { if ( xhr. readyState == 4 ) { if ( xhr. status >= 200 && xhr. status < 300 ) { resolve ( { status: xhr. status, message: xhr. statusText, data: xhr. response} ) } else { reject ( new Error ( '请求失败,失败的状态码为:' + xhr. status) ) } } } } )
} ajax. get = function ( url, options) { let config = Object. assign ( options, { method: 'GET' , url: url } ) return ajax ( config)
} ajax. post = function ( url, options) { let config = Object. assign ( options, { method: 'POST' , url: url } ) return ajax ( config)
} ajax. put = function ( url, options) { let config = Object. assign ( options, { method: 'PUT' , url: url } ) return ajax ( config)
} ajax. delete = function ( url, options) { let config = Object. assign ( options, { method: 'DELETE' , url: url } ) return ajax ( config)
} ajax. patch = function ( url, options) { let config = Object. assign ( options, { method: 'PATCH' , url: url } ) return ajax ( config)
}
2、datePicker
< ! DOCTYPE html>
< html lang= "en" > < head> < meta charset= "UTF-8" > < meta http- equiv= "X-UA-Compatible" content= "IE=edge" > < meta name= "viewport" content= "width=device-width, initial-scale=1.0" > < title> Document< / title> < link rel= "stylesheet" href= "./index.css" >
< / head> < body> < div id= "date-picker" > < / div> < script src= "./index.js" > < / script> < script> calender. init ( { el: document. getElementById ( 'date-picker' ) , getDate: function ( date) { console. log ( "回调=>" , date) } } ) < / script>
< / body> < / html>
. picker- input { position: relative;
}
. picker- input input { display: inline - block; height: 40 px; line- height: 40 px; color: #606266 ; padding: 0 30 px; border: 1 px solid #dcdef6; border- radius: 4 px; outline: none;
}
. picker- input . picker- prefix { position: absolute; left: 5 px; display: inline - block; width: 25 px; height: 40 px; background- color: red;
} . calender { width: 322 px; height: 329 px; border: 1 px solid #e4e4e4; border- radius: 4 px; box- shadow: 0 2 px 12 px 0 rgba ( 0 , 0 , 0 , 0.1 ) ; margin- top: 5 px; user- select: none;
} . calender . header { padding: 15 px 0 10 px; text- align: center;
} . calender . picker- btn { display: inline - block; width: 12 px; height: 12 px; margin: 0 5 px; cursor: pointer;
} . calender . picker- btn. picker- prev- year { color: #606266 ; font- size: 14 px;
}
. calender . picker- btn. picker- prev- month { color: #606266 ; font- size: 14 px;
}
. calender . picker- btn. picker- next- month { color: #606266 ; font- size: 14 px;
}
. calender . picker- btn. picker- next- year { color: #606266 ; font- size: 14 px;
}
. calender . picker- date { color: #606266 ; font- size: 15 px; font- weight: 500 ; margin: 0 50 px;
} . calender . content { padding: 0 10 px 10 px 10 px; color: #606266 ;
} . calender . picker- weeks { height: 40 px; line- height: 40 px; font- size: 14 px; border- bottom: 1 px solid #ebeef5;
}
. calender . picker- weeks div,
. calender . picker- days div { float : left; width: 30 px; height: 30 px; line- height: 30 px; text- align: center; margin: 4 px 6 px;
}
. calender . picker- days div { font- size: 13 px; cursor: pointer;
}
. calender . picker- days div: hover { color: #409 eff;
} . calender . picker- days div. is- today { color: #409 eff; font- weight: 700 ;
}
. calender . picker- days div. other- month { color: #c0c4cc;
}
. calender . picker- days div. is- select { color: #fff; background: #409 eff; border- radius: 50 % ;
}
var calender = { date: new Date ( ) , weeks: [ '日' , '一' , '二' , '三' , '四' , '五' , '六' ] , showDate: { year: 0 , month: 0 , day: 0 } , showDays: [ ] , showCalender: false, init: function ( options) { this. initData ( options) this. render ( ) this. handler ( ) } , initData: function ( options) { this. el = options. elthis. getDate = options. getDatethis. showDate = this. getCalender ( this. date) this. showDays = this. getDays ( ) this. selectDay = this. getSelectDay ( this. showDate) } , getCalender: function ( date) { var year = date. getFullYear ( ) var month = date. getMonth ( ) var day = date. getDate ( ) return { year: year, month: month, day: day} } , getDays: function ( ) { var arr = [ ] var firstDay = new Date ( this. showDate. year, this. showDate. month, 1 ) let weekIndex = firstDay. getDay ( ) let startDay = firstDay - weekIndex * 24 * 60 * 60 * 1000 for ( let i = 0 ; i < 42 ; i++ ) { arr[ i] = new Date ( startDay + i * 24 * 60 * 60 * 1000 ) } return arr} , getSelectDay: function ( date) { if ( date instanceof Date) { return `${ date. getFullYear ( ) } - ${ date. getMonth ( ) + 1 } - ${ date. getDate ( ) } `} return `${ date. year} - ${ date. month + 1 } - ${ date. day} `} , render: function ( ) { this. el. innerHTML = this. renderInput ( ) + this. renderCalender ( ) } , renderInput: function ( ) { return `< div class= "picker-input" > < span class= "picker-prefix" > < / span> < input type= "text" value= "${this.selectDay}" > < / div> `} , renderCalender: function ( ) { return `< div class= "calender" style= "display: ${this.showCalender ? 'block' : 'none'}" > ${ this. renderHeader ( ) } ${ this. renderContent ( ) } < / div> `} , renderHeader: function ( ) { return `< div class= "header" > < span class= "picker-btn picker-prev-year" > & lt; & lt; < / span> < span class= "picker-btn picker-prev-month" > & lt; < / span> < span class= "picker-date" > ${ this. showDate. year} 年 ${ this. showDate. month + 1 } 月< / span> < span class= "picker-btn picker-next-month" > & gt; < / span> < span class= "picker-btn picker-next-year" > & gt; & gt; < / span> < / div> `} , renderContent: function ( ) { return `< div class= "picker-weeks" > ${ this. renderWeeks ( ) } < / div> < div class= "picker-days" > ${ this. renderDays ( ) } < / div> `} , renderWeeks: function ( ) { var template = '' for ( var i = 0 ; i < this. weeks. length; i++ ) { template += `< div> ${ this. weeks[ i] } < / div> `} return template} , renderDays: function ( ) { var template = '' for ( var i = 0 ; i < 42 ; i++ ) { var date = this. showDays[ i] var isCurMonth = this. isCurrentMonth ( date) template += `< divclass= "${ isCurMonth. month ? '' : 'other-month' } ${ isCurMonth. today ? 'is-today' : '' } ${ isCurMonth. select ? 'is-select' : '' } "data- index= ${ i} > ${ date. getDate ( ) } < / div> `} return template} , isCurrentMonth: function ( date) { var year = this. getCalender ( date) . yearvar month = this. getCalender ( date) . monthvar day = this. getCalender ( date) . dayvar showDate = this. showDatevar curYear = showDate. yearvar curMonth = showDate. monthvar todayDate = this. getCalender ( this. date) var todayYear = todayDate. yearvar todayMonth = todayDate. monthvar todayDay = todayDate. dayvar selectDate = this. getCalender ( new Date ( this. selectDay) ) var selectYear = selectDate. yearvar selectMonth = selectDate. monthvar chooseDay = selectDate. dayreturn { month: year == = curYear && month == = curMonth, today: year == = todayYear && month == = todayMonth && day == = todayDay, select: year == = selectYear && month == = selectMonth && day == = chooseDay} } , handler: function ( ) { var that = thisdocument. onclick = function ( e) { var dom = e. targetvar isElChild = that. el. contains ( dom) && dom != = that. elif ( isElChild && ! that. showCalender) { that. changeCalender ( true) } else if ( ! isElChild && that. showCalender) { that. changeCalender ( false) } if ( isElChild) { var isDay = dom. parentNode. classList. contains ( 'picker-days' ) var isBtn = dom. classList. contains ( 'picker-btn' ) var isYearBtn = isBtn && dom. getAttribute ( 'class' ) . includes ( '-year' ) var isMonthBtn = isBtn && dom. getAttribute ( 'class' ) . includes ( '-month' ) if ( isDay) { that. handleDay ( dom) } else if ( isYearBtn) { that. handleYear ( dom) } else if ( isMonthBtn) { that. handleMonth ( dom) } } } } , changeCalender: function ( isShowCalender) { this. showCalender = isShowCalendervar calenderDom = this. el. getElementsByClassName ( 'calender' ) [ 0 ] calenderDom. style. display = isShowCalender ? 'block' : 'none' } , handleDay: function ( dom) { var index = dom. dataset. indexvar date = this. showDays[ index] var selectMonth = date. getMonth ( ) this. selectDay = this. getSelectDay ( date) if ( selectMonth != = this. showDate. month) { this. showDate. month = selectMonththis. showDays = this. getDays ( ) } this. showCalender = falsethis. getDate ( this. selectDay) this. render ( ) } , handleMonth: function ( dom) { var isPrev = dom. getAttribute ( 'class' ) . includes ( 'prev' ) var moveMonth = isPrev ? - 1 : + 1 var showDate = new Date ( this. showDate. year, this. showDate. month, this. showDate. day) showDate. setMonth ( this. showDate. month + moveMonth) this. showDate. month = showDate. getMonth ( ) this. showDate. year = showDate. getFullYear ( ) this. showDays = this. getDays ( ) this. render ( ) } , handleYear: function ( dom) { var isPrev = dom. getAttribute ( 'class' ) . includes ( 'prev' ) var moveYear = isPrev ? - 1 : + 1 this. showDate. year += moveYearthis. showDays = this. getDays ( ) this. render ( ) }
}
3、文件导出功能的实现
3-1 导出 Word
import docxtemplater from 'docxtemplater' ;
import { saveAs } from 'file-saver' ;
import JSZipUtils from 'jszip-utils' ;
import PizZip from 'pizzip' ;
export const exportWord = ( templateDocxPath, exportWordData, outFileName) = > { JSZipUtils. getBinaryContent ( templateDocxPath, function ( error, content) { if ( error) { throw error; } let zip = new PizZip ( content) ; let doc = new docxtemplater ( ) ; doc. loadZip ( zip) ; doc. setData ( exportWordData) ; try { doc. render ( ) ; } catch ( error) { let e = { message: error. message, name: error. name, stack: error. stack, properties: error. properties} ; console. log ( JSON. stringify ( { error: e} ) ) ; throw error; } let out = doc. getZip ( ) . generate ( { type: "blob" , mimeType: "application/vnd.openxmlformats-officedocument.wordprocessingml.document" } ) ; saveAs ( out, outFileName) ; } ) ;
}
三、项目打包
1、打包前准备
1.1 初始化项目
npm init - y
1.2 下载依赖
下载 webpack 和 webpack-cli 的依赖 如果你对别的打包工具比较熟的话,也可以换成其他打包工具
npm install webpack webpack- cli
1.3 配置 Webpack
需要在项目目录下创建一个 webpack.config.js 文件
const path = require ( 'path' ) module. exports = { mode: 'production' , entry: './src/index.js' , output: { path: path. resolve ( __dirname, 'dist' ) , filename: 'lgk-js-tools.js' , library: 'Utils' , libraryTarget: 'umd' }
}
1.4 配置打包命令
在 package.json 文件中的 scripts 属性添加 打包命令 “build”: “webpack --watch”
"scripts" : { "test" : "echo \"Error: no test specified\" && exit 1" , "build" : "webpack --watch" } ,
1.5 项目打包
npm run build
1.6 测试
export function test ( ) { console. log ( "这是一个测试方法!!" )
}
在 test/index.html 文件中测试使用
< ! DOCTYPE html>
< html lang= "en" > < head> < meta charset= "UTF-8" > < meta http- equiv= "X-UA-Compatible" content= "IE=edge" > < meta name= "viewport" content= "width=device-width, initial-scale=1.0" > < title> Document< / title>
< / head> < body> < ! -- 引入打包后的 JS 文件 -- > < script src= "./../dist/lgk-js-tools.js" > < / script> < script> console. log ( Utils. test ( ) ) < / script>
< / body> < / html>
2、暴露工具函数
2.1 在工具函数中使用 export 导出
export function ajax ( { method, url, params, data } ) { method = method. toUpperCase ( ) return new Promise ( ( resolve, reject) = > { let xhr = nullif ( window. XMLHttpRequest) { xhr = new XMLHttpRequest ( ) ; } else { xhr = new ActiveObject ( "Microsoft.XMLHTTP" ) ; } let str = "" for ( let k in params) { str += `${ k} = ${ params[ k] } & `} str = str. slice ( 0 , - 1 ) xhr. open ( method, url + '?' + str) if ( method == = 'POST' || method == = 'PUT' || method == = 'DELETE' || method == = 'PATCH' ) { xhr. setRequestHeader ( 'Content-type' , 'application/json' ) xhr. send ( JSON. stringify ( data) ) } else { xhr. send ( ) } xhr. responseType = 'json' xhr. onreadystatechange = function ( ) { if ( xhr. readyState == 4 ) { if ( xhr. status >= 200 && xhr. status < 300 ) { resolve ( { status: xhr. status, message: xhr. statusText, data: xhr. response} ) } else { reject ( new Error ( '请求失败,失败的状态码为:' + xhr. status) ) } } } } )
} ajax. get = function ( url, options) { let config = Object. assign ( options, { method: 'GET' , url: url } ) return ajax ( config)
} ajax. post = function ( url, options) { let config = Object. assign ( options, { method: 'POST' , url: url } ) return ajax ( config)
} ajax. put = function ( url, options) { let config = Object. assign ( options, { method: 'PUT' , url: url } ) return ajax ( config)
} ajax. delete = function ( url, options) { let config = Object. assign ( options, { method: 'DELETE' , url: url } ) return ajax ( config)
} ajax. patch = function ( url, options) { let config = Object. assign ( options, { method: 'PATCH' , url: url } ) return ajax ( config)
}
2.2 在入口函数引入
export { ajax } from "./ajax/index.js"
2.3 测试使用
npm install lgk- js- tools
import * as Utils from "lgk-js-tools"
在 test/index.html 文件中直接引入测试使用
< ! DOCTYPE html>
< html lang= "en" > < head> < meta charset= "UTF-8" > < meta http- equiv= "X-UA-Compatible" content= "IE=edge" > < meta name= "viewport" content= "width=device-width, initial-scale=1.0" > < title> Document< / title>
< / head> < body> < ! -- 引入 -- > < script src= "./../dist/lgk-js-tools.js" > < / script> < script> Utils. ajax. get ( '这里填URL' , { params: { a: 100 } , } ) . then ( res = > { console. log ( "res=>" , res) } ) . catch ( err = > { console. log ( "err=>" , err) } ) < / script>
< / body> < / html>
四、项目发布
1、注册 npm 账号
2、修改 package.json 配置
name 属性值必须唯一 ,在发布之前将想发布的名称到 npm 仓库搜一下看有没有version 版本号每次发布必须与之前发布的不相同 ,否则会报错main 属性值必须指定为打包生成的 js 文件 author 属性用于指定作者(可以不添加) description 属性用于描述这个工具库的作用(可以不添加) keywords 属性用于填写关键词,方便别人检索(可以不添加)
{ "name" : "lgk-js-tools" , "version" : "1.0.1" , "main" : "./dist/lgk-js-tools.js" , "description" : "" , "author" : { "name" : "lgk" } , "keywords" : [ "ajax" , "js" , "lgk" , "utils" ] , "scripts" : { "test" : "echo \"Error: no test specified\" && exit 1" , "build" : "webpack --watch" } , "license" : "ISC" , "dependencies" : { "webpack" : "^5.71.0" , "webpack-cli" : "^4.9.2" }
}
3、切换 npm 源
npm get registry
检查现在所使用的 npm 源,如果不是 npm 源,需要切换回来
nrm ls
切换 npm 源为 https://registry.npmjs.org/
npm config set registry https:
npm config set registry http:
4、登录与发布
cd lgk- js- tools
npm login
npm addUser
填写登录信息:用户名、密码、邮箱、验证码 发布
npm publish
需要等几分钟后就可以在 npm 查看了
5、强制删除已发布的库
⚠️注意:必须在 72 小时之内,否则不能再被删除 执行删除命令
npm unpublish -- force
项目源码
源码地址:https://gitee.com/lgk2021/lgk-js-tools