手把手教你如何寫vue.js的插件,跨項目依賴。學不會你來打我!

前言

  • vue.js作為前端三大框架之一,它的快速開發(fā)特點深受開發(fā)者的喜愛。通常,我們使用vue.js會集成Router、Axios、Vuex、Element-UI等插件,那么你知道它們是如何無縫對接vue.js的嗎?接下來,我們參考Router插件無縫對接vue.js的原理來手動開發(fā)一個插件,并以npm的方式導入項目中。你準備好了嗎?(ps:接下來的內容,你需要有ES6語法基礎、Vue.js插件,混入,組件,指令相關知識點才能看懂)

一、vue-router集成vue.js的原理

  • 我們知道,在使用vue-cli2.0腳手架搭建vue.js項目時,它支持Router的選項,如下所示:

當我們輸入Y時,Router插件就在項目中生效了。如果我們要添加路由,直接修改router/index.js文件即可,如下所示(為HelloWorld頁面再添加一個路由):

毋庸置疑,在使用vue-cli2.0腳手架搭建項目時,針對于Router這個插件內部肯定做了很多事,今天咱們不深究到底做了哪些事,咱們來探究下main.js的內容:


// The Vue build version to load with the `import` command

// (runtime-only or standalone) has been set in webpack.base.conf with an alias.

import Vue from 'vue'

import App from './App'

import router from './router'

Vue.config.productionTip = false

/* eslint-disable no-new */

new Vue({

  el: '#app',

  // 這里用了ES6的簡便語法,

  // 實際為:  router: router, 當key和value的名稱一致時,可以省略冒號

  router,   

  components: { App },

  template: '<App/>'

})

有一個可疑點,就是在傳入new Vue() 構造方法的參數(shù)中,為什么添加了router,難道這樣就能無縫集成vue.js了嗎?我們不得而知,但是從官網(wǎng)插件部分內容來看[點擊查看],還需要使用類似Vue.use(router)的代碼來將路由集成至vue.js中。那么,這段代碼是在哪里被執(zhí)行的呢?我們從main.js中開始看,可以看到這么一段代碼:


import router from './router'

于是我們定位至router文件夾中去,發(fā)現(xiàn)內部存在一個index.js文件,其內部就是我們定義路由的內容:

其中,我們很容易發(fā)現(xiàn),內部執(zhí)行了這么一段代碼:


Vue.use(Router)

突然發(fā)現(xiàn),好像是符合官網(wǎng)的規(guī)則。那為什么還需要在main.js中的new Vue()有參構造方法中傳入router呢?這里又涉及到了Vue.js的全局混入的知識點[點擊查看]

根據(jù)全局混入知識點可知,它有缺點:每當創(chuàng)建一個Vue實例時,都會進行混入。白話來講就是:每創(chuàng)建一個Vue實例,都會調用上圖的created鉤子函數(shù)。從上述圖中的代碼來看,console.log(myOption)這行代碼的執(zhí)行是有條件的,只有當前vue實例的$options對象中的myOption屬性為true才能正常執(zhí)行。那么我們是不是可以大致猜測下:router插件集成vue.js的原因就是基于插件 + 混入來實現(xiàn)的? 可以自己做個實驗:把main.js中Vue的構造方法中的router刪除后,看項目還是否能夠正常路由至HelloWorld頁面?

二、如何自定義插件

  • 可以細看官網(wǎng)demo。說實話,vue.js官網(wǎng)真的很nice,基本上所有vue.js的功能都可以在官網(wǎng)中找到demo(讀到這里的你,是否發(fā)覺官網(wǎng)的重要性了呢?)?,F(xiàn)在,咱們直接利用官網(wǎng)的demo,來實現(xiàn)一個插件,包含如下功能:

1.擁有一個SayHi組件,其中擁有一個叫content的props,默認值為avengerEug。

  實現(xiàn)的功能 :在瀏覽器中渲染出: Hi {{ content }} (其中content為默認值或傳入的值)

2.擁有一個avenger-eug的指令,傳入一個字體的style顏色樣式

  實現(xiàn)的功能:當傳入red時,標簽中的字體顏色變成紅色

3.擁有一個全局彈框方法

  實現(xiàn)的功能:當我們執(zhí)行this.$myMessage('Hello')時,會在頁面彈出一個alert框,且內容為Hello
  • 實現(xiàn)步驟

  • 第一:創(chuàng)建如下圖所示的目錄結構:

  • 第二:在src/myPlugin/index.js文件中填充如下內容:

export default {

  install: (Vue) => {

    Vue.mixin({

      created: function () {

        // 當在vue的構造方法中,存在avengerEug這個key時,就會

        // 創(chuàng)建全局組件、指令和方法

        if (this.$options.avengerEug) {



          Vue.prototype.$myMessage = function (params) {

            window.alert(params)

          }

          Vue.component('SayHi', {

            template: '<h1> Hi {{ content }} </h1>',

            props: {

              content: {

                type: String,

                default: () => { return 'avengerEug' }

              }

            },

            created() {

              console.log('調用了SayHi組件的created鉤子函數(shù)')

            }

          })

          Vue.directive('avenger-eug', {

            bind(el, binding, vnode, oldVnode) {

              if (binding.value) {

                el.style.color = binding.value

              }

            }

          })

        }

      }

    })

  }

}

  • 第三:在main.js中添加如下代碼:
  • 第四:校驗:

由上可知,我們使用插件 + 混入的方式將自己寫的插件給集成到了當前項目中了。這里提一句:為什么我們寫的組件、指令、方法都能在其他組件中不需要注冊而直接使用呢?還記得官網(wǎng)中對插件章節(jié)的描述么?它要求第一個參數(shù)為Vue對象,而且必須要在new Vue代碼之前執(zhí)行Vue.use相關的代碼。那只有一個說法能夠說明,那就是在執(zhí)行new Vue構造方式時,內部對所有的插件進行了遍歷,并把自己作為參數(shù),調用每個插件的install方法,而此時的this就是全局Vue對象。 可能有人會問:我想把我的插件發(fā)布至npm中,后續(xù)其他項目直接使用npm install my-plugin時就能把上述的三個功能給加到項目中去,那該怎么辦?咱們繼續(xù)往下看。

三、如何跨項目依賴自己的插件

  • 在第二章中,我們實現(xiàn)了自定義的插件,并且集成到當前項目中去了。那么要如何跨項目依賴自己編寫的插件呢?這里就需要把自己的插件打成包發(fā)布至npm中去了。不急,咱們來搞定它!

  • 步驟如下:

    1.使用vuecli2.0腳手架搭建簡單版本vue.js項目(防止插件依賴過多的類庫)


# 注意,項目名必須唯一,不然在發(fā)布時會報403錯誤,npm認為你要更新別人的插件

# 但是發(fā)現(xiàn)不是同一個人,所以會報無權限

  vue init webpack-simple my-plugin-avenger

ps: 上述的項目名為my-plugin-avenger,先記住它,后續(xù)我們在npm install 和 import都需要用到它。

2.編寫自定義插件,為了方便,我直接copy第二章創(chuàng)建插件的代碼,最終內容如下所示:

3.創(chuàng)建src/index.js文件(為了將插件打包),如下所示:

4.修改webpack.config.js文件


  // 對應的修改內容如下:

  module.exports = {

  entry: './src/index.js',

  output: {

    // 模塊名, 其他類庫使用require的方式引用的原因就是配置了這個

    library: 'my-plugin-avenger',

    // libraryTarget會生成不同umd的代碼,可以只是commonjs標準的,也可以是指amd標準的,也可以只是通過script標簽引入的

    libraryTarget: 'umd',

    umdNamedDefine: true,  // 會對 UMD 的構建過程中的 AMD 模塊進行命名。否則就使用匿名的 define

    // 后面內容省略

  },

  // 后面內容省略

  }

> 5.修改package.json文件,指定插件入口

  // 修改如下配置。因為需要發(fā)布, 因此需要將這個字段改為 false

  `"private": false, `

  // 新增如下配置。當在第三方使用類庫, 使用 import MyPluginAvenger from 'my-plugin-avenger'時, 會根據(jù)插件的package.json的main入口找文件

"main": "dist/build.js",

6.執(zhí)行npm install引入依賴

7.執(zhí)行npm run build打包

8.自己在npm中注冊賬號(若已有賬號,此步驟忽略)

>9.設置`npm config set registry http://registry.npmjs.org/`命令配置npm源

>10.執(zhí)行` npm adduser `命令綁定賬號,輸入如下信息:

**Username: your name

Password: your password

Email: yourmail**

11.更新項目中的README.md文件內容,描述該插件有何用,如何使用(當在npm官網(wǎng)查找插件時,可以看到)。本人圖方便,未更改。

12.執(zhí)行npm publish命令發(fā)布npm包

13.npm官網(wǎng)查看發(fā)布的插件

14.跨項目依賴,在項目中執(zhí)行:npm i my-plugin-avenger

15.在項目的main.js中加入如下代碼:


import MyPluginAvenger from 'my-plugin-avenger'

Vue.use(MyPluginAvenger)

// 并在vue構造器中添加avengerEug: true

new Vue({

el: '#app',

router,

components: { App },

template: '<App/>',

avengerEug: true

})

16.在任意頁面使用第二章所說的組件、指令和全局函數(shù),你會發(fā)現(xiàn),成功了!

四、總結

  • 在npm發(fā)布的過程中,會出現(xiàn)一些其他錯誤,如下:
錯誤 原因
no_perms Private mode enable, only admin can publish this module 默認鏡像非官方的, 需要重新設置.命令: npm config set registry http://registry.npmjs.org
npm publish failed put 500 unexpected status code 401 沒有登錄,需要登錄: npm login 即可
npm ERR! you do not have permission to publish "your module name". Are you logged in as the correct user? 包名被占用, 需要重新命名. 命名之前最好先去npm官網(wǎng)查看包名是否被占用
You cannot publish over the previously published versions 每次發(fā)布時需要更新版本, 修改package.json文件的version字段即可.
npm publish時經(jīng)常報403 可以確認下注冊的賬號是否在郵箱中驗證完畢,或確認發(fā)布的項目名是否唯一
  • I am a slow walker, but I never walk backwards.
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

友情鏈接更多精彩內容