vue cli4構建基於typescript的vue組件並發布到npm


基於vue cli創建一個vue項目

  首先安裝最新的vue cli腳手架,

  npm install --global @vue/cli

npm WARN optional SKIPPING OPTIONAL DEPENDENCY: fsevents@1.2.13 (node_modules\@vue\cli\node_modules\fsevents):
npm WARN notsup SKIPPING OPTIONAL DEPENDENCY: Unsupported platform for fsevents@1.2.13: wanted {"os":"darwin","arch":"any"} (current: {"os":"win32","arch":"x64"}) + @vue/cli@4.4.6 added 1230 packages from 670 contributors in 118.122s

  查看安裝的vue -V

@vue/cli 4.4.6

   創建項目:vue create my-project-name(“my-project-name”,這個可以根據需要命名,盡量用英文)

Vue CLI v4.4.6
? Please pick a preset: Manually select features ? Check the features needed for your project: Babel, TS, Router, Vuex, CSS Pre-processors, Linter ? Use class-style component syntax? Yes ? Use Babel alongside TypeScript (required for modern mode, auto-detected polyfills, transpiling JSX)? Yes ? Use history mode for router? (Requires proper server setup for index fallback in production) Yes ? Pick a CSS pre-processor (PostCSS, Autoprefixer and CSS Modules are supported by default): Sass/SCSS (with node-sass) ? Pick a linter / formatter config: Prettier ? Pick additional lint features: Lint on save ? Where do you prefer placing config for Babel, ESLint, etc.? In dedicated config files ? Save this as a preset for future projects? Yes ? Save preset as: ts_tmpl

  創建完成之后,會出現如下提示

⚓  Running completion hooks...

�  Generating README.md...

�  Successfully created project my-project-name. � Get started with the following commands: $ cd my-project-name $ npm run serve

  根據提示執行命令

E:\vue_codes>cd my-project-name

E:\vue_codes\my-project-name>npm run serve > my-project-name@0.1.0 serve E:\vue_codes\my-project-name > vue-cli-service serve INFO Starting development server... Starting type checking service... Using 1 worker with 2048MB memory limit 98% after emitting CopyPlugin DONE Compiled successfully in 5304ms 上午11:13:54 No type errors found Version: typescript 3.9.7 Time: 3160ms App running at: - Local: http://localhost:8080/ - Network: http://192.168.1.95:8080/  Note that the development build is not optimized. To create a production build, run npm run build.

  在瀏覽器輸入地址:http://localhost:8080/

  出現如上圖所示界面,表示項目創建成功了。

   生成的代碼目錄結構如下:

   兩個聲明文件:shims-vue.d.tsshims.tsx.d.ts

  shims-vue.d.ts由於 TypeScript 默認並不支持 *.vue 后綴的文件,所以在 vue 項目中引入的時候需要創建一個shims-vue.d.ts 文件,放在項目項目對應使用目錄下,例如 src/shims-vue.d.ts,用來支持*.vue 后綴的文件

  shims-tsx.d.ts允許.tsx 結尾的文件,在 Vue 項目中編寫 jsx 代碼

  tsconfig.json:typescript配置文件,主要用於指定待編譯的文件和定義編譯選項

  normalize.css:Normalize.css 是一個可以定制的CSS文件,它讓不同的瀏覽器在渲染網頁元素的時候形式更統一。Normalize.css是一種CSS reset的替代方案。

  .browserslistrc:這個配置能夠分享目標瀏覽器和nodejs版本在不同的前端工具。這些工具能根據目標瀏覽器自動來進行配置,Browserslist這個東西單獨是沒用的,(補充: 在vue官方腳手架中,browserslist字段會被 @babel/preset-env 和 Autoprefixer 用來確定需要轉譯的 JavaScript 特性和需要添加的 CSS 瀏覽器前綴。)

   browserslist的配置文件:
  > 1% 兼容全球使用率大於1%的游覽器
  last 2 versions 兼容每個游覽器的最近兩個版本
  not ie <= 8 不兼容ie8及以下
  具體可見 browserslist。

  babel.config.js:Babel 是一個工具鏈,主要用於將 ECMAScript 2015+ 版本的代碼轉換為向后兼容的 JavaScript 語法,以便能夠運行在當前和舊版本的瀏覽器或其他環境中。
  postcss.config.js:用於配置將px轉化成rem,和自動添加CSS瀏覽器前綴等。
  esnext 是一個 JavaScript 庫,可以將 ES6 草案規范語法轉成今天的 JavaScript 語法。

改造項目結構

  這種組件項目和我們日常的項目還是有很大區別的,由於前面我采用的是vue cli創建的完整模板項目,這里許多東西用不到,我們就將其刪掉,最終項目目錄結構如下:

   examples:是組件使用示例

  src/components:是組件源碼

  package.json代碼如下:

{
  "name": "jie-echarts", "version": "0.1.0", "private": false, "description": "echarts組件", "main": "dist/JieEcharts.common.js", "author": "zouqj<zouyujie@126.com>", "license": "MIT", "scripts": { "serve": "vue-cli-service serve", "build": "vue-cli-service build", "lint": "vue-cli-service lint", "lib": "vue-cli-service build --target lib --name JieEcharts ./src/index.ts" },
  "repository": {
    "type": "git",
    "url": "git+https://github.com/zouyujie/vue-components/tree/master/jie-echarts"
  },
  "bugs": {
    "url": "https://github.com/zouyujie/vue-components/issues"
  },
  "homepage": "https://github.com/zouyujie/vue-components/tree/master/jie-echarts",
  "keywords": [
    "vue",
    "vuejs",
    "typescript",
    "vuecli4.x"
  ],
 "dependencies": { "core-js": "^3.6.5", "echarts": "^4.8.0", "ts-loader": "^8.0.1", "vue": "^2.6.11", "vue-class-component": "^7.2.3", "vue-property-decorator": "^8.4.2", "vue-router": "^3.2.0", "vuex": "^3.4.0" }, "devDependencies": { "@types/echarts": "^4.6.4", "@typescript-eslint/eslint-plugin": "^2.33.0", "@typescript-eslint/parser": "^2.33.0", "@vue/cli-plugin-babel": "~4.4.0", "@vue/cli-plugin-eslint": "~4.4.0", "@vue/cli-plugin-router": "~4.4.0", "@vue/cli-plugin-typescript": "~4.4.0", "@vue/cli-plugin-vuex": "~4.4.0", "@vue/cli-service": "~4.4.0", "@vue/eslint-config-prettier": "^6.0.0", "@vue/eslint-config-typescript": "^5.0.2", "eslint": "^6.7.2", "eslint-plugin-prettier": "^3.1.3", "eslint-plugin-vue": "^6.2.2", "node-sass": "^4.12.0", "prettier": "^1.19.1", "sass-loader": "^8.0.2", "typescript": "~3.9.3", "vue-template-compiler": "^2.6.11" } }

  重點注意標紅部分的配置。

  tsconfig.json

{
  "compilerOptions": { "target": "esnext", "module": "esnext", "strict": true, "jsx": "preserve", "importHelpers": true, "moduleResolution": "node", "experimentalDecorators": true, "esModuleInterop": true, "allowSyntheticDefaultImports": true, "sourceMap": true, "baseUrl": ".", "typeRoots": ["/@types", "./node_modules/@types"], "types": ["webpack-env"], "paths": { "@/*": ["src/*"] }, "lib": ["esnext", "dom", "dom.iterable", "scripthost"] }, "include": [ "src/**/*.ts", "src/**/*.tsx", "src/**/*.vue", "tests/**/*.ts", "tests/**/*.tsx" ], "exclude": ["node_modules"] }

  vue.config.js代碼如下:

'use strict';
// Template version: 1.3.1 // see http://vuejs-templates.github.io/webpack for documentation.  const UglifyJsPlugin = require('uglifyjs-webpack-plugin'); const webpack = require('webpack'); const path = require('path'); const resolve = (dir) => path.resolve(__dirname, dir); module.exports = { // 修改 src 目錄 為 examples 目錄  pages: { index: {  entry: 'examples/main.ts', template: 'public/index.html', filename: 'index.html', }, }, // vue 通過 file-loader 用版本哈希值和正確的公共基礎路徑來決定最終的圖片路徑,再用 url-loader 將小於 4kb 的 // 圖片內聯,以減少 HTTP 請求的數量。所以我們可以通過 chainWebpack 調整圖片的大小限制。例如,我們將 // 圖片大小限制設置為 13kb,低於13kb的圖片全部被內聯,高於13kb的圖片會放在單獨的img文件夾中。 chainWebpack: (config) => { const imagesRule = config.module.rule('images'); imagesRule .use('url-loader') .loader('url-loader') .tap((options) => Object.assign(options, { limit: 13312 })); }, // 設置css: { extract: false },可以強制內聯,就不會將css單獨打包成一個文件,導致頁面沒有style css: { extract: false }, productionSourceMap: false, };

  說明:UglifyJS Webpack Plugin插件用來縮小(壓縮優化)js文件,修改應用入口文件,examples/main.ts,方便執行npm run serve的時候,可以直接查看組件的示例。

 .npmignore可以將一些不需要發布到npm的文件忽略掉,.npmignore配置如下:

.*
package-lock.json /.git/ /.vscode/ tslint.json tsconfig.json *.log .DS_Store /dist /examples /node_modules /public /src /tests .browserslistrc jest.config.js vue.config.js # local env files .env.local .env.*.local # Log files npm-debug.log* yarn-debug.log* yarn-error.log* # Editor directories and files .idea .vscode .gitignore .npmignore .npmrc *.suo *.ntvs* *.njsproj *.sln *.sw?

  components下面

  index.ts代碼,以插件的形式進行封裝,方便全局引用:

import jieEcharts from './jie-echarts.vue';

(jieEcharts as any).install = (Vue: any) => { Vue.component(jieEcharts.name, jieEcharts); }; export default jieEcharts;

  jie-echarts.vue,是組件源碼,代碼:

<template>
  <!-- 每一個圖表都有自己唯一的id,需要動態傳入。 -->
  <div :ref="id" :id="id" :class="myclass" :style="style" />
</template>
<script lang="ts">
import { Component, Vue, Prop, Watch } from "vue-property-decorator"; import Echarts from "echarts"; @Component({ name: "jie-echarts" }) export default class extends Vue { @Prop({ default: "myCharts" }) private id!: string; @Prop({ default: "100%" }) private width!: string; @Prop({ default: "200px" }) private height!: string; @Prop({ default: "echarts-line" }) private myclass!: string; @Prop() private options!: object; @Prop({ default: false }) private loading!: boolean; private MyEcharts: any = null; // echarts實例  created() { console.log("this.options :>> ", this.options); } mounted() { this.InitCharts(); } get style() { return { height: this.height, width: this.width }; } @Watch("options", { deep: true }) onChangeOption(newVal: string, oldVal: string) { if (this.MyEcharts) { if (newVal) { // console.log(JSON.stringify(newVal)) this.MyEcharts.setOption(newVal, true); } else { this.MyEcharts.setOption(oldVal, true); } setTimeout(() => { this.MyEcharts.resize(); }); } else { this.InitCharts(); } } @Watch("height") onChangeHeight(val: string) { if (val) { this.height = val; } if (this.MyEcharts) { this.MyEcharts.setOption(this.options, true); } else { this.InitCharts(); } } @Watch("loading") onChangeLoading(val: boolean) { if (val == true) { this.showLoading(); } if (val == false) { this.hideLoading(); } } //-----------------------method---------------------- // 組件初始化  private InitCharts() { const dom: any = this.$refs[this.id] as HTMLDivElement; // document.getElementById(this.id); this.MyEcharts = Echarts.init(dom); if (this.loading == true) { this.showLoading(); } /** * 此方法適用於所有項目的圖表,但是每個配置都需要在父組件傳進來,相當於每個圖表的配置都需要寫一遍,不是特別的省代碼,主要是靈活度高 * echarts的配置項,你可以直接在外邊配置好,直接扔進來一個this.option */ this.MyEcharts.clear(); // 適用於大數據量的切換時圖表繪制錯誤,先清空在重繪 this.MyEcharts.setOption(this.options, true); // 設置為true可以是圖表切換數據時重新渲染  setTimeout(() => { this.MyEcharts.resize(); }); // 當窗口變化時隨瀏覽器大小而改變  window.addEventListener("resize", () => { this.MyEcharts.resize(); }); this.MyEcharts.on("click", (params: any) => { this.mapClick(params); }); } //組件單擊事件  private mapClick(params: any) { // console.log(params, 999999);  const data = { color: params.color, data: params.data, dataIndex: params.dataIndex, seriesIndex: params.seriesIndex, chartType: params.componentSubType }; this.$parent.$emit("chartParams", JSON.stringify(data)); if (params.seriesType == "map") { this.$emit("mapValue", params.name); }  this.$emit("eclick", params); } private showLoading() { if (this.MyEcharts) { this.MyEcharts.showLoading({ text: "loading" // color: '#4cbbff', // textColor: '#4cbbff',  }); } } private hideLoading() { if (this.MyEcharts) { this.MyEcharts.hideLoading(); } }
  beforeDestroy() {
    window.removeEventListener("resize", () => {
      this.MyEcharts.resize();
    });
  } } </script> <style lang="scss" scoped> .echarts-line { height: 100%; } </style>

  @types目錄下:

  component.d.ts代碼:

import Vue from 'vue';

export class VanComponent {
  static name: string;
  static install(vue: typeof Vue): void; }

  說明:@types是npm的一個分支,當我們把npm包發上去,npm包就會托管到服務器,供大家下載,但是ts為了代碼的可復用性,要申明一些靜態類型文件,那些文件就是*.d.ts

  shims-vue.d.ts代碼:

declare module "*.vue" {
  import Vue from "vue"; export default Vue; }

  App.vue,組件引入演示界面,代碼:

<template>
  <div id="app">
    <jie-echarts :options="echartsOptions"></jie-echarts>
  </div>
</template>
<script lang="ts">
import { Component, Vue, Watch, Prop } from "vue-property-decorator"; import jieEcharts from "../src/index"; @Component({ components: { jieEcharts } }) export default class TestJieEchartsPreview extends Vue { protected echartsOptions = { xAxis: { type: "category", data: ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"] }, yAxis: { type: "value" }, series: [ { data: [820, 932, 901, 934, 1290, 1330, 1320], type: "line" } ] }; } </script> <style lang="scss"> #app { font-family: Avenir, Helvetica, Arial, sans-serif; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; text-align: center; color: #2c3e50; } #nav { padding: 30px; a { font-weight: bold; color: #2c3e50; &.router-link-exact-active { color: #42b983; } } } </style>

  執行npm run serve,運行結果如下:

發布到NPM

  1.去 https://www.npmjs.com/注冊一個賬號
  2.登錄郵箱,點擊激活連接

  3.執行npm login,進行登錄

PS E:\vue_codes\my-project-name> npm login
Username: zouyujie
Password:
Email: (this IS public) zouyujie@126.com

  如果你是使用的淘寶鏡像,注意啊要先切換到npm官網鏡像,切換方式:npm config set registry https://registry.npmjs.org/

  4.執行命令 npm publish,進行發布,如果出現如下圖所示錯誤:

   說明郵箱沒有綁定成功,點擊https://www.npmjs.com/email-edit,進行綁定,然后重新執行npm publish,運行結果如下:

PS E:\vue_codes\my-project-name> npm publish
npm notice 
npm notice package: jie-echarts@0.1.0 npm notice === Tarball Contents === npm notice 632B dist/index.html npm notice 4.3kB dist/favicon.ico npm notice 66B babel.config.js npm notice 965.0kB dist/js/chunk-vendors.80f39f1d.js npm notice 6.3kB dist/js/index.f9222971.js npm notice 1.4kB package.json npm notice 327B README.md npm notice === Tarball Details === npm notice name: jie-echarts npm notice version: 0.1.0 npm notice package size: 341.3 kB npm notice unpacked size: 978.0 kB npm notice shasum: 2b65bfa887ba4677dc95a36a4b0403ebfecc9fde npm notice integrity: sha512-RwSE3lC8N3wZT[...]b1b9cvJ8UtL/w== npm notice total files: 7 npm notice + jie-echarts@0.1.0

  至此,npm發布成功。

  然后我們去npm上,查看我們發布的npm包,

   如果能看到如下圖所示界面:

   說明已發布成功。

  注意:每次重新發布都要記得修改一下版本號,否則會發布失敗。發布成功后,你的npm郵箱都會受到一封npm組件發布成功的郵件通知。

  npm上地址:https://www.npmjs.com/package/jie-echarts

安裝jie-echarts

     npm i jie-echarts


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM