vue项目小记小结

目录:

  1. 1.1.      生命周期
  2. 1.2.       v-if 和 v-show的区别
  3. 1.3.       data 为什么一定是一个函数
  4. 1.4.       slot插槽
  5. 1.5.       杂记
  6. 1.6.       混入 mixins
  7. 1.7.       自定义指令
  8. 1.8.       渲染函数render
  9. 1.9.       过滤器
  10. 1.10.     路由
  11. 1.11.     状态管理
  12. 1.12.     多语言
  13. 1.13.     axios
  14. 1.14.     mock模拟json数据
  15. 1.15.     iconfont阿里巴巴图标库使用
  16. 1.16      项目地址
  • 生命周期
     

    可以在浏览器中运行以下代码,更能清楚的认识和理解生命周期
    官方:https://cn.vuejs.org/v2/guide/instance.html

    <!DOCTYPE html>
    <html>
    <head>
        <title></title>
        <script type="text/javascript" src="https://cdn.jsdelivr.net/vue/2.1.3/vue.js"></script>
    </head>
    <body>
    <div id="app">
         <p>{{ message }}</p>
    </div>
    <script type="text/javascript">
      var app = new Vue({
          el: '#app',
          data: {
              message : "xuxiao is boy"
          },
           beforeCreate: function () {
                    console.group('beforeCreate 创建前状态===============》');
                   console.log("%c%s", "color:red" , "el     : " + this.$el); //undefined
                   console.log("%c%s", "color:red","data   : " + this.$data); //undefined
                   console.log("%c%s", "color:red","message: " + this.message) 
            },
            created: function () {
                console.group('created 创建完毕状态===============》');
                console.log("%c%s", "color:red","el     : " + this.$el); //undefined
                   console.log("%c%s", "color:red","data   : " + this.$data); //已被初始化
                   console.log("%c%s", "color:red","message: " + this.message); //已被初始化
            },
            beforeMount: function () {
               console.group('beforeMount 挂载前状态===============》');
               console.log("%c%s", "color:red","el     : " + (this.$el)); //已被初始化
               console.log(this.$el);
               console.log("%c%s", "color:red","data   : " + this.$data); //已被初始化 
               console.log("%c%s", "color:red","message: " + this.message); //已被初始化 
            },
            mounted: function () {
                console.group('mounted 挂载结束状态===============》');
                console.log("%c%s", "color:red","el     : " + this.$el); //已被初始化
                console.log(this.$el);   
                   console.log("%c%s", "color:red","data   : " + this.$data); //已被初始化
                   console.log("%c%s", "color:red","message: " + this.message); //已被初始化
            },
            beforeUpdate: function () {
                console.group('beforeUpdate 更新前状态===============》');
                console.log("%c%s", "color:red","el     : " + this.$el);
                console.log(this.$el);  
                   console.log("%c%s", "color:red","data   : " + this.$data);
                   console.log("%c%s", "color:red","message: " + this.message);
            },
            updated: function () {
                console.group('updated 更新完成状态===============》');
                console.log("%c%s", "color:red","el     : " + this.$el);
                console.log(this.$el);
                   console.log("%c%s", "color:red","data   : " + this.$data);
                   console.log("%c%s", "color:red","message: " + this.message);
            },
            beforeDestroy: function () {
                console.group('beforeDestroy 销毁前状态===============》');
                console.log("%c%s", "color:red","el     : " + this.$el);
                console.log(this.$el);   
                   console.log("%c%s", "color:red","data   : " + this.$data);
                   console.log("%c%s", "color:red","message: " + this.message);
            },
            destroyed: function () {
                console.group('destroyed 销毁完成状态===============》');
                console.log("%c%s", "color:red","el     : " + this.$el);
                console.log(this.$el); 
                   console.log("%c%s", "color:red","data   : " + this.$data);
                   console.log("%c%s", "color:red","message: " + this.message)
            }
        })
    </script>
    </body>
    </html>

    我们可以利用chrome的开发者工具,来显示的调用上面html的方法,app是vue的实例,例如app. destroyed() 

  • v-if 和 v-show的区别

 官方:https://cn.vuejs.org/v2/guide/conditional.html

一般会用作面试题

区别:v-if 如果第一次为false,此条件块并不会进行渲染,直到为true时,开始渲染,会根据条件适当的销毁与重建条件块内的组件与事件监听器 而 v-show 无论初始条件是什么,其都会进行渲染,渲染为 display:none 与block的切换,建议频繁使用的话用v-show 记一下:v-ifv-for 一起使用时,v-for优先级更高,so,我们才会写 v-for=”item in arr” v-if=”item.a === 3 :key=”item.b”…….

官方:https://cn.vuejs.org/v2/guide/components.html 

  • data 为什么一定是一个函数
     
data: {
    count: 0
  }
上面的写法其实就是一个对象,你用到对象就要考虑对象的引用,这很容易会影响到其他组件的使用,so,组件的data必须是一个函数,返回对象的独立拷贝,即return{}

1 匿名插槽:

  <slot></slot>

组件渲染的时候,会将slot替换为你的元素,当然如果你没给这个口子的话,任何传入组件的内容都会被抛弃

2 具名插槽 

我们给slot添加一个name属性,

<slot name="header"></slot> 使用的时候可以在任意标签上,给其一个slot=“header”来告诉vue的渲染机制,这个元素就是插到 这个地方的,默认插槽,给个默认值的意思。

 3 作用域插槽

可以从子组件获取数据的插槽,官方写的很好,看到这个,可以想到elementUi里的el-table-cloumn就是


<el-table-column
  prop="name"
  label="企业名称"
  align="center"
  :show-overflow-tooltip="true"
  min-width="120">
  <template slot-scope="scope">
    <el-button @click.native="hanldeClick(scope.row)" type="text" class="table-link">
      {{scope.row.name}}
    </el-button>
  </template>
  </el-table-column>
可以清楚的看到 这种插槽的强大之处

   异步组件,在vue-router使用,达到懒加载即按需引入的需求

  • 杂记
component: resolve => {
  require.ensure([], () => {
    resolve(require('../../page/main_$tp/wait-approval/trade-orders.vue'))
  }, 'mainwaitApproval')
}

Vue的广播事件,emitbus,达到非父子组件的消息传递 

Vue的动画,实现炫酷的css效果,轮播图的实现变得非常简单 

Vue.prototype 添加vue的实例方法  

 官方:https://cn.vuejs.org/v2/guide/mixins.html

这东西让我的感觉就像是vue实例初始化的copy,使用例如我们可以先定一个js文件 取名formatDate.js

  • 混入 mixins
import moment from 'moment'
  const mixin = {
  methods: {
    /**
     * 格式化时间
     * @param {string|number|object|Array} dateTime - 时间,可以是一个字符串、时间戳、表示时间的对象、Date对象或者******表示时间的数组
     * @param {string} [fmt] - 格式
     * @returns {string} 返回格式化后的日期时间,默认格式:2018年1月11日 15:00
     * @see [momentjs]{@tutorial http://momentjs.cn/}
     */
    formatDate (dateTime, fmt = 'YYYY年M月DD日 HH:mm:ss') {
      if (!dateTime) {
        return ''
      }
      moment.locale('zh-CN')
      dateTime = moment(dateTime).format(fmt)
      return dateTime
    }
  }
}
  export default mixin
/////// 组件内使用
全局使用:在main.js入口文件中
  import mixinfrom'com@/mixin/formatDate'
  Vue.mixin(mixin) 
  弄完之后在组件中,可以直接在data初始化时,直接使用
官方不推荐使用全局混入,因为这个会影响到每个单独创建的vue实例
局部使用: 在组件中

可以直接在data初始化时,直接使用

 官方:https://cn.vuejs.org/v2/guide/custom-directive.html

例如,我们可以创建一个focus.js的文件

  • 自定义指令
import Vue from 'vue';
Vue.directive('autoFcs',{
  // 钩子函数,被绑定元素插入父节点时调用 (父节点存在即可调用,不必存在于 document 中)。
  inserted(el){
    el.focus()
  }
})

在main.js入口文件全局引入import 'com@/directives/focus'

 在组件中 和v-model类似  直接 v-autoFcs

上面是使用,理解 我们可以看一下下面的html

<html>
  <head>
     <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
  </head>
<h1>自定义指令及其生命周期</h1>
<div id="app">
    <div v-mydirective.modify1.mofify22="mycolor">
        {{ name }}
    </div>
</div>
<button onclick="unbindApp()">解绑</button>
<script>
    function unbindApp() {
        app.$destroy();
    }
    Vue.directive("mydirective",{
        bind:function (el, binding, vnode) { //1-被绑定
            console.log("1-bind 被绑定");
            console.log("el:",el);
            console.log("binding:",binding);
            console.log("vnode:",vnode);
            el.style.color=binding.value;
        },
        inserted:function (el, binding, vnode) { //2-被插入
            console.log("2-inserted 被插入");
        },
        update:function (el, binding, vnode) { //3-更新
            console.log("3-update 更新");
        },
        componentUpdated:function (el, binding, vnode) { //4-更新完成
            console.log("4-componentUpdated 更新完成");
        },
        unbind:function (el, binding, vnode) { //5-解绑
            console.log("5-unbind 解绑");
        }
    });

    var app =new Vue({
        el:"#app",
        data:{
            mycolor:"blue",
            name:"mydirective指令"
        }
    });

</script>

</html>

Chrmo下开发者工具使用app来调用方法 

 官方:https://cn.vuejs.org/v2/guide/render-function.html

例:iview在的table渲染居然是用的reder,牛皮了哇,实现table可编辑,这里吐槽一下,elementUi用的是真的舒服,文档界面,代码使用都 good!

<!DOCTYPE html>
<html>
<head>
    <title></title>
    <link rel="stylesheet" type="text/css" href="http://unpkg.com/iview/dist/styles/iview.css">
    <script type="text/javascript" src="http://vuejs.org/js/vue.min.js"></script>
    <script type="text/javascript" src="http://unpkg.com/iview/dist/iview.min.js"></script>
</head>
<body>
<div id="app">
    <i-table  border :columns="columns2" :data="data3"></i-table>
</div>

<script>
   
  var app = new Vue({
      el: '#app',
      data () {
        return {
             list: [],
                columns2: [
                     {
                        title: 'Name',
                        key: 'name'
                    },
                    {
                        title: 'Age',
                        key: 'age',
                           render: (h, params) => {
                            if (params.row.$isEdit) {
                              return h('input', {

                                domProps: {
                                  value: params.row.age
                                },
                                on: {
                                  input: function (event) {
                                    this.$emit('input', event.target.value)
                                  }
                                }
                              });
                            } else  {
                             
                              return h('div', params.row.age);
                            }
                        }
                    },
                    {
                        title: 'Address',
                        key: 'address'
                    },
                    {
                        title: 'Action',
                        key: 'action',
                        render: (h, params) => {
                            return h('Button', {
                                    props: {
                                        type: 'text',
                                        size: 'small'
                                    },
                                    on: {
                                      click: () => {
                                        if (params.row.$isEdit) {
                                          this.handleSave(params.row)
                                        } else {
                                          this.handleEdit(params.row)
                                        }
                                      }
                                    }
                                }, params.row.$isEdit ? '保存' : '编辑')
                        }
                    }
                ],
                data3: [
                    {
                        name: '哈哈',
                        age: 18,
                        address: '上海',
                        $isEdit: false
                    },
                    {
                        name: '啦啦',
                        age: 24,
                        address: '北京',
                        $isEdit: false
                    }
                ]
              }
      },
        methods: {
            handleEdit (row) {
               this.$set(row, '$isEdit', true)
            },
            handleSave (row) {
              this.$set(row, '$isEdit', false)
            }
}
    })
</script>
</body>
</html>

直接运行,看效果即可,看不懂的,建议看一下我上面写的vue官方文档的解释 

  • 过滤器

官方:https://cn.vuejs.org/v2/guide/filters.html

使用:我们可以创建一个money.js的文件。来帮我们改变参数达到需要的样子

import Vue from 'vue';

  /**

 * 转换为金额
 * @param s 需要转换的数字
 * @param n 金额后面保留的小数点的位数
 * @return {string}
 */
  const fmtMoney = (s, n) => {
  let leZero = s < 0;
  n = n > 0 && n <= 20 ? n : 2
  s = parseFloat((s + '').replace(/[^\d\.-]/g, '')).toFixed(n) + ''
  if(leZero) s = s.substr(1)
  var l = s.split('.')[0].split('').reverse(), r = s.split('.')[1]
  let t = ''
  for (let i = 0; i < l.length; i++) {
    t += l[i] + ((i + 1) % 3 == 0 && (i + 1) != l.length ? ',' : '')
  }
  let rst = t.split('').reverse().join('') + '.' + r
  return leZero ? '-'+rst : rst
  }


  /**

 * 金额转换为数字
 * @param s 需要转换的金额字符串
 * @return {Number}
 */
  const parseMoney = (s) => {
  return parseFloat(s.replace(/[^\d\.-]/g, ''))
}
  /**
 * @param num 需要转换的数字金额
 * @returns {string} 金额中文大写
 */
  const numToChinese = (num) => {
  // 小数
  let fraction = ['角', '分']

  // 数字
  let digit = [
    '零', '壹', '贰', '叁', '肆',
    '伍', '陆', '柒', '捌', '玖'
  ]
  let unit = [
    ['元', '万', '亿'],
    ['', '拾', '佰', '仟']
  ]
  let head = num < 0 ? '负' : ''
  num = Math.abs(num)
  let s = ''
  for (let i = 0; i < fraction.length; i++) {
    s += (digit[Math.floor(num * 10 * Math.pow(10, i)) % 10] + fraction[i]).replace(/零./, '')
  }
  s = s || '整'
  num = Math.floor(num)
  for (let i = 0; i < unit[0].length && num > 0; i++) {
    let p = ''
    for (let j = 0; j < unit[1].length && num > 0; j++) {
      p = digit[num % 10] + unit[1][j] + p
      num = Math.floor(num / 10)
    }
    s = p.replace(/(零.)*零$/, '').replace(/^$/, '零') + unit[0][i] + s
  }
  return head + s.replace(/(零.)*零元/, '元')
    .replace(/(零.)+/g, '零')
    .replace(/^整$/, '零元整')
}
Vue.filter('fmtMoney', fmtMoney);
Vue.filter('parseMoney', parseMoney);
Vue.filter('numToChinese', numToChinese);

 定义全局过滤器:在man.js中 import 'com@/filters/money' 

在组件中即可使用    当然,我们可以串联过滤器,传递多个参数{{price| fmtMoney(3)}} price是fmtMoney函数的第一个参数,传入的参数从第二个后续排入

  • 路由

官方:https://router.vuejs.org/zh/

使用,先npm install vue-router --save

                   import router from './router'
new Vue({
  el: '#app',
  router,
  store,
  i18n,
  components: { Layout },
  template: '<Layout/>'
})

这样就可以在项目中使用 

里面有很多东西,建议将router的配置 放置在一个单独的文件里,最后引入main.js即可,用的最多当然是路由传参

这里以router-link为例,当然 this.$touter.push 也是一样的

路由配置

1
<router-link :to="{path: 'detail/analysis' , query: {id: 22}}">立即购买</router-link>

这里的参数会在url后面以?拼接,可以用route.query来获取

2
<router-link :to="{name: 'analysis' , query: {id: 22}}">立即购买</router-link>

效果和上面一样

3
<router-link :to="{name: 'analysis' , params: {id: 22}}">立即购买</router-link>
url没有变化,可以用route.parmas 来获取
注意 第三种,不可以使用path来传递参数params,否则获取不到

4
路由配置
<router-link :to="{name: 'analysis' , params: {id: 22}}">立即购买</router-link>
以/的形式拼接到url后面
或者
<router-link :to="{path: `detail/analysis/${333}`}">立即购买</router-link>

 
  • 状态管理

官方:https://vuex.vuejs.org/zh/

vuex 传递参数,兄弟组件传参 通过eventbus广播传递,而父子组件通过prop emit传递,而vuex做到了把组件的共享状态抽取出来,以一个全局的单例模式(即全局只有一个vue实例)统一来进行管理,官方图例:

组件通过dispatch来触发action,而action通过commit来操作mutations从而改变其中的state数据,最后达到渲染到组件上,一个循环。当然,vue也提高了getter函数来让我们直接获取state数据

直接上手栗子:

新建一个js文件,基本结构:

import Vue from 'vue'
  import {getAppData} from 'api@/list-api'
  const state = {
   orderList: [],
   params: {}
}
  const getters = {
   getOrderList:  state => state.orderList
  }

  const actions = {
   fetchOrderList ({commit, state}) {
     getAppData(state.params).then((rst) => {
       state.orderList = rst.data.data.getOrderList.list
     }).catch((err) => {
       console.log(err)
     })
   }
}

  const mutations = {
  changeOrderList (state, payload) {
    state.orderList = payload
  },
  updateParams (state, {key, val}) {
    state.params[key] = val
  }
}

  export default {
  state,
  getters,
  actions,
  mutations
  }

actions相比于mutations的好处在于其可以执行异步操作,api请求啊,promise等等,我们可以放到一个index.js出口文件统一将其导出 

import Vuex from 'vuex'
  import Vue from 'vue'
  import orderList from './modules/orderList'

  Vue.use(Vuex)
  export default new Vuex.Store({
  modules: {
    orderList
  }
})

最后将其import倒入main.js入口文件,即可全局使用操作orderList

  • 多语言

项目上实现多语言

首先需要导入 vue-il8n,

简单demo:

当然我这边也是为了练习,自己写了个demo,so我将其放到了store去管理,当然,实际项目不需要。

// import Cookies from 'js-cookie'

  const app = {
  state: {
    language: localStorage.getItem('language') || 'en'
  },
  getters: {
    getLanguage:  state => state.language
  },
  mutations: {
    SET_LANGUAGE: (state, language) => {
      state.language = language
      localStorage.setItem('language', language)
    },
    DEL_LANGUAGE: (state) => {
      localStorage.removeItem('language')
    },
  },
  actions: {
    setLanguage({ commit }, language) {
      commit('SET_LANGUAGE', language)
    },
    delLanguage({ commit }) {
      commit('DEL_LANGUAGE')
    }
  }
}

  export default app

之前是将信息放到cookie里面去了,放到localStorage也能达到效果,而且浏览器工具也能看到  

主要js,去使用VueI18n

import Vue from 'vue'
  import VueI18n from 'vue-i18n'
  // import Cookies from 'js-cookie'
  import enLocale from './en'
  import zhLocale from './zh'

  Vue.use(VueI18n)

  const messages = {
  en: {
    ...enLocale,
  },
  zh: {
    ...zhLocale,
  }
}

  const i18n = new VueI18n({
  // set locale
  // options: en or zh
  locale: localStorage.getItem('language') || 'en',
  // set locale messages
  messages
  })
  export default i18n

 上面可以看到有两个文件,json格式存放中英文  全局导入main.js           即可在页面下拉选切换

  • axios

vue官方有一个叫vue-resource的插件来处理请求,但是尤大推荐axios等工具来请求api,简单封装一下

import axios from 'axios'

  // create an axios instance
  const demoApi = axios.create({
  baseURL: process.env.BASE_API, // api的base_url
  timeout: 5000 // request timeout
  // headers: {
  //   Authorization: store.getters.token
  // }
  })

  // request interceptor
  demoApi.interceptors.request.use(
  config => {
    // Do something before request is sent
    // if (store.getters.token) {
    //   // 让每个请求携带token-- ['X-Token']为自定义key 请根据实际情况自行修改
    //   config.headers['X-Token'] = getToken()
    // }
    return config
  },
  error => {
    // Do something with request error
    console.log(error) // for debug
    Promise.reject(error)
  }
)

  // respone interceptor
  demoApi.interceptors.response.use(
  response => response,
  /**
   * 下面的注释为通过在response里,自定义code来标示请求状态
   * 当code返回如下情况则说明权限有问题,登出并返回到登录页
   * 如想通过xmlhttprequest来状态码标识 逻辑可写在下面error中
   * 以下代码均为样例,请结合自生需求加以修改,若不需要,则可删除

   */
  // response => {
  //   const res = response.data
  //   if (res.code !== 20000) {
  //     Message({
  //       message: res.message,
  //       type: 'error',
  //       duration: 5 * 1000
  //     })
  //     // 50008:非法的token; 50012:其他客户端登录了;  50014:Token 过期了;
  //     if (res.code === 50008 || res.code === 50012 || res.code === 50014) {
  //       // 请自行在引入 MessageBox
  //       // import { Message, MessageBox } from 'element-ui'
  //       MessageBox.confirm('你已被登出,可以取消继续留在该页面,或者重新登录', '确定登出', {
  //         confirmButtonText: '重新登录',
  //         cancelButtonText: '取消',
  //         type: 'warning'
  //       }).then(() => {
  //         store.dispatch('FedLogOut').then(() => {
  //           location.reload() // 为了重新实例化vue-router对象 避免bug
  //         })
  //       })
  //     }
  //     return Promise.reject('error')
  //   } else {
  //     return response.data
  //   }
  // },
  error => {
    console.log('err' + error) // for debug
    return Promise.reject(error)
  }
)
  
  export {demoApi}

单独Api的js文件 只给了个get形式 

import { demoApi } from '../fetch.js'

  export function getAppData(params) {
  return demoApi({
    url: '/appData',
    method: 'get',
    params: { params }
  })
}

即可在组件内import内直接倒入使用

  • mock模拟JSON数据

1  项目本地创建一个json文件,里面类似模拟后台到前端的数据  在 webpack.dev.config.js中就可以在单组件中使用/api/appData来获取数据   当然。我不推荐这种写法,我推荐一个网站https://www.easy-mock.com/,来mock数据,适合个人团队,模拟的数据也是什么的棒,上面的写法推到服务器上是不适用的,而easy-mock 可以,不用考虑跨域问题,适合自己写一个demo配置不同环境的api路径   栗:在dev.env.js中配置

在 prod.env.js配置这样就可以实现线上与本地的api基本路径请求

  • iconfont阿里巴巴图表库使用

这种网上的很多,栗子:https://www.cnblogs.com/xuange306/p/9156651.html   我说的基于上面的基础上的,我建议是封装一个vue组件,我这边

<style lang="scss" rel="stylesheet/scss">
  @import "iconfont.css";
  </style>
  <template>
  <i :class="classes" :style="styles"></i>
  </template>
  <script>
  const prefixCls = 'uzi-icon'
  export default {
    name: 'UziIcon',
    componentName: 'UziIcon',
    props: {
      type: String,
      size: [Number, String],
      color: String,
      fontStyle: {
        default: 'normal',
        type: String
      }
    },
    computed: {
      classes () {
        return `${prefixCls} ${prefixCls}-${this.type}`
      },
      styles () {
        let style = {}
        style['font-style'] = `normal`
        if (this.size) {
          style['font-size'] = `${this.size}rem`
        }
        if (this.fontStyle) {
          style['font-style'] = this.fontStyle
        }
        if (this.color) {
          style.color = this.color
        }
        return style
      }
    }
  }
  </script>

极大的方便我们的使用,入口文件导出供其他组件使用

import Icon from './icon.vue'

 export default Icon

当然这样我门就可以用了,但是我比较懒,我想实现启动项目或者运行命令,自动化拉取更新iconfont几个文件,而且实现多个图标库的一起使用,

我在build目录下新建了一个icon.js的文件

const chalk = require('chalk')
  const _ = require('lodash')
  const path = require('path')
  const fs = require('fs')
  const request = require('request')
  const wget = require('wget')
  
  const FONT_FILE_TYPE_EOT = 'eot'
  const FONT_FILE_TYPE_WOFF = 'woff'
  const FONT_FILE_TYPE_TTF = 'ttf'
  const FONT_FILE_TYPE_SVG = 'svg'
 
  const icon = [{  // 自动维护图标
  aliUrl: '//at.alicdn.com/t/font_819408_9zb80t2tc6.css',  // 暂时只支持使用阿里巴巴图标库
  dir: 'src/components/uzi-icon'  // 公共图标
  }]
  
  const postUrl = (_url,fn) => {
  request(_url, function (error, response, body) {
    if (!error && response.statusCode == 200) {
      fn(body)
    }else {
      throw new Error("gen Icon error")
    }
  })
}
  
  const downIcon = (iconUrl,dir)=> {
  postUrl('https:'+iconUrl,(chunk)=>{
    let form = 0
    let to = form
    let urlList = []
    let count = 0
    while (form !== -1 && to !== -1){
      count++
      if(count > 3000) throw new Error("gen icon failed")
      form = to + 1
      form = chunk.indexOf("url(",form)
      to = chunk.indexOf(")",form+1)
      if(form !== -1 && to !== -1){
        urlList.push(chunk.substr(form+5,to - form-6))
      }
    }

    urlList = _.uniq( urlList.map(_url => _url.split("#")[0]) )
    count = urlList.length
    urlList.forEach(_url => {
      let __url = _url.split("?")[0]
      let {ext} = path.parse(__url)
      let fileName = "iconfont"+ext
      let filePath = path.join(dir,fileName)
      fs.existsSync(filePath) && fs.unlinkSync(filePath)
      if(__url[0] !== '/') return
      let download = wget.download("https:"+__url, filePath, {})
      chunk.split(_url).join("")
      download.on('error', function(err) {
        throw err
      })
    })

    urlList.forEach(_url => {
      let strs = _url.split('?')[0].split('.')
      let type = strs[strs.length - 1]
      if(_url[0] !== '/') return
      chunk = chunk.replace(_url, './iconfont.' + type)
      chunk = chunk.replace(_url, './iconfont.' + type)
    })
    fs.writeFileSync(path.join(dir, 'iconfont.css'),chunk)
  })
}
  for(let item of icon){
 downIcon(item.aliUrl,path.resolve(item.dir))
}

通过wget插件实现下载,在package.json 中

或者启动项目运行,只需当然你需要更新图标路径:再每次启动项目 或者运行npm run uzi-icon 即可

当然这种方法 不是最好的,如何优雅的使用icon中这篇文章 推荐使用svg,我这篇也写过,在博客中有,个人推荐使用svg-icon

最后贴一下项目地址

https://github.com/goSunadeod/vue-demo1

猜你喜欢

转载自blog.csdn.net/shentibeitaokong/article/details/82461739