封装组件
我这里选择的是表情的一个组件例子,npm 包名称 aimee-plugins-emoji
首先创建组件项目
通过Vue 脚手架创建简易webpage项目
vue init webpack-simple aimee-plugins-emoji
生成后的目录如下
安装依赖 并 运行
cd webpack-simple aimee-plugins-emoji
npm install
npm run dev
添加自己的组件
创建组件文件
<!-- 留言评论模块 -->
<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() { //选项 / 数据
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':'发红包','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)
})
}
/* 支持使用标签的方式引入 */
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>
到这个地方项目已经创建完了 ,接下来就是修改配置文件
修改配置文件
主要修改的配置文件为 webpack.config.js 和 package.json
webpack.config.js设置
首先项目中因为有图片的引用,需要设置图片为base64,可以通过设置limit 的值来实现。
{
test: /\.(png|jpg|gif|svg)$/,
loader: 'url-loader',
options: {
limit: 50000000,
name: '[name].[ext]?[hash]'
}
}
设置入口和输出路径
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标准的,也可以是指amd标准的,也可以只是通过script标签引入的
umdNamedDefine: true, // 会对 UMD 的构建过程中的 AMD 模块进行命名。否则就使用匿名的 define
},
package.json设置
设置private属性为false,默认为true,npm 发布的时候如果为true会失败。
添加node_module 的入口文件设置,"main": "dist/aimee-plugins-emoji.js"
"private": false,
"main": "dist/aimee-plugins-emoji.js",
上传到git 仓库管理
注意 这里gitignore中需要取消对dist文件夹的忽略
仓库管理项目文件
发布到npm
前提:需要注册npm 账号并激活
登录 npm login
需要看清楚是否是注册的registry,如果是淘宝的会报错
发布 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
如果要修改组件内容,需要修改package.json中的版本号,然后重新发布
在项目中使用
通过npm install aimee-plugins-emoji --save-dev 安装到本地
在 项目的main.js 中引用
import aimeePluginsEmoji from 'aimee-plugins-emoji'
Vue.use(aimeePluginsEmoji)
组件中可以通过<aimee-emoji></aimee-emoji> 使用