zoukankan      html  css  js  c++  java
  • Vue 中如何定义全局的变量和常量

    Vue 中如何定义全局的变量和常量

    我想要定义一个变量, 在项目的任何地方都可以访问到, 不需要每一次使用的时候, 都引入.

    尝试1:
    创建 global.js 并且在其中定义

     
    let a = 10;

    在入口文件中引入 global.js

    import './global.js'

    在项目中使用:

    a // 报错
    

    发现报错了, a 并没有定义. 为什么?

    这个涉及到模块作用域:
    1 每一个 js 都相当于一个模块, 一个模块有自己的模块作用域.
    意思就是说: 其中的变量方法, 都只在这个模块上面生效.

    尝试2:
    将变量放到 Vue.prototype 上面, 通过插件全局引入
    创建 global.js, 这样写:

    let a = 10;
    export default {
        install () {
            Vue.prototype.$a = a;
        }
    }

    在 入口文件中引入:

    import G from './global'
    Vue.use(G);

    在项目中使用:

    this.$a
    

    的确可以, 但是这样的方式并不好, 在任何 this 不指向 Vue 的地方, 你都没有办法使用这个变量.

    尝试3:
    将变量放到 window 对象上面
    创建 global.js

    window.a = 10;

    在入口文件中引入

    import './global.js'

    在项目中使用:

    a 
    

    可行, 这种方式只要你能访问到 window 对象, 就能访问到这个变量.
    有什么缺点吗?
    暂时没有发现.

    实际的场景分析:
    在实际情景上, 你可能拥有一份配置, 比如说微信公众号开发的时候, 你有一份配置, 写着
    appId 和 appKey, 希望可以全局访问到.
    按照上面的讨论, 你应该这么写:

    global.js

    
    window.appId = 123;
    window.appKey = 'abc';
    

    可以很明显的看到, 一旦你要定义的变量或者常量过多, 就能疯了.
    所以我们希望有一种方式, 我们定义还是按照自己的方式定义:

    
    appId = 123;
    appKey = 'abc';
    

    然后有一个方法fn, 可以将这两个参数, 直接绑定到 window 对象上面

    fn (appId, appKey);

    结果就是 appId, appKey 都会被绑定到 window 对象上面.

    实现:
    你需要传递一个对象给方法 fn, fn 负责将这个对象中的每一个 key 都绑定到 window 对象上面.

    
    let bindToGlobal = obj => {
        for (let key in obj) {
            window[key] = obj[key]
        }
    }
    
    

    更新版本:
    你这样用之后, 所有的变量/常量都绑定在 window 对象上面, 很容易就和已经存在 window 对象上面的变量
    冲突, 所以要收敛你的行为, 这样:
    你先在window 对象上面设置一个属性, 属性值是一个对象, 比如这样:

    
    window.key = {};
    

    然后将你所有需要设置的全局变量, 方法, 都放到 window.key 里面而不是 window 上面.

    
    let bindToGlobal = obj => {
        window.abc = {};
        for (let key in obj) {
            window.abc[key] = obj[key]
        }
    }
    

    更近一步, 可以让这个 key 的名字为 _const 或者 _var, 或者让用户自己控制这个变量的名字.

    
    let bindToGlobal = (obj, key='var') => {
        window[key] = {};
        for (let i in obj) {
            window[key][i] = obj[i]
        }
    }
    

    现在大致已经可以了, 然后你要解决一下, 如果重复调用 'bindToGlobal' 后面的会覆盖掉前面
    所定义的 变量/常量, 而我们要的是 追加, 不是覆盖, 所以代码做个调整:

    
    let bindToGlobal = (obj, key='var') => {
        if (typeof window[key] === 'undefined') {
            window[key] = {};
        }
        
        for (let i in obj) {
            window[key][i] = obj[i]
        }
    }
    

    到这里已经结束了.
    最后对 'bindToGlobal' 做一个修改, 使得你以后使用的时候比较简单方便一点

    讨论一下:

    虽然开放了绑定在 window 对象上面的对象的名字, 但是你是不是就可以随便起名字?

    假设你有两份配置, 都是常量,
    一份是 http.js, 配置了全局请求的域名
    一份是 wexin.js 配置了公众号里面的一些 appId, appkey

    你是这样绑定呢:

    bindToGlobal(http, '_http');
    bindToGlobal(wexin, '_wexin');

    这样访问:

    _http.host 
    _wexin.appId
    

    还是按照它是常量还是变量去绑定:

    bindToGlobal(httpConfig, '_const');
    bindToGlobal(wexin, '_const');

    这样访问:

    _const.host;
    _const.appId;
    

    前者语义上面肯定是优秀的, 但是我考虑的不是这么一个点:
    1 如果有新人要来维护你的代码, 他想访问一个常量, 要先知道你定义的常量的名字是什么, 比如知道了
    是 'wexin', 然后再知道那个变量的名字是啥, 比如说 appId, 这个时候才能访问:

    wexin.appId;

    而如果你统一都是用 '_const', 他只要去配置文件里面看下名字是 appId, 就可以这么用

    _const.appId; // over
    

    也就是说 牺牲语义, 换来维护简单一点.
    试想如果追求语义, 你分的非常细, 定了七八个 key。

    2 记忆上面的问题, 未来的你, 放了几个月再来维护的时候, 或者某天你搞这个项目都搞的要吐了, 新访问
    一个变量的时候, 还要想一下 key 名字, 怂.
    而统一 _const.appId, 多简单的事情.

  • 相关阅读:
    聊聊WS-Federation
    用双十一的故事串起碎片的网络协议(上)
    责任链模式的使用-Netty ChannelPipeline和Mina IoFilterChain分析
    最小化局部边际的合并聚类算法(中篇)
    最小化局部边际的合并聚类算法(上篇)
    UVaLive 7371 Triangle (水题,判矩形)
    UVaLive 7372 Excellence (水题,贪心)
    POJ 3312 Mahershalalhashbaz, Nebuchadnezzar, and Billy Bob Benjamin Go to the Regionals (水题,贪心)
    UVa 1252 Twenty Questions (状压DP+记忆化搜索)
    UVa 10817 Headmaster's Headache (状压DP+记忆化搜索)
  • 原文地址:https://www.cnblogs.com/vicky-li/p/11673242.html
Copyright © 2011-2022 走看看