1. 先来说一说export, export default,module.exports的区别和使用
他们都是成对使用的,不能乱用:
(1)module.exports 和 exports对应的是require:是属于CommonJS模块规范。
- module.exports导出如下:
// 在fun.js 写入
const arr = [1, 2, 3]
module.exports = {
arr
}复制代码
可以批量导出, fun.js如果有多个module.exports, 只有最后一个生效。如果有其他的exports, 它们都不会生效
- exports导出如下:
// 在fun.js 写入
exports.arr = [1, 2, 3] 复制代码
单个导出,fun.js可以有多个exports
- 使用CommonJS模块规范进行导出,在引入时候有两种方式:一种是:在引入时候可以使用{}解构出来,另一种是:直接引入。如下:
let { arr } = require('./fun') // [1, 2, 3]
let obj = require('./fun') // { arr: [1, 2, 3] }
复制代码
(2)export 和 export default,对应的是import:是属于ES6语法
- 一个文件可以使用export导出多个,引入的时候需要使用 {}。如下:
// 在fun.js 写入
export let arr = [1, 2, 3]
export let obj = { name: '123' }
// 页面引用
import {arr, obj } from './fun'复制代码
- export default 只能有一个,可以批量导出,引入的时候不能使用 {} 。文件里可以同时存在export 和export default ,并且分别引入的话,都是生效的。如下:
// 在fun.js 写入
export let arr = [1, 2, 3]
export let obj = { name: '123' }
export default {
age: 12
}
// 页面引用
import {arr, obj } from './fun' // [1, 2, 3], { name: '123' }
import myObj from './test1' // { age: 12}复制代码
2. 添加全局方法或属性
(1)使用Vue.prototype
// 在main.js中写
Vue.prototype.getData = (params) => {
...
}复制代码
(2)使用install + Vue.prototype
// 在你的全局函数文件fun.js中写
export default {
install (Vue) {
Vue.prototype.getData = () => {
return { name: 'scout'}
}
}
}
// main.js 引入
import getData from './fun'
Vue.use(getData) 复制代码
Vue.use 会自动阻止多次注册相同插件,届时即使多次调用也只会注册一次该插件。以上两种方式注册全局方法,实现的原理都是在 Vue.prototype 上添加了一个方法。在任何vue组件里都能使用 this.getData() // { name: 'scout'}
什么时候该使用Vue.use()方式,什么时候可以直接挂在prototype上呢,那你就要知道Vue.use() 到底干了什么?
Vue规定引入的插件必须是对象或者函数。
- 如果引入的插件是个对象:必须提供install方法,例如: element-ui组件库 , 需要使用Vue.use(),该方法默认会调用install方法;
- 如果引入的插件是个函数,不是按照vue规则设计(准确地说不是专门为VUE服务)里面没有install方法,例如:axios函数库。 那么就通过添加到vue原型链上的方式使用,它会被直接当作install函数执行。
3. 添加全局组件
// 公共vue组件: components文件夹下面的Loading.vue文件:
import LoadingComponent from '@/components/Loading'
export default {
install (Vue) {
Vue.component('Loading', LoadingComponent)
}
}
// 全局组件: public文件夹下面的Loading.js文件。在main.js中引入:
import Loading from "@/public/Loading"
Vue.use(Loading)
// 在vue任何组件上都可以直接使用: 复制代码
4. 添加全局过滤器
自定义指令、添加全局方法等 都可以采用此种方式比较方便
// 在public文件夹下的filter.js文件中:
export const isEmpty = (value) => {
return value || '-'
}
//在main.js中注册
import * as filters from './filters'
Object.keys(filters).forEach(key => {
Vue.filter(key, filters[key])
})
// 在任何组件中都可以使用此过滤器:| 符号左侧的是传参
{{message | isEmpty}}
复制代码
5. 添加全局自定义指令
自定义指令为我们提供了几个钩子函数(均为可选项):
- bind: 只调用一次,指令第一次绑定到元素时调用,用这个钩子函数可以定义一个在绑定时执行一次的初始化动作。
- inserted: 被绑定元素插入父节点时调用(仅保证父节点存在,但不一定被插入到DOM)。
- update: 被绑定元素所在的模板更新时调用,而不论绑定值是否变化。通过比较更新前后的绑定值,可以忽略不必要的模板更新
- componentUpdated: 被绑定元素所在模板完成一次更新周期时调用。
- unbind: 只调用一次, 指令与元素解绑时调用。
我这里以inserted为例,添加一个全局的表格拖拽的自定义指令 v-tableDrag 。此处使用了sortablejs这个函数库(ps: 这个包的使用方法可以去npm查看,这里不做赘述。不用关注这个,主要是看如何进行指令的注册)。
// 这是directive文件夹下面的 tableDrag.js文件:
import Sortable from 'sortablejs'
export default {
install (Vue) {
Vue.directive('tableDrop', {
inserted (el, binding, vnode) {
let { value } = binding
let column = el.querySelector('.ivu-table-header thead tr')
Sortable.create(column, {
animation: 200,
filter: `.ivu-table-header thead tr th:nth-child(${column.childElementCount})`,
onMove (e) {
if (e.related.innerText === column.children[`${column.childElementCount - 1}`].innerText) {
return false
}
},
onEnd (e) {
// 列表数据的改变
let { item, oldIndex, newIndex } = e
let oldItem = value[oldIndex]
value.splice(oldIndex, 1)
value.splice(newIndex, 0, oldItem)
// 表头的改变
let fatherNode = item.parentElement
let flag = fatherNode.children[newIndex]
fatherNode.removeChild(flag)
fatherNode.insertBefore(flag, fatherNode.children[oldIndex])
}
})
}
})
}
}复制代码
注册完后使用:
//在main.js中引入
import tableDrag from '@/directive/tableDrag'
Vue.use(tableDrag)
// 任何组件中都可以使用指令: v-tableDrag 这个指令实现了表格的行,列,都可以进行拖拽复制代码
其实钩子函数中常用的参数就这三个(详细参数查看下图):
- el:所绑定的元素DOM节点;
- binding: 是一个对象,包含很多值,常用的就这么两个:name:指令名;value: 绑定的值,如:v-tableDrag='123', value就是123。
- vnode: Vue编译生成的虚拟DOM节点。