{"id":19647110,"url":"https://github.com/lanif-ui/cmn-utils","last_synced_at":"2025-04-28T15:31:19.593Z","repository":{"id":44977776,"uuid":"115172978","full_name":"LANIF-UI/cmn-utils","owner":"LANIF-UI","description":"公共函数\u0026请求封装","archived":false,"fork":false,"pushed_at":"2022-12-09T08:21:24.000Z","size":2973,"stargazers_count":43,"open_issues_count":16,"forks_count":19,"subscribers_count":5,"default_branch":"master","last_synced_at":"2025-04-17T14:21:29.129Z","etag":null,"topics":["fetch","request","store","utils"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/LANIF-UI.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2017-12-23T05:27:34.000Z","updated_at":"2024-07-28T05:17:44.000Z","dependencies_parsed_at":"2023-01-26T08:30:33.161Z","dependency_job_id":null,"html_url":"https://github.com/LANIF-UI/cmn-utils","commit_stats":null,"previous_names":[],"tags_count":12,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/LANIF-UI%2Fcmn-utils","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/LANIF-UI%2Fcmn-utils/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/LANIF-UI%2Fcmn-utils/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/LANIF-UI%2Fcmn-utils/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/LANIF-UI","download_url":"https://codeload.github.com/LANIF-UI/cmn-utils/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":251338617,"owners_count":21573585,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["fetch","request","store","utils"],"created_at":"2024-11-11T14:42:32.748Z","updated_at":"2025-04-28T15:31:17.214Z","avatar_url":"https://github.com/LANIF-UI.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# cmn-utils\n\n[![NPM version](https://img.shields.io/npm/v/cmn-utils.svg?style=flat)](https://npmjs.org/package/cmn-utils)\n[![NPM downloads](http://img.shields.io/npm/dm/cmn-utils.svg?style=flat)](https://npmjs.org/package/cmn-utils)\n[![Dependencies](https://david-dm.org/sorrycc/cmn-utils/status.svg)](https://david-dm.org/sorrycc/cmn-utils)\n\n可复用的通用模块, 一些不常用的函数，或在全局函数里会引起奇异的函数没有引出到全局，可以使用$$.request | $$.store 等间接使用，或`import { request } from 'cmn-utils'`，也可以直接使用 `import request from 'cmn-utils/lib/request'`\n\n# 目录\n\n* [Request](#request) [详细](https://github.com/LANIF-UI/cmn-utils/tree/master/src/request)\n* [Store](#store) [详细](https://github.com/LANIF-UI/cmn-utils/tree/master/src/store)\n* [Event](#event)\n* [UI](#ui)\n* [Utils](#utils)\n* [Download](#download)\n\n# Request\n\n简单包装的Fetch\n\n## API\n- requestConfig 配置所有默认选项\n- requestHeaders 设置headers, 支持 object | key-value | function 类型参数\n- send 发送请求\n- getform, postform, get, post, head, del, put 发送请求(这些都是简化的send)\n- 支持jsonp\n- *下面为不在$$中的方法*\n- create 返回新实例\n- config 同 requestConfig\n- headers 同 requestHeaders\n- prefix 设置请求前缀，可在config中设置\n- beforeRequest 请求前hook\n- afterResponse 响应后hook\n- contentType 设置content-type\n\n## 使用\n\n```javascript\nimport $$ from 'cmn-utils';\n\n// 发送请求\n$$.send('/send')\n$$.get('/get/1')\n$$.post('/post')\n$$.put('/put')\n$$.del('/put/1')\n$$.jsonp('abc.jsonp').then(resp =\u003e resp.json())\n```\n#### 默认选项\n```\n{\n    method: 'POST',         // default 'POST'\n    mode: 'cors',\n    cache: 'no-cache',\n    credentials: 'include',\n    headers: {\n      'content-type': 'application/json'\n    },\n    responseType: 'json',   // text or blob or formData https://fetch.spec.whatwg.org/\n    prefix: '',             // request prefix\n    beforeRequest: null,    // before request check, return false or a rejected Promise will stop request\n    afterResponse: null,    // after request hook\n    timeout: null,          // request timeout (ms)\n  }\n```\n\n### 基本使用\n\n#### 简化写法\n\n```javascript\n// 原始fetch 写法\nfetch('http://httpbin.org/post', {\n  method: 'POST',\n  headers: {\n    'content-type': 'application/json'\n  },\n  body: JSON.stringify({\n    name: 'weiq',\n  })\n})\n.then(function(response) {\n  if (response.status \u003e= 200 \u0026\u0026 response.status \u003c 300) {\n    return response.json()\n  }\n  throw new Error(response.statusText)\n})\n.then(function(json) {\n  // ...\n})\n\n// 等价于，直接使用send方法\n$$.send('http://httpbin.org/post', {\n    method: 'POST',\n    data: {name: 'weiq'}\n  }).then(resp =\u003e {\n    console.log(resp.json) // {name: 'weiq'}\n  })\n\n// 等价于，使用提供的post方法\n$$.post('http://httpbin.org/post', {name: 'weiq'})\n  .then(resp =\u003e {\n    console.log(resp.json) // {name: 'weiq'}\n  })\n```\n\n#### 提交form表单\n\n```js\n// 提交form表单\n$$.getform('/form', {name: 'weiq'}) // 将拼接到url后面\n  //.postform('/form', {name: 'weiq'}) // 将做为Form Data发送\n  .then(resp =\u003e {\n    console.log(resp.json) // {name: 'weiq'}\n  })\n```\n\n#### 使用FormData \u0026\u0026 上传 \n```html\n\u003ch1\u003eUpload FormData\u003c/h1\u003e\n\u003cinput type=\"file\" id=\"avatar\" name=\"avatar\" /\u003e\n```\n注：不能用get方法\n```js\nconst data = new FormData();\ndata.append('file', document.querySelector('#avatar').files[0]);\ndata.append('user', 'weiq');\n\n$$.post('http://httpbin.org/post', data)\n  .catch(e =\u003e console.error('upload error!', e));\n```\n\n#### 全局配置, 将会覆盖默认参数, 一般全局配置一次\n\n```js\n// 全局配置, 将会覆盖默认参数, 一般全局配置一次\n$$.requestConfig('method', 'GET')\n  .requestConfig({\n    headers: {'content-type': 'application/json'},\n    prefix: '/api'\n  })\n// 配置请求头\n$$.requestHeaders('Accept', 'application/json')  // key-value\n  .requestHeaders({ Accept: 'application/json' }) // json\n\n// 用函数反回头\n$$.requestHeaders(_ =\u003e ({\n    random: Math.random()\n  }))\n```\n\n#### 临时改变配置项\n\n```js\n$$.post('http://httpbin.org/post', {name: 'weiq'}, {\n    headers: {\n      'content-type': 'application/json'\n    },\n    responseType: 'json', // 转成json\n  })\n  .then(resp =\u003e {\n    console.log(resp.json) // {name: 'weiq'}\n  })\n```\n\n#### 获取原始响应结果 \u0026 单独处理响应\n\n当返回值不是统一格式时，使用`afterResponse: null`,可以不走全局的拦截器，或者想取原始响应结果时使用`responseType: null`\n\n```js\n$$.get(\"http://httpbin.org/get\", {}, {\n  responseType: null,  // 不处理返回结果\n  afterResponse: null  // 不走公共 afterResponse\n})\n  .then(function(resp) {\n    console.log(resp)\n  })\n  .catch(e =\u003e console.log(e));\n```\n\n#### 并发请求\n\n```js\nfunction concurrencyRequest() {\n  let r1 = $$.get(\"http://httpbin.org/get\");\n  let r2 = $$.post(\"http://httpbin.org/post\");\n  let r3 = $$.put(\"http://httpbin.org/put\");\n\n  Promise.all([r1, r2, r3])\n}\n```\n\n# Store\n\n简单包装的store2\n\n## API\n- setStore\n- getStore \n- removeStore \n- clearStore\n- *下面为不在$$中的方法*\n- getStoreAsync\n- create\n- getStoreInfo\n- getStoreInfoAsync\n- session\n- local\n\n```javascript\n$$.setStore(\"name\", \"abc\")\n  .setStore(\"multi\", {ip: '0.0.0.0'})\n  .setStore(\"age\", 18)\n  .setStore({\n    a: 1,\n    b: 2,\n    c: true\n  })\n$$.getStore(\"multi\");\n\n$$.removeStore('name')\n\n$$.clearStore()\n\n$$.store.getStoreAsync(\"name\").then(value =\u003e console.log(\"async:\", value));\n\n$$.store.getStoreInfo();\n\n$$.store\n  .getStoreInfoAsync(value =\u003e console.log(value))\n  .setStore('name', 'abc');\n\n$$.store.session('name', 'abc'); // 存储到 sessionStorage中\n$$.store.local('name', 'abc'); // 存储到 localStorage中\n```\n\n# Event\n\n让组件可以发射、监听自定义事件, 有时我们可能需要让两个没有太大关系的组件间建立联系，比如增加商品到购物车这个场景，一般会在页面头部（`Header`组件）放置购物车的图标，商品列表（`Goods`组件）中有一个添加到购物车的图标，我们想点击这个图标时，让头部购物车图标显示+1的效果，有几种方案，其一是在头部定义一个`changeCardNumber`方法，然后把这个方法层层传递到商品列表（`Goods`）中，进行调用，这很容易出错，其二是点击商品列表中商品时，通过`dispatch`发出一个类型是`changeCardNumber`的`action`，这种方法我们不得不把`Header`包装一下才可以让它处理`dispatch`的能力, 最后如果我们用自定义事件可以更容易实现这个效果，即在`Header`中订阅一个`changeCardNumber`这个事件，在其它任何地方只有触发`trigger`这个事件就可以了，只需要注意不用的事件要及时移除。\n\n## API\n\n- on 注册事件监听\n- off 移除事件监听\n- once 注册一次事件监听，只能触发一次trigger触发后即自动从监听中移除\n- trigger 触发事件\n\n#### 示例\n\n```javascript\n$$.on('eventName', function(value) {\n  console.log(value)\n});\n\n$$.trigger('eventName');\n\n$$.off('eventName');\n\n$$.once('eventName', function(value) {\n  console.log(value)\n});\n```\n\n# Download\n\n下载文件 `$$.download(data, strFileName, strMimeType);`\n\n#### 示例\n```javascript\n$$.download(\"hello world\", \"dlText.txt\", \"text/plain\");\n\n$$.download(\"data:text/plain,hello%20world\", \"dlDataUrlText.txt\", \"text/plain\");\n\n$$.download(new Blob([\"hello world\"]), \"dlTextBlob.txt\", \"text/plain\");\n\n$$.download(\"/robots.txt\");\n\nvar str= \"hello world\",\tarr= new Uint8Array(str.length);\nstr.split(\"\").forEach(function(a,b){\n  arr[b]=a.charCodeAt();\n});\n$$.download( arr, \"textUInt8Array.txt\", \"text/plain\" );\n\n$$.download(\"/diff6.png\");\n\nvar x=new XMLHttpRequest();\nx.open( \"GET\", \"/diff6.png\" , true);\nx.responseType=\"blob\";\nx.onload= function(e){\n  $$.download(e.target.response, \"awesomesauce.png\", \"image/png\");\n};\nx.send();\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flanif-ui%2Fcmn-utils","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Flanif-ui%2Fcmn-utils","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flanif-ui%2Fcmn-utils/lists"}