如何在 Vue.js 中使用第三方js库


Posted in Javascript onApril 25, 2017

在诸多 Vue.js 应用中, Lodash, Moment, Axios, Async等都是一些非常有用的 JavaScript 库. 但随着项目越来越复杂, 可能会采取组件化和模块化的方式来组织代码, 还可能要使应用支持不同环境下的服务端渲染. 除非你找到了一个简单而又健壮的方式来引入这些库供不同的组件和模块使用, 不然, 这些第三方库的管理会给你带来一些麻烦.

本文将介绍一些在 Vue.js 中使用第三方库的方式.

全局变量

在项目中添加第三方库的最简单方式是讲其作为一个全局变量, 挂载到 window 对象上:

entry.js

window._ = require('lodash');

MyComponent.vue

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

这种方式不适合于服务端渲染, 因为服务端没有 window 对象, 是 undefined , 当试图去访问属性时会报错.

在每个文件中引入

另一个简单的方式是在每一个需要该库的文件中导入:

MyComponent.vue

import _ from 'lodash';

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

这种方式是允许的, 但是比较繁琐, 并且带来的问题是: 你必须记住在哪些文件引用了该库, 如果项目不再依赖这个库时, 得去找到每一个引用该库的文件并删除该库的引用. 如果构建工具没设置正确, 可能导致该库的多份拷贝被引用.

优雅的方式

在 Vuejs 项目中使用 JavaScript 库的一个优雅方式是讲其代理到 Vue 的原型对象上去. 按照这种方式, 我们引入 Moment 库:

entry.js

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

由于所有的组件都会从 Vue 的原型对象上继承它们的方法, 因此在所有组件/实例中都可以通过 this.$moment: 的方式访问 Moment 而不需要定义全局变量或者手动的引入.

MyNewComponent.vue

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

接下来就了解下这种方式的工作原理.

Object.defineProperty

一般而言, 可以按照下面的方式来给对象设置属性:

Vue.prototype.$moment = moment;

可以这样做, 但是 Object.defineProperty 允许我们通过一个 descriptor 来定义属性. Descriptor 运行我们去设置对象属性的一些底层(low-level)细节, 如是否允许属性可写? 是否允许属性在 for 循环中被遍历.

通常, 我们不会为此感到困扰, 因为大部分时候, 对于属性赋值, 我们不需要考虑这样的细节. 但这有一个明显的优点: 通过 descriptor 创建的属性默认是只读的 .

这就意味着, 一些处于迷糊状态的(coffee-deprived)开发者不能在组件内去做一些很愚蠢的事情, 就像这样:

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

此外, 试图给只读实例的方法重新赋值会得到 TypeError: Cannot assign to read only property 的错误.

$

你可能会注意到, 代理第三库的属性会有一个 $ 前缀, 也可能看到其它类似 $refs, $on, $mount 的属性和方式, 它们也有这个前缀.

这个不是强制要求, 给属性添加 $ 前缀是提供那些处于迷糊状态(coffee-deprived)的开发者这是一个公开的 API, 和 Vuejs 的一些内部属性和方法区分开来.

this

你还可能注意到, 在组件内是通过 this.libraryName 的方式来使用第三方库的, 当你知道它是一个实例方法时就不会感到意外了. 但与全局变量不同, 通过 this 来使用第三方库时, 必须确保 this 处于正确的作用域. 在回调方法中 this 的作用域会有不同, 但箭头式回调风格能保证 this 的作用域是正确的:

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

插件

如果你想在多个项目中使用同一个库, 或者想将其分享给其他人, 可以将其写成一个插件:

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

在应用的入口引入插件之后, 就可以在任何一个组件内像使用 Vue Router , Vuex 一样使用你定义的库了.

写一个插件

首先, 创建一个文件用于编写自己的插件. 在示例中, 我会将 Axios 作为插件添加到项目中, 因而我给文件起名为 axios.js . 其次, 插件要对外暴露一个 install 方法, 该方法的第一个参数是 Vue 的构造函数:

axios.js

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

可以使用先前将库添加到原型对象上的方法:

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 提供的一个通用名字. 因而可以提供一个可选的参数允许他们随意命名:

axions.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..');
 }
})

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
Prototype ObjectRange对象学习
Jul 19 Javascript
jQuery 行背景颜色的交替显示(隔行变色)实现代码
Dec 13 Javascript
70+漂亮且极具亲和力的导航菜单设计国外网站推荐
Sep 20 Javascript
jQuery输入城市查看地图使用介绍
May 08 Javascript
微信支付如何实现内置浏览器的H5页面支付
Sep 25 Javascript
解决JavaScript数字精度丢失问题的方法
Dec 03 Javascript
JS中使用apply、bind实现为函数或者类传入动态个数的参数
Apr 26 Javascript
javascript构造函数以及原型对象的理解
Jan 13 Javascript
微信小程序图片自适应支持多图实例详解
Jun 21 Javascript
vue 兄弟组件的信息传递的方法实例详解
Aug 30 Javascript
js常用方法、检查是否有特殊字符串、倒序截取字符串操作完整示例
Jan 26 Javascript
jQuery 实现扁平式小清新导航
Jul 07 jQuery
Javascript中click与blur事件的顺序详析
Apr 25 #Javascript
完美解决UI-Grid表格元素中多个空格显示为一个空格的问题
Apr 25 #Javascript
ES6中Math对象新增的方法实例详解
Apr 25 #Javascript
jquery.form.js异步提交表单详解
Apr 25 #jQuery
关于jQuery中fade(),show()起始位置的一点小发现
Apr 25 #jQuery
深入理解Javascript中的作用域链和闭包
Apr 25 #Javascript
js中字符型和数值型数字的互相转化方法(必看)
Apr 25 #Javascript
You might like
PHP isset()与empty()的使用区别详解
2017/02/10 PHP
JavaScript中实现块作用域的方法
2010/04/01 Javascript
网页编辑器ckeditor和ckfinder配置步骤分享
2012/05/24 Javascript
输入密码检测大写是否锁定js实现代码
2012/12/03 Javascript
JavaScript实现的简单烟花特效代码
2015/10/20 Javascript
JavaScript和HTML DOM的区别与联系及Javascript和DOM的关系
2015/11/15 Javascript
js定时器实例分享
2016/12/20 Javascript
node.js入门教程之querystring模块的使用方法
2017/02/27 Javascript
Mac下安装vue
2018/04/11 Javascript
vue循环数组改变点击文字的颜色
2019/10/14 Javascript
Vue Render函数原理及代码实例解析
2020/07/30 Javascript
toString.call()通用的判断数据类型方法示例
2020/08/28 Javascript
vue-router 按需加载 component: () => import() 报错的解决
2020/09/22 Javascript
[01:02:07]Liquid vs Newbee 2019国际邀请赛小组赛 BO2 第一场 8.15
2019/08/16 DOTA
pygame学习笔记(6):完成一个简单的游戏
2015/04/15 Python
python 连接各类主流数据库的实例代码
2018/01/30 Python
python logging日志模块以及多进程日志详解
2018/04/18 Python
Python实现base64编码的图片保存到本地功能示例
2018/06/22 Python
Python中的Numpy矩阵操作
2018/08/12 Python
Python 200行代码实现一个滑动验证码过程详解
2019/07/11 Python
django 环境变量配置过程详解
2019/08/06 Python
Pytorch 保存模型生成图片方式
2020/01/10 Python
浅谈keras中的Merge层(实现层的相加、相减、相乘实例)
2020/05/23 Python
基于Pyinstaller打包Python程序并压缩文件大小
2020/05/28 Python
CSS3让登陆面板3D旋转起来
2016/05/03 HTML / CSS
老板电器官方购物商城:老板油烟机、燃气灶、消毒柜、电烤箱
2018/05/30 全球购物
Java TransactionAPI (JTA) 主要包含几部分
2012/12/07 面试题
.NET remoting中对象激活的两种方式
2015/06/08 面试题
人力资源专业推荐信
2013/11/29 职场文书
实用求职信范文分享
2013/12/25 职场文书
南京市纪委监察局整改方案
2014/09/16 职场文书
公司副总经理岗位职责
2014/10/01 职场文书
催款律师函范文
2015/05/27 职场文书
对领导班子的意见和建议
2015/06/08 职场文书
初一英语教学反思
2016/02/15 职场文书
JS Canvas接口和动画效果大全
2021/04/29 Javascript