npm打包svg成vue组件

目录:(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属性可以用来指定要展示的组件名称

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,293评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,604评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,958评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,729评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,719评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,630评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,000评论 3 397
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,665评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,909评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,646评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,726评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,400评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,986评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,959评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,197评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,996评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,481评论 2 342

推荐阅读更多精彩内容