vue2插件

插件

插件通常用來(lái)為 Vue 添加全局功能酿雪。插件的功能范圍沒(méi)有嚴(yán)格的限制——一般有下面幾種:

  1. 添加全局方法或者 property指黎。如:vue-custom-element

  2. 添加全局資源:指令/過(guò)濾器/過(guò)渡等州丹。如 vue-touch

  3. 通過(guò)全局混入來(lái)添加一些組件選項(xiàng)。如 vue-router

  4. 添加 Vue 實(shí)例方法亲怠,通過(guò)把它們添加到 Vue.prototype 上實(shí)現(xiàn)柠辞。

  5. 一個(gè)庫(kù)钾腺,提供自己的 API,同時(shí)提供上面提到的一個(gè)或多個(gè)功能姻报。如 vue-router

使用插件

通過(guò)全局方法 Vue.use() 使用插件吴旋。它需要在你調(diào)用 new Vue() 啟動(dòng)應(yīng)用之前完成:

// 調(diào)用 `MyPlugin.install(Vue)`
Vue.use(MyPlugin)

new Vue({
  // ...組件選項(xiàng)
})

也可以傳入一個(gè)可選的選項(xiàng)對(duì)象:

Vue.use(MyPlugin, { someOption: true })

Vue.use 會(huì)自動(dòng)阻止多次注冊(cè)相同插件厢破,屆時(shí)即使多次調(diào)用也只會(huì)注冊(cè)一次該插件摩泪。
Vue.js 官方提供的一些插件 (例如 vue-router) 在檢測(cè)到 Vue 是可訪問(wèn)的全局變量時(shí)會(huì)自動(dòng)調(diào)用 Vue.use()。然而在像 CommonJS 這樣的模塊環(huán)境中嚷掠,你應(yīng)該始終顯式地調(diào)用 Vue.use():

// 用 Browserify 或 webpack 提供的 CommonJS 模塊環(huán)境時(shí)
var Vue = require('vue')
var VueRouter = require('vue-router')

// 不要忘了調(diào)用此方法
Vue.use(VueRouter)

awesome-vue 集合了大量由社區(qū)貢獻(xiàn)的插件和庫(kù)不皆。

開(kāi)發(fā)插件

Vue.js 的插件應(yīng)該暴露一個(gè) install 方法熊楼。這個(gè)方法的第一個(gè)參數(shù)是 Vue 構(gòu)造器鲫骗,第二個(gè)參數(shù)是一個(gè)可選的選項(xiàng)對(duì)象:

MyPlugin.install = function (Vue, options) {
  // 1. 添加全局方法或 property
  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) {
    // 邏輯...
  }
}
數(shù)字驗(yàn)證碼:
import SIdentify from './src/identify'

/* istanbul ignore next */
SIdentify.install = function (Vue) {
  Vue.component(SIdentify.name, SIdentify)
}

export default SIdentify
<template>
  <div class="s-canvas" style="display: flex;">
    <canvas id="s-canvas" :width="contentWidth" :height="contentHeight" @click="getValidCode"></canvas>
  </div>
</template>
<script>
export default {
  name: 'SIdentify',
  props: {
    identifyCode: {
      type: String,
      default: '1234'
    },
    fontSizeMin: {
      type: Number,
      default: 16
    },
    fontSizeMax: {
      type: Number,
      default: 40
    },
    backgroundColorMin: {
      type: Number,
      default: 180
    },
    backgroundColorMax: {
      type: Number,
      default: 240
    },
    colorMin: {
      type: Number,
      default: 50
    },
    colorMax: {
      type: Number,
      default: 160
    },
    lineColorMin: {
      type: Number,
      default: 40
    },
    lineColorMax: {
      type: Number,
      default: 180
    },
    dotColorMin: {
      type: Number,
      default: 0
    },
    dotColorMax: {
      type: Number,
      default: 255
    },
    contentWidth: {
      type: Number,
      default: 153
    },
    contentHeight: {
      type: Number,
      default: 40
    }
  },
  methods: {
    // 生成一個(gè)隨機(jī)數(shù)
    randomNum (min, max) {
      return Math.floor(Math.random() * (max - min) + min)
    },
    // 生成一個(gè)隨機(jī)的顏色
    randomColor (min, max) {
      const r = this.randomNum(min, max)
      const g = this.randomNum(min, max)
      const b = this.randomNum(min, max)
      return 'rgb(' + r + ',' + g + ',' + b + ')'
    },
    drawPic () {
      const canvas = document.getElementById('s-canvas')
      const ctx = canvas.getContext('2d')
      ctx.textBaseline = 'bottom'
      // 繪制背景
      ctx.fillStyle = this.randomColor(this.backgroundColorMin, this.backgroundColorMax)
      ctx.fillRect(0, 0, this.contentWidth, this.contentHeight)
      // 繪制文字
      for (let i = 0; i < this.identifyCode.length; i++) {
        this.drawText(ctx, this.identifyCode[i], i)
      }
      this.drawLine(ctx)
      this.drawDot(ctx)
    },
    drawText (ctx, txt, i) {
      ctx.fillStyle = this.randomColor(this.colorMin, this.colorMax)
      ctx.font = this.randomNum(this.fontSizeMin, this.fontSizeMax) + 'px SimHei'
      const x = (i + 1) * (this.contentWidth / (this.identifyCode.length + 1))
      const y = this.randomNum(this.fontSizeMax, this.contentHeight - 5)
      const deg = this.randomNum(-45, 45)
      // 修改坐標(biāo)原點(diǎn)和旋轉(zhuǎn)角度
      ctx.translate(x, y)
      ctx.rotate(deg * Math.PI / 180)
      ctx.fillText(txt, 0, 0)
      // 恢復(fù)坐標(biāo)原點(diǎn)和旋轉(zhuǎn)角度
      ctx.rotate(-deg * Math.PI / 180)
      ctx.translate(-x, -y)
    },
    drawLine (ctx) {
      // 繪制干擾線
      for (let i = 0; i < 8; i++) {
        ctx.strokeStyle = this.randomColor(this.lineColorMin, this.lineColorMax)
        ctx.beginPath()
        ctx.moveTo(this.randomNum(0, this.contentWidth), this.randomNum(0, this.contentHeight))
        ctx.lineTo(this.randomNum(0, this.contentWidth), this.randomNum(0, this.contentHeight))
        ctx.stroke()
      }
    },
    drawDot (ctx) {
      // 繪制干擾點(diǎn)
      for (let i = 0; i < 100; i++) {
        ctx.fillStyle = this.randomColor(0, 255)
        ctx.beginPath()
        ctx.arc(this.randomNum(0, this.contentWidth), this.randomNum(0, this.contentHeight), 1, 0, 2 * Math.PI)
        ctx.fill()
      }
    },
    getValidCode () {
      this.$emit('getValidCode')
    }
  },
  watch: {
    identifyCode () {
      this.drawPic()
    }
  },
  mounted () {
    this.drawPic()
  }
}
</script>

提示信息

import OperMsg from './components/OperMsg.vue'

const OperTip = {
  install: function (Vue, options = {}) {
    const VueMsg = Vue.extend(OperMsg)
    let msg = null

    const $operTip = {
      show(methodOps = {}) {
        return new Promise(resolve => {
          let defaultNote = '操作成功'
          if (!msg) {
            msg = new VueMsg()
            console.log(msg.$props)
            if (msg.$props.msgType === 'error') {
              defaultNote = '操作失敗'
            }
            msg.$props.msgType = methodOps.type || 'success'
            msg.$props.msgContent = methodOps.content || defaultNote
            msg.$mount()
            document.querySelector(options.container || 'body').appendChild(msg.$el)
          }
          if (msg.$props.msgType === 'error') {
            defaultNote = '操作失敗'
          }
          msg.$props.msgType = methodOps.type || 'success'
          msg.$props.msgContent = methodOps.content || defaultNote
          msg.show()
          resolve()
        })
      },
      hide() {
        return new Promise(resolve => {
          if (!msg) {
            resolve()
            return
          }
          msg.hide()
        })
      }
    }

    Vue.operTip = Vue.prototype.$operTip = $operTip
    // 注冊(cè)組件
    Vue.component('operTip', OperMsg)
  }
}

export default OperTip
<template>
  <div class="oper-msg-container"
       ref="msgContainer">
    <transition name="slide">
      <div class="msg"
           v-if="isShowMsg === 'show'"
           :style='{ backgroundColor: color }'>
        <img src="../../../assets/personalCenter/oper-tip-icon.png">
        &nbsp;&nbsp;{{ msgContent.length > 15 ? msgContent.substr(0, 15) + '...' :  msgContent }}
      </div>
    </transition>
  </div>
</template>
<script>
export default {
  name: 'OperMsg',
  props: {
    msgType: {
      type: String,
      default: 'success'
    },
    msgContent: {
      type: String,
      default: ''
    }
  },
  data () {
    return {
      isShowMsg: 'hide',
      timer: null,
      clearHeightTimer: null,
      color: '#FFA300'
    }
  },
  mounted () {
  },
  watch: {
    isShowMsg (oldVal, newVal) {
      if (this.timer) {
        clearTimeout(this.timer)
      }
      if (newVal === 'hide') {
        this.timer = setTimeout(() => {
          this.hide()
        }, 3000)
      }
    }
  },
  methods: {
    show () {
      console.log(this.msgType)
      if (this.msgType === 'error') {
        this.color = '#ED6355'
      } else {
        this.color = '#FFA300'
      }
      this.isShowMsg = 'show'
    },
    hide () {
      this.isShowMsg = 'hide'
    }
  }
}
</script>
<style lang="scss" scoped>
.oper-msg-container {
  width: 100%;
  display: flex;
  justify-content: center;
  align-items: center;
  z-index: 10000;
  position: fixed;
  top: 5px;
  top: calc(5px + constant(safe-area-inset-top));
  top: calc(5px + env(safe-area-inset-top));
  background: transparent;
  .msg {
    display: flex;
    justify-content: center;
    align-items: center;
    padding: 10px 30px;
    font-size: 14px;
    font-weight: 500;
    color: rgba(255, 255, 255, 1);
    line-height: 14px;
    // background: rgba(255,163,0,1);
    border-radius: 20px;
    img {
      width: 20px;
      height: 20px;
    }
  }
  .slide-enter-active {
    animation: slideInDown 0.5s;
  }
  .slide-leave-active {
    animation: slideOutUp 0.5s;
  }
  @-webkit-keyframes slideInDown {
    from {
      -webkit-transform: translate3d(0, -100%, 0);
      transform: translate3d(0, -100%, 0);
      visibility: visible;
    }
    to {
      -webkit-transform: translate3d(0, 0, 0);
      transform: translate3d(0, 0, 0);
    }
  }
  @-webkit-keyframes slideOutUp {
    from {
      -webkit-transform: translate3d(0, 0, 0);
      transform: translate3d(0, 0, 0);
    }
    to {
      visibility: hidden;
      -webkit-transform: translate3d(0, -100%, 0);
      transform: translate3d(0, -100%, 0);
    }
  }
}
</style>
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末顿苇,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子凑队,更是在濱河造成了極大的恐慌幔翰,老刑警劉巖遗增,帶你破解...
    沈念sama閱讀 206,311評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件做修,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡饰及,警方通過(guò)查閱死者的電腦和手機(jī)燎含,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,339評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門屏箍,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人谚咬,你說(shuō)我怎么就攤上這事尚粘±杉蓿” “怎么了?”我有些...
    開(kāi)封第一講書人閱讀 152,671評(píng)論 0 342
  • 文/不壞的土叔 我叫張陵尚辑,是天一觀的道長(zhǎng)杠茬。 經(jīng)常有香客問(wèn)我,道長(zhǎng)宁赤,這世上最難降的妖魔是什么栓票? 我笑而不...
    開(kāi)封第一講書人閱讀 55,252評(píng)論 1 279
  • 正文 為了忘掉前任走贪,我火速辦了婚禮,結(jié)果婚禮上继找,老公的妹妹穿的比我還像新娘擦秽。我一直安慰自己感挥,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,253評(píng)論 5 371
  • 文/花漫 我一把揭開(kāi)白布硼瓣。 她就那樣靜靜地躺著堂鲤,像睡著了一般媒峡。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上半哟,一...
    開(kāi)封第一講書人閱讀 49,031評(píng)論 1 285
  • 那天寓涨,我揣著相機(jī)與錄音氯檐,去河邊找鬼。 笑死糯崎,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的奏司。 我是一名探鬼主播,決...
    沈念sama閱讀 38,340評(píng)論 3 399
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼黄锤,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼食拜!你這毒婦竟也來(lái)了负甸?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書人閱讀 36,973評(píng)論 0 259
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤呻待,失蹤者是張志新(化名)和其女友劉穎打月,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體蚕捉,經(jīng)...
    沈念sama閱讀 43,466評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡奏篙,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,937評(píng)論 2 323
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了迫淹。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片秘通。...
    茶點(diǎn)故事閱讀 38,039評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖敛熬,靈堂內(nèi)的尸體忽然破棺而出肺稀,到底是詐尸還是另有隱情,我是刑警寧澤话原,帶...
    沈念sama閱讀 33,701評(píng)論 4 323
  • 正文 年R本政府宣布,位于F島的核電站瑞妇,受9級(jí)特大地震影響稿静,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜辕狰,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,254評(píng)論 3 307
  • 文/蒙蒙 一改备、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧蔓倍,春花似錦悬钳、人聲如沸盐捷。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 30,259評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)碉渡。三九已至,卻和暖如春母剥,著一層夾襖步出監(jiān)牢的瞬間滞诺,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 31,485評(píng)論 1 262
  • 我被黑心中介騙來(lái)泰國(guó)打工环疼, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留习霹,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 45,497評(píng)論 2 354
  • 正文 我出身青樓炫隶,卻偏偏與公主長(zhǎng)得像淋叶,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子伪阶,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,786評(píng)論 2 345

推薦閱讀更多精彩內(nèi)容

  • 一煞檩、UI組件及框架 element - 餓了么出品的Vue2的web UI工具套件 mint-ui - Vue 2...
    站著瞌睡閱讀 811評(píng)論 0 3
  • 插件 插件通常用來(lái)為 Vue 添加全局功能。插件的功能范圍沒(méi)有嚴(yán)格的限制——一般有下面幾種: 添加全局方法或者 p...
    莫伊劍客閱讀 282評(píng)論 0 0
  • plugin 的作用 插件通常用來(lái)為 Vue 添加全局功能栅贴。插件的功能范圍沒(méi)有嚴(yán)格的限制——一般有下面幾種: 添加...
    櫻桃小白菜閱讀 137評(píng)論 0 0
  • 1. 簡(jiǎn)介 本節(jié)我們將介紹 Vue 的插件斟湃。包括什么是插件、如何使用插件筹误、如何編寫一個(gè)簡(jiǎn)單的插件桐早。其中,編寫和使用...
    木子教程閱讀 287評(píng)論 0 1
  • 一厨剪、本質(zhì) 造輪子哄酝,給Vue生態(tài)圈提供更多優(yōu)良的插件或工具 插件通常用來(lái)為 Vue 添加全局功能。插件的功能范圍沒(méi)有...
    MonkeyCode閱讀 133評(píng)論 0 0