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)目錄
通過運(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文件夾苫耸,所有自定義組件都放這里
其中州邢,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
這是從網(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 文件余爆,如圖所示:
- 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)目。