Vue插件開發(fā)與發(fā)布

Vue.js 作為當(dāng)下比較熱門的技術(shù)隆夯,它的核心庫只關(guān)注視圖層宗雇,容易上手昂芜。組件是Vue.js最強(qiáng)大的功能之一。組件可以擴(kuò)展HTML元素赔蒲,封裝可重用的代碼泌神。在較高層面上,組件是自定義的元素舞虱,Vue.js的編譯器為它添加特殊功能欢际。在有些情況下,組件也可以是原生HTML元素的形式矾兜,以js特性擴(kuò)展损趋。

這篇文章帶你創(chuàng)建屬于自己的組件庫,并打包到 npm 供更多人使用椅寺。

一舶沿、 創(chuàng)建 Vue 項(xiàng)目

使用 vue-cli 腳手架創(chuàng)建項(xiàng)目 guoxb-ui

vue init webpack guoxb-ui

當(dāng)然,也可以用 vue init webpack-simple guoxb-ui 創(chuàng)建簡(jiǎn)潔的項(xiàng)目

二配并、 項(xiàng)目架構(gòu)目錄

ico_jiegou.png

通過運(yùn)行上述指令括荡,生成的項(xiàng)目結(jié)構(gòu)如圖所示,大結(jié)構(gòu)基本不用動(dòng)溉旋,只需要添加自己的配置文件以及自己的文件夾即可畸冲。

添加的配置如下(從上至下依次拆分):

1. build 目錄添加 webpack.dist.config.js

build 目錄下存放著 webpack 的配置信息,在該目錄下添加了一個(gè)單獨(dú)打包插件的配置文件 webpack.dist.config.js

var path = require('path')
var webpack = require('webpack')

module.exports = {
**entry: './src/plugin/index.js', // 入口文件
  output: {
    path: path.resolve(__dirname, '../dist'), // 打包后的文件放這里
    publicPath: '/dist/',
    filename: 'guoxb-ui.js',
    library: 'guoxb-ui', // library指定的是引入項(xiàng)目的模塊名
    libraryTarget: 'umd', // libraryTarget會(huì)生成不同umd的代碼,可以只是commonjs標(biāo)準(zhǔn)的,也可以是指amd標(biāo)準(zhǔn)的邑闲,也可以只是通過script標(biāo)簽引入的(必須加上)
    umdNamedDefine: true // 會(huì)對(duì) UMD 的構(gòu)建過程中的 AMD 模塊進(jìn)行命名算行。否則就使用匿名的 define(必須加上)
  },**
  module: {
    rules: [
      {
        test: /\.css$/,
        use: [
          'vue-style-loader',
          'css-loader'
        ],
      },
      {
        test: /\.scss$/,
        use: [
          'vue-style-loader',
          'css-loader',
          'sass-loader'
        ],
      },
      {
        test: /\.sass$/,
        use: [
          'vue-style-loader',
          'css-loader',
          'sass-loader?indentedSyntax'
        ],
      },
      {
        test: /\.vue$/,
        loader: 'vue-loader',
        options: {
          loaders: {
            // Since sass-loader (weirdly) has SCSS as its default parse mode, we map
            // the "scss" and "sass" values for the lang attribute to the right configs here.
            // other preprocessors should work out of the box, no loader config like this necessary.
            'scss': [
              'vue-style-loader',
              'css-loader',
              'sass-loader'
            ],
            'sass': [
              'vue-style-loader',
              'css-loader',
              'sass-loader?indentedSyntax'
            ]
          }
          // other vue-loader options go here
        }
      },
      {
        test: /\.js$/,
        loader: 'babel-loader',
        exclude: /node_modules/
      },
      {
        test: /\.(png|jpg|gif|svg)$/,
        loader: 'file-loader',
        options: {
          name: '[name].[ext]?[hash]'
        }
      }
    ]
  },
  resolve: {
    alias: {
      'vue$': 'vue/dist/vue.esm.js'
    },
    extensions: ['*', '.js', '.vue', '.json']
  },
  devServer: {
    historyApiFallback: true,
    noInfo: true,
    overlay: true
  },
  performance: {
    hints: false
  },
  devtool: '#eval-source-map'
}

if (process.env.NODE_ENV === 'production') {
  module.exports.devtool = '#source-map'
  // http://vue-loader.vuejs.org/en/workflow/production.html
  module.exports.plugins = (module.exports.plugins || []).concat([
    new webpack.DefinePlugin({
      'process.env': {
        NODE_ENV: '"production"'
      }
    }),
    new webpack.optimize.UglifyJsPlugin({
      sourceMap: true,
      compress: {
        warnings: false
      }
    }),
    new webpack.LoaderOptionsPlugin({
      minimize: true
    })
  ])
}

這段配置代碼實(shí)際是 npm init webpack-simple guoxb-ui 生成項(xiàng)目中的 webpack.config.js 文件中的代碼,我們只需要改的就是 入口文件 和 輸出文件

2. src下創(chuàng)建plugin文件夾苫耸,所有自定義組件都放這里
ico_jiegou3.png

其中州邢,button 文件夾存放 自定義的button組件 button.vue 以及 用于導(dǎo)出組件的 index.js;

plugin 目錄下的 index.js 用于添加我們的組件內(nèi)容褪子,以及注冊(cè)組件量淌。

plugin -> button -> button.vue 源碼
<template>
  <div>
    <button
      class="guoxb-button"
      :class="['guoxb-button--' + type, 'guoxb-button--' + (round ? 'round' : '')]"
    >
      <slot></slot>
    </button>
  </div>
</template>

<script>
export default {
  name: "g-button", // *** 我們是全局注入組件,所以在后面引入我們的組件后嫌褪,會(huì)使用這個(gè)命名的標(biāo)簽 ***
  props: {
    type: {
      type: String,
      default: "normal"
    },
    round: {
      type: Boolean,
      default: false
    }
  }
};
</script>

<style scoped>
.guoxb-button {
  font-size: 14px;
  color: #f68;
  background: #fff;
  border: 1px solid #eee;
}
.guoxb-button--normal {
  width: 100px;
  line-height: 40px;
}
.guoxb-button--small {
  width: 80px;
  line-height: 30px;
  font-size: 12px;
}
.guoxb-button--large {
  width: 120px;
  line-height: 50px;
  font-size: 16px;
}
.guoxb-button--round {
  border-radius: 5px;
}
</style>
plugin -> button -> index.js 源碼
export { default } from './button.vue';
plugin -> index.js 源碼
import GButton from './button';
import *** from './***';

const install = function(Vue, options) {
    if (install.installed) return;
    Vue.component(GButton.name, GButton);
    Vue.component(***.name, ***);
}

/* 支持使用標(biāo)簽的方式引入 */
if (typeof window !== 'undefined' && window.Vue) {
    install(window.Vue);
}

export default {
    install,
    GButton,
    ***
}
疑問:為什么在button文件夾下還要?jiǎng)?chuàng)建index.js
1556517520350.jpg

這是從網(wǎng)上找到的答案呀枢,可能并沒有太大說服力,所以又仔細(xì)的查看了vue官方文檔

插件通常用來為 Vue 添加全局功能笼痛。插件的功能范圍沒有嚴(yán)格的限制——一般有下面幾種:
(1) 添加全局方法或者屬性裙秋。如: vue-custom-element
(2) 添加全局資源:指令/過濾器/過渡等。如 vue-touch
(3) 通過全局混入來添加一些組件選項(xiàng)缨伊。如 vue-router
(4) 添加 Vue 實(shí)例方法摘刑,通過把它們添加到 Vue.prototype 上實(shí)現(xiàn)。
(5) 一個(gè)庫刻坊,提供自己的 API枷恕,同時(shí)提供上面提到的一個(gè)或多個(gè)功能。如 vue-router

不難理解紧唱,當(dāng)我們的組件需要為Vue添加全局功能的時(shí)候活尊,是需要在index.js導(dǎo)出組件之前隶校,來完成這步操作的漏益!

所以,官方文檔也給出了為Vue添加全局功能的方法:

MyPlugin.install = function (Vue, options) {
  // 1. 添加全局方法或?qū)傩?  Vue.myGlobalMethod = function () {
    // 邏輯...
  }

  // 2. 添加全局資源
  Vue.directive('my-directive', {
    bind (el, binding, vnode, oldVnode) {
      // 邏輯...
    }
    ...
  })

  // 3. 注入組件選項(xiàng)
  Vue.mixin({
    created: function () {
      // 邏輯...
    }
    ...
  })

  // 4. 添加實(shí)例方法
  Vue.prototype.$myMethod = function (methodOptions) {
    // 邏輯...
  }
}

這段代碼是要寫在組件內(nèi)部的 index.js 里面的深胳。

三绰疤、 測(cè)試組件

在任一頁面引入組件,作測(cè)試舞终,例如:

在src - components - HelloWorld.vue 下引入組件

<template>
  <div class="hello">
   <g-button :round="true" type="normal">按鈕</g-button>
  </div>
</template>

<script>

import Vue from 'vue';
/* 打包前的組件測(cè)試 */
import GuoUI from '@/plugin/index.js';
/* 打包后的組件測(cè)試(打包后轻庆,會(huì)在項(xiàng)目根目錄生成dist文件夾) */
// import GuoUI from '../../dist/guoxb-ui.js';
Vue.use(GuoUI);

export default {
  name: 'HelloWorld',
  data () {
    return {

    }
  }
}
</script>

運(yùn)行項(xiàng)目,測(cè)試組件

四敛劝、 打包

這里需要修改 package.json 文件余爆,如圖所示:

WX20190429-144512.png
  • main屬性:打包到dist下的文件,也是以后安裝引用使用的js文件
  • scripts 中添加 "dist": "webpack --config build/webpack.dist.config.js" 用于打包
  • repository 倉庫夸盟,可以不寫蛾方,如果不寫,npm官網(wǎng)就沒有跳到你github上的入口

做完以上配置,控制臺(tái)輸入 npm run dist 開始打包桩砰,打包成功后拓春,會(huì)在項(xiàng)目根目錄生成 dist 文件夾,里面是package.json -> main屬性配置的 guoxb-ui.js 文件

可以再引入 dist 下的 guoxb-ui.js 文件測(cè)試組件

五亚隅、 發(fā)布組件

測(cè)試ok了硼莽,接下來就是發(fā)布組件到 npm,首先得有npm賬號(hào)煮纵,如果沒有請(qǐng)走注冊(cè)懂鸵。

控制臺(tái),項(xiàng)目根目錄下醉途,執(zhí)行命令:npm login 登錄 npm矾瑰,此時(shí)會(huì)讓輸入用戶名、密碼以及郵箱隘擎;

登錄成功之后殴穴,執(zhí)行命令:npm publish 即可。

記住货葬,每次發(fā)布采幌,需要修改 package.json 版本號(hào),不然報(bào)錯(cuò)震桶。

發(fā)布完之后休傍,就可以轉(zhuǎn)到我們的 npm官網(wǎng) 上查看我們的項(xiàng)目。

https://www.npmjs.com/package/guoxb-ui

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末蹲姐,一起剝皮案震驚了整個(gè)濱河市磨取,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌柴墩,老刑警劉巖忙厌,帶你破解...
    沈念sama閱讀 216,919評(píng)論 6 502
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異江咳,居然都是意外死亡逢净,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,567評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門歼指,熙熙樓的掌柜王于貴愁眉苦臉地迎上來爹土,“玉大人,你說我怎么就攤上這事踩身≌鸵穑” “怎么了?”我有些...
    開封第一講書人閱讀 163,316評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵挟阻,是天一觀的道長(zhǎng)琼娘。 經(jīng)常有香客問我呵哨,道長(zhǎng),這世上最難降的妖魔是什么轨奄? 我笑而不...
    開封第一講書人閱讀 58,294評(píng)論 1 292
  • 正文 為了忘掉前任孟害,我火速辦了婚禮,結(jié)果婚禮上挪拟,老公的妹妹穿的比我還像新娘挨务。我一直安慰自己,他們只是感情好玉组,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,318評(píng)論 6 390
  • 文/花漫 我一把揭開白布谎柄。 她就那樣靜靜地躺著,像睡著了一般惯雳。 火紅的嫁衣襯著肌膚如雪朝巫。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,245評(píng)論 1 299
  • 那天石景,我揣著相機(jī)與錄音劈猿,去河邊找鬼。 笑死潮孽,一個(gè)胖子當(dāng)著我的面吹牛揪荣,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播往史,決...
    沈念sama閱讀 40,120評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼仗颈,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了椎例?” 一聲冷哼從身側(cè)響起挨决,我...
    開封第一講書人閱讀 38,964評(píng)論 0 275
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎订歪,沒想到半個(gè)月后脖祈,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,376評(píng)論 1 313
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡陌粹,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,592評(píng)論 2 333
  • 正文 我和宋清朗相戀三年撒犀,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了福压。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片掏秩。...
    茶點(diǎn)故事閱讀 39,764評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖荆姆,靈堂內(nèi)的尸體忽然破棺而出蒙幻,到底是詐尸還是另有隱情,我是刑警寧澤胆筒,帶...
    沈念sama閱讀 35,460評(píng)論 5 344
  • 正文 年R本政府宣布邮破,位于F島的核電站诈豌,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏抒和。R本人自食惡果不足惜矫渔,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,070評(píng)論 3 327
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望摧莽。 院中可真熱鬧庙洼,春花似錦、人聲如沸镊辕。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,697評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽征懈。三九已至石咬,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間卖哎,已是汗流浹背鬼悠。 一陣腳步聲響...
    開封第一講書人閱讀 32,846評(píng)論 1 269
  • 我被黑心中介騙來泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留亏娜,地道東北人厦章。 一個(gè)月前我還...
    沈念sama閱讀 47,819評(píng)論 2 370
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像照藻,于是被迫代替她去往敵國(guó)和親袜啃。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,665評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容