目录:(packages里是对应的所有源svg文件,lib里是所有svg对应的Vue组件。通过loaders 里的svgToComponents.js对应的node方法给每一个svg文件在lib下生成对应格式的vue文件以及index.js文件。)
svgToComponents.js:
var fs = require('fs');
var path = require('path');
var util = require('util');
var filePath = path.resolve('./packages/icons');
var template = require('lodash');
var fileList = [];
//调用文件遍历方法
fileDisplay(filePath);
// 生成index.js文件
var indexContent = fileList.map(function(d) {
return `import ${d} from './${d}.vue';\n`
}).join('')+"\n const components = ["+ fileList.join(',\n')+"];\n const install = function(Vue){components.forEach(component => {Vue.component(component.name, component);});}\n"+
"export default {install,"+ fileList.join(',\n')+"}"
fs.writeFileSync(path.resolve(__dirname, `../lib/index.js`), indexContent);
//examples中本地页面显示所有图标
var svgVue = "<template>\n<div class='container'>\n"+fileList.map(function(d) {
return `<div class="master-icon"><${d}/><aside>${d}</aside></div>\n`
}).join('')+"\n</div>\n</template>\n<script>"+fileList.map(function(d) {
return `import ${d} from '../../lib/${d}.vue';\n`
}).join('')+"export default {components: {"+fileList.map(function(d) {
return `${d},\n`
}).join('')+"}\n}\n</script>" +
`
<style>
body{margin: 0;width: 100%;}
.container{
flex-wrap: wrap;
display: flex;
}
.master-icon {width: 140px; height: 120px; color: #666; font-size: 24px;
display: flex;
align-items: center;
flex-direction: column;
}
.master-icon aside {text-align: center; font-size: 12px; color: #99a9bf;margin-top: 30px;}
</style>
`;
fs.writeFileSync(path.resolve(__dirname, `../examples/components/svgDemo.vue`), svgVue);
//文件遍历方法
function fileDisplay(filePath) {
//根据文件路径读取文件,返回文件列表
let files = fs.readdirSync(filePath);
//遍历读取到的文件列表
files.forEach(function (filename) {
//获取当前文件的绝对路径
var filedir = path.join(filePath, filename);
//根据文件路径获取文件信息,返回一个fs.Stats对象
var stats = fs.statSync(filedir);
var isFile = stats.isFile();//是文件
var isDir = stats.isDirectory();//是文件夹
if (isFile) {
var fileName = filedir.match(/([^\/\.]*)\..*$/)[1];
var pattern = /-([a-z0-9])/g;
fileName = fileName.replace(pattern,function(all,letter){
return letter.toUpperCase();
});
fileName = fileName.charAt(0).toUpperCase() + fileName.slice(1);
if(fileName){
// 读取文件内容
var svgContent = fs.readFileSync(filedir, 'utf-8');
var render = template(`
<template>
${svgContent
.replace(/<g[^>]*>((?:\n.*)*)<\/g>/, '$1')
.replace(/<defs>(\n.*)*<\/defs>/, '')
.replace('<svg','<svg :style="{fontSize:size,color: fill,transform:`rotate(${rotate}deg)`}"')
.replace('width="14"','width="1em"')
.replace('height="14"','height="1em"')
.replace(/(fill|stroke)=[\'\"](?!none)[^\'\"]*[\'\"]/g,'$1="currentcolor"')
}
</template>
<script>
export default {
name:"${fileName}Icon",
props:{
size: {
type: String,
default: 'inherit'
},
rotate: {
type: String,
default: '0'
},
fill: {
type: String,
default: 'none'
}
}
};
</script>`);
fs.writeFileSync(path.resolve(__dirname, `../lib/${fileName}Icon.vue`), render)
fileList.push(fileName+'Icon');
}
}
if (isDir) {
fileDisplay(filedir);//递归,如果是文件夹,就继续遍历该文件夹下面的文件
}
});
}
package.json:(main里是组件库的入口文件, 也就是别人安装该组件库后首要加载的文件)
need-to-insert-img
vue.config.js:
const path = require('path');
module.exports = {
lintOnSave: false,
// 修改 src 目录 为 examples 目录
publicPath: '/',
pages: {
index: {
entry: 'examples/main.js',
template: 'public/index.html',
filename: 'index.html',
},
},
configureWebpack: {
resolveLoader: {
modules: ['node_modules', './loaders'],
},
},
// 扩展 webpack 配置,使 packages 加入编译
chainWebpack: (config) => {
config.module
.rule('svg')
.test(/\.svg$/)
.include
.add(path.resolve(__dirname + './packages/icons'))
.end()
.use('svgToComponent')
.loader('svgToComponent');
},
};
命令行中登陆npm 账号、发布:
npm login
然后在package.json的目录下,然后运行npm publish 即发布成功。
lib/index.js里const install = function(Vue){components.forEach(component => {Vue.component(component.name, component);});}
所以别的项目用的时候只需要use一下即可注册所有库里的组件。
vue插件,Vue.use()会优先查找install(),这个方法里可以对所有组件注册到Vue上,Vue.component(name,component)全局注册组件
局部注册是在组件的export default{components:{}}里注册
添加组件名就可以直接渲染该组件
component是一个占位符,:is属性可以用来指定要展示的组件名称