vue 組件封裝并發(fā)布npm包詳解

封裝組件

我這里選擇的是表情的一個組件例子胸私,npm 包名稱 aimee-plugins-emoji


image.png

首先創(chuàng)建組件項目

通過Vue 腳手架創(chuàng)建簡易webpage項目

vue init webpack-simple aimee-plugins-emoji

生成后的目錄如下


image.png

安裝依賴 并 運行

cd webpack-simple aimee-plugins-emoji
npm install
npm run dev

添加自己的組件
創(chuàng)建組件文件

<!-- 留言評論模塊 -->
<template>
    <div class="box">
    <div class="face-box">
            <textarea name="face" ref="textareaBox" cols="30" rows="10" v-model="message" placeholder="說點什么呢``" ></textarea>
            <div class="face-sina">
                <div class="face-logo" @click="pBody=!pBody">
                    <span>sina表情</span>
                </div>
                <div class="face-sina-body" v-show="pBody">
                    <ul class="face-sina-items face-sina-items-show">
                      <li v-for="(item, index) in faceList" :key="index" class="face-sina-item" @click="choseHandle(item.title)">
                        <img :src="require('../../assets/emot/image/'+item.url)" alt="">
                      </li>
                    </ul>
                </div>
            </div>
    </div>
    <div class="face-show-box" v-html="messageshow">
    </div>
</div>
</template>

<script>
export default {
  name: 'aimee-emoji',
  data() { //選項 / 數(shù)據(jù)
    return {
      faceList:[//表情包和表情路徑
          {'title':'微笑','url':'weixiao.gif'},
          {'title':'嘻嘻','url':'xixi.gif'},
          {'title':'哈哈','url':'haha.gif'},
          {'title':'可愛','url':'keai.gif'},
          {'title':'可憐','url':'kelian.gif'},
          {'title':'挖鼻','url':'wabi.gif'},
          {'title':'吃驚','url':'chijing.gif'},
          {'title':'害羞','url':'haixiu.gif'},
          {'title':'擠眼','url':'jiyan.gif'},
          {'title':'閉嘴','url':'bizui.gif'},
          {'title':'鄙視','url':'bishi.gif'},
          {'title':'愛你','url':'aini.gif'},
          {'title':'淚','url':'lei.gif'},
          {'title':'偷笑','url':'touxiao.gif'},
          {'title':'親親','url':'qinqin.gif'},
          {'title':'生病','url':'shengbing.gif'},
          {'title':'太開心','url':'taikaixin.gif'},
          {'title':'白眼','url':'baiyan.gif'},
          {'title':'右哼哼','url':'youhengheng.gif'},
          {'title':'左哼哼','url':'zuohengheng.gif'},
          {'title':'噓','url':'xu.gif'},
          {'title':'衰','url':'shuai.gif'},
          {'title':'吐','url':'tu.gif'},
          {'title':'哈欠','url':'haqian.gif'},
          {'title':'抱抱','url':'baobao.gif'},
          {'title':'怒','url':'nu.gif'},
          {'title':'疑問','url':'yiwen.gif'},
          {'title':'饞嘴','url':'chanzui.gif'},
          {'title':'拜拜','url':'baibai.gif'},
          {'title':'思考','url':'sikao.gif'},
          {'title':'汗','url':'han.gif'},
          {'title':'困','url':'kun.gif'},
          {'title':'睡','url':'shui.gif'},
          {'title':'錢','url':'qian.gif'},
          {'title':'失望','url':'shiwang.gif'},
          {'title':'酷','url':'ku.gif'},
          {'title':'色','url':'se.gif'},
          {'title':'哼','url':'heng.gif'},
          {'title':'鼓掌','url':'guzhang.gif'},
          {'title':'暈','url':'yun.gif'},
          {'title':'悲傷','url':'beishang.gif'},
          {'title':'抓狂','url':'zhuakuang.gif'},
          {'title':'黑線','url':'heixian.gif'},
          {'title':'陰險','url':'yinxian.gif'},
          {'title':'怒罵','url':'numa.gif'},
          {'title':'互粉','url':'hufen.gif'},
          {'title':'書呆子','url':'shudaizi.gif'},
          {'title':'憤怒','url':'fennu.gif'},
          {'title':'感冒','url':'ganmao.gif'},
          {'title':'心','url':'xin.gif'},
          {'title':'傷心','url':'shangxin.gif'},
          {'title':'豬','url':'zhu.gif'},
          {'title':'熊貓','url':'xiongmao.gif'},
          {'title':'兔子','url':'tuzi.gif'},
          {'title':'喔克','url':'ok.gif'},
          {'title':'耶','url':'ye.gif'},
          {'title':'棒棒','url':'good.gif'},
          {'title':'不','url':'no.gif'},
          {'title':'贊','url':'zan.gif'},
          {'title':'來','url':'lai.gif'},
          {'title':'弱','url':'ruo.gif'},
          {'title':'草泥馬','url':'caonima.gif'},
          {'title':'神馬','url':'shenma.gif'},
          {'title':'囧','url':'jiong.gif'},
          {'title':'浮云','url':'fuyun.gif'},
          {'title':'給力','url':'geili.gif'},
          {'title':'圍觀','url':'weiguan.gif'},
          {'title':'威武','url':'weiwu.gif'},
          {'title':'話筒','url':'huatong.gif'},
          {'title':'蠟燭','url':'lazhu.gif'},
          {'title':'蛋糕','url':'dangao.gif'},
          {'title':'發(fā)紅包','url':'fahongbao.gif'}
      ],
      pBody:false,//是否展示表情框
      message: '',
      lastposition: 0
    }
  },
  computed: {
    messageshow(){
      var pat01 = /\[[\u4e00-\u9fa5]+\]/g;
      var pat02 = /\[[\u4e00-\u9fa5]+\]/;
      var content = this.message.match(pat01);
      var str = this.message;
      if(content){
        for(var i=0;i<content.length;i++){
          for(var j=0;j<this.faceList.length;j++){
            if("["+this.faceList[j].title +"]" == content[i]){
                var src = this.faceList[j].url;
                break;
            }
          }
          str = str.replace(pat02,'<img src="'+require('../../assets/emot/image/'+src)+'"/>');
        }
      }
      return str
    }
  },
  methods: {
    getCursortPosition (ctrl) {
      var CaretPos = 0 // IE Support
      if (document.selection) {
        ctrl.focus()
        var Sel = document.selection.createRange()
        Sel.moveStart('character', -ctrl.value.length)
        CaretPos = Sel.text.length
      } else if (ctrl.selectionStart || ctrl.selectionStart == '0') { // Firefox support
        CaretPos = ctrl.selectionStart
      }
      return (CaretPos)
    },
    choseHandle(title) {
      var position = this.getCursortPosition(this.$refs.textareaBox)    
      this.message = this.message.substring(0, position) + '[' + title + ']' + this.message.substring(position, this.message.length)  
      this.pBody = false
    }
  }
}
</script>
<style lang="less">
  .box{
  width:600px;
  margin: 0 auto;
}
.face-box textarea{
  background:#f4f6f7;
  width:100%;
  height:100px;
  margin-bottom: 10px;
  border-radius: 5px;
  box-sizing: border-box;
}
.face-sina{
  position: relative;
  z-index: 1;
}
.face-sina .face-logo ,.face-sina .face-showbtn{
  position: relative;
  border-radius: 4px;
  color:#444;
  display: inline-block;
  background: #fff;
  border:1px solid #ddd;
  font-size: 13px;
  padding:0 6px;
  cursor: pointer;
  height:30px;
  box-sizing: border-box;
  z-index: 2;
  line-height: 30px;
  margin-right:20px;
  transition:all 0.3s ease;
}
.face-sina .face-logo:hover,.face-sina .face-showbtn:hover{
  background-color: #f4f6f7;
}
.face-sina .face-sina-body{
  position: absolute;
  background: #fff;
  border:1px solid #ddd;
  z-index: 1;
  top:29px;
  border-radius: 0 4px 4px 4px;

}
.face-sina-open .face-sina-body{
  display: block;
}
.face-sina-open .face-logo{
  border-radius: 4px 4px 0 0;

}
.face-sina-open .face-logo:hover{
  animation:none;
  -webkit-animation:none;
}
.face-sina .face-sina-items {
  max-height: 197px;
  overflow: scroll;
  font-size: 0;
  padding:10px;
  z-index: 1
}
.face-sina .face-sina-items .face-sina-item{
  background: #f7f7f7;
  padding:5px 10px;
  border-radius: 5px;
  display: inline-block;
  margin: 0 10px 12px 0;
  transition: 0.3s;
  line-height: 19px;
  font-size: 20px;
  cursor: pointer;
}
.face-sina .face-sina-items .face-sina-item:hover{
  background: #eee;
  box-shadow: 0 2px 2px 0 rgba(0,0,0,.14),
  0 3px 1px -2px rgba(0,0,0,.2),
  0 1px 5px 0 rgba(0,0,0,.12);
  animation:a 5s infinite ease-in-out;
  -webkit-animation:a 5s infinite ease-in-out;
}
.face-show-box{
  width:100%;
  margin: 300px 0;
  padding:20px;
  border: 1px solid #999;
  background: #f4f6f7;
  box-sizing: border-box;
  border-radius: 5px;
  vertical-align: middle;
  img{
    vertical-align: middle;
  }
}

</style>

在main.js 入口文件的同級目錄下床玻,添加index.js 打包的入口文件

import emoji from './plugins/emoji/index.vue'

const components = [
  emoji
]
const install = function (Vue, opts = {}) {
  components.map(component => {
    Vue.component(component.name, component)
  })
}

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

export default {install, emoji}

可以在入口文件main.js 中正常引用

import aimeePluginsEmoji from './index.js'
Vue.use(aimeePluginsEmoji)

這樣在項目中任何地方可以直接使用組件,如下我在app.vue 文件中直接引入<aimee-emoji></aimee-emoji>使用

<template>
  <div id="app">
    <aimee-emoji></aimee-emoji>
  </div>
</template>

<script>
export default {
  name: 'app',
  data () {
    return {
      msg: 'Welcome to Your Vue.js App'
    }
  }
}
</script>

<style>
#app {
  font-family: 'Avenir', Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
  margin-top: 60px;
}
</style>

到這個地方項目已經(jīng)創(chuàng)建完了 淀弹,接下來就是修改配置文件

修改配置文件

主要修改的配置文件為 webpack.config.js 和 package.json

webpack.config.js設(shè)置

首先項目中因為有圖片的引用债鸡,需要設(shè)置圖片為base64捌木,可以通過設(shè)置limit 的值來實現(xiàn)。

{
    test: /\.(png|jpg|gif|svg)$/,
        loader: 'url-loader',
        options: {
          limit: 50000000,
          name: '[name].[ext]?[hash]'
        }
      }

設(shè)置入口和輸出路徑

  entry: process.env.NODE_ENV === 'production'? './src/index.js' : './src/main.js',
  output: {
    path: path.resolve(__dirname, './dist'),
    publicPath: '/dist/',
    filename: 'aimee-plugins-emoji.js',
    library: 'aimee-plugins-emoji', // 指定的就是你使用require時的模塊名
    libraryTarget: 'umd', // libraryTarget會生成不同umd的代碼,可以只是commonjs標(biāo)準(zhǔn)的焕窝,也可以是指amd標(biāo)準(zhǔn)的蹬挺,也可以只是通過script標(biāo)簽引入的
    umdNamedDefine: true, // 會對 UMD 的構(gòu)建過程中的 AMD 模塊進(jìn)行命名。否則就使用匿名的 define
  },
package.json設(shè)置

設(shè)置private屬性為false它掂,默認(rèn)為true巴帮,npm 發(fā)布的時候如果為true會失敗。
添加node_module 的入口文件設(shè)置虐秋,"main": "dist/aimee-plugins-emoji.js"

  "private": false,
  "main": "dist/aimee-plugins-emoji.js",

上傳到git 倉庫管理

注意 這里gitignore中需要取消對dist文件夾的忽略
倉庫管理項目文件

發(fā)布到npm

前提:需要注冊npm 賬號并激活

登錄 npm login
image.png

需要看清楚是否是注冊的registry榕茧,如果是淘寶的會報錯

發(fā)布 npm publish
![image.png](https://upload-images.jianshu.io/upload_images/13238271-7d21ddfd4202bc15.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

生成后的npm包https://www.npmjs.com/package/aimee-plugins-emoji
如果要修改組件內(nèi)容,需要修改package.json中的版本號客给,然后重新發(fā)布

在項目中使用

通過npm install aimee-plugins-emoji --save-dev 安裝到本地
在 項目的main.js 中引用

import aimeePluginsEmoji from 'aimee-plugins-emoji'
Vue.use(aimeePluginsEmoji)

組件中可以通過<aimee-emoji></aimee-emoji> 使用

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末用押,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子靶剑,更是在濱河造成了極大的恐慌只恨,老刑警劉巖,帶你破解...
    沈念sama閱讀 222,104評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件抬虽,死亡現(xiàn)場離奇詭異,居然都是意外死亡纵菌,警方通過查閱死者的電腦和手機(jī)阐污,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,816評論 3 399
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來咱圆,“玉大人笛辟,你說我怎么就攤上這事⌒蛩眨” “怎么了手幢?”我有些...
    開封第一講書人閱讀 168,697評論 0 360
  • 文/不壞的土叔 我叫張陵,是天一觀的道長忱详。 經(jīng)常有香客問我围来,道長,這世上最難降的妖魔是什么匈睁? 我笑而不...
    開封第一講書人閱讀 59,836評論 1 298
  • 正文 為了忘掉前任监透,我火速辦了婚禮,結(jié)果婚禮上航唆,老公的妹妹穿的比我還像新娘胀蛮。我一直安慰自己,他們只是感情好糯钙,可當(dāng)我...
    茶點故事閱讀 68,851評論 6 397
  • 文/花漫 我一把揭開白布粪狼。 她就那樣靜靜地躺著退腥,像睡著了一般。 火紅的嫁衣襯著肌膚如雪再榄。 梳的紋絲不亂的頭發(fā)上狡刘,一...
    開封第一講書人閱讀 52,441評論 1 310
  • 那天,我揣著相機(jī)與錄音不跟,去河邊找鬼颓帝。 笑死,一個胖子當(dāng)著我的面吹牛窝革,可吹牛的內(nèi)容都是我干的购城。 我是一名探鬼主播,決...
    沈念sama閱讀 40,992評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼虐译,長吁一口氣:“原來是場噩夢啊……” “哼瘪板!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起漆诽,我...
    開封第一講書人閱讀 39,899評論 0 276
  • 序言:老撾萬榮一對情侶失蹤侮攀,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后厢拭,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體兰英,經(jīng)...
    沈念sama閱讀 46,457評論 1 318
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,529評論 3 341
  • 正文 我和宋清朗相戀三年供鸠,在試婚紗的時候發(fā)現(xiàn)自己被綠了畦贸。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,664評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡楞捂,死狀恐怖薄坏,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情寨闹,我是刑警寧澤胶坠,帶...
    沈念sama閱讀 36,346評論 5 350
  • 正文 年R本政府宣布,位于F島的核電站繁堡,受9級特大地震影響沈善,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜帖蔓,卻給世界環(huán)境...
    茶點故事閱讀 42,025評論 3 334
  • 文/蒙蒙 一矮瘟、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧塑娇,春花似錦澈侠、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,511評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽烧栋。三九已至,卻和暖如春拳球,著一層夾襖步出監(jiān)牢的瞬間审姓,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,611評論 1 272
  • 我被黑心中介騙來泰國打工祝峻, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留魔吐,地道東北人。 一個月前我還...
    沈念sama閱讀 49,081評論 3 377
  • 正文 我出身青樓莱找,卻偏偏與公主長得像酬姆,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子奥溺,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,675評論 2 359

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