vue 全局挂载自定义函数(class)

对接千牛平台时需要在多个组件中调用点亮旺旺图标的方法,最后采用了class来做

使用场景

  • 背景:对接千牛平台时,需要在页面中将旺旺图标换成千牛官网文档中给出的新元素标签,并调用点亮旺旺图标的方法,点亮后的旺旺图标在点击后可开启千牛的聊天窗口
    • 目前只在一个组件中需要使用点亮的方法,为预防后续更多位置需要使用到,先把该方法提到utils中单独处理
  • 参考下方 全局挂载自定义函数 的 方法1 来实现
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    // utils下创建wwLight.js
    import _get from 'lodash/get';
    import _isFunction from 'lodash/isFunction';
    import { loadScript } from '@/utils'
    import { selectShopPlatformListApi } from '@/api/system';

    class WwLight {
    constructor(param) {
    // 如果有调用时传的参数就赋在param上(比如new WwLight(aa),则this.param = aa)
    if (param) (this.param = param);
    this.getAppKey().then((res) => {
    // 千牛的官网文档要求旺旺图标的元素标签上需要传appKey
    this.appKey = res
    })
    }

    // 初始化单个旺旺图标
    initWW(id) {
    const Light = window.Light
    if (_isFunction(Light?.light)) {
    Light.light(id)
    return true
    }
    return false
    }

    // 点亮单个旺旺图标
    async light(id) {
    const webwwDependencies = {
    kissy: 'https://assets.alicdn.com/s/kissy/1.2.0/kissy-min.js',
    webww: 'https://market.m.taobao.com/app/aliww/bc-ww/webww',
    }
    if (!_isFunction(_get(window, 'KISSY.config'))) {
    await loadScript(webwwDependencies.kissy)
    }
    if (!this.initWW(id)) {
    await loadScript(webwwDependencies.webww)
    this.initWW(id)
    }
    }

    // 初始化列表中所有旺旺图标
    initAllWW() {
    const Light = window.Light
    if (_isFunction(Light?.init)) {
    Light.init()
    return true
    }
    return false
    }

    // 点亮所有旺旺图标
    async lightAll() {
    const webwwDependencies = {
    kissy: 'https://assets.alicdn.com/s/kissy/1.2.0/kissy-min.js',
    webww: 'https://market.m.taobao.com/app/aliww/bc-ww/webww',
    }
    if (!_isFunction(_get(window, 'KISSY.config'))) {
    await loadScript(webwwDependencies.kissy)
    }
    if (!this.initAllWW()) {
    await loadScript(webwwDependencies.webww)
    this.initAllWW()
    }
    }

    // 目前只有一个组件中调用WwLight类,所以getAppKey暂时放这没问题
    // 后期如果需要多页面调用时可以把getAppKey抽出去vuex中
    async getAppKey() {
    const { data: platformOption } = await selectShopPlatformListApi()
    const tbPlatformInfo = platformOption.find(i => i.platformCode == '01') // 淘宝
    return tbPlatformInfo.appKey
    }
    }

    export default WwLight;
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    // 调用的组件中
    <template>
    <!-- 列表中,row为当行数据 -->
    <!-- 新的旺旺图标 -->
    <span
    class="J_WangWang"
    data-display="inline"
    data-icon="small"
    data-encode="true"
    data-bizdomain="taobao"
    data-biztype="1"
    :data-appKey="wwAppKey"
    :data-nick="row.buyerNick"
    :data-encryptuid="row.buyerOpenUid"
    :key="`${row.orderNo || ''}_` + row.buyerNick"
    :data-sceneparam="JSON.stringify({toRole: '', bizRef: ''})"
    >
    </span>
    </template>

    <script>
    import WwLight from '@/utils/wwLight.js'
    // 在这个位置new则不管该页面调用cipher-text组件多少次,都只执行一次WwLight的构造函数
    const wwLight = new WwLight()

    export default {
    name: 'cipher-text', // 组件名,位于table插槽中的组件
    components: {},
    props: {},
    data() {
    return {
    wwAppKey: '',
    }
    },
    mounted() {
    this.wwAppKey = wwLight.appKey
    },
    methods: {
    goToQn() {
    // 点亮新的旺旺聊天图标(千牛)
    await wwLight.lightAll()
    },
    },
    }

全局挂载自定义函数

方法1 utils下创建class 导出挂载到Vue原型

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// function.js
class Func {
/**
* 比如 存储Storage
*/
setStorage(name, content, type = "local") {
if (!name) return;
let storage;
//必须判断是否字符串
if (typeof content !== "string") {
content = JSON.stringify(content);
}
type === "local"
? (storage = window.localStorage)
: (storage = window.sessionStorage);
storage.setItem(name, content);
}
}
export default new Func();
1
2
3
4
5
6
7
8
9
// utils/index.js
import Vue from "vue";
import myService from "./request";
import Func from "./function";

Vue.prototype = Object.assign(Vue.prototype, {
$axios: myService,
$F: Func,
});
1
2
//使用
this.$F.setStorage()

方法2 Vue.prototype

  • 注意:prototype(显式原型)是函数独有的,vue实例 是通过 构造函数Vue 生成的
  • 原理:当通过 构造函数Vue 创建的 对象vue 找不到 属性getToken 时,会去对象vue的__proto__属性(隐式原型)上找,即 构造函数Vue 的prototype(显式原型)上找(参考
    1
    2
    3
    4
    5
    6
    7
    // mian.js中写入函数
    // 注意:这里Vue是构造函数,不是构造函数Vue生成的vue实例,prototype是函数独有的
    import Vue from 'vue';

    Vue.prototype.getToken = function (){
    ...
    }
    1
    2
    // 在所有组件里可调用函数
    this.getToken();

方法3 install+Vue.prototype

Vue.use()为注册全局插件所用,接收 函数 或者一个包含 install属性 的对象为参数,如果参数带有install就执行install, 如果没有就直接将参数当install执行。
Vue.use() 的注册本质上就是执行了一个 install 方法,install 里的内容可由开发者自己定义。

1
2
3
4
5
6
7
8
// 写好自己需要的公共JS文件(fun.js)
export default {
install(Vue) {
Vue.prototype.getToken = {
...
}
}
}
1
2
3
4
5
// main.js 引入并使用
import Vue from 'vue';
import fun from './fun' // 路径示公共JS位置决定

Vue.use(fun); // 全局注册Vue
1
2
// 所有组件里可调用函数
this.getToken();

参考

, , ,