必备技能6、Vue框架引入JS库的正确姿式

在Vue.js应用中,可能须要引入Lodash,Moment,Axios,Async等很是好用的JavaScript库。当项目变得复杂庞大,一般会将代码进行模块化拆分。可能还须要跑在不一样的环境下,好比浏览器,服务端。vue

如何在各个模块和组件文件中引入须要的库呢? 找到一种简单靠谱的方式,能够省去不少的麻烦。ios

错误示范

全局变量法

最不靠谱的方式就是将导入的库挂在所有变量window对象下:axios

entry.js浏览器

window._ = require('lodash'); 

MyComponent.vuedom

export default { created() { console.log(_.isEmpty() ? 'Lodash everywhere!' : 'Uh oh..'); } } 

这种方式的缺点有不少,咱们只说其中一个关键的点:不支持服务端渲染。当应用跑在服务端时,window对象不存在,固然试图去访问window下的属性会抛出错误。模块化

到处引入法

另一个不太优雅的方式就是在须要的每一个文件中都引入对应的库:函数

MyComponent.vueui

import _ from 'lodash';

export default {
  created() {
    console.log(_.isEmpty() ? 'Lodash is available here!' : 'Uh oh..');
  }
}

虽然这方法是可行的,可是太不简洁。你必须在每一个文件中都记得引入, 并且若是不须要了,又得从新删除。另外,若是打包策略不够明智的话,可能会打包出多份重复的代码。this

正确引入方式

最简单靠谱的方式是用库变成Vue的原型对象的属性。下面,我来演示如何将Moment库引入:url

entry.js

import moment from 'moment';
Object.defineProperty(Vue.prototype, '$moment', { value: moment });

因为全部的组件都会继承Vue原型对象上的方法,所以这些方法在任何组件文件中都能经过this.$moment访问到:

MyNewComponent.vue

export default {
  created() {
    console.log('The time is ' . this.$moment().format("HH:mm"));
  }
}

咱们来仔细看一下其中的原理。

Object.defineProperty

一般咱们会以下设置对象属性:

Vue.prototype.$moment = moment;

你也能够这么作,可是Object.defineProperty容许咱们用属性描述器来定义咱们的属性。咱们能够定义该属性是否可写,可枚举,可配置。

通常状况下,咱们不须要用那么复杂的方式来赋值属性。但这里用它有个好处:用属性描述器定义的属性是默认只读的。

这能防止那些脑子不清醒的开发者(极可能是你哦~~)犯下一些低级错误:

this.$http = 'Assign some random thing to the instance method';
this.$http.get('/'); // TypeError: this.$http.get is not a function

Object.defineProperty能保护引入的库不被从新赋值,若是你尝试重写,程序会抛出“TypeError: Cannot assign to read only property”的错误。

$

可能你注意到,咱们用“$”开头的属性来存放引入的库。固然,你应该记得还有其余的一些属性也是这样的,好比$refs, $on, $mount

这种作法不是强制的,这个前缀就是为了提醒某些昏昏沉沉的开发者(怎么又是你?!),这些属性是公有的,你能够在任何地方使用。反之,某些属性只能在Vue内部使用。

做为一门以原型为基本的语言,JavaScript中并无真正的类,因此也就没有所谓的公有,私有变量,或者静态方法。上面这种约定,我以为是种不错的选择。

this

如今你能用this.$libraryName的方式来访问你须要的库了。但,你得保证this的指向。若是你在回调函数中使用this,一般这个this再也不指向Vue实例。

箭头函数是解决这个问题的好方法。

this.$http.get('/').then(res => {
  if (res.status !== 200) {
    this.$http.get('/') // etc
    // Only works in a fat arrow callback.
  }
});

写成插件

若是你在项目的不少地方都用了某个库,或者你但愿全局可用,你能够构建本身的Vue插件。

插件能化繁为简,能让你像下面这样很简单地引入本身想要的库:

import MyLibraryPlugin from 'my-library-plugin';
Vue.use(MyLibraryPlugin);

就像Vue Route,Vuex等插件同样,咱们的库仅仅须要两行,就能在任何地方使用了。

如何写插件

首先,建立一个文件。本例中,我将引入一个Axios库的插件。咱们就把这个文件命名为axios.js吧。

最关键的地方在于,咱们须要暴露一个将Vue构造器做为第一个参数的install方法。

axios.js

export default {
  install: function(Vue) {
    // Do stuff
  }
}

  

而后咱们能够用以前的方式将库添加到Vue的原型对象上:

axios.js

import axios from 'axios';

export default {
  install: function(Vue) {
    Object.defineProperty(Vue.prototype, '$http', { value: axios });
  }
}

  

接着咱们只须要Vue实例的use方法就能将这个库引入整个项目了。咱们像下面代码同样简单引入:

entry.js

import AxiosPlugin from './axios.js';
Vue.use(AxiosPlugin);

new Vue({
  created() {
    console.log(this.$http ? 'Axios works!' : 'Uh oh..');
  }
})

  

插件参数设置

插件的install方法还能够接受其余的可选参数。有些开发者可能不喜欢Axios实例对象的方法名$http,由于Vue resource插件的方法名也是这个。而后,让咱们利用第二个参数来修改它。

axios.js

import axios from 'axios';

export default {
  install: function(Vue, name = '$http') {
    Object.defineProperty(Vue.prototype, name, { value: axios });
  }
}

entry.js

import AxiosPlugin from './axios.js';
Vue.use(AxiosPlugin, '$axios');

new Vue({
  created() {
    console.log(this.$axios ? 'Axios works!' : 'Uh oh..');
  }
})

固然上面,咱们能够直接在Object.defineProperty的中将name属性写死成$axios。也能够在install方法中引入多个须要的库。

 

转载:https://blog.csdn.net/fen747042796/article/details/70660419

相关文章
相关标签/搜索